swapstats.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. <template>
  2. <view class="page_view">
  3. <top-return color="#FFF" text="日常记录"></top-return>
  4. <!-- 背景 -->
  5. <view class="bg_box"></view>
  6. <!-- 页面标题内容 -->
  7. <view class="flex_cloumn">
  8. <view class="flex_baseline">
  9. <view class="content_title" style="font-size: 60rpx;">{{dayTime.split('月')[0]}}</view>
  10. <view class="content_title" style="margin-left: 10rpx;">月</view>
  11. <view class="content_title" style="font-size: 60rpx; margin-left: 10rpx;">{{dayTime.split('月')[1]}}
  12. </view>
  13. <view class="content_title" style="margin-left: 10rpx;">日</view>
  14. <view class="content_title" style="font-size: 60rpx;margin-left: 20rpx;">{{weekTime}}</view>
  15. </view>
  16. <view class="flex_baseline">
  17. <view class="content_subtitle" style="opacity: 0.8;">记录今日孩子表现吧</view>
  18. </view>
  19. </view>
  20. <!-- 记录模块 -->
  21. <view class="module_box" style="margin-top: 20rpx;">
  22. <view class="_item" v-for="(item,index) in moduleData" :key="index" :style="item.color"
  23. @click="setTime(index)">
  24. <view class="_item_subtext" style="margin-left: 30rpx;">{{item.text}}</view>
  25. <view class="flex_baseline" style="margin-left: 30rpx;" v-if="item.numData === ''">
  26. <text class="_item_text" style="transform: skew(-15deg);">记录</text>
  27. <text class="_item_subtext" style="margin-left: 10rpx;opacity:0.8;">今日时长</text>
  28. </view>
  29. <view class="flex_baseline" style="margin-left: 30rpx;"
  30. v-if="item.numData.includes('小时') && item.numData != ''">
  31. <text class="_item_text" style="transform: skew(-15deg);">{{item.numData.split('小时')[0]}}</text>
  32. <text class="_item_subtext" style="margin-left: 10rpx;opacity:0.8;">小时</text>
  33. <text class="_item_text"
  34. style="margin-left: 10rpx;transform: skew(-15deg);">{{item.numData.split('小时')[1].replace('分','')}}</text>
  35. <text class="_item_subtext" style="margin-left: 10rpx;opacity:0.8;">分钟</text>
  36. </view>
  37. <view class="flex_baseline" style="margin-left: 30rpx;"
  38. v-if="item.numData.includes('小时') === false && item.numData != ''">
  39. <text class="_item_text"
  40. style="margin-left: 10rpx;transform: skew(-15deg);">{{item.numData.replace('分','')}}</text>
  41. <text class="_item_subtext" style="margin-left: 10rpx;opacity:0.8;">分钟</text>
  42. </view>
  43. <view :class="item.icon"></view>
  44. </view>
  45. </view>
  46. <!-- 时间选择器 -->
  47. <u-picker :show="setTimePicker" :columns="pickerList" @confirm="pickerConfirm" @cancel="cancel">
  48. </u-picker>
  49. <!-- 统计列表 -->
  50. <view class="card_view" style="margin-top: 0;">
  51. <!-- 统计列表 -->
  52. <view class="flex_cloumn_box" style="margin-left: 20rpx;">
  53. <view class="title" style="font-size: 32rpx;">近期统计</view>
  54. <view class="bottom_tag"
  55. style="background-image: linear-gradient(to right, #4169E1, rgba(255, 255, 255, 0.01));"></view>
  56. </view>
  57. <!-- 总成绩对比 -->
  58. <view class="card_item" style="width: 100%;">
  59. <view class="card_title">
  60. <view class="front_tag"></view>
  61. <view class="title">学习娱乐时长对比</view>
  62. </view>
  63. <view class="chart_box">
  64. <qiun-data-charts type="column" ontouch="true" :chartData="swapChartData[0]"
  65. tooltipFormat='tooltipHourColum' :canvas2d="true" canvasId="swap_chart1" />
  66. </view>
  67. </view>
  68. <!-- 单科与平均对比 -->
  69. <view class="card_item">
  70. <view class="card_title">
  71. <view class="front_tag"></view>
  72. <view class="title">近期运动记录</view>
  73. </view>
  74. <view class="chart_box" style="height: 350rpx;">
  75. <qiun-data-charts type="pie" :chartData="swapChartData[1]" tooltipFormat='pieMinute'
  76. :canvas2d="true" canvasId="swap_chart2" />
  77. </view>
  78. </view>
  79. <view class="card_item">
  80. <view class="card_title">
  81. <view class="front_tag"></view>
  82. <view class="title">近期睡眠记录</view>
  83. </view>
  84. <view class="chart_box" style="height: 350rpx;">
  85. <qiun-data-charts type="ring" :chartData="swapChartData[2]" tooltipFormat='pieHour' :canvas2d="true"
  86. canvasId="swap_chart3" :opts="ringOpts" />
  87. </view>
  88. </view>
  89. </view>
  90. </view>
  91. </template>
  92. <script>
  93. import {
  94. mapState,
  95. mapMutations
  96. } from 'vuex'
  97. export default {
  98. computed: {
  99. ...mapState('m_chart', ['swapChartData'])
  100. },
  101. data() {
  102. return {
  103. //记录卡片
  104. moduleData: [{
  105. text: '学习时长',
  106. color: 'background-color: #4169E1;',
  107. icon: 't-icon t-icon-bianjibi',
  108. numData: '',
  109. },
  110. {
  111. text: '娱乐时长',
  112. color: 'background-color: #ff5959;',
  113. icon: 't-icon t-icon-leimucuyule',
  114. numData: '',
  115. },
  116. {
  117. text: '运动时长',
  118. color: 'background-color: #ff8caf;',
  119. icon: 't-icon t-icon-yundong',
  120. numData: '',
  121. },
  122. {
  123. text: '睡眠时长',
  124. color: 'background-color: #f9c752;',
  125. icon: 't-icon t-icon-a-icon_wananyueliangshuimian',
  126. numData: '',
  127. }
  128. ],
  129. //标题配置
  130. ringOpts: {},
  131. //当前记录卡片
  132. cardCurrent: 5,
  133. //选择器
  134. setTimePicker: false,
  135. //时间表
  136. pickerList: [
  137. ['0小时', '1小时', '2小时', '3小时', '4小时', '5小时', '6小时', '7小时', '8小时', '9小时', '10小时'],
  138. ['5分', '10分', '15分', '20分', '25分', '30分', '35分', '40分', '45分', '50分', '55分']
  139. ],
  140. //历史数据
  141. dayTime: '',
  142. weekTime: '',
  143. //是否重新记录
  144. setTimeRecord: false
  145. }
  146. },
  147. onLoad() {
  148. this.init()
  149. },
  150. methods: {
  151. ...mapMutations('m_chart', ['updateSwapChartData']),
  152. init() {
  153. this.getToday()
  154. this.getData()
  155. this.getRingOpts()
  156. },
  157. getToday() {
  158. this.dayTime = (new Date()).format('M-d').replace('-', '月')
  159. this.weekTime = "星期" + "日一二三四五六".charAt(new Date().getDay());
  160. },
  161. //记录信息初始化
  162. getData() {
  163. if (uni.getStorageSync('moduleData'))
  164. this.moduleData = JSON.parse(uni.getStorageSync('moduleData'));
  165. if (uni.getStorageSync('historyData')) {
  166. this.historyData = JSON.parse(uni.getStorageSync('historyData'));
  167. this.saveToStudyChart()
  168. }
  169. },
  170. getRingOpts() {
  171. let sleepData = ''
  172. if (uni.getStorageSync('historyData')) {
  173. sleepData = JSON.parse(uni.getStorageSync('historyData')).sleep;
  174. let sum = 0
  175. for (let i = 0; i < sleepData.length; i++) {
  176. sum += sleepData[i]
  177. }
  178. let sleepAvg = (sum/sleepData.length).toFixed(1)
  179. let opt = {
  180. title: {
  181. name: '平均睡眠',
  182. color: '#909399'
  183. },
  184. subtitle: {
  185. name: sleepAvg + ' 小时',
  186. color: '#4169E1'
  187. },
  188. }
  189. this.ringOpts = opt
  190. }
  191. },
  192. //点击卡片唤起picker
  193. setTime(index) {
  194. if (this.moduleData[index].numData === '') {
  195. this.cardCurrent = index
  196. this.setTimePicker = true
  197. }
  198. if (this.moduleData[index].numData != '') {
  199. let that = this;
  200. uni.showModal({
  201. title: `今日${that.moduleData[index].text}已记录`,
  202. content: '需要重新记录吗?',
  203. success: function(res) {
  204. if (res.confirm) {
  205. that.cardCurrent = index
  206. that.setTimePicker = true
  207. that.setTimeRecord = true
  208. } else if (res.cancel) {
  209. console.log('取消记录');
  210. }
  211. }
  212. })
  213. }
  214. },
  215. //记录数据
  216. pickerConfirm(e) {
  217. if (this.setTimeRecord) {
  218. if (e.value[0] === '0小时') {
  219. this.moduleData[this.cardCurrent].numData = e.value[1]
  220. } else {
  221. this.moduleData[this.cardCurrent].numData = e.value[0] + e.value[1]
  222. }
  223. //转换为数据记录到图表中
  224. if (this.moduleData[this.cardCurrent].numData.includes('小时') === false) {
  225. let timeData = parseFloat((parseInt(this.moduleData[this.cardCurrent].numData.replace('分', '')) /
  226. 60)
  227. .toFixed(1))
  228. switch (this.cardCurrent) {
  229. case 0:
  230. this.historyData.study[6] = timeData
  231. break
  232. case 1:
  233. this.historyData.rest[6] = timeData
  234. break
  235. case 2:
  236. let numExercise = parseInt(this.moduleData[this.cardCurrent].numData.replace('分', ''))
  237. this.historyData.exercise[6] = numExercise
  238. break
  239. case 3:
  240. this.historyData.sleep[6] = timeData
  241. break
  242. }
  243. uni.setStorageSync('moduleData', JSON.stringify(this.moduleData))
  244. uni.setStorageSync('historyData', JSON.stringify(this.historyData))
  245. this.saveToStudyChart()
  246. } else {
  247. let timeTemp = this.moduleData[this.cardCurrent].numData.replace('小时', '.').replace('分', '').split(
  248. '.')
  249. let timeData = parseInt(timeTemp[0]) + parseFloat((timeTemp[1] / 60).toFixed(1))
  250. switch (this.cardCurrent) {
  251. case 0:
  252. this.historyData.study[6] = timeData
  253. break
  254. case 1:
  255. this.historyData.rest[6] = timeData
  256. break
  257. case 2:
  258. let numExerciseData = parseInt(timeTemp[0] * 60) + parseFloat((timeTemp[1]))
  259. this.historyData.exercise[6] = numExerciseData
  260. break
  261. case 3:
  262. this.historyData.sleep[6] = timeData
  263. break
  264. }
  265. uni.setStorageSync('moduleData', JSON.stringify(this.moduleData))
  266. uni.setStorageSync('historyData', JSON.stringify(this.historyData))
  267. // 记录到图表
  268. this.saveToStudyChart()
  269. }
  270. this.setTimePicker = false
  271. this.setTimeRecord = false
  272. } else {
  273. if (e.value[0] === '0小时') {
  274. this.moduleData[this.cardCurrent].numData = e.value[1]
  275. } else {
  276. this.moduleData[this.cardCurrent].numData = e.value[0] + e.value[1]
  277. }
  278. //转换为数据记录到图表中
  279. if (this.moduleData[this.cardCurrent].numData.includes('小时') === false) {
  280. let timeData = parseFloat((parseInt(this.moduleData[this.cardCurrent].numData.replace('分', '')) /
  281. 60)
  282. .toFixed(1))
  283. switch (this.cardCurrent) {
  284. case 0:
  285. this.historyData.study.push(timeData)
  286. this.historyData.study.shift()
  287. break
  288. case 1:
  289. this.historyData.rest.push(timeData)
  290. this.historyData.rest.shift()
  291. break
  292. case 2:
  293. let numExercise = parseInt(this.moduleData[this.cardCurrent].numData.replace('分', ''))
  294. this.historyData.exercise.push(numExercise)
  295. this.historyData.exercise.shift()
  296. break
  297. case 3:
  298. this.historyData.sleep.push(timeData)
  299. this.historyData.sleep.shift()
  300. break
  301. }
  302. uni.setStorageSync('moduleData', JSON.stringify(this.moduleData))
  303. uni.setStorageSync('historyData', JSON.stringify(this.historyData))
  304. this.saveToStudyChart()
  305. } else {
  306. let timeTemp = this.moduleData[this.cardCurrent].numData.replace('小时', '.').replace('分', '').split(
  307. '.')
  308. let timeData = parseInt(timeTemp[0]) + parseFloat((timeTemp[1] / 60).toFixed(1))
  309. switch (this.cardCurrent) {
  310. case 0:
  311. this.historyData.study.push(timeData)
  312. this.historyData.study.shift()
  313. break
  314. case 1:
  315. this.historyData.rest.push(timeData)
  316. this.historyData.rest.shift()
  317. break
  318. case 2:
  319. let numExerciseData = parseInt(timeTemp[0] * 60) + parseFloat((timeTemp[1]))
  320. this.historyData.exercise.push(numExerciseData)
  321. this.historyData.exercise.shift()
  322. break
  323. case 3:
  324. this.historyData.sleep.push(timeData)
  325. this.historyData.sleep.shift()
  326. break
  327. }
  328. uni.setStorageSync('moduleData', JSON.stringify(this.moduleData))
  329. uni.setStorageSync('historyData', JSON.stringify(this.historyData))
  330. // 记录到图表
  331. this.saveToStudyChart()
  332. }
  333. this.setTimePicker = false
  334. }
  335. },
  336. //取消
  337. cancel() {
  338. this.setTimePicker = false
  339. },
  340. //存储到图表
  341. saveToStudyChart() {
  342. let swapChartData = []
  343. let studyColumn = {
  344. categories: [],
  345. series: [{
  346. name: '自主学习',
  347. data: this.historyData.study
  348. },
  349. {
  350. name: '娱乐放松',
  351. data: this.historyData.rest
  352. }
  353. ]
  354. }
  355. //时间
  356. studyColumn.categories = this.$getRecentDateArray(this.historyData.study.length)
  357. //学习记录表数据记录
  358. switch (this.cardCurrent) {
  359. case 0:
  360. studyColumn.series[0].data = this.historyData.study
  361. break
  362. case 1:
  363. studyColumn.series[1].data = this.historyData.rest
  364. break
  365. }
  366. //运动记录表
  367. let exercisePie = {
  368. series: [{
  369. data: [{}, {}, {}, {}, {}, {}, {}]
  370. }]
  371. }
  372. //睡眠记录表
  373. let sleepRing = {
  374. series: [{
  375. data: [{}, {}, {}, {}, {}, {}, {}]
  376. }]
  377. }
  378. studyColumn.categories.forEach((value, index) => {
  379. exercisePie.series[0].data[index].name = value
  380. exercisePie.series[0].data[index].value = parseFloat((this.historyData.exercise[index])
  381. .toFixed(1))
  382. sleepRing.series[0].data[index].name = value
  383. sleepRing.series[0].data[index].value = this.historyData.sleep[index]
  384. })
  385. swapChartData.push(studyColumn)
  386. swapChartData.push(exercisePie)
  387. swapChartData.push(sleepRing)
  388. this.updateSwapChartData(swapChartData)
  389. this.getRingOpts()
  390. },
  391. }
  392. }
  393. </script>
  394. <style lang="scss">
  395. .chart_box {
  396. width: 100%;
  397. height: 500rpx;
  398. }
  399. .flex_cloumn_box {
  400. margin: 20rpx 0;
  401. display: flex;
  402. flex-direction: column;
  403. z-index: 55;
  404. }
  405. .flex_cloumn {
  406. margin: 140rpx 0 0 50rpx;
  407. height: 170rpx;
  408. justify-content: space-around;
  409. .content_title {
  410. font-size: 35rpx;
  411. font-weight: bold;
  412. transform: skew(-15deg);
  413. color: #FFF;
  414. z-index: 2;
  415. }
  416. .content_subtitle {
  417. font-size: 35rpx;
  418. color: #FFF;
  419. z-index: 2;
  420. }
  421. }
  422. .module_box {
  423. display: flex;
  424. flex-flow: row wrap;
  425. margin: 0 20rpx;
  426. justify-content: space-between;
  427. ._item {
  428. margin: 2% 0;
  429. width: 48%;
  430. height: auto;
  431. display: flex;
  432. flex-direction: column;
  433. padding: 24rpx 0 20rpx 0;
  434. background-color: #FFF;
  435. border-radius: 20rpx;
  436. justify-content: space-between;
  437. overflow: hidden;
  438. z-index: 3;
  439. &_text {
  440. line-height: 80rpx;
  441. color: #FFF;
  442. font-size: 50rpx;
  443. font-weight: bold;
  444. z-index: 5;
  445. }
  446. &_subtext {
  447. line-height: 80rpx;
  448. color: #FFF;
  449. font-size: 30rpx;
  450. font-weight: bold;
  451. z-index: 5;
  452. }
  453. }
  454. .t-icon {
  455. width: 250rpx;
  456. height: 250rpx;
  457. margin: -250rpx 0 0 160rpx;
  458. z-index: 1;
  459. }
  460. }
  461. </style>