健康同学微信公众号h5项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1471 lines
46KB

  1. <template>
  2. <div class="psychological-container">
  3. <van-nav-bar title="情绪监测" :border="true" :left-arrow="true" @click-left="onNavBack" left-text="返回">
  4. <template #left>
  5. <van-icon name="arrow-left" size="24" style="padding: 0" />
  6. <span>返回</span>
  7. </template>
  8. </van-nav-bar>
  9. <div class="tab-bar">
  10. <div class="date-tab-con">
  11. <div class="date-tab-list">
  12. <div
  13. :class="['date-tab-item', { active: current === index, notClick: false }]"
  14. @click="onTabClick(item.value, index)"
  15. v-for="(item, index) in dateList"
  16. :key="index"
  17. >
  18. <img :src="tabImgUrl" alt v-if="index == 3" />
  19. <span>{{ item.text }}</span>
  20. <img class="more" :src="selectDownImg" alt v-if="index == 3" />
  21. </div>
  22. </div>
  23. </div>
  24. </div>
  25. <div class="main" v-show="current !== 3">
  26. <div class="top">
  27. <!-- 日期选择 -->
  28. <!-- 标题 -->
  29. <div class="title">
  30. <div class="title-left">{{ titleLeft }}<van-icon name="question-o" @click="onHelp" /></div>
  31. <div class="title-right" v-show="currentDays === 0">
  32. <p @click="onHistory">历史监测</p>
  33. </div>
  34. </div>
  35. <!-- 日历 -->
  36. <van-dialog
  37. class="calenddar-dialog"
  38. v-model="calendarDialogShow"
  39. :show-confirm-button="false"
  40. :show-cancle-button="false"
  41. :close-on-click-overlay="true"
  42. ref="calenddarDialog"
  43. >
  44. <template #default>
  45. <div class="calendar" ref="calendarCon">
  46. <van-calendar
  47. v-model="calendarShow"
  48. :min-date="minDate"
  49. :max-date="maxDate"
  50. :default-date="defaultDate"
  51. :round="false"
  52. :poppable="false"
  53. color="#179b3b"
  54. :show-confirm="false"
  55. :show-title="false"
  56. :show-subtitle="false"
  57. :formatter="formatter"
  58. @select="onSelect"
  59. />
  60. </div>
  61. </template>
  62. </van-dialog>
  63. <!-- 监测次数 -->
  64. <div class="monitoring-count">
  65. <p>监测次数:{{ monitoringCount || '0' }}次</p>
  66. </div>
  67. <!-- 折线图-非日报 -->
  68. <div class="pie-chart-con">
  69. <div class="pie-chart-left">
  70. <div id="pieChart" ref="pieChart"></div>
  71. </div>
  72. <div class="pie-chart-right">
  73. <div class="list">
  74. <div class="item" v-for="(item, index) in pieRightList" :key="index">
  75. <div class="item-left">
  76. <div class="circle" :style="{ backgroundColor: item.color }"></div>
  77. <span class="text">{{ item.text || '--' }}</span>
  78. </div>
  79. <div class="item-right">
  80. <span :style="{ color: item.color }">{{ item.count ? item.count + '次' : '0次' }}</span>
  81. <label :style="{ color: item.color }">{{
  82. item.percentage ? '(' + item.percentage + '%' + ')' : '(0%)'
  83. }}</label>
  84. </div>
  85. </div>
  86. </div>
  87. </div>
  88. </div>
  89. <!-- 统计 -->
  90. <div class="statistics">
  91. <div class="list">
  92. <div class="item" v-for="(item, index) in statisticsList" :key="index" :style="{ backgroundColor: '' }">
  93. <div class="top">
  94. <span>{{ item.label || '--' }}</span>
  95. </div>
  96. <div class="middle">
  97. <span :style="{ color: calcColor(item.value) }">{{ item.value || '--' }}</span>
  98. </div>
  99. <div class="bottom">
  100. <span>{{ item.time || '--' }}</span>
  101. </div>
  102. </div>
  103. </div>
  104. </div>
  105. </div>
  106. <!-- 分割线 -->
  107. <!-- 情绪切换 -->
  108. <div class="psy-tab-bar">
  109. <div class="psy-tab-con">
  110. <div class="psy-tab-list">
  111. <div
  112. :class="['psy-tab-item', { active: psyCurrent === index, notClick: false }]"
  113. @click="onPsyTabClick(item.name, index)"
  114. v-for="(item, index) in psyList"
  115. :key="index"
  116. >
  117. <span>{{ item.text }}</span>
  118. </div>
  119. </div>
  120. </div>
  121. </div>
  122. <div class="line"></div>
  123. <!-- 底部 -->
  124. <div class="bottom">
  125. <div class="echart-container">
  126. <div class="echart" ref="charts"></div>
  127. </div>
  128. <div class="line-gray"></div>
  129. <div class="result" v-if="monitoringCount == ''">
  130. <div class="result-con">
  131. <div class="title">
  132. <span class="title-no-data">结果解读</span>
  133. <div class="no-data">
  134. <img :src="noDataImg" alt />
  135. <p>暂无数据</p>
  136. </div>
  137. </div>
  138. </div>
  139. </div>
  140. <div class="result" v-else>
  141. <div class="result-con reminder" v-show="current === 0">
  142. <div class="title">
  143. <span class="title-reminder">结果解读</span>
  144. <p class="title-emo" :style="{ color: currentColor }">{{ result }}</p>
  145. <span class="font-28"
  146. ><!-- 继续保持积极乐观,培养健康的生活习惯,预防消极事件对情绪带来的不良影响。 -->{{ advice }}</span
  147. >
  148. </div>
  149. <div class="friendly-reminder" v-if="emoType === 2">
  150. <p :style="{ color: currentColor }">友情提示:</p>
  151. <span
  152. >如果您发现抑郁倾向分值升高或处于轻度水平,不需要过度紧张,这可能是由正常的情绪波动或者生活习惯(睡眠时间、运动量等)的改变造成的。如果您发现抑郁倾向分值连续7天及以上处于中度或重度水平,建议您寻求家人朋友或心理咨询师的帮助,及早进行干预。</span
  153. >
  154. </div>
  155. <div class="warm-reminder">
  156. <p :style="{ color: currentColor }">温馨提示:</p>
  157. <span>{{ warmTips }}</span>
  158. </div>
  159. </div>
  160. <div class="result-con" v-show="current > 0">
  161. <div class="title">
  162. <span class="title-text">{{ surveyTitle }}</span>
  163. <div class="mood-list" v-if="emotionList.length > 0">
  164. <div class="item" v-for="(item, index) in emotionList" :key="index">
  165. <p>
  166. <span :style="{ color: item.color }" class="day">{{ item.days }}</span>
  167. <span class="day-text">天</span>
  168. </p>
  169. <p>{{ item.text }}</p>
  170. </div>
  171. </div>
  172. <div class="mood-list-no-data" v-else>
  173. <div class="no-data">
  174. <img :src="noDataImg" alt />
  175. <p>暂无数据</p>
  176. </div>
  177. </div>
  178. </div>
  179. </div>
  180. </div>
  181. <!-- -->
  182. </div>
  183. </div>
  184. <!-- 周报菜单 -->
  185. <div class="main report" v-show="current == 3">
  186. <div class="content">
  187. <div class="list" v-if="weekList.length > 0">
  188. <div class="item" v-for="(item, index) in weekList" :key="index" @click="onClickItem(item.recordId)">
  189. <div class="left">
  190. <img :src="weekImg" alt />
  191. <div class="middle">
  192. <div class="title">
  193. <span>周报</span>
  194. <p>{{ item.name }}</p>
  195. </div>
  196. <div class="overall">
  197. <div class="left">
  198. <span>总评</span>
  199. <p :style="{ color: calcResultColor(item.summaryLevel) }">{{ item.summary }}</p>
  200. </div>
  201. </div>
  202. <!-- <div class="trend">
  203. <p>( <span>无抑郁倾向</span><span>5%</span>,<span>轻度抑郁倾向</span> <span>5%</span> )</p>
  204. </div>-->
  205. </div>
  206. </div>
  207. <div class="right">
  208. <img :src="moreImg" alt />
  209. </div>
  210. </div>
  211. </div>
  212. <div class="list no-data" v-else>
  213. <img :src="noDataImg" alt />
  214. <p>连续佩戴两周产生对比数据</p>
  215. </div>
  216. </div>
  217. </div>
  218. <!-- 弹出层 -->
  219. <van-popup v-model="isPopup">
  220. <div class="popup">
  221. <div class="item science-tips first" v-if="emoType === 2">
  222. <div class="tips"><h5>小科普</h5></div>
  223. <p>
  224. 症是一抑郁种心理疾病,严重时可发展为精神障碍。然而当我们体会到了痛苦、悲伤、和郁闷等负面情绪,并不意味着我们就是抑郁症。日常的短时的喜、怒、哀、乐,都是正常的情绪变化,然而长期的低落情绪、兴趣缺失等可能会让我们有抑郁的风险。
  225. </p>
  226. </div>
  227. <div class="item">
  228. <h5 v-html="title1"></h5>
  229. <div v-html="article1"></div>
  230. </div>
  231. <div class="item">
  232. <h5 v-html="title2"></h5>
  233. <div v-html="article2"></div>
  234. </div>
  235. <van-button size="large" @click="onClose">返回</van-button>
  236. </div>
  237. </van-popup>
  238. </div>
  239. </template>
  240. <script>
  241. import { EmotionModel, PsyBaseUrl } from '@/config/models';
  242. import axios from 'axios';
  243. export default {
  244. name: 'psychological-monitor',
  245. data() {
  246. return {
  247. // 日期选择标签
  248. dateList: [
  249. { name: 'today', text: '今天', value: 0 },
  250. { name: 'week', text: '7天', value: 7 },
  251. { name: 'month', text: '30天', value: 30 }
  252. /* { name: 'weekReport', text: '周报', value: 49 } */
  253. ],
  254. // 情绪tab
  255. psyList: [
  256. { name: 'tiredness', text: '疲劳', value: 0 },
  257. { name: 'stress', text: '压力', value: 1 },
  258. { name: 'depression', text: '抑郁', value: 2 }
  259. ],
  260. // 当前情绪下标
  261. psyCurrent: 0,
  262. current: 0, // 日期选择标签-当前选中的标签
  263. currentDays: 0, //日期选择标签-日期参数
  264. emotionData: [], //情绪数据,TODO 接口对接
  265. echarts: null, //折线图
  266. itemHeight: Number(((document.body.clientWidth / 750) * 95).toFixed()), // 日历组件item高度
  267. xAxisData: [], //图表x轴展示的数据
  268. monitoringCount: '', //监测次数
  269. pieEcharts: null, //饼状图
  270. pieData: [], //饼状图数据
  271. //饼状图右边数据,TODO 根据接口数据和 模块 重新封装数组
  272. pieRightList: [
  273. /* {
  274. text: "无情绪倾向",
  275. count: 12,
  276. percentage: "80",
  277. color: "#179b3b"
  278. },
  279. {
  280. text: "轻度情绪倾向",
  281. count: 2,
  282. percentage: "80",
  283. color: "#8dc21f"
  284. },
  285. {
  286. text: "中度情绪倾向",
  287. count: 1,
  288. percentage: "80",
  289. color: "#2ea7e0"
  290. },
  291. {
  292. text: "重度情绪倾向",
  293. count: 1,
  294. percentage: "80",
  295. color: "#ff5f8b"
  296. } */
  297. ],
  298. // 情绪状态列表
  299. statisticsList: [
  300. /* { label: "最大值", value: "75", time: "08:15" },
  301. { label: "最小值", value: "40", time: "10:15" },
  302. { label: "最近值", value: "50", time: "18:15" } */
  303. ],
  304. // 周报-情绪计算
  305. emotionList: [
  306. /* { days: "5", text: "无情绪倾向", color: "#179b3b" },
  307. { days: "4", text: "轻度情绪倾向", color: "#8dc21f" },
  308. { days: "3", text: "中度情绪倾向", color: "#2ea7e0" },
  309. { days: "2", text: "重度情绪倾向", color: "#ACACAC" } */
  310. ],
  311. // 弹窗-日历是否显示
  312. calendarDialogShow: false,
  313. // 日历是否显示,默认为true
  314. calendarShow: true,
  315. // 日历 默认最小可选择日期,默认为最近1个月
  316. minDate: new Date(
  317. this.$dayjs()
  318. .month(this.$dayjs().month() - 1)
  319. .hour(0)
  320. .minute(0)
  321. .second(0)
  322. .format()
  323. ),
  324. // 日历 默认最小可选择日期,默认为当前时间
  325. maxDate: new Date(this.$dayjs().hour(0).minute(0).second(0).format()),
  326. // 默认日历日期时间
  327. defaultDate: new Date(this.$dayjs().hour(0).minute(0).second(0).format()),
  328. // 路由传过来的情绪参数
  329. emoName: '',
  330. // 默认折线图 Series 配置
  331. defaultSeries: null,
  332. // 非日报折线图 Series 配置
  333. weekAndMonthSeries: null,
  334. // 当前情绪类型
  335. emoType: '',
  336. // 结果解读
  337. result: '',
  338. // 需要高亮的日期数组
  339. highlightDates: [],
  340. // 选中的日历日期
  341. selectDate: '',
  342. uid: '',
  343. // 建议
  344. advice: '',
  345. // 底部天数标题
  346. surveyTitle: '' || '7天概览',
  347. // 路由中的日期
  348. routeDate: '',
  349. // 路由参数
  350. params: {},
  351. // 是否显示帮助
  352. isPopup: false,
  353. // 结果等级
  354. resultLevel: '',
  355. // 轻度级别颜色
  356. mildColor: '#8dc21f',
  357. // 中度级别颜色
  358. severeColor: '#2ea7e0',
  359. // 重度级别颜色
  360. moderateColor: '#ff5f8b',
  361. // 7天和30天最大数据列表
  362. weekAndMonData: [],
  363. tabImgUrl: require('@/assets/today/icons/statistical_form.png'),
  364. selectDownImg: require('@/assets/today/icons/select_down.png'),
  365. weekImg: require('@/assets/today/icons/week_report.png'),
  366. moreImg: require('@/assets/today/icons/more.png'),
  367. noDataImg: require('@/assets/today/images/no_data_01.png'),
  368. weekList: [],
  369. startDate: '', //接口需要的开始时间
  370. endDate: '', //接口需要的结束时间
  371. currentEmoName: '' //当前情绪名称
  372. };
  373. },
  374. computed: {
  375. // 默认折线图配置,echarts 具体配置 见 https://echarts.apache.org/zh/option.html#title
  376. defaultOptions() {
  377. return {
  378. time: {
  379. useUTC: false
  380. },
  381. title: {
  382. text: this.echartsTitle,
  383. left: 1,
  384. right: 25,
  385. bottom: 20,
  386. top: '3%',
  387. textStyle: {
  388. fontSize: 16,
  389. fontWeight: 'bold'
  390. }
  391. },
  392. legend: {
  393. width: '65%',
  394. orient: 'horizontal',
  395. right: 'right',
  396. top: 1,
  397. bottom: '1%',
  398. itemHeight: 12,
  399. itemWidth: 12,
  400. itemGap: 10,
  401. align: 'left',
  402. selectedMode: false,
  403. data: [
  404. {
  405. name: `轻度${this.emoName}倾向`,
  406. icon: 'rect',
  407. itemStyle: {
  408. color: '#8dc21f'
  409. },
  410. textStyle: {
  411. fontSize: 12
  412. }
  413. },
  414. {
  415. name: `中度${this.emoName}倾向`,
  416. itemStyle: {
  417. color: '#2ea7e0'
  418. },
  419. icon: 'rect',
  420. textStyle: {
  421. fontSize: 12
  422. }
  423. },
  424. {
  425. name: `重度${this.emoName}倾向`,
  426. itemStyle: {
  427. color: '#ff5f8b'
  428. },
  429. icon: 'rect',
  430. textStyle: {
  431. fontSize: 12
  432. }
  433. },
  434. {
  435. name: `无${this.emoName}倾向`,
  436. icon: 'rect',
  437. itemStyle: {
  438. color: '#179b3b'
  439. },
  440. textStyle: {
  441. fontSize: 12
  442. }
  443. }
  444. ],
  445. formatter: function (name) {
  446. // 自定义显示内容
  447. if (name.length > 6) {
  448. return name.substring(0, 6) + '\n' + name.substring(6);
  449. } else {
  450. return name;
  451. }
  452. }
  453. },
  454. grid: {
  455. show: true,
  456. borderWidth: 1,
  457. top: '20%',
  458. left: '1%',
  459. right: '5%',
  460. bottom: '10%',
  461. containLabel: true
  462. },
  463. xAxis: {
  464. type: 'category',
  465. axisLine: {
  466. show: false
  467. },
  468. textStyle: {
  469. fontSize: 10
  470. },
  471. axisTick: {
  472. show: false
  473. },
  474. splitLine: {
  475. show: false,
  476. lineStyle: {
  477. color: '#ddd',
  478. width: 2
  479. }
  480. },
  481. nameLocation: 'center',
  482. axisLabel: {
  483. show: true,
  484. fontSize: 12,
  485. showMinLabel: true, //显示最小值
  486. showMaxLabel: true //显示最大值
  487. },
  488. data: this.xAxisData
  489. },
  490. dataZoom: [
  491. /* {
  492. type: "inside",
  493. start: 0,
  494. end: 100,
  495. }, */
  496. {
  497. start: 0,
  498. end: 100,
  499. textStyle: {
  500. color: '#FFF',
  501. fontSize: 14
  502. },
  503. show: true,
  504. height: 15,
  505. bottom: 5,
  506. handleStyle: {
  507. borderWidth: 1,
  508. borderCap: 'square'
  509. }
  510. }
  511. ],
  512. tooltip: {
  513. trigger: 'axis',
  514. textStyle: {
  515. fontSize: 14,
  516. align: 'center'
  517. },
  518. formatter: function (params) {
  519. return params[0].marker + params[0].name + '</br>' + params[0].value;
  520. }
  521. },
  522. yAxis: {
  523. type: 'value',
  524. max: 100,
  525. min: 0,
  526. interval: 20,
  527. splitNumber: 1,
  528. boundaryGap: ['5%', '5%'],
  529. nameTextStyle: {
  530. fontSize: 13
  531. },
  532. alignTicks: true,
  533. axisTick: {
  534. show: true
  535. },
  536. axisLabel: {
  537. show: true,
  538. fontSize: 13
  539. },
  540. splitLine: {
  541. show: true,
  542. lineStyle: {
  543. color: '#ddd',
  544. width: 1
  545. }
  546. }
  547. },
  548. series: [
  549. {
  550. name: `无${this.emoName}倾向`,
  551. type: 'line',
  552. padding: 5,
  553. smooth: true,
  554. data: this.emotionData,
  555. symbol: 'circle',
  556. symbolSize: 10,
  557. itemStyle: {
  558. color: '#fff',
  559. borderWidth: 2
  560. },
  561. lineStyle: {
  562. width: 6,
  563. type: 'solid',
  564. color: '#189b3b'
  565. }
  566. },
  567. {
  568. name: `轻度${this.emoName}倾向`,
  569. type: 'line',
  570. data: ''
  571. },
  572. {
  573. name: `中度${this.emoName}倾向`,
  574. type: 'line',
  575. data: ''
  576. },
  577. {
  578. name: `重度${this.emoName}倾向`,
  579. type: 'line',
  580. data: ''
  581. }
  582. ]
  583. };
  584. },
  585. imei() {
  586. return this.$store.getters.serialNo;
  587. },
  588. // 饼状图配置
  589. pieOption() {
  590. return {
  591. tooltip: {
  592. trigger: 'item',
  593. textStyle: {
  594. fontSize: 14
  595. },
  596. position: 'right'
  597. },
  598. legend: {
  599. top: '5%',
  600. left: 'center',
  601. show: false
  602. },
  603. series: [
  604. {
  605. type: 'pie',
  606. radius: ['40%', '80%'],
  607. avoidLabelOverlap: false,
  608. startAngle: 270, // 设置逆时针渲染
  609. itemStyle: {
  610. borderRadius: 5,
  611. borderColor: '#fff',
  612. borderWidth: 2,
  613. fontSize: 16
  614. },
  615. label: {
  616. show: false,
  617. position: 'center',
  618. fontSize: 16
  619. },
  620. emphasis: {
  621. label: {
  622. show: false,
  623. fontSize: 16,
  624. fontWeight: 'bold'
  625. }
  626. },
  627. labelLine: {
  628. show: false
  629. },
  630. data: this.pieData
  631. }
  632. ]
  633. };
  634. },
  635. titleLeft() {
  636. let text = this.emoName === 'depression' ? '趋势' : '';
  637. let today = '';
  638. if (this.currentDays !== 0) {
  639. today = '';
  640. } else {
  641. today =
  642. this.$dayjs(this.selectDate || this.defaultDate).format('YYYY-MM-DD') ===
  643. this.$dayjs(new Date()).format('YYYY-MM-DD')
  644. ? '今天'
  645. : '';
  646. }
  647. return `${today}${this.emoName}倾向${text}`;
  648. },
  649. // 折线图标题
  650. echartsTitle() {
  651. let today = '';
  652. if (this.currentDays !== 0) {
  653. today = '';
  654. } else {
  655. today =
  656. this.$dayjs(this.selectDate || this.defaultDate).format('YYYY-MM-DD') ===
  657. this.$dayjs(new Date()).format('YYYY-MM-DD')
  658. ? '今天'
  659. : '';
  660. }
  661. return `${today}${this.emoName}数据图`;
  662. },
  663. warmTips() {
  664. return `正常连续佩戴腕表,每${this.emoType == 2 ? '一' : '半'}小时计算一个${this.emoName}分值。`;
  665. /* return `正常连续佩戴手表,每半小时计算一个${this.emoName}分值,睡眠期间不进行计算。` */
  666. },
  667. title1() {
  668. return EmotionModel[this.params.name].title1;
  669. },
  670. article1() {
  671. return EmotionModel[this.params.name].article1;
  672. },
  673. title2() {
  674. return EmotionModel[this.params.name].title2;
  675. },
  676. article2() {
  677. return EmotionModel[this.params.name].article2;
  678. },
  679. // 当前情绪颜色
  680. currentColor() {
  681. return this.calcResultColor(this.resultLevel) || '#179b3b';
  682. }
  683. },
  684. watch: {
  685. // 监听数据发生变化 初始化各项图表
  686. emotionData: {
  687. handler() {
  688. this.initEchart();
  689. },
  690. deep: true
  691. },
  692. xAxisData: {
  693. handler() {
  694. this.initEchart();
  695. },
  696. deep: true
  697. },
  698. pieData: {
  699. handler() {
  700. this.initPieEchart();
  701. },
  702. deep: true
  703. }
  704. },
  705. created() {
  706. // 读取路由传过来的参数,根据路由传过来的参数判断是哪种情绪
  707. this.loadParams();
  708. this.initEchartText();
  709. this.getPieData();
  710. this.getCalendarData();
  711. this.getPsychologiclData('2023-11-21');
  712. //this.getWeekResult();
  713. },
  714. mounted() {
  715. this.initEchart();
  716. this.current = Number(this.$store.getters.tabClick) || 0;
  717. this.currentDays = this.calcDaysByTabClick(Number(this.$store.getters.tabClick));
  718. this.psyCurrent = this.calcPsyTabindex(EmotionModel[this.params.name].type);
  719. },
  720. methods: {
  721. loadParams() {
  722. let params = this.$route.query;
  723. if (params) {
  724. this.emoName = EmotionModel[params.name].name;
  725. this.emoType = EmotionModel[params.name].type;
  726. this.uid = params.uid;
  727. this.routeDate = params.date;
  728. this.params = params;
  729. this.currentEmoName = params.name;
  730. if (params.date) {
  731. this.dateList[0].text =
  732. this.$dayjs(params.date).format('YYYY-MM-DD') === this.$dayjs(new Date()).format('YYYY-MM-DD')
  733. ? '今天'
  734. : this.$dayjs(params.date).format('MM-DD');
  735. this.defaultDate = new Date(this.$dayjs(params.date).hour(0).minute(0).second(0).format());
  736. }
  737. }
  738. },
  739. // 计算点击的天数
  740. calcDaysByTabClick(value) {
  741. let days = '';
  742. console.log('value', value);
  743. switch (value) {
  744. case 0:
  745. days = 0;
  746. break;
  747. case 1:
  748. days = 7;
  749. break;
  750. case 2:
  751. days = 30;
  752. break;
  753. case 3:
  754. days = 49;
  755. break;
  756. default:
  757. break;
  758. }
  759. return days;
  760. },
  761. // 计算psyTab的下标值
  762. calcPsyTabindex(type) {
  763. let psyIndex = '';
  764. switch (type) {
  765. case 1:
  766. psyIndex = 1;
  767. break;
  768. case 2:
  769. psyIndex = 2;
  770. break;
  771. case 3:
  772. psyIndex = 0;
  773. break;
  774. default:
  775. break;
  776. }
  777. return psyIndex;
  778. },
  779. // 获取这个月中有数据的日期,控制日历组件的日期样式
  780. getCalendarData() {
  781. let currentDate = new Date();
  782. // 获取最近30天的心情等级日历数据
  783. let dateList = this.getPostDate(currentDate, 30, true);
  784. let reqUrl = `${PsyBaseUrl}/api/Data/GetCalendarData`;
  785. let reqParams = {
  786. uid: this.uid,
  787. startDate: dateList[0],
  788. endDate: dateList[1]
  789. };
  790. axios
  791. .get(reqUrl, {
  792. params: { ...reqParams },
  793. headers: { AccessToken: this.$store.getters.ssjlToken }
  794. })
  795. .then(res => {
  796. if (res.data) {
  797. let data = res.data.response;
  798. // const mergedArr = [...new Set([...arr1, ...arr2, ...arr3])];
  799. /* let name = this.params.name.charAt(0).toUpperCase()+ this.params.name.slice(1); */
  800. let currentName = this.params.name;
  801. let list = [];
  802. if (currentName === 'stress') {
  803. list = data.Stress;
  804. } else if (currentName === 'depression') {
  805. list = data.Depression;
  806. } else {
  807. list = data.Tiredness;
  808. }
  809. list = list.map(item => {
  810. item.Date = this.$dayjs(item.Date.replace(/-/g, '/')).format('YYYY/MM/DD');
  811. return item;
  812. });
  813. this.highlightDates = [...list];
  814. }
  815. });
  816. },
  817. // 获取饼状图数据,TODO 对接接口数据
  818. getPieData() {
  819. this.pieData = [
  820. { value: 12, name: '', itemStyle: { color: 'green' } },
  821. { value: 2, name: '', itemStyle: { color: 'orange' } },
  822. { value: 1, name: '', itemStyle: { color: '#FFC0CB' } },
  823. { value: 1, name: '', itemStyle: { color: 'red' } }
  824. ];
  825. },
  826. // 获取情绪数据
  827. getPsychologiclData(date, startDate, endDate) {
  828. this.$toast.loading({
  829. message: '数据加载中'
  830. });
  831. let reqDate = date
  832. ? this.$dayjs(date).format('YYYY-MM-DD')
  833. : this.routeDate || this.$dayjs(this.defaultDate).format('YYYY-MM-DD'); /* "2023-05-23" */
  834. let reqParams = {
  835. uid: this.uid,
  836. startDate: startDate || reqDate,
  837. endDate: endDate || reqDate,
  838. type: this.emoType
  839. };
  840. console.log('请求参数', reqParams);
  841. let reqUrl = `${PsyBaseUrl}/api/Data/GetHisData`;
  842. axios
  843. .get(reqUrl, {
  844. params: { ...reqParams },
  845. headers: { AccessToken: this.$store.getters.ssjlToken }
  846. })
  847. .then(res => {
  848. if (res.data) {
  849. let data = res.data.response;
  850. // 监测次数
  851. this.monitoringCount = data.Count;
  852. this.pieRightList = [];
  853. this.statisticsList = [];
  854. this.emotionList = [];
  855. let None = {
  856. count: data.None,
  857. percentage: this.calcPercentage(data.None, data.Count),
  858. text: `无${this.emoName}倾向`,
  859. color: '#179b3b'
  860. };
  861. let Mild = {
  862. count: data.Mild,
  863. percentage: this.calcPercentage(data.Mild, data.Count),
  864. text: `轻度${this.emoName}倾向`,
  865. color: '#8dc21f'
  866. };
  867. let Moderate = {
  868. count: data.Moderate,
  869. percentage: this.calcPercentage(data.Moderate, data.Count),
  870. text: `中度${this.emoName}倾向`,
  871. color: '#2ea7e0'
  872. };
  873. let Severe = {
  874. count: data.Severe,
  875. percentage: this.calcPercentage(data.Severe, data.Count),
  876. text: `重度${this.emoName}倾向`,
  877. color: '#ff5f8b'
  878. };
  879. // 饼状图右边数据
  880. this.pieRightList.push(None);
  881. this.pieRightList.push(Mild);
  882. this.pieRightList.push(Moderate);
  883. this.pieRightList.push(Severe);
  884. this.pieData = this.pieRightList.map(item => {
  885. item.value = item.count;
  886. item.itemStyle = {
  887. color: item.color
  888. };
  889. return item;
  890. });
  891. // 最大,最小和最近值
  892. let Max = {
  893. label: '最大值',
  894. value: data.Max,
  895. time: data.MaxDesc
  896. ? this.currentDays === 0
  897. ? this.$dayjs(data.MaxDesc).format('HH:mm')
  898. : this.$dayjs(data.MaxDesc).format('MM/DD HH:mm')
  899. : ''
  900. };
  901. let Min = {
  902. label: '最小值',
  903. value: data.Min,
  904. time: data.MinDesc
  905. ? this.currentDays === 0
  906. ? this.$dayjs(data.MinDesc).format('HH:mm')
  907. : this.$dayjs(data.MinDesc).format('MM/DD HH:mm')
  908. : ''
  909. };
  910. let Avg = {
  911. label: '平均值',
  912. value: data.Avg,
  913. time: data.AvgDesc
  914. ? this.currentDays === 0
  915. ? this.$dayjs(data.AvgDesc).format('HH:mm')
  916. : this.$dayjs(data.AvgDesc).format('MM/DD HH:mm')
  917. : ''
  918. };
  919. let Current = {
  920. label: '最近值',
  921. value: data.Current,
  922. time: data.CurrentDesc
  923. ? this.currentDays === 0
  924. ? this.$dayjs(data.CurrentDesc).format('HH:mm')
  925. : this.$dayjs(data.CurrentDesc).format('MM/DD HH:mm')
  926. : ''
  927. };
  928. this.statisticsList.push(Max);
  929. this.statisticsList.push(Min);
  930. this.statisticsList.push(Avg);
  931. this.statisticsList.push(Current);
  932. // 周报月报底部显示数据
  933. let NoneDay = {
  934. days: data.NoneDay,
  935. text: `无${this.emoName}倾向`,
  936. color: '#179b3b'
  937. };
  938. let MildDay = {
  939. days: data.MildDay,
  940. text: `轻度${this.emoName}倾向`,
  941. color: '#8dc21f'
  942. };
  943. let ModerateDay = {
  944. days: data.ModerateDay,
  945. text: `中度${this.emoName}倾向`,
  946. color: '#2ea7e0'
  947. };
  948. let SevereDay = {
  949. days: data.SevereDay,
  950. text: `重度${this.emoName}倾向`,
  951. color: '#ff5f8b'
  952. };
  953. this.emotionList.push(NoneDay);
  954. this.emotionList.push(MildDay);
  955. this.emotionList.push(ModerateDay);
  956. this.emotionList.push(SevereDay);
  957. // 图表数据
  958. this.emotionData = data.ChartDatas.map(item => {
  959. return {
  960. value: item.Value,
  961. itemStyle: {
  962. borderColor: this.calcResultColor(item.Level)
  963. }
  964. };
  965. });
  966. // 7天 和 30天柱形图显示
  967. this.weekAndMonData = data.ChartDatas.map((item, index) => {
  968. return {
  969. value: [index, item.MinValue, item.MaxValue]
  970. };
  971. });
  972. // x轴显示数据
  973. if (this.currentDays === 0) {
  974. // 显示今天数据
  975. this.xAxisData = data.ChartDatas.map(item => {
  976. return this.$dayjs(item.Key.replace(/-/g, '/')).format('HH:mm');
  977. });
  978. } else {
  979. this.xAxisData = data.ChartDatas.map(item => {
  980. return this.$dayjs(item.Key.replace(/-/g, '/')).format('MM/DD');
  981. });
  982. let that = this;
  983. // 7天和30天变成柱状图
  984. this.weekAndMonthSeries = [
  985. {
  986. name: '平均值',
  987. type: 'scatter',
  988. symbolSize: 8,
  989. data: this.emotionData
  990. },
  991. {
  992. name: '',
  993. type: 'custom',
  994. data: this.weekAndMonData,
  995. renderItem: function (params, api) {
  996. var categoryIndex = api.value(0);
  997. var end = api.coord([categoryIndex, api.value(1)]);
  998. var start = api.coord([categoryIndex, api.value(2)]);
  999. var width = 8;
  1000. var rectShape = that.$echarts.graphic.clipRectByRect(
  1001. {
  1002. x: start[0] - width / 2,
  1003. y: start[1],
  1004. width: 8,
  1005. height: end[1] - start[1]
  1006. },
  1007. {
  1008. x: params.coordSys.x,
  1009. y: params.coordSys.y,
  1010. width: params.coordSys.width,
  1011. height: params.coordSys.height
  1012. }
  1013. );
  1014. if (rectShape) {
  1015. rectShape.r = [10];
  1016. }
  1017. return (
  1018. rectShape && {
  1019. type: 'rect',
  1020. shape: rectShape,
  1021. style: api.style()
  1022. }
  1023. );
  1024. },
  1025. itemStyle: {
  1026. opacity: 0.8
  1027. },
  1028. encode: {
  1029. y: [1, 2],
  1030. x: 0
  1031. }
  1032. },
  1033. {
  1034. name: `轻度${this.emoName}倾向`,
  1035. type: 'scatter',
  1036. symbolSize: 8,
  1037. data: ''
  1038. },
  1039. {
  1040. name: `中度${this.emoName}倾向`,
  1041. type: 'scatter',
  1042. symbolSize: 8,
  1043. data: ''
  1044. },
  1045. {
  1046. name: `重度${this.emoName}倾向`,
  1047. type: 'scatter',
  1048. symbolSize: 8,
  1049. data: ''
  1050. },
  1051. {
  1052. name: `无${this.emoName}倾向`,
  1053. type: 'scatter',
  1054. symbolSize: 8,
  1055. data: ''
  1056. }
  1057. ];
  1058. // 点击提示此时为空
  1059. this.defaultOptions.tooltip = {
  1060. trigger: 'axis',
  1061. formatter: function (params) {
  1062. return (
  1063. params[0].marker +
  1064. '平均值:' +
  1065. params[0].name +
  1066. '--' +
  1067. params[0].value +
  1068. '</br>' +
  1069. params[1].marker +
  1070. '最大值:' +
  1071. params[1].name +
  1072. '--' +
  1073. params[1].value[2] +
  1074. '</br>' +
  1075. params[1].marker +
  1076. '最小值:' +
  1077. params[1].name +
  1078. '--' +
  1079. params[1].value[1]
  1080. );
  1081. }
  1082. };
  1083. this.defaultOptions.series = this.weekAndMonthSeries;
  1084. }
  1085. // 结果解读
  1086. this.result = data.Result;
  1087. this.resultLevel = data.ResultLevel;
  1088. this.advice = data.Advice;
  1089. this.$toast.success({
  1090. message: '数据加载完成'
  1091. });
  1092. }
  1093. })
  1094. .catch(() => {
  1095. this.$dialog({
  1096. message: '登录过期,请重新进入'
  1097. });
  1098. })
  1099. .finally(() => {});
  1100. },
  1101. // 计算百分比
  1102. calcPercentage(value, total) {
  1103. if (typeof value !== 'number' || typeof total !== 'number' || total === 0) {
  1104. return 0;
  1105. }
  1106. let milValue = value * 1000;
  1107. let milTotal = total * 1000;
  1108. return Math.round((milValue / milTotal) * 100);
  1109. },
  1110. // 初始化图表的文字内容
  1111. initEchartText() {
  1112. this.result = `无${this.emoName}倾向`;
  1113. this.defaultSeries = [
  1114. {
  1115. name: ``,
  1116. type: 'line',
  1117. padding: 5,
  1118. data: this.emotionData,
  1119. symbol: 'circle',
  1120. symbolSize: 12, // 拐点圆的大小
  1121. areaStyle: {}
  1122. },
  1123. {
  1124. name: `轻度${this.emoName}倾向`,
  1125. type: 'line',
  1126. padding: 10,
  1127. data: '',
  1128. symbol: 'circle',
  1129. symbolSize: 12 // 拐点圆的大小
  1130. },
  1131. {
  1132. name: `中度${this.emoName}倾向`,
  1133. type: 'line',
  1134. data: ''
  1135. },
  1136. {
  1137. name: `重度${this.emoName}倾向`,
  1138. type: 'line',
  1139. data: ''
  1140. }
  1141. ];
  1142. this.pieRightList = this.pieRightList.map(item => {
  1143. item.text = item.text.replace('情绪', this.emoName);
  1144. return item;
  1145. });
  1146. },
  1147. // 初始化饼状图
  1148. initPieEchart() {
  1149. if (this.pieEcharts != null && this.pieEcharts != '' && this.pieEcharts != undefined) {
  1150. this.pieEcharts.dispose();
  1151. }
  1152. this.pieEcharts = this.$echarts.init(this.$refs.pieChart);
  1153. this.pieEcharts.setOption(this.pieOption);
  1154. },
  1155. // 格式化日期显示参数
  1156. formatter(day) {
  1157. const formatDate = this.$dayjs(day.date).format('YYYY/MM/DD');
  1158. const currentDate = this.$dayjs(new Date()).format('YYYY/MM/DD');
  1159. day.className = 'custom-calendar';
  1160. for (let h = 0; h < this.highlightDates.length; h++) {
  1161. if (this.highlightDates[h].Date === formatDate) {
  1162. day.className = `highlight-border ${this.calcResultColor(this.highlightDates[h].SummaryLevel, true)}`;
  1163. } else if (formatDate === currentDate) {
  1164. day.text = '今天';
  1165. }
  1166. }
  1167. return day;
  1168. },
  1169. // 返回
  1170. onNavBack() {
  1171. this.$router.push({
  1172. name: 'Today'
  1173. });
  1174. },
  1175. // 点击日期选择
  1176. onTabClick(value, index) {
  1177. this.current = index;
  1178. this.currentDays = value;
  1179. this.$store.commit('tabClick', index);
  1180. /* let currentDate = new Date(); */
  1181. this.surveyTitle = value === 7 ? '7天概览' : '30天概览';
  1182. if (value === 7) {
  1183. /* let dateList = this.getPostDate(currentDate, 6, true); */
  1184. this.getPsychologiclData('', /* dateList[0] */ '2023-11-15', /* dateList[1] */ '2023-11-21');
  1185. this.startDate = /* dateList[0] */ '2023-11-15';
  1186. this.endDate = /* dateList[1] */ '2023-11-21';
  1187. } else if (value === 0) {
  1188. // 今天
  1189. this.defaultOptions.xAxis.data = this.xAxisData;
  1190. this.defaultOptions.series = this.defaultSeries;
  1191. this.defaultOptions.series[0].data = this.emotionData;
  1192. this.getPsychologiclData(
  1193. this.selectDate ? this.selectDate : /* this.$dayjs(currentDate).format('YYYY-MM-DD') */ '2023-11-21'
  1194. );
  1195. this.startDate = /* this.$dayjs(currentDate).format('YYYY-MM-DD') */ '2023-11-21';
  1196. this.endDate = /* this.$dayjs(currentDate).format('YYYY-MM-DD') */ '2023-11-21';
  1197. } else if (value === 30) {
  1198. // 30天
  1199. this.defaultOptions.xAxis.data = this.xAxisData;
  1200. this.defaultOptions.series = this.defaultSeries;
  1201. this.defaultOptions.series[0].data = this.emotionData;
  1202. /* let dateList = this.getPostDate(currentDate, 30, true); */
  1203. this.getPsychologiclData('', /* dateList[0] */ '2023-11-21', /* dateList[1] */ '2023-12-21');
  1204. this.startDate = /* dateList[0] */ '2023-11-21';
  1205. this.endDate = /* dateList[1] */ '2023-12-21';
  1206. } else {
  1207. // 周报菜单
  1208. this.getWeekResult();
  1209. }
  1210. },
  1211. // 点击情绪tab
  1212. onPsyTabClick(name, index) {
  1213. this.psyCurrent = index;
  1214. this.emoName = EmotionModel[name].name;
  1215. this.currentEmoName = name;
  1216. this.emoType = EmotionModel[name].type;
  1217. console.log('this.currentDays', this.currentDays);
  1218. if (this.currentDays === 49) {
  1219. // 即点击了周报,此时调用获取周报接口
  1220. this.getWeekResult();
  1221. } else {
  1222. this.getPsychologiclData(this.startDate, this.endDate);
  1223. }
  1224. },
  1225. getCurrentMonthStaAndEnd(currentDate) {
  1226. let list = [];
  1227. let monthStart = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1); // 获取本月第一天的日期时间
  1228. let monthEnd = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0, 23, 59, 59); // 获取本月最后一天的日期时间(时间为23:59:59)
  1229. list.push(this.$dayjs(monthStart).format('YYYY-MM-DD'));
  1230. list.push(this.$dayjs(monthEnd).format('YYYY-MM-DD'));
  1231. return list;
  1232. },
  1233. // 获取指定天数的起始日期
  1234. /**
  1235. *
  1236. * @param dateNow :Date类
  1237. * @param intervalDays :间隔天数
  1238. * @param bolPastTime :Boolean,判断在参数date之前,还是之后,
  1239. */
  1240. getPostDate(dateNow, intervalDays, bolPastTime) {
  1241. let oneDayTime = 24 * 60 * 60 * 1000;
  1242. let list = [];
  1243. let lastDay;
  1244. if (bolPastTime == true) {
  1245. lastDay = new Date(dateNow.getTime() - intervalDays * oneDayTime);
  1246. list.push(this.formateDate(lastDay));
  1247. list.push(this.formateDate(dateNow));
  1248. } else {
  1249. lastDay = new Date(dateNow.getTime() + intervalDays * oneDayTime);
  1250. list.push(this.formateDate(dateNow));
  1251. list.push(this.formateDate(lastDay));
  1252. }
  1253. return list;
  1254. },
  1255. formateDate(time) {
  1256. let year = time.getFullYear();
  1257. let month = time.getMonth() + 1;
  1258. let day = time.getDate();
  1259. if (month < 10) {
  1260. month = '0' + month;
  1261. }
  1262. if (day < 10) {
  1263. day = '0' + day;
  1264. }
  1265. return year + '-' + month + '-' + day + '';
  1266. },
  1267. // 字体大小转化
  1268. fontChar(res) {
  1269. const clientWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
  1270. if (!clientWidth) return;
  1271. let fontSize = clientWidth / 750;
  1272. return res * fontSize;
  1273. },
  1274. // 初始化折线图表
  1275. initEchart() {
  1276. if (this.echarts != null && this.echarts != '' && this.echarts != undefined) {
  1277. this.echarts.dispose();
  1278. }
  1279. this.echarts = this.$echarts.init(this.$refs.charts);
  1280. this.echarts.setOption(this.defaultOptions);
  1281. },
  1282. // 点击历史监测,打开日历
  1283. onHistory() {
  1284. this.calendarDialogShow = true;
  1285. },
  1286. // 选择日历具体某一个日期
  1287. onSelect(value) {
  1288. const selectDate = this.$dayjs(value).format('YYYY-MM-DD');
  1289. this.dateList[0].text =
  1290. this.$dayjs(value).format('YYYY-MM-DD') === this.$dayjs(new Date()).format('YYYY-MM-DD')
  1291. ? '今天'
  1292. : this.$dayjs(value).format('MM-DD');
  1293. this.calendarDialogShow = false;
  1294. this.selectDate = selectDate;
  1295. this.getPsychologiclData(selectDate);
  1296. },
  1297. // 计算字体显示的颜色
  1298. calcColor(value) {
  1299. let color = '';
  1300. if (value <= 40) {
  1301. color = '#179b3b';
  1302. } else if (value > 40 && value <= 65) {
  1303. color = '#8dc21f';
  1304. } else if (value > 65 && value <= 80) {
  1305. color = '#2ea7e0';
  1306. } else if (value > 80) {
  1307. color = '#ff5f8b';
  1308. } else {
  1309. color = '';
  1310. }
  1311. return color;
  1312. },
  1313. // 计算结果采用哪种颜色
  1314. calcResultColor(value, isCallBackClass) {
  1315. let color = '';
  1316. let className = '';
  1317. switch (Number(value)) {
  1318. case 0:
  1319. color = '#179b3b';
  1320. className = 'none';
  1321. break;
  1322. case 1:
  1323. color = '#8dc21f';
  1324. className = 'mild';
  1325. break;
  1326. case 2:
  1327. color = '#2ea7e0';
  1328. className = 'moderate';
  1329. break;
  1330. case 3:
  1331. color = '#ff5f8b';
  1332. className = 'severe';
  1333. break;
  1334. }
  1335. return isCallBackClass ? className : color;
  1336. },
  1337. // 点击帮助
  1338. onHelp() {
  1339. this.isPopup = true;
  1340. },
  1341. // 关闭poup
  1342. onClose() {
  1343. this.isPopup = false;
  1344. },
  1345. getWeekResult() {
  1346. this.$toast.loading('数据加载中');
  1347. let baseUrl =
  1348. process.env.NODE_ENV === 'production' ? 'https://dbmq.rzliot.com/auth_heart' : 'https://dbmq.rzliot.com/heart';
  1349. let reqUrl = `${baseUrl}/api/Data/GetWeekResult`;
  1350. let reqParams = {
  1351. uid: this.uid /* '2023101521270090082 */,
  1352. type: this.emoType
  1353. };
  1354. axios
  1355. .get(reqUrl, {
  1356. params: { ...reqParams }
  1357. /* headers: { 'AccessToken': this.$store.getters.ssjlToken } */
  1358. })
  1359. .then(res => {
  1360. console.log('res', res);
  1361. const data = res.data.response;
  1362. this.weekList = data
  1363. .map(item => {
  1364. return {
  1365. name: item.Name.replace('周报', '').replace(/-/g, '.').replace(/~/g, '-'),
  1366. recordId: item.RecordId,
  1367. summary: item.Summary,
  1368. summaryLevel: item.SummaryLevel,
  1369. type: this.emoType
  1370. };
  1371. })
  1372. .reverse();
  1373. this.$toast.success('数据加载完成');
  1374. });
  1375. },
  1376. onClickItem(recordId) {
  1377. this.$router.push({
  1378. name: 'report',
  1379. query: {
  1380. recordId: recordId,
  1381. name: this.currentEmoName,
  1382. isShowLeft: true,
  1383. uid: this.uid
  1384. }
  1385. });
  1386. }
  1387. }
  1388. };
  1389. </script>
  1390. <style lang="scss">
  1391. .van-nav-bar .van-icon {
  1392. padding-left: 10px;
  1393. }
  1394. .calenddar-dialog {
  1395. overflow: scroll;
  1396. }
  1397. .calendar {
  1398. overflow: scroll;
  1399. .van-calendar {
  1400. height: 350px;
  1401. .van-calendar__header {
  1402. display: none;
  1403. }
  1404. .van-calendar__days .van-calendar__day {
  1405. width: 27px;
  1406. height: 27px;
  1407. margin: 5px;
  1408. font-size: 12px;
  1409. &.custom-calendar {
  1410. width: 27px;
  1411. height: 27px;
  1412. }
  1413. &.highlight-border {
  1414. border: 1px solid #62bd48;
  1415. width: 27px;
  1416. height: 27px;
  1417. border-radius: 50%;
  1418. &.none {
  1419. border: 1px solid #62bd48;
  1420. }
  1421. &.mild {
  1422. border: 1px solid #8dc21f;
  1423. }
  1424. &.moderate {
  1425. border: 1px solid #2ea7e0;
  1426. }
  1427. &.severe {
  1428. border: 1px solid #ff5f8b;
  1429. }
  1430. }
  1431. }
  1432. .van-calendar__selected-day {
  1433. width: 27px;
  1434. height: 27px;
  1435. border-radius: 50%;
  1436. font-size: 12px;
  1437. }
  1438. }
  1439. }
  1440. </style>
  1441. <style scoped lang="scss">
  1442. @import './scss/emotion-details.scss';
  1443. </style>