Browse Source

`2023年12月21日` FETURE

- 增加 情绪,情绪周报和体征详情页面
test
chenJinxu 11 months ago
parent
commit
f4a6cbf465
20 changed files with 4248 additions and 47 deletions
  1. +4
    -0
      README.md
  2. +6
    -0
      src/assets/css/mixin.scss
  3. BIN
      src/assets/today/icons/2_33.png
  4. BIN
      src/assets/today/icons/down.png
  5. BIN
      src/assets/today/icons/more.png
  6. BIN
      src/assets/today/icons/select_down.png
  7. BIN
      src/assets/today/icons/statistical_form.png
  8. BIN
      src/assets/today/icons/up.png
  9. BIN
      src/assets/today/icons/week_report.png
  10. BIN
      src/assets/today/images/no_data_01.png
  11. +37
    -0
      src/config/models.js
  12. +18
    -0
      src/router/router.config.js
  13. +24
    -1
      src/store/index.js
  14. +1470
    -0
      src/views/today/emotionDetails.vue
  15. +59
    -46
      src/views/today/index.vue
  16. +970
    -0
      src/views/today/report.vue
  17. +536
    -0
      src/views/today/scss/emotion-details.scss
  18. +321
    -0
      src/views/today/scss/report.scss
  19. +386
    -0
      src/views/today/scss/signs-details.scss
  20. +417
    -0
      src/views/today/signsDetails.vue

+ 4
- 0
README.md View File

@@ -52,3 +52,7 @@ npm run lint
- 增加 路由拦截
- 增加 登陆和绑定页面
- 修改 tabbar 图标

`2023年12月21日` FETURE

- 增加 情绪,情绪周报和体征详情页面

+ 6
- 0
src/assets/css/mixin.scss View File

@@ -7,6 +7,12 @@ $border_color: #d1d1d1;
$green: #189b3b;
$next_green: #8ccd9d;
$red: #ff8c8c;
$com_blue: #2ea7e0;
$com_red: #ff5f8b;
$com_light_green: #8dc21f;

// 灰色线条
$lineGray: #F5F5F5;

// 清除浮动
@mixin clearfix {


BIN
src/assets/today/icons/2_33.png View File

Before After
Width: 84  |  Height: 42  |  Size: 574B

BIN
src/assets/today/icons/down.png View File

Before After
Width: 15  |  Height: 23  |  Size: 440B

BIN
src/assets/today/icons/more.png View File

Before After
Width: 14  |  Height: 23  |  Size: 661B

BIN
src/assets/today/icons/select_down.png View File

Before After
Width: 15  |  Height: 9  |  Size: 406B

BIN
src/assets/today/icons/statistical_form.png View File

Before After
Width: 29  |  Height: 29  |  Size: 1.1KB

BIN
src/assets/today/icons/up.png View File

Before After
Width: 15  |  Height: 23  |  Size: 419B

BIN
src/assets/today/icons/week_report.png View File

Before After
Width: 38  |  Height: 38  |  Size: 2.6KB

BIN
src/assets/today/images/no_data_01.png View File

Before After
Width: 263  |  Height: 165  |  Size: 24KB

+ 37
- 0
src/config/models.js View File

@@ -92,3 +92,40 @@ export const ErrorAMapMsgModel = {
OVER_DIRECTION_RANGE: 'OVER_DIRECTION_RANGE', // 使用路径规划服务接口时可能出现该问题,路线计算失败,通常是由于道路起点和终点距离过长导致
NO_DATA: 'NO_DATA' // 此错误在服务接口status='complete'时的result.info值出现,故判断时需要注意(与以上的错误不一样,status!=='complete')
};
// 情绪模型
export const EmotionModel = {
// 抑郁
depression: {
name: '抑郁',
type: 2,
title1: '抑郁倾向',
article1: `<p>设备所检测的是个体的抑郁倾向。通过将个人的生理特征(脉搏波、心率变异性等)和行为习惯(运动、作息等)与临床诊断为抑郁症的患者的相应特征进行对比,判断出个体的抑郁倾向(即抑郁症的可能性)程度。抑郁倾向持续的时间越长、程度越严重,代表患有抑郁症的风险就越大。</p>`,
title2: '抑郁倾向算法原理',
article2: `<p>1.研究发现,抑郁症等情绪障碍可能会引起个体外周生理系统反应的钝化,因此患者可能在面临危险、压力等应激状态下表现出较低的生理反应唤醒水平。这一点能够通过皮肤电、心率变异性等生理特征的周期性变化来判断。</p>
<p>2.抑郁症等情绪障碍的患者会出现明显的失眠、运动少、和生物钟紊乱,算法能够有效分析判断出这些异常的行为特征。</p>`
},
// 压力
stress: {
name: '压力',
type: 1,
title1: '压力',
article1: `<p>心理压力是指个体面对实际上的或认识上的至关重要的环境要求时,产生的通过各种生理和心理反应表现出来的身心紧张状态,也被称为心理应激。在心理学中,压力或应激一般指紧张感和压力感。</p>`,
title2: '压力算法原理',
article2: `<p>压力的生理反应可以涉及全身各个系统和器官,大脑皮质通过自主神经系统传递关于血管压力的感觉信号,这部分感受器可以感知应激反应带来的血压波动,发挥感受压力的作用。设备通过脉搏波显性反馈压力血氧反应指数,从而更加科学的判断个体的压力水平。</p>`
},
// 疲劳
tiredness: {
name: '疲劳',
type: 3,
title1: '疲劳',
article1: `<p>疲劳分为两类「生理疲劳」和「心理疲劳」。两者有本质区别,前者是:心里想做但身体无力,后者是:身体有力但心里不想做。</p>
<p>生理疲劳:人体因生理状态而产生的困倦和技能失调的现象,指工作活动主要由身体肌肉承担产生的疲劳,又称肌肉疲劳、体力疲劳。</p>
<p>心理疲劳:长期、单调、高压力的工作引发的力竭性心理反应,又被称为心理耗竭。主要指肌肉工作强度不大,由于工作中信息加工要求较高和情绪压力较大,或由于工作过于单调而产生的疲劳。</p>`,
title2: '疲劳算法原理',
article2: `<p>设备的疲劳值是生理疲劳和心理疲劳的综合值,主要通过个体日常生活中的心率,心率变异性的变化及运动体力的变化情况来进行科学计算而来。</p>`
}
};

//心理健康相关接口地址
export const PsyBaseUrl =
process.env.NODE_ENV === 'production' ? 'https://dbmq.rzliot.com/auth_heart' : 'https://dbmq.rzliot.com/heart';

+ 18
- 0
src/router/router.config.js View File

@@ -259,6 +259,24 @@ export const constantRouterMap = [
name: 'bind',
component: () => import('@/views/login/bindDevices'),
meta: { title: '绑定设备', keepAlive: false }
},
{
path: '/emotionDetails',
name: 'emotionDetails',
component: () => import('@/views/today/emotionDetails'),
meta: { title: '情绪监测', keepAlive: false }
},
{
path: '/signsDetails',
name: 'signsDetails',
component: () => import('@/views/today/signsDetails'),
meta: { title: '体征监测', keepAlive: false }
},
{
path: '/report',
name: 'report',
component: () => import('@/views/today/report'),
meta: { title: '心理监测周报', keepAlive: false }
}
]
}


+ 24
- 1
src/store/index.js View File

@@ -48,13 +48,20 @@ export default new Vuex.Store({
watchRole: '',
iotCardTitle: '', //物联网卡商名字
fromRuoter: null,
deviceVersion: '' //设备版本号
deviceVersion: '', //设备版本号
ssjlToken: '', //b端接口token
tabClick: '' //心理监测点击tab
},
mutations: {
authToken(state, token) {
state.authToken = token;
window.localStorage[prefix + 'authToken'] = token;
},
ssjlToken(state, ssjlToken) {
state.ssjlToken = ssjlToken;
window.localStorage[prefix + 'ssjlToken'] = ssjlToken;
},

userId(state, userId) {
state.userId = userId;
window.localStorage[prefix + 'userId'] = userId;
@@ -167,6 +174,10 @@ export default new Vuex.Store({
deviceVersion(state, deviceVersion) {
state.deviceVersion = deviceVersion;
window.localStorage[prefix + 'deviceVersion'] = deviceVersion;
},
tabClick(state, tabClick) {
state.tabClick = tabClick;
window.localStorage[prefix + 'tabClick'] = tabClick;
}
},
getters: {
@@ -177,6 +188,14 @@ export default new Vuex.Store({
return window.localStorage[prefix + 'authToken'] == null ? '' : window.localStorage[prefix + 'authToken'];
}
},
ssjlToken: state => {
if (state.ssjlToken != '') {
return state.ssjlToken;
} else {
return window.localStorage[prefix + 'ssjlToken'] == null ? '' : window.localStorage[prefix + 'ssjlToken'];
}
},

userId: state => {
if (state.userId != '') return state.userId;
return window.localStorage[prefix + 'userId'] == null ? '' : window.localStorage[prefix + 'userId'];
@@ -298,6 +317,10 @@ export default new Vuex.Store({
deviceVersion: state => {
if (state.deviceVersion != '') return state.deviceVersion;
return window.localStorage[prefix + 'deviceVersion'] == null ? '' : window.localStorage[prefix + 'deviceVersion'];
},
tabClick: state => {
if (state.tabClick != '') return state.tabClick;
return window.localStorage[prefix + 'tabClick'] == null ? '' : window.localStorage[prefix + 'tabClick'];
}
},
actions: {},


+ 1470
- 0
src/views/today/emotionDetails.vue
File diff suppressed because it is too large
View File


+ 59
- 46
src/views/today/index.vue View File

@@ -4,7 +4,7 @@
<!-- 今日状态 -->
<div class="today-status">
<img class="img" src="@/assets/today/images/2_03.png" />
<img class="icon" src="@/assets/today/icons/2_12.png" @click="show = true"/>
<img class="icon" src="@/assets/today/icons/2_12.png" @click="show = true" />
<div class="status">
<p>状态优秀</p>
<ul>
@@ -15,12 +15,11 @@
</ul>
</div>
<div class="interpret">
<p>工作学习要有度,适当摸鱼也很好,不用太卷哟!保持张弛
有度的节奏,是应对压力的有效方法。
综合今日的HRV(MSSD)和静息心率情况看,你今天整体状
态优秀,身体压力状态较小,能很好应对今日工作生活中的
挑战,请继续保持优秀状态。
相信自己,你一定可以实现你的目标!</p>
<p>
工作学习要有度,适当摸鱼也很好,不用太卷哟!保持张弛 有度的节奏,是应对压力的有效方法。
综合今日的HRV(MSSD)和静息心率情况看,你今天整体状 态优秀,身体压力状态较小,能很好应对今日工作生活中的
挑战,请继续保持优秀状态。 相信自己,你一定可以实现你的目标!
</p>
<hr />
<div class="bottom">
<p>详细解读</p>
@@ -33,7 +32,7 @@
</div>
<!-- 今日情绪感知 -->
<div class="emotion">
<div class="title">
<div class="title" @click="onRouterTo('emotionDetails')">
<p>今日情绪感知</p>
<div>
<p>4.28</p>
@@ -63,7 +62,7 @@
</div>
<!-- 今体征感知 -->
<div class="perception">
<div class="title">
<div class="title" @click="onRouterTo('signsDetails')">
<p>今体征感知</p>
<div>
<p>4.28</p>
@@ -86,7 +85,10 @@
</ul>
<div class="tip">
<img class="img" src="@/assets/today/icons/2_25.png" />
<p><span>温馨提示:</span>检测数据仅供参考,<span>不可做医疗诊断和治疗依据</span>,在运动、工作等场景会影响健康检测。</p>
<p>
<span>温馨提示:</span
>检测数据仅供参考,<span>不可做医疗诊断和治疗依据</span>,在运动、工作等场景会影响健康检测。
</p>
</div>
</div>
<!-- 步数 -->
@@ -108,22 +110,22 @@
</ul>
<div class="annular">
<van-circle
v-model="currentRate1"
size="160px"
color="#179b3b"
layer-color="#F8F8F8"
:rate="90"
:speed="50"
:stroke-width="120"
v-model="currentRate1"
size="160px"
color="#179b3b"
layer-color="#F8F8F8"
:rate="90"
:speed="50"
:stroke-width="120"
/>
<van-circle
v-model="currentRate2"
size="129px"
color="#ff5f8b"
layer-color="#F8F8F8"
:rate="80"
:speed="50"
:stroke-width="140"
v-model="currentRate2"
size="129px"
color="#ff5f8b"
layer-color="#F8F8F8"
:rate="80"
:speed="50"
:stroke-width="140"
/>
<p>多走4567步</p>
</div>
@@ -174,19 +176,11 @@
<div class="main">
<ul>
<li>
<p>
健康同学 测量的
什么压力?
测量原理是什么?
</p>
<p>健康同学 测量的 什么压力? 测量原理是什么?</p>
<img src="@/assets/today/images/2_42.png" />
</li>
<li>
<p>
健康同学 测量的
什么压力?
测量原理是什么?
</p>
<p>健康同学 测量的 什么压力? 测量原理是什么?</p>
<img src="@/assets/today/images/2_48.png" />
</li>
</ul>
@@ -195,19 +189,14 @@
<!-- 底部导航 -->
<TabBar />
<!-- 日期选择 -->
<van-calendar
v-model="show"
:show-confirm="false"
@confirm="onConfirm"
:min-date="minDate"
:max-date="maxDate"
/>
<van-calendar v-model="show" :show-confirm="false" @confirm="onConfirm" :min-date="minDate" :max-date="maxDate" />
</div>
</template>

<script>
import TabBar from '@/components/TabBar';
import { Calendar, Circle, Checkbox, CheckboxGroup } from 'vant';
import APICore from '@/api/core';
export default {
components: {
TabBar,
@@ -224,10 +213,12 @@ export default {
maxDate: new Date(2023, 12, 18),
currentRate1: 0,
currentRate2: 0,
result: [],
result: []
};
},
created() {},
created() {
this.getAuth();
},
mounted() {},
methods: {
formatDate(date) {
@@ -235,12 +226,34 @@ export default {
},
onConfirm(date) {
this.show = false;
console.log(date)
console.log(this.formatDate(date))
console.log(date);
console.log(this.formatDate(date));
},
onRouterTo(name) {
if (name) {
this.$router.push({
name: name,
query: {
// 参数默认传疲劳,uid暂时写死,上线通过接口获取
name: 'tiredness',
uid: '2023101521270090082'
}
});
}
},
// 获取b端token
getAuth() {
let manufactorId = '5bf13062-a41e-4d00-ba14-1101aad12650';
APICore.getAuth({ manufactorId: manufactorId }).then(res => {
let data = res.data;
if (data.code === 0) {
this.$store.commit('ssjlToken', res.data.data);
}
});
}
}
};
</script>
<style scoped>
@import url("./scss/index.scss");
@import url('./scss/index.scss');
</style>

+ 970
- 0
src/views/today/report.vue View File

@@ -0,0 +1,970 @@
<template>
<!-- 周/月报 -->
<div class="report">
<van-nav-bar title="心理监测周报" :border="true" @click-left="onNavBack">
<template #left>
<van-icon name="arrow-left" size="24" style="padding: 0" v-show="params.isShowLeft" />
<span v-show="params.isShowLeft">返回</span>
</template>
</van-nav-bar>
<div class="main">
<!-- 总评 -->
<div class="overall-rating">
<div class="con">
<p class="space-between">
<span class="bold">本周总评</span>
<span class="time">{{ resetDate(weekResult.StartDate, weekResult.EndDate) || '--' }}</span>
</p>
<p class="bold-pro" :style="{ color: calcResultColor(weekResult.SummaryLevel) || '--' }">
{{ weekResult.Summary }}
</p>
<p class="normal">监测次数: {{ weekResult.Total || '--' }}次</p>
<p class="normal">{{ weekResult.Explain || '--' }}</p>
</div>
</div>
<div class="line"></div>
<div class="pie-chart-top">
<p class="bold">上周趋势对比</p>
<p>{{ resetDate(weekResult.StartDate, weekResult.EndDate) || '--' }}</p>
</div>
<div class="count">
<p>监测次数:{{ weekResult.LastTotal || '--' }}次</p>
</div>
<!-- 趋势对比-饼状图 -->
<div class="pie-chart-con">
<div class="pie-chart-left">
<div id="pieChart" ref="pieChart"></div>
</div>

<div class="pie-chart-right">
<div class="list">
<div class="item" v-for="(item, index) in pieRightList" :key="index">
<div class="item-left">
<div class="circle" :style="{ backgroundColor: item.color }"></div>
<span class="text">{{ item.text || '--' }}</span>
</div>

<div class="item-right">
<span :style="{ color: item.color }">{{ item.count ? item.count + '次' : '0次' }}</span>
<label :style="{ color: item.color }">{{
item.percentage ? '(' + item.percentage + '%' + ')' : '(0%)'
}}</label>
</div>

<div class="status">
<img :src="calcImg(item.percentage, item.lastPercentage)" alt="" />
<span :style="{ color: calcImg(item.percentage, item.lastPercentage, true) != 0 ? item.color : '' }">{{
calcImg(item.percentage, item.lastPercentage, true)
? Math.abs(calcImg(item.percentage, item.lastPercentage, true)) + '%'
: '持平'
}}</span>
</div>
</div>
</div>
</div>
</div>
<div class="statistics">
<div class="list">
<div class="item" v-for="(item, index) in statisticsList" :key="index">
<div class="top">
<span>{{ item.label || '--' }}</span>
</div>

<div class="middle">
<span :style="{ color: calcColor(item.value) }">{{ item.value || '--' }}</span>
</div>

<div class="bottom">
<span>{{ item.time || '--' }}</span>
</div>
</div>
</div>
</div>
<div class="line"></div>
<!-- 数据图-柱形图 -->
<div class="bar-chart">
<div class="echart" ref="charts"></div>
</div>
<div class="line"></div>
<!-- 建议 -->
<div class="advice">
<div class="content">
<p class="title">健康建议</p>
<p>{{ weekResult.Advice || '--' }}</p>
</div>
</div>
<!-- 概览 -->
<div class="overview">
<div class="content">
<div class="title">
<span class="title-text">{{ surveyTitle }}</span>
<div class="mood-list">
<div class="item" v-for="(item, index) in emotionList" :key="index">
<p>
<span :style="{ color: item.color }" class="day">{{ item.days }}</span>
<span class="day-text">天</span>
<img :src="calcWeekImg(item.days, item.lastDay)" alt="" />
<span class="day-text status">{{ calcWeekImg(item.days, item.lastDay, true) }}</span>
</p>
<p>{{ item.text }}</p>
</div>
</div>
<!-- <div class="mood-list-no-data" v-else>
<div class="no-data">
<img src="../../../../assets/img/no_data_01.png" alt />
<p>暂无数据</p>
</div>
</div>-->
</div>
</div>
</div>
</div>
<div class="main no-data">
<img src="../../assets/today/images/no_data_01.png" alt />
<p>暂无数据</p>
</div>
</div>
</template>

<script>
import { isNotNull } from '@/services/utils-service';
import axios from 'axios';
import APICore from '@/api/core';
export default {
name: '',
data() {
return {
pieRightList: [
/* {
text: "无情绪倾向",
count: 12,
percentage: "80",
color: "#179b3b"
},
{
text: "轻度情绪倾向",
count: 2,
percentage: "80",
color: "#8dc21f"
},
{
text: "中度情绪倾向",
count: 1,
percentage: "80",
color: "#2ea7e0"
},
{
text: "重度情绪倾向",
count: 1,
percentage: "80",
color: "#ff5f8b"
} */
],
statisticsList: [
/* { label: "最大值", value: "75", time: "08:15" },
{ label: "最小值", value: "40", time: "10:15" },
{ label: "最近值", value: "50", time: "18:15" } */
],
emotionList: [],
surveyTitle: '本周概览',
echarts: null,
// 路由传过来的情绪参数
emoName: '',
pieData: [],
xAxisData: [],
pieEcharts: null,
monitoringCount: '',
// 7天和30天最大数据列表
weekAndMonData: [],
defaultSeries: null,
defaultLegend: [
{
name: `轻度${this.emoName}倾向`,
icon: 'rect',
itemStyle: {
color: '#8dc21f'
},
textStyle: {
fontSize: 12
}
},
{
name: `中度${this.emoName}倾向`,
itemStyle: {
color: '#2ea7e0'
},
icon: 'rect',
textStyle: {
fontSize: 12
}
},
{
name: `重度${this.emoName}倾向`,
itemStyle: {
color: '#ff5f8b'
},
icon: 'rect',
textStyle: {
fontSize: 12
}
},
{
name: `无${this.emoName}倾向`,
icon: 'rect',
itemStyle: {
color: '#179b3b'
},
textStyle: {
// 项目遗留问题,新项目不需重新转换文字大小
fontSize: 12
}
}
],
params: {},
weekResult: {},
upImg: require('@/assets/today/icons/up.png'),
downImg: require('@/assets/today/icons/down.png')
};
},
created() {
this.initEchartText();
},
mounted() {
this.loadParams();
this.initEchart();
},
watch: {
// 监听数据发生变化 初始化各项图表
emotionData: {
handler() {
this.initEchart();
},
deep: true
},
xAxisData: {
handler() {
this.initEchart();
},
deep: true
},
pieData: {
handler() {
this.initPieEchart();
},
deep: true
}
},
computed: {
// 折线图标题
echartsTitle() {
return `${this.emoName}数据图`;
},
defaultOptions() {
return {
time: {
useUTC: false
},
title: {
text: this.echartsTitle,
left: 1,
right: 25,
bottom: 20,
top: '3%',
textStyle: {
fontSize: 18,
fontWeight: 'bold'
}
},
legend: {
width: '65%',
orient: 'horizontal',
right: 'right',
top: '3%',
bottom: '1%',
itemHeight: 12,
itemWidth: 12,
itemGap: 10,
align: 'left',
selectedMode: false,
data: [
{
name: `轻度${this.emoName}倾向`,
icon: 'rect',
itemStyle: {
color: '#8dc21f'
},
textStyle: {
fontSize: 12
}
},
{
name: `中度${this.emoName}倾向`,
itemStyle: {
color: '#2ea7e0'
},
icon: 'rect',
textStyle: {
fontSize: 12
}
},
{
name: `重度${this.emoName}倾向`,
itemStyle: {
color: '#ff5f8b'
},
icon: 'rect',
textStyle: {
fontSize: 12
}
},
{
name: `无${this.emoName}倾向`,
icon: 'rect',
itemStyle: {
color: '#179b3b'
},
textStyle: {
fontSize: 12
}
}
],
formatter: function (name) {
// 自定义显示内容
if (name.length > 6) {
return name.substring(0, 6) + '\n' + name.substring(6);
} else {
return name;
}
}
},
grid: {
show: true,
borderWidth: 1,
top: '20%',
left: '1%',
right: '5%',
bottom: '15%',
containLabel: true
},
xAxis: {
type: 'category',
axisLine: {
show: false
},
textStyle: {
fontSize: 10
},
axisTick: {
show: false
},
splitLine: {
show: false,
lineStyle: {
color: '#ddd',
width: 2
}
},
nameLocation: 'center',
axisLabel: {
show: true,
fontSize: 12,
showMinLabel: true, //显示最小值
showMaxLabel: true //显示最大值
},
data: this.xAxisData
},
dataZoom: [
{
type: 'inside',
start: 0,
end: 100
},
{
start: 0,
end: 100,
textStyle: {
color: '#FFF',
fontSize: 14
},
show: true,
height: 25,
bottom: '3%',
handleStyle: {
borderWidth: 1,
borderCap: 'square'
}
}
],
tooltip: {
trigger: 'axis',
textStyle: {
fontSize: 14,
align: 'center'
},
formatter: function (params) {
return params[0].marker + params[0].name + '--' + params[0].value + '</br>';
}
},
yAxis: {
type: 'value',
max: 100,
min: 0,
interval: 20,
splitNumber: 1,
boundaryGap: ['5%', '5%'],
nameTextStyle: {
fontSize: 13
},
alignTicks: true,
axisTick: {
show: true
},
axisLabel: {
show: true,
fontSize: 13
},
splitLine: {
show: true,
lineStyle: {
color: '#ddd',
width: 1
}
}
},
series: [
{
name: `无${this.emoName}倾向`,
type: 'line',
padding: 5,
data: this.emotionData,
symbol: 'circle',
symbolSize: 8
},
{
name: `轻度${this.emoName}倾向`,
type: 'line',
data: ''
},
{
name: `中度${this.emoName}倾向`,
type: 'line',
data: ''
},
{
name: `重度${this.emoName}倾向`,
type: 'line',
data: ''
}
]
};
},
// 饼状图配置
pieOption() {
return {
tooltip: {
trigger: 'item',
textStyle: {
fontSize: 14
},
position: 'right'
},
legend: {
top: '5%',
left: 'center',
show: false
},
series: [
{
type: 'pie',
radius: ['40%', '80%'],
avoidLabelOverlap: false,
startAngle: 270, // 设置逆时针渲染
itemStyle: {
borderRadius: 5,
borderColor: '#fff',
borderWidth: 2,
fontSize: 16
},
label: {
show: false,
position: 'center',
fontSize: 16
},
emphasis: {
label: {
show: false,
fontSize: 16,
fontWeight: 'bold'
}
},
labelLine: {
show: false
},
data: this.pieData
}
]
};
}
},
methods: {
calcWeekImg(cur, last, callBackText) {
let imgurl = '';
let text = '';
if (isNotNull(cur) && isNotNull(last) && this.weekAndMonData.length > 0) {
let curNumber = Number(cur);
let latNumber = Number(last);
if (curNumber - latNumber == 0) {
text = '持平';
} else {
imgurl = curNumber < latNumber ? this.downImg : this.upImg;
text = Math.abs(curNumber - latNumber) + '天';
}
if (callBackText) {
return text;
} else {
return imgurl;
}
}
},
// 计算显示是上升or下降的图片
/**
*
* @param { 本周情绪比例} current
* @param { 上周情绪比例 } last
* @param { 是否返回对比比例 } isCallBackCompare
*/
calcImg(current, last, isCallBackCompare) {
let imgUrl = '';
let compare = '';
if (isNotNull(current) && isNotNull(last)) {
compare = Number(current) - Number(last);
imgUrl = compare > 0 ? this.upImg : compare == 0 ? '' : this.downImg;
}
if (isCallBackCompare) {
return compare;
} else {
return imgUrl;
}
},
async loadParams() {
let params = this.$route.query;
if (params) {
this.params = params;
if (!params.accessToken) {
let authToken = await this.getAuth();
this.$store.commit('ssjlToken', authToken);
} else {
this.$store.commit('ssjlToken', params.accessToken);
}
this.getWeekResultDetail();
}
},
// 获取b端token
getAuth() {
let manufactorId = '5bf13062-a41e-4d00-ba14-1101aad12650';
return new Promise((resolve, reject) => {
APICore.getAuth({ manufactorId: manufactorId }).then(res => {
let data = res.data;
if (data.code === 0) {
resolve(res.data.data);
} else {
this.$toast.fail(`${data.message}`);
reject('');
}
});
});
},
initEchartText() {
this.defaultSeries = [
{
name: ``,
type: 'line',
padding: 5,
data: this.emotionData,
symbol: 'circle',
symbolSize: 8, // 拐点圆的大小
areaStyle: {}
},
{
name: `轻度${this.emoName}倾向`,
type: 'line',
padding: 10,
data: '',
symbol: 'circle',
symbolSize: 8 // 拐点圆的大小
},
{
name: `中度${this.emoName}倾向`,
type: 'line',
data: ''
},
{
name: `重度${this.emoName}倾向`,
type: 'line',
data: ''
}
];
},
calcTitle(type) {
let title = '';
switch (type) {
case 1:
title = '压力';
break;
case 2:
title = '抑郁';
break;
case 3:
title = '疲劳';
break;
default:
break;
}
return title;
},
getWeekResultDetail() {
this.$toast.loading('数据加载中');
let baseUrl =
process.env.NODE_ENV === 'production' ? 'https://dbmq.rzliot.com/auth_heart' : 'https://dbmq.rzliot.com/heart';
let reqUrl = `${baseUrl}/api/Data/GetWeekResultDetail`;
let reqParams = {
recordId: this.params.recordId
};
axios
.get(reqUrl, {
params: { ...reqParams }
/* headers: { 'AccessToken': this.$store.getters.ssjlToken } */
})
.then(res => {
const data = res.data.response;
let chartData = data.ChartData
? JSON.parse(data.ChartData).filter(item => {
return item.Key;
})
: [];
if (data) {
this.monitoringCount = data.Total;
this.pieRightList = [];
this.statisticsList = [];
this.emotionList = [];
this.weekResult = data;
this.emoName = this.calcTitle(data.Type);
}
let None = {
count: data.None,
percentage: this.calcPercentage(data.None, data.Total),
text: `无${this.emoName}倾向`,
color: '#179b3b',
scale: data.NoneRatio,
lastPercentage: this.calcPercentage(data.LastNone, data.LastTotal)
};
let Mild = {
count: data.Mild,
percentage: this.calcPercentage(data.Mild, data.Total),
text: `轻度${this.emoName}倾向`,
color: '#8dc21f',
scale: data.MildRatio,
lastPercentage: this.calcPercentage(data.LastMild, data.LastTotal)
};
let Moderate = {
count: data.Moderate,
percentage: this.calcPercentage(data.Moderate, data.Total),
text: `中度${this.emoName}倾向`,
color: '#2ea7e0',
scale: data.ModerateRatio,
lastPercentage: this.calcPercentage(data.LastModerate, data.LastTotal)
};
let Severe = {
count: data.Severe,
percentage: this.calcPercentage(data.Severe, data.Total),
text: `重度${this.emoName}倾向`,
color: '#ff5f8b',
scale: data.SevereRatio,
lastPercentage: this.calcPercentage(data.LastSevere, data.LastTotal)
};
// 饼状图右边数据
this.pieRightList.push(None);
this.pieRightList.push(Mild);
this.pieRightList.push(Moderate);
this.pieRightList.push(Severe);
this.pieData = this.pieRightList.map(item => {
item.value = item.count;
item.itemStyle = {
color: item.color
};
return item;
});
let Max = {
label: '最大值',
value: data.Max,
time: data.MaxDesc
? this.currentDays === 0
? this.$dayjs(data.MaxDesc).format('HH:mm')
: this.$dayjs(data.MaxDesc).format('MM/DD HH:mm')
: ''
};
let Min = {
label: '最小值',
value: data.Min,
time: data.MinDesc
? this.currentDays === 0
? this.$dayjs(data.MinDesc).format('HH:mm')
: this.$dayjs(data.MinDesc).format('MM/DD HH:mm')
: ''
};
let Avg = {
label: '平均值',
value: data.Avg,
time: data.AvgDesc
? this.currentDays === 0
? this.$dayjs(data.AvgDesc).format('HH:mm')
: this.$dayjs(data.AvgDesc).format('MM/DD HH:mm')
: ''
};
this.statisticsList.push(Max);
this.statisticsList.push(Min);
this.statisticsList.push(Avg);
let NoneDay = {
days: data.NoneDay,
text: `无${this.emoName}倾向`,
color: '#179b3b',
lastDay: data.LastNoneDay,
scale: data.NoneDayRatio
};
let MildDay = {
days: data.MildDay,
text: `轻度${this.emoName}倾向`,
color: '#8dc21f',
lastDay: data.LastMildDay,
scale: data.MildDayRatio
};
let ModerateDay = {
days: data.ModerateDay,
text: `中度${this.emoName}倾向`,
color: '#2ea7e0',
lastDay: data.LastModerateDay,
scale: data.ModerateDayRatio
};
let SevereDay = {
days: data.SevereDay,
text: `重度${this.emoName}倾向`,
color: '#ff5f8b',
lastDay: data.LastSevereDay,
scale: data.SevereDayRatio
};
this.emotionList.push(NoneDay);
this.emotionList.push(MildDay);
this.emotionList.push(ModerateDay);
this.emotionList.push(SevereDay);
// 图表数据
this.emotionData = chartData.map(item => {
return {
value: item.Value,
itemStyle: {
color: this.calcResultColor(item.Level)
}
};
});
this.weekAndMonData = chartData.map((item, index) => {
return {
value: [index, item.MinValue, item.MaxValue]
};
});
this.xAxisData = chartData.map(item => {
return item.Key ? this.$dayjs(item.Key.replace(/-/g, '/')).format('MM/DD') : item.key;
});
let that = this;
// 7天和30天变成柱状图
this.weekAndMonthSeries = [
{
name: '平均值',
type: 'scatter',
symbolSize: 8,
data: this.emotionData
},
{
name: '',
type: 'custom',
data: this.weekAndMonData,
renderItem: function (params, api) {
var categoryIndex = api.value(0);
var end = api.coord([categoryIndex, api.value(1)]);
var start = api.coord([categoryIndex, api.value(2)]);
var width = 8;
var rectShape = that.$echarts.graphic.clipRectByRect(
{
x: start[0] - width / 2,
y: start[1],
width: 8,
height: end[1] - start[1]
},
{
x: params.coordSys.x,
y: params.coordSys.y,
width: params.coordSys.width,
height: params.coordSys.height
}
);
if (rectShape) {
rectShape.r = [10];
}
return (
rectShape && {
type: 'rect',
shape: rectShape,
style: api.style()
}
);
},
itemStyle: {
opacity: 0.8
},
encode: {
y: [1, 2],
x: 0
}
},
{
name: `轻度${this.emoName}倾向`,
type: 'scatter',
symbolSize: 8,
data: ''
},
{
name: `中度${this.emoName}倾向`,
type: 'scatter',
symbolSize: 8,
data: ''
},
{
name: `重度${this.emoName}倾向`,
type: 'scatter',
symbolSize: 8,
data: ''
},
{
name: `无${this.emoName}倾向`,
type: 'scatter',
symbolSize: 8,
data: ''
}
];
// 点击提示此时为空
this.defaultOptions.tooltip = {
trigger: 'axis',
formatter: function (params) {
if (params) {
return (
params[0].marker +
'平均值:' +
params[0].name +
'--' +
params[0].value +
'</br>' +
params[1].marker +
'最大值:' +
params[1].name +
'--' +
params[1].value[2] +
'</br>' +
params[1].marker +
'最小值:' +
params[1].name +
'--' +
params[1].value[1]
);
}
}
};
this.defaultOptions.series = this.weekAndMonthSeries;
this.$toast.success('数据加载完成');
});
},
initEchart() {
if (this.echarts != null && this.echarts != '' && this.echarts != undefined) {
this.echarts.dispose();
}
this.echarts = this.$echarts.init(this.$refs.charts);
this.echarts.setOption(this.defaultOptions);
},
// 初始化饼状图
initPieEchart() {
if (this.pieEcharts != null && this.pieEcharts != '' && this.pieEcharts != undefined) {
this.pieEcharts.dispose();
}
this.pieEcharts = this.$echarts.init(this.$refs.pieChart);
this.pieEcharts.setOption(this.pieOption);
},
onNavBack() {
this.$router.push({
name: 'emotionDetails',
query: {
uid: this.params.uid,
name: this.params.name
}
});
},
// 计算字体显示的颜色
calcColor(value) {
let color = '';
if (value <= 40) {
color = '#179b3b';
} else if (value > 40 && value <= 65) {
color = '#8dc21f';
} else if (value > 65 && value <= 80) {
color = '#2ea7e0';
} else if (value > 80) {
color = '#ff5f8b';
} else {
color = '';
}
return color;
},
// 计算百分比
calcPercentage(value, total) {
if (typeof value !== 'number' || typeof total !== 'number' || total === 0) {
return 0;
}
let milValue = value * 1000;
let milTotal = total * 1000;
return Math.round((milValue / milTotal) * 100);
},
// 计算结果采用哪种颜色
calcResultColor(value, isCallBackClass) {
let color = '';
let className = '';
switch (value) {
case ('0', 0):
color = '#179b3b';
className = 'none';
break;
case ('1', 1):
color = '#8dc21f';
className = 'mild';
break;
case ('2', 2):
color = '#2ea7e0';
className = 'moderate';
break;
case ('3', 3):
color = '#ff5f8b';
className = 'severe';
break;
}
return isCallBackClass ? className : color;
},
// 重新拼接日期
resetDate(startDate, endDate) {
let callBackDate = '';
if (startDate && endDate) {
callBackDate = startDate.replace(/-/g, '.') + '-' + endDate.slice(5, endDate.length).replace(/-/g, '.');
}
return callBackDate;
}
}
};
</script>

<style scoped lang="scss">
@import './scss/report.scss';
</style>

+ 536
- 0
src/views/today/scss/emotion-details.scss View File

@@ -0,0 +1,536 @@
.psychological-container{
min-height: 100vh;
width: 100%;
overflow: hidden;
background-color: #fff;
.tab-bar{
padding: 20px;
position: relative;
.date-tab-con {
height: 50px;
display: flex;
justify-content: flex-start;
align-items: center;
background: #EEEEEE;
border-top-left-radius: 40px;
border-top-right-radius: 40px;
border-bottom-left-radius: 40px;
border-bottom-right-radius: 40px;
.date-tab-list {
display: flex;
justify-content: space-around;
align-items: center;
color: #fff;
flex: 1;
height: 50px;
.date-tab-item {
position: relative;
padding: 0 20px;
height: 100%;
width: 100%;
border-radius: 40px;
color: #6D6D6D;
font-size: 28px;
font-weight: bold;
@include center();
img {
height: 50px;
width: 50px;
padding: 0 16px;
}
.more {
width: 20px;
height: 12px;
}
/* &.active::after {
content: '';
width: 88px;
position: absolute;
right: 25%;
bottom: -20px;
box-sizing: border-box;
border-bottom: 8px solid $green;
} */
&.active {
color: #333;
background-color: $green;
}
&.notClick {
background-color: $border_color;
color: #fff;
border: 1px solid #fff;
}
}
.date-tab-item:nth-child(3) {
border-right: 1px solid #E0E0E0;
}
/* .date-tab-item:first-child {
border-top-left-radius: 15px;
border-bottom-left-radius: 15px;
}
.date-tab-item:last-child {
border-top-right-radius: 15px;
border-bottom-right-radius: 15px;
} */
}
}
}
.psy-tab-bar {
height: 50px;
position: relative;
margin: 20px 0 40px 0;
padding: 0 20px;
.psy-tab-con {
background-color: #EEEEEE;
border-top-left-radius: 40px;
border-top-right-radius: 40px;
border-bottom-left-radius: 40px;
border-bottom-right-radius: 40px;
.psy-tab-list {
display: flex;
justify-content: space-around;
align-items: center;
color: #fff;
height: 50px;
width: 100%;
/* background-color: red; */
.psy-tab-item {
position: relative;
padding: 0 20px;
color: #6D6D6D;
height: 100%;
width: 100%;
font-size: 28px;
border-radius: 40px;
font-weight: bold;
@include center();
&.active {
color: #333;
background-color: $green;
}
}
}
}
}
.main {
position: relative;
height: calc(100vh - 200px);
overflow: scroll;
.top {
flex: 1;
.title {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0px 32px 20px 26px;
font-size: 36px;
.title-left {
font-weight: bold;
.van-icon {
margin-left: 5px;
font-size: 18px;
}
}
}
.monitoring-count {
text-align: left;
padding: 6px 28px;
line-height: 40px;
p {
font-size: 24px;
color: #8B8B8B;
}
}
.pie-chart-con {
flex: 1;
padding: 10px 0 20px 0;
display: flex;
justify-content: space-between;
align-items: flex-start;
.pie-chart-left {
position: relative;
height: 300px;
padding-left: 30px;
width: 35%;
@include center();
#pieChart {
height: 212px;
width: 212px;
}
}
.pie-chart-right {
height: 300px;
width: 65%;
padding-right: 40px;
@include center();
.list {
flex-direction: column;
.item {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 24px;
padding: 18px 0;
.item-left {
display: flex;
justify-content: flex-start;
align-items: center;
padding-right: 20px;
.circle {
height: 24px;
width: 24px;
margin: 0 8px;
}
span {
font-size: 24px;
}
.text {
color: #000;
font-size: 24px;
}
}
.item-right {
display: flex;
justify-content: center;
align-items: center;
}
}
}
}
}
.statistics {
position: relative;
padding: 0px 20px 10px 20px;
.list {
flex: 1;
width: 100%;
display: flex;
justify-content: space-around;
align-items: center;
font-size: 32px;
.item {
@include center();
width: 126px;
padding: 20px;
/* height: px2rem(136); */
flex-direction: column;
/* border: 1px solid $border_color;
border-radius: 30px; */
.top {
font-size: 24px;
}
.middle {
font-size: 48px;
font-weight: bold;
padding: 10px;
}
.bottom {
font-size: 18px
}
}
}
}
}
.line {
position: relative;
height: 22px;
background-color: $lineGray;
}
.bottom {
flex: 1;
.echart-container {
height: 500px;
background-color:#fff;
padding: 0 10px;
.echart {
height: 500px;
padding: 0 10px;
}
}
.line-gray {
height: 22px;
width: 100%;
background-color: $lineGray;
margin-top: 20px;
}
.result {
.result-con {
height: 100%;
background-color: #fff;
border-radius: 20px;
&.reminder {
padding: 0 32px 40px 32px;
}
.title {
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-direction: column;
margin-bottom: 20px;
span {
font-size: 36px;
font-weight: bold;
}
.font-28 {
font-weight: 400;
font-size: 26px;
color: #8B8B8B;
text-align: left;
}
.title-no-data {
padding: 68px 0 26px 30px;
}
p {
font-size: 24px;
color: $green;
}
.title-emo {
font-size: 48px;
padding: 28px 0 42px 0;
text-align: left;
}
.no-data {
height: 500px;
width: 100%;
@include center();
flex-direction: column;
img {
height: 220px;
width: 350px;
}
p {
color: #999;
font-size: 24px;
padding: 40px 0 130px 0;
}
}
}
.title-text {
padding: 68px 0 26px 30px;
}
.title-reminder {
padding: 68px 0 0 0;
}
.friendly-reminder, .warm-reminder {
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-direction: column;
margin-bottom: 20px;
background-color: #F2F2F2;
padding: 40px 38px 38px 28px;
p {
font-weight: bold;
text-align: left;
padding-bottom: 22px;
font-size: 30px;
}
span {
text-align: left;
font-size: 24px;
}
}
.mood-list {
display: grid;
grid-template-columns: repeat(2, 1fr); //定义了一个 2x2 的网格布
grid-template-rows: repeat(2, 1fr);
gap: 42px;
//width: 100%;
padding: 0 88px 40px 74px;
.item {
width: 274px;
height: 188px;
/* padding: px2rem(47) px2rem(57) px2rem(49) px2rem(57); */
background-color: #F2F6FF;
@include center();
flex-direction: column;
p {
font-size: 24px;
padding: 0;
color: #666666;
.day {
padding: 10px;
font-size: 56px;
}
.day-text {
font-size: 24px
}
}
}
}
.mood-list-no-data {
height: 500px;
width: 100%;
.no-data {
@include center();
flex-direction: column;
img {
height: 220px;
width: 350px;
}
p {
color: #999;
font-size: 24px;
padding: 40px 0 130px 0;
}
}
}
}
}
}
&.report {
position: relative;
height: calc(100vh - 300px);
overflow: scroll;
background-color: #f5f5f5;
.content {
position: relative;
.list {
position: relative;

.item {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 68px 30px;
background-color: #fff;
margin-bottom: 22px;
.left {
display: flex;
justify-content: flex-start;
align-items: flex-start;
img {
height: 50px;
width: 50px;
}
.middle {
.title,
.overall,
.trend {
display: flex;
justify-content: flex-start;
align-items: center;
padding-left: 26px;
span,
p {
font-size: 36px;
font-family: Source Han Sans CN;
font-weight: 400;
color: #8d8d8d;
line-height: 60px;
}
}
.title {
span {
padding-right: 40px;
}
p {
color: #282828;
}
}
.overall {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
.left {
p {
padding-left: 40px;
font-weight: bold;
}
}
.right {
img {
height: 30px;
width: 18px;
}
}
}
.trend {
align-items: flex-start;
text-align: left;
}
}
}
.right {
img {
width: 18px;
height: 30px;
}
}
}
&.no-data {
height: calc(100vh - 200px);
width: 100%;
@include center();
flex-direction: column;
img {
height: 220px;
width: 350px;
}
p {
color: #999;
font-size: 32px;
padding: 40px 0 130px 0;
}
}
}
}
}
}

.title {
font-size: 32px;
}
.van-popup {
flex: 1;
max-height: 600px;
width: 100%;
background-color: $background;
}
.popup {
/* height: 100%;
width: 100%; */
background-color: $background;
padding: 40px;
.item {
flex: 1;
padding: 20px;
margin: 30px 0;
text-align: left;
font-size: 28px;
background-color: #fff;
border-radius: 20px;
p {
margin: 10px 0;
}
h5 {
margin: 10px 0;
font-size: 32px;
}
&.first {
padding-top: 0;
}
&.science-tips {
.tips {
width: 120px;
height: 40px;
color: #fff;
@include center();
background-color: red;
border-top-left-radius: 40px;
border-top-right-radius: 30px;
border-bottom-right-radius: 30px;
}
}
}
.van-button {
height: 40px;
background-color: $green;
color: #fff;
border-radius: 20px;
}
}
}

+ 321
- 0
src/views/today/scss/report.scss View File

@@ -0,0 +1,321 @@
.report {
height: 100vh;
width: 100%;
overflow: hidden;
background-color: #F5F5F5;
font-family: Source Han Sans CN;

.main {
height: calc(100vh - 90px);
overflow: scroll;
background-color: #fff;

.line {
height: 22px;
background-color: $lineGray;
}

.overall-rating {
padding: 46px 30px;
margin-bottom: 18px;

.con {
padding: 34px 36px;
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-direction: column;
font-size: 28px;
background: #FFFFFF;
border: 1px solid #535353;
box-shadow: 2px 10px 0px 0px $green;
border-radius: 10px;

p {
font-size: 36px;
font-family: Source Han Sans CN;
color: #666666;

.bold {
color: #282828;
font-weight: bold;
}
}

.space-between {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;

.time {
font-size: 24px;
}
}

.normal {
font-size: 26px;
line-height: 42px;
text-align: left;
color: #666666;
}

.bold-pro {
color: #282828;
font-size: 48px;
font-weight: bold;
padding: 24px 0;
}
}
}

.pie-chart-top {
display: flex;
justify-content: space-between;
align-items: flex-start;
padding: 46px 30px 32px 30px;

p {
font-size: 24px;
font-family: Source Han Sans CN;
line-height: 42px;
}

.bold {
font-size: 36px;
font-weight: bold;
color: #282828;
line-height: 36px;
}
}

.count {
padding: 0 30px 10px 30px;
text-align: left;

p {
font-size: 24px;
font-family: Source Han Sans CN;
font-weight: 400;
color: #8B8B8B;
line-height: 36px;
}
}

.pie-chart-con {
flex: 1;
padding: 10px 0 20px 0;
display: flex;
justify-content: space-between;
align-items: flex-start;
background-color: #fff;

.pie-chart-left {
position: relative;
height: 300px;
padding-left: 30px;
width: 35%;
@include center();

#pieChart {
height: 212px;
width: 212px;
}
}

.pie-chart-right {
height: 300px;
width: 65%;
@include center();

.list {
display: flex;
justify-content: center;
flex-direction: column;
.item {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 24px;
padding: 18px 0;
.item-left {
display: flex;
justify-content: flex-start;
align-items: center;
padding-right: 20px;

.circle {
height: 24px;
width: 24px;
margin: 0 8px;
}

span {
font-size: 24px;
}

.text {
color: #000;
font-size: 24px;
}
}

.item-right {
@include center();
span {
font-size: 24px;
}
}
.status {
padding: 0 10px;
@include center();
img {
height: 30px;
width: 18px;
padding: 0 6px ;
}
}
}
}
}
}

.statistics {
position: relative;
padding: 10px 28px 10px 28px;
.list {
flex: 1;
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 32px;

.item {
@include center();
width: 136px;
padding: 10px;
/* height: px2rem(136); */
flex-direction: column;
border: 1px solid $border_color;
border-radius: 30px;
.top {
font-size: 24px;
}

.middle {
font-size: 48px;
font-weight: bold;
padding: 10px;
}

.bottom {
font-size: 18px
}
}
}
}

.bar-chart {
height: 700px;
background-color: #fff;
padding: 0 10px;

.echart {
height: 700px;
padding: 0 10px;
}
}

.advice {
padding: 52px 30px 60px 30px;

.content {
background: #F2F6FF;
border-radius: 20px;
padding: 40px 30px;
text-align: left;

p {
font-size: 30px;
font-weight: 400;
color: #707070;
line-height: 46px;
}

.title {
font-size: 36px;
font-weight: bold;
color: $green;
line-height: 36px;
padding-bottom: 26px;
}
}
}

.overview {
padding: 0 30px 32px 30px;

.content {
.title {
text-align: left;

.title-text {
font-size: 36px;
font-weight: bold;
color: #282828;
line-height: 36px;
}

.mood-list {
display: grid;
grid-template-columns: repeat(2, 1fr); //定义了一个 2x2 的网格布
grid-template-rows: repeat(2, 1fr);
gap: 42px;
padding: 42px 42px 44px 40px;

.item {
width: 214px;
height: 198px;
background-color: #F2F6FF;
display: flex;
justify-content: center;
align-items: flex-start;
flex-direction: column;
padding-left: 60px;

p {
font-size: 28px;
padding: 0;
color: #666666;
@include center();
/* align-items: flex-end; */
.day {
/* padding: 5px; */
font-size: 56px;
}

.day-text {
font-size: 24px;
padding: 0 10px;
}
img {
height: 30px;
width: 18px;
}
}
}
}
}
}
}
&.no-data {
@include center();
flex-direction: column;
p {
font-size: 32px;
}
}
}
}

+ 386
- 0
src/views/today/scss/signs-details.scss View File

@@ -0,0 +1,386 @@
.signs {
min-height: 100vh;
width: 100%;
overflow: hidden;
background-color: #fff;
.main {
position: relative;
height: calc(100vh - 100px);
overflow: scroll;
.date {
padding: 20px 40px;
color: #8B8B8B;
display: flex;
justify-content: space-between;
align-items: center;
/* justify-content: space-around; */
.left{
font-size: 28px;
}
.right {
font-size: 32px;
}
}
.circle {
position: relative;
padding: 80px;
display: flex;
justify-content: center;
align-items: center;
.van-circle {
height: 200px !important;
width: 200px !important;
position: relative;
.circle-text {
height: 100%;
padding: 0 20px;
display: flex;
justify-content: center;
align-items: center;
.left {
@include center();
font-size: 62px;
color: #333;
}
.right {
display: flex;
justify-content: flex-start;
align-self: center;
flex-direction: column;
img {
height: 50px;
width: 50px;
margin: 0 10px;
object-fit: contain;
}
span {
font-size: 18px;
}
}
/* flex-direction: column; */
}
}
.circle-white {
position:absolute;
bottom: 78px;
right: 45%;
height: 50px;
width: 50px;
border: 2px solid;
border-radius: 50%;
background: #fff;
}
}
.progress {
position: relative;
flex: 1;
font-size: 30px;
padding: 0 40px;
display: flex;
justify-content: space-between;
align-items: center;
.progress-circle {
position: absolute;
top: -12px;
left: 0;
height: 35px;
width: 35px;
background-color: #fff;
border-radius: 50%;
border: 12px solid;
z-index: 99;
}
.state-item {
width: 100%;
.state-line {
position: relative;
height: 30px;
font-size: 32px;
&.low {
border-top-left-radius: 20px;
border-bottom-left-radius: 20px;
}
&.blue {
background-color: $green;
}
&.hight {
background-color: $com_red;
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
}
}
.state-text {
padding: 40px 0 40px 0;
@include center();
color: #333;
font-weight: bold;
}
}
}
.statistics {
position: relative;
padding: 0px 28px 10px 28px;
.list {
flex: 1;
width: 100%;
display: flex;
justify-content: space-around;
align-items: center;
font-size: 32px;
.item {
display: flex;
justify-content: flex-start;
align-items: flex-start;
width: 126px;
padding: 30px 60px 30px 20px;
/* height: px2rem(136); */
flex-direction: column;
border: 1px solid $border_color;
border-radius: 30px;
color: #fff;
.top {
font-size: 24px;
}
.middle {
font-size: 48px;
/* padding: 10px; */
}
.bottom {
font-size: 24px
}
.line {
height: 3px;
width: 100%;
margin: 5px 0;
background-color: #fff;
@include center();
}
}
}
}
.warn-tips {
padding: 40px 40px;
display: flex;
justify-content: flex-start;
align-items: center;
.left {
img {
height: 60px;
width: 60px;
object-fit: contain;
margin-right: 30px;
}
}
.right {
font-size: 28px;
.orange {
color: #edb21d;
}
}
}
.tab-bar{
padding: 20px 40px;
position: relative;
.date-tab-con {
height: 50px;
display: flex;
justify-content: flex-start;
align-items: center;
background: #fff;
border-top-left-radius: 40px;
border-top-right-radius: 40px;
border-bottom-left-radius: 40px;
border-bottom-right-radius: 40px;
.date-tab-list {
display: flex;
justify-content: space-around;
align-items: center;
color: #fff;
flex: 1;
height: 50px;
.date-tab-item {
position: relative;
margin: 0 8px;
height: 100%;
width: 100%;
border-radius: 40px;
color: #6D6D6D;
font-size: 28px;
font-weight: bold;
@include center();
background-color: #e6e6e6;
img {
height: 50px;
width: 50px;
padding: 0 16px;
}
.more {
width: 20px;
height: 12px;
}
/* &.active::after {
content: '';
width: 88px;
position: absolute;
right: 25%;
bottom: -20px;
box-sizing: border-box;
border-bottom: 8px solid $green;
} */
&.active {
color: #333;
background-color: $green;
}
&.notClick {
background-color: $border_color;
color: #fff;
border: 1px solid #fff;
}
}
.date-tab-item:nth-child(3) {
border-right: 1px solid #E0E0E0;
}
/* .date-tab-item:first-child {
border-top-left-radius: 15px;
border-bottom-left-radius: 15px;
}
.date-tab-item:last-child {
border-top-right-radius: 15px;
border-bottom-right-radius: 15px;
} */
}
img {
height: 50xp;
width: 50px;
object-fit: contain;
}
}
}
.line-chart-con {
height: 600px;
padding: 20px;
.line-chart {
height: 580px;
padding: 20px;
background-color:#fff;
border: 1px solid $com_light_green;
border-radius: 40px;
}
}
.bottom {
flex: 1;
.result {
padding: 20px 40px;
.result-con {
.title {
span {
font-size: 46px;
font-weight: bold;
}
}
.status {
display: flex;
flex-wrap: wrap;
align-items: center;
align-content: space-between;
justify-content: space-between;
width: 100%;
margin: 20px 0;
p {
font-size: 52px;
color: $green;
font-weight: bold;
}
ul {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: flex-start;
li {
width: 40px;
height: 30px;
border-radius: 20px;
position: relative;
& + li {
margin-left: 10px;
}
&.toobad {
background-color: #ff5f8b;
&:after{
background-color: #ff5f8b;
}
}
&.ordinary {
background-color: #2ea7e0;
&:after{
background-color: #2ea7e0;
}
}
&.sameas {
background-color: #8dc21f;
&:after{
background-color: #8dc21f;
}
}
&.excellent {
background-color: #179b3b;
&:after{
background-color: #179b3b;
}
}
&.active {
width: 240px;
&:after {
opacity: 1;
}
&:before {
opacity: 1;
}
}
&:after {
content: '';
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
width: 60px;
height: 60px;
opacity: 0;
border-radius: 50%;
}
&:before {
content: '';
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
width: 35px;
height: 35px;
opacity: 0;
border-radius: 50%;
background-color:#fff;
z-index: 2;
}
}
}
}
.tips {
font-size: 24px;
}
}
}
.wran-tips {
padding: 20px 40px 50px 40px;
font-size: 24px;
.tips-title {
font-weight: bold;
padding: 20px 0;
color: #333;
}
}
}
}
}

+ 417
- 0
src/views/today/signsDetails.vue View File

@@ -0,0 +1,417 @@
<!-- -->
<template>
<div class="signs">
<van-nav-bar title="心率监测" :border="true" :left-arrow="true" @click-left="onNavBack" left-text="返回">
</van-nav-bar>
<div class="main">
<div class="date">
<div class="left">
<span>2023-04-29 18:08</span>
</div>
<div class="right">
<span>历史监测</span>
</div>
</div>
<div class="circle">
<van-circle
v-model="currentRateOut"
layer-color="#f0f0f0"
:color="$green"
:rate="systolicRate"
:speed="100"
stroke-linecap="butt"
size="210"
stroke-width="120"
>
<template #default>
<div class="circle-text">
<div class="left">
<span>92</span>
</div>
<div class="right">
<img :src="circleBpm" alt="" />
<span>bpm</span>
</div>
</div>
</template></van-circle
>
<div class="circle-white" :style="{ borderColor: this.$green }"></div>
</div>
<div class="progress">
<div class="progress-circle" :style="{ borderColor: this.$green, left: '45%' }"></div>
<div class="state-item" v-for="(item, index) in statesList" :key="index">
<div :class="['state-line', item.state]" :style="{ backgroundColor: item.color }"></div>
<div class="state-text">
<span :style="{}"> {{ item.text }} </span>
</div>
</div>
</div>
<div class="statistics">
<div class="list">
<div
class="item"
v-for="(item, index) in statisticsList"
:key="index"
:style="{ backgroundColor: item.bgColor }"
>
<div class="middle">
<span :style="{ color: '#fff' }">{{ item.value || '--' }}</span>
</div>
<div class="top">
<span>{{ item.label || '--' }}</span>
</div>
<div class="line"></div>
<div class="bottom">
<span>{{ item.time || '--' }}</span>
</div>
</div>
</div>
</div>
<div class="warn-tips">
<div class="left">
<img :src="warnImg" alt="" />
</div>
<div class="right">
<p>
<span class="orange">温馨提示: </span>检测数据仅供参考,<span class="orange"
>不可做医疗诊断和治疗依据。</span
>
</p>
</div>
</div>
<div class="tab-bar">
<div class="date-tab-con">
<div class="date-tab-list">
<div
:class="['date-tab-item', { active: current === index, notClick: false }]"
@click="onTabClick(item.value, index)"
v-for="(item, index) in dateList"
:key="index"
>
<img :src="tabImgUrl" alt v-if="index == 3" />
<span>{{ item.text }}</span>
<img class="more" :src="selectDownImg" alt v-if="index == 3" />
</div>
<img :src="dateImg" alt="" />
</div>
</div>
</div>
<div class="line-chart-con">
<div class="line-chart" ref="lineChart"></div>
</div>
<div class="bottom">
<div class="result">
<div class="result-con">
<div class="title">
<span class="title-no-data">结果解读</span>
</div>
<div class="status">
<p>心率正常</p>
<ul>
<li class="ordinary"></li>
<li class="excellent active"></li>
<li class="toobad"></li>
</ul>
</div>
<div class="tips">
<span>您的心率属于正常水平值,请继续保持注意合理膳食,少吃太甜太 咸的东西,少吃高热量食物。</span>
</div>
</div>
</div>
<div class="wran-tips">
<p class="tips-title">温馨提示:</p>
<p>检测数据仅供参考,不可做医疗诊断和治疗依据</p>
</div>
</div>
</div>
</div>
</template>

<script>
export default {
data() {
return {
currentRateOut: 100,
systolicRate: 50,
monitoringCount: '', //监测次数
circleBpm: require('@/assets/today/icons/2_33.png'),
// 状态条
statesList: [
{ color: '#2ea7e0', text: '偏低', state: 'low' },
{ color: '#189b3b', text: '正常', state: 'normal' },
{ color: '#ff5f8b', text: '偏高', state: 'hight' }
],
// 情绪状态列表
statisticsList: [
{ label: '最低心率', value: '75', time: '08:15', bgColor: '#2ea7e0' },
{ label: '最高心率', value: '148', time: '10:15', bgColor: '#189b3b' },
{ label: '平均心率', value: '50', time: '18:15', bgColor: '#ff5f8b' }
],
warnImg: require('@/assets/today/icons/2_25.png'),
// 日期选择标签
dateList: [
{ name: 'today', text: '今天', value: 0 },
{ name: 'week', text: '7天', value: 7 },
{ name: 'month', text: '30天', value: 30 }
/* { name: 'weekReport', text: '周报', value: 49 } */
],
tabImgUrl: require('@/assets/today/icons/statistical_form.png'),
selectDownImg: require('@/assets/today/icons/select_down.png'),
dateImg: require('@/assets/today/icons/2_12.png'),
current: 0, // 日期选择标签-当前选中的标签
currentDays: 0, //日期选择标签-日期参数
emotionData: [],
xAxisData: ['6:00', '8:00', '10:00', '12:00', '14:00', '16:00', '18:00', '20:00'], //图表x轴展示的数据
echarts: null
};
},
watch: {
emotionData: {
handler() {
this.initEchart();
},
deep: true
}
},
computed: {
echartsTitle() {
return '心率数据图';
},
defaultOptions() {
return {
time: {
useUTC: false
},
title: {
text: this.echartsTitle,
left: 10,
right: 25,
bottom: 20,
top: '3%',
textStyle: {
fontSize: 22,
fontWeight: 'bold'
}
},
legend: {
width: '60%',
orient: 'horizontal',
right: 'right',
top: '5%',
bottom: '1%',
itemHeight: 5,
itemWidth: 5,
itemGap: 5,
align: 'left',
selectedMode: false,
data: [
{
name: `心率偏低`,
icon: 'rect',
itemStyle: {
color: '#2ea7e0'
},
textStyle: {
fontSize: 12
}
},
{
name: `心率正常`,
itemStyle: {
color: '#189b3b'
},
icon: 'rect',
textStyle: {
fontSize: 12
}
},
{
name: `心率偏高`,
itemStyle: {
color: '#ff5f8b'
},
icon: 'rect',
textStyle: {
fontSize: 12
}
}
],
formatter: function (name) {
// 自定义显示内容
if (name.length > 6) {
return name.substring(0, 6) + '\n' + name.substring(6);
} else {
return name;
}
}
},
grid: {
show: true,
borderWidth: 1,
top: '20%',
left: '1%',
right: '2%',
bottom: '10%',
containLabel: true
},
xAxis: {
type: 'category',
axisLine: {
show: false
},
textStyle: {
fontSize: 10
},
axisTick: {
show: false
},
splitLine: {
show: false,
lineStyle: {
color: '#ddd',
width: 2
}
},
nameLocation: 'left',
axisLabel: {
show: true,
fontSize: 12,
showMinLabel: true, //显示最小值
showMaxLabel: true //显示最大值
},
data: this.xAxisData
},
dataZoom: [
{
start: 0,
end: 100,
textStyle: {
color: '#FFF',
fontSize: 14
},
show: false,
height: 15,
bottom: 5,
handleStyle: {
borderWidth: 1,
borderCap: 'square'
}
}
],
tooltip: {
trigger: 'axis',
textStyle: {
fontSize: 14,
align: 'center'
},
formatter: function (params) {
return params[0].name + '</br>' + params[0].value;
}
},
yAxis: {
type: 'value',
max: 150,
min: 50,
interval: 20,
splitNumber: 1,
boundaryGap: ['5%', '5%'],
nameTextStyle: {
fontSize: 13
},
alignTicks: true,
axisTick: {
show: false
},
axisLabel: {
show: true,
fontSize: 13
},
splitLine: {
show: false,
lineStyle: {
color: '#ddd',
width: 1
}
}
},
series: [
{
name: `心率偏低`,
type: 'line',
padding: 5,
data: this.emotionData,
symbol: 'circle',
symbolSize: 12,
smooth: true,
itemStyle: {
normal: {
color: '#fff',
borderWidth: 2,
lineStyle: {
width: 6,
type: 'solid',
color: '#189b3b'
}
}
}
},
{
name: `心率正常`,
type: 'line',
data: ''
},
{
name: `心率偏高`,
type: 'line',
data: ''
}
]
};
}
},
created() {
this.createList();
},
mounted() {
this.initEchart();
},
methods: {
onNavBack() {
this.$router.push({
name: 'Today'
});
},
onTabClick(value, index) {
this.current = index;
this.currentDays = value;
this.createList();
},
createList() {
// 模拟数据
this.emotionData = [];
const colors = ['#189b3b', '#2ea7e0', '#ff5f8b'];
for (let i = 0; i < 10; i++) {
let value = Math.floor(Math.random() * 60) + 80;
let color = colors[Math.floor(Math.random() * colors.length)];
this.emotionData.push({
value,
itemStyle: {
borderColor: color
}
});
}
},
initEchart() {
if (this.echarts != null && this.echarts != '' && this.echarts != undefined) {
this.echarts.dispose();
}
this.echarts = this.$echarts.init(this.$refs.lineChart);
this.echarts.setOption(this.defaultOptions);
}
}
};
</script>
<style scoped lang="scss">
@import './scss//signs-details.scss';
/* @import url(); 引入css类 */
</style>

Loading…
Cancel
Save