健康同学微信公众号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.

1698 lines
45KB

  1. <!-- -->
  2. <template>
  3. <div class="pageContent insight">
  4. <div class="periodNav">
  5. <div class="periodItem week" :class="{ active: active == 0 }" @click="active = 0">周</div>
  6. <div class="periodItem month" :class="{ active: active == 1 }" @click="active = 1">月</div>
  7. </div>
  8. <DateSwitch :dateType="active == 0 ? 'week' : 'month'" @updateDate="updateDate" v-if="false"></DateSwitch>
  9. <!-- <div class="periodSwitch">
  10. <div class="arrow arrowLeft">
  11. <van-icon name="arrow-left"></van-icon>
  12. </div>
  13. <div class="timearea">2023-11-15~2023-11-22</div>
  14. <div class="arrow arrowRight">
  15. <van-icon name="arrow"></van-icon>
  16. </div>
  17. </div> -->
  18. <div class="label">
  19. <div class="left">情绪感知</div>
  20. <div class="right">
  21. <span @click="onRouterTo('emo')">详情 ></span>
  22. </div>
  23. </div>
  24. <div class="periodNav">
  25. <div
  26. class="periodItem minPeriodItem"
  27. :class="{ active: emotionActive == index }"
  28. v-for="(item, index) in psyList"
  29. :key="index"
  30. @click="onEmotionClick(item, index)"
  31. >
  32. <span>{{ item.name }}</span>
  33. </div>
  34. </div>
  35. <div class="echart-container">
  36. <div class="echart">
  37. <EchartBox
  38. echartId="emotionChart"
  39. :outTitle="emoLegend.outTitle"
  40. height="200"
  41. width="200"
  42. :legend="emoLegend"
  43. :options="defaultOptions"
  44. ></EchartBox>
  45. </div>
  46. </div>
  47. <div class="grid">
  48. <div class="gridItem" :style="`background:${item.color};`" v-for="(item, index) in emotionList" :key="index">
  49. <div class="time">
  50. <span class="number">{{ item.days }}</span>
  51. <span>天</span>
  52. </div>
  53. <div class="title">{{ item.text }}</div>
  54. </div>
  55. </div>
  56. <div class="label">
  57. <div class="left">体征感知</div>
  58. <div class="right">
  59. <span @click="onRouterTo('signs')">详情 ></span>
  60. </div>
  61. </div>
  62. <div class="periodNav">
  63. <div
  64. class="periodItem minPeriodItem"
  65. :class="{ active: signActive == index }"
  66. v-for="(item, index) in signList"
  67. :key="index"
  68. @click="onSignClick(index)"
  69. >
  70. <span>{{ item.name }}</span>
  71. </div>
  72. </div>
  73. <!-- bmi显示/输入 -->
  74. <div class="bmi" v-show="signActive == 2">
  75. <p>身高:<span>170</span>cm</p>
  76. <p>体重:<span>60</span>kg</p>
  77. <p>BMI:<span>24.5</span></p>
  78. <p>{{ bmi.result }}</p>
  79. <van-button size="mini">更新</van-button>
  80. </div>
  81. <div class="ChatBox" :class="{ hiddenChart: signActive == 2 }">
  82. <div class="legendBox minLegendBox">
  83. <div class="legend">
  84. <div class="legendItem" :class="item.type" v-for="(item, index) in signGrid" :key="index">
  85. <span>{{ item.name }}</span>
  86. </div>
  87. </div>
  88. </div>
  89. <div class="Chat signChart" id="signChart"></div>
  90. </div>
  91. <div class="grid">
  92. <div
  93. class="gridItem"
  94. v-show="signActive != 2"
  95. :style="`background:${item.color};`"
  96. v-for="(item, index) in signDaysList"
  97. :key="index"
  98. >
  99. <div class="time">
  100. <span class="number">{{ item.day }}</span>
  101. <span>天</span>
  102. </div>
  103. <div class="title">{{ item.name }}</div>
  104. </div>
  105. </div>
  106. <div class="ChatBox minChartBox" :class="{ hiddenChart: signActive != 2 }">
  107. <h4>运动步数</h4>
  108. <div class="Chat stepChart" id="stepChart"></div>
  109. <div class="result">
  110. <div class="wrapBox">
  111. <div class="text">
  112. <div class="left">
  113. <p>总步数:{{ stepsData.total || '--' }}</p>
  114. </div>
  115. <div class="right">
  116. <img :src="stepsData.lastStepTotalCompare > 0 ? upImg : downImg" alt="" />
  117. <span>{{ Math.abs(stepsData.lastStepTotalCompare) || '--' }}</span>
  118. </div>
  119. </div>
  120. <div class="text">
  121. <div class="left">
  122. <p>平均步数:{{ stepsData.avg || '--' }}</p>
  123. </div>
  124. <div class="right">
  125. <img :src="stepsData.lastStepAvgCompare > 0 ? upImg : downImg" alt="" />
  126. <span>{{ Math.abs(stepsData.lastStepAvgCompare) || '--' }}</span>
  127. </div>
  128. </div>
  129. </div>
  130. </div>
  131. </div>
  132. <div class="ChatBox minChartBox" :class="{ hiddenChart: signActive != 2 }">
  133. <h4>热量消耗</h4>
  134. <div class="Chat calorieChart" id="calorieChart"></div>
  135. <div class="result">
  136. <div class="wrapBox">
  137. <div class="text">
  138. <div class="left">
  139. <p>总消耗:{{ calorieData.total || '--' }}</p>
  140. </div>
  141. <div class="right">
  142. <img :src="calorieData.lastCalorieTotalCompare > 0 ? upImg : downImg" alt="" />
  143. <span>{{ Math.abs(calorieData.lastCalorieTotalCompare) || '--' }}</span>
  144. </div>
  145. </div>
  146. <div class="text">
  147. <div class="left">
  148. <p>平均消耗:{{ calorieData.avg || '--' }}</p>
  149. </div>
  150. <div class="right">
  151. <img :src="calorieData.lastCalorieAvgCompare > 0 ? upImg : downImg" alt="" />
  152. <span>{{ Math.abs(calorieData.avg) || '--' }}</span>
  153. </div>
  154. </div>
  155. </div>
  156. </div>
  157. </div>
  158. </div>
  159. </template>
  160. <script>
  161. import DateSwitch from '@/components/DateSwitch.vue';
  162. import { format, startOfMonth, endOfMonth } from 'date-fns';
  163. import ToastService from '@/services/toast-service';
  164. import { /* EmotionModel, */ PsyBaseUrl } from '@/config/models';
  165. import axios from 'axios';
  166. import EchartBox from '@/components/EchartBox';
  167. import APIHealthUser from '@/api/health-user';
  168. export default {
  169. components: {
  170. DateSwitch,
  171. EchartBox
  172. },
  173. data() {
  174. return {
  175. active: 0,
  176. emotionActive: 0,
  177. signActive: 0,
  178. emotionChart: null,
  179. signChart: null,
  180. stepChart: null,
  181. calorieChart: null,
  182. psyList: [
  183. {
  184. name: '疲劳',
  185. type: 3
  186. },
  187. {
  188. name: '压力',
  189. type: 1
  190. },
  191. {
  192. name: '抑郁',
  193. type: 2
  194. }
  195. ],
  196. degreeList: [
  197. {
  198. name: '无',
  199. type: 'not',
  200. color: '#179B3B'
  201. },
  202. {
  203. name: '轻度',
  204. type: 'mild',
  205. color: '#2EA7E0'
  206. },
  207. {
  208. name: '中度',
  209. type: 'moderate',
  210. color: '#8DC21F'
  211. },
  212. {
  213. name: '重度',
  214. type: 'severe',
  215. color: '#FF5F8B'
  216. }
  217. ],
  218. signList: [
  219. {
  220. grid: 'heartRateList',
  221. name: '心率'
  222. },
  223. {
  224. grid: 'temperatureList',
  225. name: '体温'
  226. },
  227. {
  228. grid: null,
  229. name: '运动'
  230. }
  231. ],
  232. heartRateList: [
  233. {
  234. name: '正常',
  235. type: 'moderate',
  236. color: '#179B3B'
  237. },
  238. {
  239. name: '偏高',
  240. type: 'severe',
  241. color: '#FF5F8B'
  242. },
  243. {
  244. name: '偏低',
  245. type: 'mild',
  246. color: '#2EA7E0'
  247. }
  248. ],
  249. temperatureList: [
  250. {
  251. name: '正常',
  252. type: 'moderate',
  253. color: '#179B3B'
  254. },
  255. {
  256. name: '发烧',
  257. type: 'severe',
  258. color: '#FF5F8B'
  259. }
  260. ],
  261. bmi: {
  262. height: '170',
  263. weight: '57',
  264. value: '24.5',
  265. result: '肥胖'
  266. },
  267. upImg: require('@/assets/today/icons/up.png'),
  268. downImg: require('@/assets/today/icons/down.png'),
  269. date: '',
  270. monthDate: {},
  271. dateList: [],
  272. emotionData: [],
  273. xAxisData: [], //图表x轴展示的数据
  274. echarts: null,
  275. signCurrent: 0,
  276. emoName: '',
  277. result: '',
  278. // 需要高亮的日期数组
  279. highlightDates: [],
  280. // 日历 默认最小可选择日期,默认为当前时间
  281. maxDate: new Date(this.$dayjs().hour(0).minute(0).second(0).format()),
  282. // 默认日历日期时间
  283. defaultDate: new Date(this.$dayjs().hour(0).minute(0).second(0).format()),
  284. uid: '2024010809384143241',
  285. // 7天和30天最大数据列表
  286. weekAndMonData: [],
  287. weekList: [],
  288. startDate: '', //接口需要的开始时间
  289. endDate: '', //接口需要的结束时间
  290. currentEmoName: '', //当前情绪名称
  291. emotionList: [],
  292. weekAndMonthSeries: null,
  293. emoType: '1',
  294. signData: {},
  295. signDaysList: [],
  296. stepsData: {},
  297. calorieData: {}
  298. };
  299. },
  300. created() {
  301. this.emoName = this.psyList[this.emotionActive].name;
  302. this.initEchartText();
  303. /* this.getPsychologiclData('', '2023-11-21', '2023-12-21'); */
  304. },
  305. mounted() {
  306. this.initData();
  307. this.getPsychologiclData();
  308. },
  309. watch: {
  310. active(val) {
  311. console.log(val);
  312. console.log('最近7天开始时间和结束时间', this.$getRangeStartAndEnd(7));
  313. let days = val === 0 ? 7 : 30;
  314. let startAndEndDate = this.$getRangeStartAndEnd(days);
  315. let date = {
  316. start: this.$dayjs(startAndEndDate.start).format('YYYY-MM-DD'),
  317. end: this.$dayjs(startAndEndDate.end).format('YYYY-MM-DD')
  318. };
  319. this.updateDate(date);
  320. },
  321. emotionActive(val) {
  322. console.log(val);
  323. /* this.$nextTick(() => {
  324. this.initEmotionChart();
  325. }); */
  326. },
  327. signActive(val) {
  328. console.log(val);
  329. this.$nextTick(() => {
  330. /* this.initSignChart(); */
  331. this.initData();
  332. });
  333. }
  334. },
  335. computed: {
  336. degreeMap() {
  337. let map = new Map();
  338. this.degreeList.forEach(item => {
  339. map.set(item.name, item.color);
  340. });
  341. return map;
  342. },
  343. heartRateMap() {
  344. let map = new Map();
  345. this.heartRateList.forEach(item => {
  346. map.set(item.name, item.color);
  347. });
  348. return map;
  349. },
  350. temperatureMap() {
  351. let map = new Map();
  352. this.temperatureList.forEach(item => {
  353. map.set(item.name, item.color);
  354. });
  355. return map;
  356. },
  357. signGrid() {
  358. let list = [];
  359. if (this.signList[this.signActive].grid) {
  360. let temp = this[`${this.signList[this.signActive].grid}`];
  361. if (temp) {
  362. list = temp;
  363. }
  364. }
  365. return list;
  366. },
  367. defaultOptions() {
  368. return {
  369. time: {
  370. useUTC: false
  371. },
  372. grid: {
  373. show: true,
  374. borderWidth: 0,
  375. top: '3%',
  376. left: '1%',
  377. right: '3%',
  378. bottom: '15%',
  379. containLabel: true
  380. },
  381. xAxis: {
  382. type: 'category',
  383. axisLine: {
  384. show: false
  385. },
  386. textStyle: {
  387. fontSize: 10
  388. },
  389. axisTick: {
  390. show: false
  391. },
  392. splitLine: {
  393. show: false,
  394. lineStyle: {
  395. color: '#ddd',
  396. width: 2
  397. }
  398. },
  399. nameLocation: 'center',
  400. axisLabel: {
  401. show: true,
  402. fontSize: 12,
  403. showMinLabel: true, //显示最小值
  404. showMaxLabel: true //显示最大值
  405. },
  406. data: this.xAxisData
  407. },
  408. dataZoom: [
  409. /* {
  410. type: "inside",
  411. start: 0,
  412. end: 100,
  413. }, */
  414. {
  415. start: 0,
  416. end: 100,
  417. textStyle: {
  418. color: '#FFF',
  419. fontSize: 14
  420. },
  421. show: true,
  422. height: 20,
  423. bottom: 4,
  424. handleStyle: {
  425. borderWidth: 1,
  426. borderCap: 'square'
  427. }
  428. }
  429. ],
  430. tooltip: {
  431. trigger: 'axis',
  432. textStyle: {
  433. fontSize: 14,
  434. align: 'center'
  435. },
  436. formatter: function (params) {
  437. return params[0].marker + params[0].name + '</br>' + params[0].value;
  438. }
  439. },
  440. yAxis: {
  441. type: 'value',
  442. max: 100,
  443. min: 0,
  444. interval: 20,
  445. splitNumber: 1,
  446. boundaryGap: ['5%', '5%'],
  447. nameTextStyle: {
  448. fontSize: 13
  449. },
  450. alignTicks: false,
  451. axisTick: {
  452. show: false
  453. },
  454. axisLabel: {
  455. show: true,
  456. fontSize: 13
  457. },
  458. splitLine: {
  459. show: false,
  460. lineStyle: {
  461. color: '#ddd',
  462. width: 1
  463. }
  464. }
  465. },
  466. series: [
  467. {
  468. name: `无${this.emoName}倾向`,
  469. type: 'line',
  470. padding: 5,
  471. smooth: true,
  472. data: this.emotionData,
  473. symbol: 'circle',
  474. symbolSize: 10,
  475. itemStyle: {
  476. color: '#fff',
  477. borderWidth: 2
  478. },
  479. lineStyle: {
  480. width: 6,
  481. type: 'solid',
  482. color: '#189b3b'
  483. }
  484. },
  485. {
  486. name: `轻度${this.emoName}倾向`,
  487. type: 'line',
  488. data: ''
  489. },
  490. {
  491. name: `中度${this.emoName}倾向`,
  492. type: 'line',
  493. data: ''
  494. },
  495. {
  496. name: `重度${this.emoName}倾向`,
  497. type: 'line',
  498. data: ''
  499. }
  500. ]
  501. };
  502. },
  503. emoLegend() {
  504. return {
  505. title: '',
  506. outTitle: `${this.emoName}数据图`,
  507. list: [
  508. { name: `无${this.emoName}倾向`, color: '#179b3b' },
  509. { name: `轻度${this.emoName}倾向`, color: '#8dc21f' },
  510. { name: `中度${this.emoName}倾向`, color: '#2ea7e0' },
  511. { name: `重度${this.emoName}倾向`, color: '#ff5f8b' }
  512. ]
  513. };
  514. }
  515. },
  516. methods: {
  517. initEchartText() {
  518. this.result = `无${this.emoName}倾向`;
  519. this.defaultSeries = [
  520. {
  521. name: ``,
  522. type: 'line',
  523. padding: 5,
  524. data: this.emotionData,
  525. symbol: 'circle',
  526. symbolSize: 12, // 拐点圆的大小
  527. areaStyle: {}
  528. },
  529. {
  530. name: `轻度${this.emoName}倾向`,
  531. type: 'line',
  532. padding: 10,
  533. data: '',
  534. symbol: 'circle',
  535. symbolSize: 12 // 拐点圆的大小
  536. },
  537. {
  538. name: `中度${this.emoName}倾向`,
  539. type: 'line',
  540. data: ''
  541. },
  542. {
  543. name: `重度${this.emoName}倾向`,
  544. type: 'line',
  545. data: ''
  546. }
  547. ];
  548. let days = this.active === 0 ? 7 : 30;
  549. let startAndEndDate = this.$getRangeStartAndEnd(days);
  550. this.date = {
  551. start: this.$dayjs(startAndEndDate.start).format('YYYY-MM-DD'),
  552. end: this.$dayjs(startAndEndDate.end).format('YYYY-MM-DD')
  553. };
  554. },
  555. // 获取情绪数据
  556. getPsychologiclData(date, startDate, endDate) {
  557. ToastService.loading({
  558. message: '数据加载中'
  559. });
  560. let reqParams = {
  561. uid: this.uid,
  562. startDate: startDate || this.date.start,
  563. endDate: endDate || this.date.end,
  564. type: this.emoType
  565. };
  566. console.log('请求参数', reqParams);
  567. let reqUrl = `${PsyBaseUrl}/api/Data/GetHisData`;
  568. axios
  569. .get(reqUrl, {
  570. params: { ...reqParams },
  571. headers: { AccessToken: this.$store.getters.ssjlToken }
  572. })
  573. .then(res => {
  574. if (res.data) {
  575. let data = res.data.response;
  576. // 监测次数
  577. this.monitoringCount = data.Count;
  578. this.pieRightList = [];
  579. this.statisticsList = [];
  580. this.emotionList = [];
  581. let None = {
  582. count: data.None,
  583. percentage: this.calcPercentage(data.None, data.Count),
  584. text: `无${this.emoName}倾向`,
  585. color: '#179b3b'
  586. };
  587. let Mild = {
  588. count: data.Mild,
  589. percentage: this.calcPercentage(data.Mild, data.Count),
  590. text: `轻度${this.emoName}倾向`,
  591. color: '#8dc21f'
  592. };
  593. let Moderate = {
  594. count: data.Moderate,
  595. percentage: this.calcPercentage(data.Moderate, data.Count),
  596. text: `中度${this.emoName}倾向`,
  597. color: '#2ea7e0'
  598. };
  599. let Severe = {
  600. count: data.Severe,
  601. percentage: this.calcPercentage(data.Severe, data.Count),
  602. text: `重度${this.emoName}倾向`,
  603. color: '#ff5f8b'
  604. };
  605. // 饼状图右边数据
  606. this.pieRightList.push(None);
  607. this.pieRightList.push(Mild);
  608. this.pieRightList.push(Moderate);
  609. this.pieRightList.push(Severe);
  610. this.pieData = this.pieRightList.map(item => {
  611. item.value = item.count;
  612. item.itemStyle = {
  613. color: item.color
  614. };
  615. return item;
  616. });
  617. // 最大,最小和最近值
  618. let Max = {
  619. label: '最大值',
  620. value: data.Max,
  621. time: data.MaxDesc
  622. ? this.currentDays === 0
  623. ? this.$dayjs(data.MaxDesc).format('HH:mm')
  624. : this.$dayjs(data.MaxDesc).format('MM/DD HH:mm')
  625. : '',
  626. bgColor: '#ff5f8b'
  627. };
  628. let Min = {
  629. label: '最小值',
  630. value: data.Min,
  631. time: data.MinDesc
  632. ? this.currentDays === 0
  633. ? this.$dayjs(data.MinDesc).format('HH:mm')
  634. : this.$dayjs(data.MinDesc).format('MM/DD HH:mm')
  635. : '',
  636. bgColor: '#189b3b'
  637. };
  638. /* let Avg = {
  639. label: '平均值',
  640. value: data.Avg,
  641. time: data.AvgDesc
  642. ? this.currentDays === 0
  643. ? this.$dayjs(data.AvgDesc).format('HH:mm')
  644. : this.$dayjs(data.AvgDesc).format('MM/DD HH:mm')
  645. : ''
  646. }; */
  647. let Current = {
  648. label: '最近值',
  649. value: data.Current,
  650. time: data.CurrentDesc
  651. ? this.currentDays === 0
  652. ? this.$dayjs(data.CurrentDesc).format('HH:mm')
  653. : this.$dayjs(data.CurrentDesc).format('MM/DD HH:mm')
  654. : '',
  655. bgColor: '#2ea7e0'
  656. };
  657. this.statisticsList.push(Max);
  658. this.statisticsList.push(Min);
  659. /* this.statisticsList.push(Avg); */
  660. this.statisticsList.push(Current);
  661. // 周报月报底部显示数据
  662. let NoneDay = {
  663. days: data.NoneDay,
  664. text: `无${this.emoName}倾向`,
  665. color: '#179b3b'
  666. };
  667. let MildDay = {
  668. days: data.MildDay,
  669. text: `轻度${this.emoName}倾向`,
  670. color: '#8dc21f'
  671. };
  672. let ModerateDay = {
  673. days: data.ModerateDay,
  674. text: `中度${this.emoName}倾向`,
  675. color: '#2ea7e0'
  676. };
  677. let SevereDay = {
  678. days: data.SevereDay,
  679. text: `重度${this.emoName}倾向`,
  680. color: '#ff5f8b'
  681. };
  682. this.emotionList.push(NoneDay);
  683. this.emotionList.push(MildDay);
  684. this.emotionList.push(ModerateDay);
  685. this.emotionList.push(SevereDay);
  686. // 图表数据
  687. this.emotionData = data.ChartDatas.map(item => {
  688. return {
  689. value: item.Value,
  690. itemStyle: {
  691. borderColor: this.calcResultColor(item.Level)
  692. }
  693. };
  694. });
  695. // 7天 和 30天柱形图显示
  696. this.weekAndMonData = data.ChartDatas.map((item, index) => {
  697. return {
  698. value: [index, item.MinValue, item.MaxValue]
  699. };
  700. });
  701. // x轴显示数据
  702. if (this.currentDays === 0) {
  703. // 显示今天数据
  704. this.xAxisData = data.ChartDatas.map(item => {
  705. return this.$dayjs(item.Key.replace(/-/g, '/')).format('HH:mm');
  706. });
  707. } else {
  708. this.xAxisData = data.ChartDatas.map(item => {
  709. return this.$dayjs(item.Key.replace(/-/g, '/')).format('MM/DD');
  710. });
  711. let that = this;
  712. // 7天和30天变成柱状图
  713. this.weekAndMonthSeries = [
  714. {
  715. name: '平均值',
  716. type: 'scatter',
  717. symbolSize: 14,
  718. data: this.emotionData
  719. },
  720. {
  721. name: '',
  722. type: 'custom',
  723. data: this.weekAndMonData,
  724. renderItem: function (params, api) {
  725. let categoryIndex = api.value(0);
  726. let end = api.coord([categoryIndex, api.value(1)]);
  727. let start = api.coord([categoryIndex, api.value(2)]);
  728. let width = 16;
  729. let rectShape = that.$echarts.graphic.clipRectByRect(
  730. {
  731. x: start[0] - width / 2,
  732. y: start[1],
  733. width: 16,
  734. height: end[1] - start[1]
  735. },
  736. {
  737. x: params.coordSys.x,
  738. y: params.coordSys.y,
  739. width: params.coordSys.width,
  740. height: params.coordSys.height
  741. }
  742. );
  743. if (rectShape) {
  744. rectShape.r = [10];
  745. }
  746. return (
  747. rectShape && {
  748. type: 'rect',
  749. shape: rectShape,
  750. style: api.style()
  751. }
  752. );
  753. },
  754. itemStyle: {
  755. opacity: 0.8
  756. },
  757. encode: {
  758. y: [1, 2],
  759. x: 0
  760. }
  761. },
  762. {
  763. name: `轻度${this.emoName}倾向`,
  764. type: 'scatter',
  765. symbolSize: 12,
  766. data: ''
  767. },
  768. {
  769. name: `中度${this.emoName}倾向`,
  770. type: 'scatter',
  771. symbolSize: 12,
  772. data: ''
  773. },
  774. {
  775. name: `重度${this.emoName}倾向`,
  776. type: 'scatter',
  777. symbolSize: 12,
  778. data: ''
  779. },
  780. {
  781. name: `无${this.emoName}倾向`,
  782. type: 'scatter',
  783. symbolSize: 12,
  784. data: ''
  785. }
  786. ];
  787. // 点击提示此时为空
  788. this.defaultOptions.tooltip = {
  789. trigger: 'axis',
  790. formatter: function (params) {
  791. return (
  792. params[0].marker +
  793. '平均值:' +
  794. params[0].name +
  795. '--' +
  796. params[0].value +
  797. '</br>' +
  798. params[1].marker +
  799. '最大值:' +
  800. params[1].name +
  801. '--' +
  802. params[1].value[2] +
  803. '</br>' +
  804. params[1].marker +
  805. '最小值:' +
  806. params[1].name +
  807. '--' +
  808. params[1].value[1]
  809. );
  810. }
  811. };
  812. this.defaultOptions.series = this.weekAndMonthSeries;
  813. }
  814. // 结果解读
  815. this.result = data.Result;
  816. this.resultLevel = data.ResultLevel;
  817. this.advice = data.Advice;
  818. ToastService.success({
  819. message: '数据加载完成'
  820. });
  821. }
  822. })
  823. .catch(error => {
  824. console.log(error);
  825. })
  826. .finally(() => {
  827. ToastService.clear();
  828. });
  829. },
  830. getPostDate(dateNow, intervalDays, bolPastTime) {
  831. let oneDayTime = 24 * 60 * 60 * 1000;
  832. let list = [];
  833. let lastDay;
  834. if (bolPastTime == true) {
  835. lastDay = new Date(dateNow.getTime() - intervalDays * oneDayTime);
  836. list.push(this.formateDate(lastDay));
  837. list.push(this.formateDate(dateNow));
  838. } else {
  839. lastDay = new Date(dateNow.getTime() + intervalDays * oneDayTime);
  840. list.push(this.formateDate(dateNow));
  841. list.push(this.formateDate(lastDay));
  842. }
  843. return list;
  844. },
  845. updateDate(value) {
  846. this.date = value;
  847. console.log('this.date', this.date);
  848. this.getPsychologiclData('', value.start, value.end);
  849. this.getReportData('', value.start, value.end);
  850. },
  851. formateDate(time) {
  852. let year = time.getFullYear();
  853. let month = time.getMonth() + 1;
  854. let day = time.getDate();
  855. if (month < 10) {
  856. month = '0' + month;
  857. }
  858. if (day < 10) {
  859. day = '0' + day;
  860. }
  861. return year + '-' + month + '-' + day + '';
  862. },
  863. // 计算结果采用哪种颜色
  864. calcResultColor(value, isCallBackClass) {
  865. let color = '';
  866. let className = '';
  867. switch (Number(value)) {
  868. case 0:
  869. color = '#179b3b';
  870. className = 'none';
  871. break;
  872. case 1:
  873. color = '#8dc21f';
  874. className = 'mild';
  875. break;
  876. case 2:
  877. color = '#2ea7e0';
  878. className = 'moderate';
  879. break;
  880. case 3:
  881. color = '#ff5f8b';
  882. className = 'severe';
  883. break;
  884. }
  885. return isCallBackClass ? className : color;
  886. },
  887. // 计算百分比
  888. calcPercentage(value, total) {
  889. if (typeof value !== 'number' || typeof total !== 'number' || total === 0) {
  890. return 0;
  891. }
  892. let milValue = value * 1000;
  893. let milTotal = total * 1000;
  894. return Math.round((milValue / milTotal) * 100);
  895. },
  896. getMonthStaEnd(value) {
  897. const dateObj = {};
  898. const start = startOfMonth(value);
  899. const end = endOfMonth(value);
  900. dateObj.start = format(start, 'yyyy-MM-dd');
  901. dateObj.end = format(end, 'yyyy-MM-dd');
  902. this.monthDate = { ...dateObj };
  903. },
  904. initData() {
  905. //初始化图表
  906. /* if (!this.emotionChart) {
  907. this.emotionChart = this.$echarts.init(document.getElementById('emotionChart'));
  908. } */
  909. if (!this.signChart) {
  910. this.signChart = this.$echarts.init(document.getElementById('signChart'));
  911. }
  912. if (!this.stepChart) {
  913. this.stepChart = this.$echarts.init(document.getElementById('stepChart'));
  914. }
  915. if (!this.calorieChart) {
  916. this.calorieChart = this.$echarts.init(document.getElementById('calorieChart'));
  917. }
  918. //渲染图表
  919. /* this.initEmotionChart(); */
  920. this.initSignChart();
  921. },
  922. initEmotionChart() {
  923. let option = this.getOption();
  924. //测试
  925. let data = [
  926. {
  927. time: '5.11',
  928. value: 10
  929. },
  930. {
  931. time: '5.12',
  932. value: 20
  933. },
  934. {
  935. time: '5.13',
  936. value: 40
  937. },
  938. {
  939. time: '5.14',
  940. value: 50
  941. },
  942. {
  943. time: '5.15',
  944. value: 60
  945. },
  946. {
  947. time: '5.16',
  948. value: 70
  949. },
  950. {
  951. time: '5.17',
  952. value: 90
  953. }
  954. ];
  955. this.formateEmotionData(option, data);
  956. this.emotionChart.setOption(option);
  957. },
  958. async initSignChart() {
  959. let option = this.getOption();
  960. let data = await this.getReportData('', this.date.start, this.date.end);
  961. if (this.signActive == 0) {
  962. //测试
  963. this.formateHeartRateData(option, data.day);
  964. this.signChart.setOption(option);
  965. } else if (this.signActive == 1) {
  966. //测试
  967. this.formateTemperatureData(option, data.day);
  968. this.signChart.setOption(option);
  969. } else if (this.signActive == 2) {
  970. option = this.getOption(false);
  971. let option2 = this.getOption(false);
  972. let data2 = await this.getReportData(3, this.date.start, this.date.end);
  973. this.stepsData = { ...data };
  974. this.calorieData = { ...data2 };
  975. this.formateStepData(option, data.day);
  976. this.formateCalorieData(option2, data2.day);
  977. this.stepChart.setOption(option);
  978. this.calorieChart.setOption(option2);
  979. }
  980. },
  981. formateEmotionData(option, data) {
  982. let xdata = [];
  983. let ydata = [];
  984. let fill = [];
  985. let max = 0;
  986. data.forEach(item => {
  987. if (item.value > max) {
  988. max = item.value;
  989. }
  990. });
  991. data.forEach(item => {
  992. xdata.push(item.time);
  993. fill.push({
  994. value: max - item.value,
  995. label: {
  996. show: false
  997. },
  998. itemStyle: {
  999. color: this.formateEmotionColor(item.value)
  1000. }
  1001. });
  1002. ydata.push({
  1003. value: item.value,
  1004. label: {
  1005. show: true
  1006. },
  1007. itemStyle: {
  1008. color: this.formateEmotionColor(item.value)
  1009. }
  1010. });
  1011. });
  1012. option.xAxis.data = xdata;
  1013. option.series[0].data = ydata;
  1014. option.series[1].data = fill;
  1015. },
  1016. formateEmotionColor(value) {
  1017. if (value > 75) {
  1018. return this.degreeMap.get('重度');
  1019. } else if (value > 50) {
  1020. return this.degreeMap.get('中度');
  1021. } else if (value > 25) {
  1022. return this.degreeMap.get('轻度');
  1023. } else {
  1024. return this.degreeMap.get('无');
  1025. }
  1026. },
  1027. formateHeartRateData(option, data) {
  1028. let xdata = [];
  1029. let ydata = [];
  1030. let fill = [];
  1031. let max = 0;
  1032. data.forEach(item => {
  1033. if (item.value > max) {
  1034. max = item.value;
  1035. }
  1036. });
  1037. data.forEach(item => {
  1038. xdata.push(item.date);
  1039. fill.push({
  1040. value: max - item.value,
  1041. label: {
  1042. show: false
  1043. },
  1044. itemStyle: {
  1045. borderWidth: 3,
  1046. borderColor: this.calcColorByEvaluate(item.evaluate)
  1047. }
  1048. });
  1049. ydata.push({
  1050. value: item.value,
  1051. label: {
  1052. show: false
  1053. },
  1054. itemStyle: {
  1055. borderWidth: 3,
  1056. borderColor: this.calcColorByEvaluate(item.evaluate)
  1057. }
  1058. });
  1059. });
  1060. option.xAxis.data = xdata;
  1061. option.series[0].data = ydata;
  1062. option.series[1].data = fill;
  1063. // 规定最小值
  1064. option.yAxis.min = 40;
  1065. // 规定最大值
  1066. option.yAxis.max = 150;
  1067. //设置高压标线
  1068. option.series[1].markLine = {
  1069. data: [
  1070. {
  1071. symbol: 'pin',
  1072. silent: true,
  1073. yAxis: 120,
  1074. lineStyle: {
  1075. color: '#C1272D'
  1076. },
  1077. label: {
  1078. color: '#C1272D'
  1079. }
  1080. }
  1081. ]
  1082. };
  1083. },
  1084. formateHeartRateColor(value) {
  1085. if (value > 120) {
  1086. return this.heartRateMap.get('偏高');
  1087. } else if (value >= 60) {
  1088. return this.heartRateMap.get('正常');
  1089. } else {
  1090. return this.heartRateMap.get('偏低');
  1091. }
  1092. },
  1093. formateTemperatureData(option, data) {
  1094. let xdata = [];
  1095. let ydata = [];
  1096. let fill = [];
  1097. let max = 0;
  1098. data.forEach(item => {
  1099. if (item.value > max) {
  1100. max = item.value;
  1101. }
  1102. });
  1103. data.forEach(item => {
  1104. xdata.push(item.date);
  1105. fill.push({
  1106. value: max - item.value,
  1107. label: {
  1108. show: false
  1109. },
  1110. itemStyle: {
  1111. borderWidth: 3,
  1112. borderColor: this.calcColorByEvaluate(item.evaluate)
  1113. }
  1114. });
  1115. ydata.push({
  1116. value: item.value,
  1117. label: {
  1118. show: false
  1119. },
  1120. itemStyle: {
  1121. borderWidth: 3,
  1122. borderColor: this.calcColorByEvaluate(item.evaluate)
  1123. }
  1124. });
  1125. });
  1126. option.xAxis.data = xdata;
  1127. option.series[0].data = ydata;
  1128. option.series[1].data = fill;
  1129. // 规定最小值
  1130. option.yAxis.min = 35;
  1131. // 规定最大值
  1132. option.yAxis.max = max;
  1133. },
  1134. formateTemperatureColor(value) {
  1135. if (value > 38) {
  1136. return this.temperatureMap.get('发烧');
  1137. } else {
  1138. return this.temperatureMap.get('正常');
  1139. }
  1140. },
  1141. formateStepData(option, data) {
  1142. let xdata = [];
  1143. let ydata = [];
  1144. data.forEach(item => {
  1145. xdata.push(item.date);
  1146. ydata.push({
  1147. value: item.value,
  1148. label: {
  1149. show: true
  1150. },
  1151. itemStyle: {
  1152. borderWidth: 3,
  1153. borderColor: this.calcColorByEvaluate(item.evaluate)
  1154. }
  1155. });
  1156. });
  1157. option.xAxis.data = xdata;
  1158. option.series[0].data = ydata;
  1159. // 隐藏y轴
  1160. option.yAxis.show = false;
  1161. },
  1162. formateCalorieData(option, data) {
  1163. let xdata = [];
  1164. let ydata = [];
  1165. data.forEach(item => {
  1166. xdata.push(item.date);
  1167. ydata.push({
  1168. value: item.value,
  1169. label: {
  1170. show: true
  1171. },
  1172. itemStyle: {
  1173. borderWidth: 3,
  1174. borderColor: this.calcColorByEvaluate(item.evaluate)
  1175. }
  1176. });
  1177. });
  1178. option.xAxis.data = xdata;
  1179. option.series[0].data = ydata;
  1180. // 隐藏y轴
  1181. option.yAxis.show = false;
  1182. },
  1183. getOption(/* point = true */) {
  1184. let option = {
  1185. grid: {
  1186. show: true,
  1187. borderWidth: 0,
  1188. top: '10%',
  1189. left: '10%',
  1190. right: '10%',
  1191. bottom: '20%'
  1192. },
  1193. xAxis: {
  1194. type: 'category',
  1195. axisLine: {
  1196. show: false
  1197. },
  1198. axisTick: {
  1199. show: false
  1200. },
  1201. splitLine: {
  1202. show: false,
  1203. lineStyle: {
  1204. color: '#ddd',
  1205. width: 4
  1206. }
  1207. },
  1208. axisLabel: {
  1209. show: true,
  1210. fontSize: 12,
  1211. showMinLabel: true, //显示最小值
  1212. showMaxLabel: true, //显示最大值
  1213. marginBottom: 10 // 调整标签与轴线的距离
  1214. }
  1215. },
  1216. yAxis: {
  1217. type: 'value',
  1218. boundaryGap: ['5%', '5%'],
  1219. nameTextStyle: {
  1220. fontSize: 13
  1221. },
  1222. alignTicks: false,
  1223. axisTick: {
  1224. show: false
  1225. },
  1226. axisLabel: {
  1227. show: true,
  1228. fontSize: 13
  1229. },
  1230. splitLine: {
  1231. show: false,
  1232. lineStyle: {
  1233. color: '#ddd',
  1234. width: 1
  1235. }
  1236. }
  1237. },
  1238. dataZoom: [
  1239. {
  1240. start: 0,
  1241. end: 100,
  1242. textStyle: {
  1243. color: '#FFF',
  1244. fontSize: 14
  1245. },
  1246. show: true,
  1247. height: 20,
  1248. bottom: 8,
  1249. handleStyle: {
  1250. borderWidth: 4,
  1251. borderCap: 'square'
  1252. }
  1253. }
  1254. ],
  1255. tooltip: {
  1256. trigger: 'axis',
  1257. textStyle: {
  1258. fontSize: 16,
  1259. align: 'center'
  1260. },
  1261. formatter: function (params) {
  1262. return params[0].marker + params[0].name + '</br>' + params[0].value;
  1263. }
  1264. },
  1265. series: [
  1266. {
  1267. type: 'line',
  1268. padding: 10,
  1269. smooth: true,
  1270. symbol: 'circle',
  1271. symbolSize: 10,
  1272. itemStyle: {
  1273. color: '#fff',
  1274. borderWidth: 4
  1275. },
  1276. lineStyle: {
  1277. width: 6,
  1278. type: 'solid',
  1279. color: '#189b3b'
  1280. }
  1281. },
  1282. {
  1283. type: 'bar',
  1284. barMaxWidth: 15,
  1285. stack: 'value',
  1286. stackStrategy: 'all',
  1287. animation: false,
  1288. itemStyle: {
  1289. borderRadius: [12, 12, 0, 0],
  1290. show: false
  1291. }
  1292. }
  1293. ]
  1294. };
  1295. /* if (!point) {
  1296. option.series = [
  1297. {
  1298. type: 'bar',
  1299. barMaxWidth: 15,
  1300. label: {
  1301. show: true,
  1302. color: '#000',
  1303. position: 'outside'
  1304. },
  1305. itemStyle: {
  1306. borderRadius: 12
  1307. }
  1308. }
  1309. ];
  1310. } */
  1311. return option;
  1312. },
  1313. onEmotionClick(item, index) {
  1314. this.emotionActive = index;
  1315. this.emoName = item.name;
  1316. this.emoType = item.type;
  1317. if (this.active == 1) {
  1318. this.getMonthStaEnd(this.date);
  1319. this.getPsychologiclData('', this.monthDate.start, this.monthDate.end);
  1320. } else {
  1321. this.getPsychologiclData('', this.date.start, this.date.end);
  1322. }
  1323. // 情绪选项变化重新渲染图表
  1324. },
  1325. onSignClick(index) {
  1326. this.signActive = index;
  1327. // 体征选项变化重新渲染图表
  1328. },
  1329. onRouterTo(name) {
  1330. this.$router.push({
  1331. name: name === 'emo' ? 'report' : 'monthReport',
  1332. query: {
  1333. name: name
  1334. }
  1335. });
  1336. },
  1337. // 根据等级计算颜色
  1338. calcColorByEvaluate(value) {
  1339. let color = '';
  1340. const intValue = Number(value);
  1341. switch (intValue) {
  1342. case 1:
  1343. // 偏高
  1344. color = '#ff5f8b';
  1345. break;
  1346. case 2:
  1347. // 正常
  1348. color = '#189b3b';
  1349. break;
  1350. case 3:
  1351. // 偏低
  1352. color = '#2ea7e0';
  1353. break;
  1354. default:
  1355. color = '#189b3b';
  1356. break;
  1357. }
  1358. return color;
  1359. },
  1360. // 获取体征历史数据
  1361. getReportData(value, startDate, endDate) {
  1362. let reqDate = this.date;
  1363. let reqBody = {
  1364. personId: this.$store.getters.personId,
  1365. dateType: 1,
  1366. healthyType: value || this.signActive,
  1367. startTime: startDate || reqDate.start,
  1368. endTime: endDate || reqDate.end
  1369. };
  1370. return new Promise(resolve => {
  1371. APIHealthUser.getReportData(reqBody).then(res => {
  1372. if (res.data.data.day) {
  1373. res.data.data.day = res.data.data.day.map(item => {
  1374. item.date = this.$dayjs(item.date).format('MM-DD');
  1375. return item;
  1376. });
  1377. }
  1378. this.signData = { ...res.data.data };
  1379. if (this.signActive === 1) {
  1380. this.signDaysList = [
  1381. { day: res.data.data.normal, name: '正常', color: '#189b3b' },
  1382. { day: res.data.data.fever, name: '偏高', color: '#ff5f8b' }
  1383. /* { day: res.data.data.low, name: '偏低', color: '#2ea7e0' } */
  1384. ];
  1385. } else {
  1386. this.signDaysList = [
  1387. { day: res.data.data.normal, name: '正常', color: '#189b3b' },
  1388. { day: res.data.data.high, name: '偏高', color: '#ff5f8b' },
  1389. { day: res.data.data.low, name: '偏低', color: '#2ea7e0' }
  1390. ];
  1391. }
  1392. resolve(res.data.data);
  1393. });
  1394. });
  1395. }
  1396. }
  1397. };
  1398. </script>
  1399. <style scoped lang="scss">
  1400. @import './include.scss';
  1401. .insight {
  1402. padding-top: 20px;
  1403. .periodNav {
  1404. display: flex;
  1405. justify-content: space-around;
  1406. align-items: center;
  1407. .periodItem {
  1408. width: 48%;
  1409. font-size: 28px;
  1410. color: black;
  1411. text-align: center;
  1412. padding: 12px;
  1413. border-radius: 30px;
  1414. background: #e6e6e6;
  1415. &.active {
  1416. color: white;
  1417. background: #179b3b;
  1418. }
  1419. }
  1420. .minPeriodItem {
  1421. width: 32%;
  1422. padding: 8px;
  1423. }
  1424. }
  1425. .periodSwitch {
  1426. display: flex;
  1427. width: 100%;
  1428. justify-content: space-between;
  1429. align-items: center;
  1430. padding: 40px 10px;
  1431. padding-bottom: 10px;
  1432. .timearea {
  1433. font-size: 28px;
  1434. justify-self: center;
  1435. color: gray;
  1436. }
  1437. .arrow {
  1438. font-size: 45px;
  1439. }
  1440. }
  1441. .bmi {
  1442. display: flex;
  1443. justify-content: flex-start;
  1444. align-items: center;
  1445. white-space: nowrap;
  1446. padding: 40px 8px 0 8px;
  1447. font-weight: bold;
  1448. p {
  1449. padding: 0 5px;
  1450. font-size: 28px;
  1451. }
  1452. .van-button {
  1453. padding: 5px 10px;
  1454. margin-left: 50px;
  1455. font-size: 12px;
  1456. color: #fff;
  1457. border-radius: 30px;
  1458. background-color: $green;
  1459. }
  1460. }
  1461. .label {
  1462. font-size: 36px;
  1463. font-weight: bold;
  1464. padding: 30px 10px 30px 0;
  1465. display: flex;
  1466. justify-content: space-between;
  1467. align-items: center;
  1468. .right {
  1469. font-size: 30px;
  1470. }
  1471. }
  1472. .echart-container {
  1473. flex: 1;
  1474. position: relative;
  1475. min-height: 600px;
  1476. background-color: #fff;
  1477. padding: 0 20px;
  1478. }
  1479. .ChatBox {
  1480. overflow: hidden;
  1481. width: calc(100vw - 60px);
  1482. height: 650px;
  1483. border: 2px solid #cdf348;
  1484. border-radius: 70px;
  1485. margin-top: 30px;
  1486. h4 {
  1487. padding: 40px 0 10px 60px;
  1488. }
  1489. .legendBox {
  1490. width: 100%;
  1491. height: 100px;
  1492. display: flex;
  1493. justify-content: flex-end;
  1494. align-items: center;
  1495. padding: 0 30px;
  1496. .legend {
  1497. display: flex;
  1498. flex-wrap: wrap;
  1499. justify-content: flex-end;
  1500. align-items: center;
  1501. font-size: 20px;
  1502. .legendItem {
  1503. position: relative;
  1504. width: 205px;
  1505. margin-top: 10px;
  1506. margin-right: 20px;
  1507. &:nth-child(2n) {
  1508. margin-right: 0;
  1509. }
  1510. }
  1511. .not {
  1512. .number {
  1513. color: #179b3b;
  1514. }
  1515. &::before {
  1516. content: '';
  1517. position: absolute;
  1518. top: 0;
  1519. bottom: 0;
  1520. left: -20px;
  1521. width: 15px;
  1522. height: 15px;
  1523. background: #179b3b;
  1524. border-radius: 50%;
  1525. margin: auto;
  1526. }
  1527. }
  1528. .mild {
  1529. .number {
  1530. color: #2ea7e0;
  1531. }
  1532. &::before {
  1533. content: '';
  1534. position: absolute;
  1535. top: 0;
  1536. bottom: 0;
  1537. left: -20px;
  1538. width: 15px;
  1539. height: 15px;
  1540. background: #2ea7e0;
  1541. border-radius: 50%;
  1542. margin: auto;
  1543. }
  1544. }
  1545. .moderate {
  1546. .number {
  1547. color: #8dc21f;
  1548. }
  1549. &::before {
  1550. content: '';
  1551. position: absolute;
  1552. top: 0;
  1553. bottom: 0;
  1554. left: -20px;
  1555. width: 15px;
  1556. height: 15px;
  1557. background: #8dc21f;
  1558. border-radius: 50%;
  1559. margin: auto;
  1560. }
  1561. }
  1562. .severe {
  1563. .number {
  1564. color: #ff5f8b;
  1565. }
  1566. &::before {
  1567. content: '';
  1568. position: absolute;
  1569. top: 0;
  1570. bottom: 0;
  1571. left: -20px;
  1572. width: 15px;
  1573. height: 15px;
  1574. background: #ff5f8b;
  1575. border-radius: 50%;
  1576. margin: auto;
  1577. }
  1578. }
  1579. }
  1580. }
  1581. .minLegendBox {
  1582. .legend {
  1583. .legendItem {
  1584. width: auto;
  1585. margin-right: 50px;
  1586. &:nth-child(2n) {
  1587. margin-right: 50px;
  1588. }
  1589. &:last-child {
  1590. margin-right: 0;
  1591. }
  1592. }
  1593. }
  1594. }
  1595. .Chat {
  1596. width: calc(100vw - 60px);
  1597. height: 500px;
  1598. }
  1599. .result {
  1600. height: 140px;
  1601. padding: 0 30px;
  1602. border-radius: 70px;
  1603. display: flex;
  1604. justify-content: center;
  1605. align-items: flex-start;
  1606. flex-direction: column;
  1607. .wrapBox {
  1608. padding: 10px 180px 10px 60px;
  1609. width: 100%;
  1610. background-color: #e6e6e6;
  1611. border-radius: 70px;
  1612. }
  1613. .text {
  1614. display: flex;
  1615. justify-content: space-between;
  1616. align-items: center;
  1617. .right {
  1618. @include center();
  1619. img {
  1620. height: 30px;
  1621. width: 30px;
  1622. object-fit: contain;
  1623. margin: 0 5px;
  1624. }
  1625. }
  1626. }
  1627. }
  1628. }
  1629. .minChartBox {
  1630. height: 760px;
  1631. }
  1632. .hiddenChart {
  1633. width: 0;
  1634. height: 0;
  1635. }
  1636. .grid {
  1637. display: flex;
  1638. flex-wrap: wrap;
  1639. justify-content: space-between;
  1640. color: white;
  1641. font-size: 30px;
  1642. .gridItem {
  1643. width: calc((100vw - 60px) * 0.48);
  1644. height: calc((100vw - 60px) * 0.48);
  1645. border-radius: 60px;
  1646. display: flex;
  1647. flex-direction: column;
  1648. justify-content: center;
  1649. align-items: center;
  1650. margin-top: 30px;
  1651. .time {
  1652. .number {
  1653. font-size: 90px;
  1654. font-weight: bold;
  1655. }
  1656. }
  1657. }
  1658. .minItem {
  1659. width: calc((100vw - 60px) * 0.32);
  1660. height: calc((100vw - 60px) * 0.32);
  1661. font-size: 28px;
  1662. .time {
  1663. .number {
  1664. font-size: 70px;
  1665. font-weight: bold;
  1666. }
  1667. }
  1668. }
  1669. }
  1670. }
  1671. </style>