ソースを参照

update

- 心理监测详情
    - 修改 天数选择方式
- 心理监测周报
    - 增加 周报列表和周报详情接口
test
JinxChen 1年前
コミット
44580a243c
18個のファイルの変更1783行の追加163行の削除
  1. +10
    -2
      README.md
  2. バイナリ
      src/assets/img/psychological/down.png
  3. バイナリ
      src/assets/img/psychological/more.png
  4. バイナリ
      src/assets/img/psychological/select_down.png
  5. バイナリ
      src/assets/img/psychological/statistical_form.png
  6. バイナリ
      src/assets/img/psychological/up.png
  7. バイナリ
      src/assets/img/psychological/week_report.png
  8. +2
    -2
      src/config/models.js
  9. +4
    -2
      src/router/index.js
  10. +11
    -0
      src/store/index.js
  11. +1
    -0
      src/views/health/psychological-main/index.vue
  12. +166
    -44
      src/views/health/psychological/index.scss
  13. +136
    -39
      src/views/health/psychological/index.vue
  14. +0
    -21
      src/views/health/psychological/report.scss
  15. +0
    -53
      src/views/health/psychological/report.vue
  16. +305
    -0
      src/views/health/psychological/report/index.scss
  17. +918
    -0
      src/views/health/psychological/report/index.vue
  18. +230
    -0
      src/views/health/psychological/report/report-entry.vue

+ 10
- 2
README.md ファイルの表示

@@ -1,7 +1,7 @@
<!--
* @Date: 2022-08-17 16:19:13
* @LastEditors: JinxChen
* @LastEditTime: 2023-11-02 09:12:50
* @LastEditTime: 2023-11-06 09:40:20
* @FilePath: \TelpoH5FrontendWeb\README.md
* @description: 项目说明
-->
@@ -770,4 +770,12 @@ fix
update
- 心理监测详情
- 修改 温馨提示语
- 新增 一个周报/月报页面
- 新增 一个周报/月报页面

## v1.0.97
`2023.11.6`
update
- 心理监测详情
- 修改 天数选择方式
- 心理监测周报
- 增加 周报列表和周报详情接口

バイナリ
src/assets/img/psychological/down.png ファイルの表示

変更前 変更後
幅: 15  |  高さ: 23  |  サイズ: 440B

バイナリ
src/assets/img/psychological/more.png ファイルの表示

変更前 変更後
幅: 14  |  高さ: 23  |  サイズ: 661B

バイナリ
src/assets/img/psychological/select_down.png ファイルの表示

変更前 変更後
幅: 15  |  高さ: 9  |  サイズ: 406B

バイナリ
src/assets/img/psychological/statistical_form.png ファイルの表示

変更前 変更後
幅: 29  |  高さ: 29  |  サイズ: 1.1KB

バイナリ
src/assets/img/psychological/up.png ファイルの表示

変更前 変更後
幅: 15  |  高さ: 23  |  サイズ: 419B

バイナリ
src/assets/img/psychological/week_report.png ファイルの表示

変更前 変更後
幅: 38  |  高さ: 38  |  サイズ: 2.6KB

+ 2
- 2
src/config/models.js ファイルの表示

@@ -1,11 +1,11 @@
/*
* @Date: 2021-11-20 10:26:39
* @LastEditors: JinxChen
* @LastEditTime: 2023-11-02 09:12:59
* @LastEditTime: 2023-11-06 09:15:22
* @FilePath: \TelpoH5FrontendWeb\src\config\models.js
* @description:
*/
export const VERSION_MODEL = '1.0.96F'; //版本号
export const VERSION_MODEL = '1.0.97F'; //版本号
export const IMAGE_URL = {
production: 'http://zfb.ssjlai.com/web/',
test: 'http://zfb.ssjlai.com/web/',


+ 4
- 2
src/router/index.js ファイルの表示

@@ -1,7 +1,7 @@
/*
* @Date: 2023-09-21 09:54:53
* @LastEditors: JinxChen
* @LastEditTime: 2023-10-30 11:31:37
* @LastEditTime: 2023-11-03 09:41:28
* @FilePath: \TelpoH5FrontendWeb\src\router\index.js
* @description:
*/
@@ -62,7 +62,9 @@ const routes = [
// 健康-抑郁,压力和疲劳汇总入口
{ path: '/psychologicalMain', name: 'psychologicalMain', component: resolve => require(['@/views/health/psychological-main'], resolve) },
// 周报/月报
{ path: '/psychologicalReport', name: 'psychologicalReport', component: resolve => require(['@/views/health/psychological/report'], resolve) },
{ path: '/psychologicalReport', name: 'psychologicalReport', component: resolve => require(['@/views/health/psychological/report/index'], resolve) },
// 周报/月报-入口
{ path: '/psychiclReportEntry', name: 'psychiclReportEntry', component: resolve => require(['@/views/health/psychological/report/report-entry'], resolve) },

// 告警详情-中间页
{ path: '/aiCallAlarm', name: 'aiCallAlarm', component: resolve => require(['@/views/ai-call-alarm'], resolve) },


+ 11
- 0
src/store/index.js ファイルの表示

@@ -23,6 +23,7 @@ export default new Vuex.Store({
ssjlToken: '',
fromSsjl: '',
active: null, //点击左边树形图下标
tabClick: '', //心理监测点击tab
},
mutations: {
imei(state, imei) {
@@ -65,6 +66,11 @@ export default new Vuex.Store({
state.active = active;
window.localStorage[prefix + 'active'] = active;
},
tabClick(state, tabClick) {
state.tabClick = tabClick;
window.localStorage[prefix + 'tabClick'] = tabClick;
},

},
getters: {
imei: state => {
@@ -107,6 +113,11 @@ export default new Vuex.Store({
if (state.active != '') return state.active;
return window.localStorage[prefix + 'active'] == null ? '' : window.localStorage[prefix + 'active'];
},
tabClick: state => {
if (state.tabClick != '') return state.tabClick;
return window.localStorage[prefix + 'tabClick'] == null ? '' : window.localStorage[prefix + 'tabClick'];
},

},
actions: {},
modules: {}

+ 1
- 0
src/views/health/psychological-main/index.vue ファイルの表示

@@ -67,6 +67,7 @@ export default {
},
mounted() {
this.loadParams();
this.$store.commit('tabClick', 0);
window.document.title = '心理监测';
},
methods: {


+ 166
- 44
src/views/health/psychological/index.scss ファイルの表示

@@ -4,54 +4,76 @@ $newBlue: #638EE4;
width: 100%;
overflow: hidden;
background-color: #fff;
.main {
height: calc(100vh - 45px);
overflow: scroll;
.top {
flex: 1;
.tab-bar {
padding: 0 13px 5px 13px;
.date-tab-con {
padding: 5px 0;
height: 30px;
display: flex;
justify-content: flex-start;
align-items: center;
.date-tab-list {
display: flex;
justify-content: flex-start;
align-items: center;
flex: 1;
border-radius: 15px;
.tab-bar {
width: 100%;
position: relative;
.date-tab-con {
display: flex;
justify-content: flex-start;
align-items: center;
background: #F6F6F6;
border: 1px solid #E0E0E0;
.date-tab-list {
display: flex;
justify-content: flex-start;
align-items: center;
color: #fff;
flex: 1;
height: 24px;
padding: 10px 0;
.date-tab-item {
position: relative;
padding: 0 20px;
color: #6D6D6D;
font-size: 18px;
@include center();
img {
height: 25px;
width: 25px;
padding: 0 8px;
}
.more {
width: 10px;
height: 6px;
}
&.active::after {
content: '';
width: 44px;
position: absolute;
right: 25%;
bottom: -10px;
box-sizing: border-box;
border-bottom: 4px solid #638EE4;
}
&.active {
color: #638EE4;
}
&.notClick {
background-color: $border_color;
color: #fff;
.date-tab-item {
height: 30px;
width: 100%;
color: #6D6D6D;
font-size: 18px;
@include center();
border: 1px solid $newBlue;
&.active {
background-color: $newBlue;
color: #fff;
}
&.notClick {
background-color: $border_color;
color: #fff;
border: 1px solid #fff;
}
}
.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;
}
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;
} */
}
}
}
.main {
position: relative;
height: calc(100vh - 90px);
overflow: scroll;
.top {
flex: 1;
.title {
display: flex;
justify-content: space-between;
@@ -310,7 +332,107 @@ $newBlue: #638EE4;
}
}
}
&.report {
position: relative;
height: calc(100vh - 90px);
overflow: scroll;
background-color: #f5f5f5;
.content {
position: relative;
.list {
position: relative;

.item {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 34px 15px;
background-color: #fff;
margin-bottom: 11px;
.left {
display: flex;
justify-content: flex-start;
align-items: flex-start;
img {
height: 25px;
width: 25px;
}
.middle {
.title,
.overall,
.trend {
display: flex;
justify-content: flex-start;
align-items: center;
padding-left: 13px;
span,
p {
font-size: 18px;
font-family: Source Han Sans CN;
font-weight: 400;
color: #8d8d8d;
line-height: 30px;
}
}
.title {
span {
padding-right: 20px;
}
p {
color: #282828;
}
}
.overall {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
.left {
p {
padding-left: 20px;
font-weight: bold;
}
}
.right {
img {
height: 15px;
width: 9px;
}
}
}
.trend {
align-items: flex-start;
text-align: left;
}
}
}
.right {
img {
width: 9px;
height: 15px;
}
}
}
&.no-data {
height: calc(100vh - 100px);
width: 100%;
@include center();
flex-direction: column;
img {
height: 110px;
width: 175px;
}
p {
color: #999;
font-size: 12px;
padding: 20px 0 65px 0;
}
}
}
}
}
}

.title {
font-size: 16px;
}


+ 136
- 39
src/views/health/psychological/index.vue ファイルの表示

@@ -5,24 +5,25 @@
<van-icon name="arrow-left" size="24" style="padding: 0"/>
</template>
</van-nav-bar>
<div class="main">
<div class="top">
<!-- 日期选择 -->
<!-- TODO 后续可做成一个组件,方便调用 -->
<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"
>
<span>{{item.text}}</span>
</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>
</div>
</div>
</div>
<div class="main" v-show="current !== 3">
<div class="top">
<!-- 日期选择 -->
<!-- 标题 -->
<div class="title">
<div class="title-left">{{ titleLeft }}<van-icon name="question-o" @click="onHelp"/></div>
@@ -112,13 +113,9 @@
</div>
</div>
</div>

<!-- 分割线 -->

<div class="line"></div>

<!-- 底部 -->

<div class="bottom">
<div class="echart-container">
<div class="echart" ref="charts"></div>
@@ -188,6 +185,46 @@
<!-- -->
</div>
</div>
<!-- 周报菜单 -->
<div class="main report" v-show="current == 3">
<div class="content">
<div class="list" v-if="weekList">
<div
class="item"
v-for="(item, index) in weekList"
:key="index"
@click="onClickItem(item.recordId)"
>
<div class="left">
<img :src="weekImg" alt />
<div class="middle">
<div class="title">
<span>周报</span>
<p>{{ item.name }}</p>
</div>
<div class="overall">
<div class="left">
<span>总评</span>
<p :style="{color: calcResultColor(item.summaryLevel)}">{{ item. summary}}</p>
</div>
</div>
<!-- <div class="trend">
<p>( <span>无抑郁倾向</span><span>5%</span>,<span>轻度抑郁倾向</span> <span>5%</span> )</p>
</div>-->
</div>
</div>

<div class="right">
<img :src="moreImg" alt />
</div>
</div>
</div>
<div class="list no-data" v-else>
<img :src="noDataImg" alt />
<p>暂无数据</p>
</div>
</div>
</div>
<!-- 弹出层 -->
<van-popup v-model="isPopup">
<div class="popup">
@@ -220,7 +257,8 @@ export default {
dateList: [
{ name: "today", text: "今天", value: 0 },
{ name: "week", text: "7天", value: 7 },
{ name: "month", text: "30天", value: 30 }
{ name: "month", text: "30天", value: 30 },
{ name: "weekReport", text: "周报", value: 49 }
],
current: 0, // 日期选择标签-当前选中的标签
currentDays: 0, //日期选择标签-日期参数
@@ -337,6 +375,12 @@ export default {
moderateColor: '#d70d0d',
// 7天和30天最大数据列表
weekAndMonData: [],
tabImgUrl: require("@/assets/img/psychological/statistical_form.png"),
selectDownImg: require("@/assets/img/psychological/select_down.png"),
weekImg: require("@/assets/img/psychological/week_report.png"),
moreImg: require("@/assets/img/psychological/more.png"),
noDataImg: require("@/assets/img/no_data_01.png"),
weekList: [],
};
},
computed: {
@@ -615,7 +659,7 @@ export default {
return `${today}${this.emoName}数据图`;
},
warmTips() {
return `正常连续佩戴腕表,每半小时计算一个${this.emoName}分值。`;
return `正常连续佩戴腕表,每${ this.emoType == 2 ? '一': ''}小时计算一个${this.emoName}分值。`;
/* return `正常连续佩戴手表,每半小时计算一个${this.emoName}分值,睡眠期间不进行计算。` */
},
title1() {
@@ -663,9 +707,11 @@ export default {
this.getPieData();
this.getCalendarData();
this.getPsychologiclData();
this.getWeekResult();
},
mounted() {
this.initEchart();
this.current = Number(this.$store.getters.tabClick) || 0;
window.document.title = '心理监测';
},
methods: {
@@ -964,6 +1010,30 @@ export default {
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 = {
@@ -1084,22 +1154,12 @@ export default {
onTabClick(value, index) {
this.current = index;
this.currentDays = value;
this.$store.commit('tabClick', index);
let currentDate = new Date();
let leftText = value === 0 ? '今天' : value === 7 ? '7天' : '30天';
this.surveyTitle = value === 7 ? '7天概览' : '30天概览';
if (value === 7) {
/* this.defaultOptions.xAxis.data = [
"周一",
"周二",
"周三",
"周四",
"周五",
"周六",
"周日"
]; */
//this.defaultOptions.xAxis.data = this.xAxisData;
let dateList = this.getPostDate(currentDate, 6, true);
console.log("dateList", dateList);
this.getPsychologiclData('', dateList[0], dateList[1]);
} else if (value === 0) {
// 今天
@@ -1107,14 +1167,16 @@ export default {
this.defaultOptions.series = this.defaultSeries;
this.defaultOptions.series[0].data = this.emotionData;
this.getPsychologiclData(this.selectDate ? this.selectDate : this .$dayjs(currentDate).format("YYYY-MM-DD"));
} else {
} else if(value === 30){
// 30天
this.defaultOptions.xAxis.data = this.xAxisData;
this.defaultOptions.series = this.defaultSeries;
this.defaultOptions.series[0].data = this.emotionData;
let dateList = this.getPostDate(currentDate, 30, true);
console.log("dateList", dateList);
this.getPsychologiclData('', dateList[0], dateList[1]);
} else {
// 周报菜单
this.getWeekResult();
}
},
getCurrentMonthStaAndEnd(currentDate) {
@@ -1215,19 +1277,19 @@ export default {
let color = "";
let className = "";
switch(value) {
case '0':
case '0', 0:
color = "#62BD48";
className = 'none';
break;
case '1':
case '1', 1:
color = "#ffde00";
className = 'mild';
break;
case '2':
case '2', 2:
color = "#ff8a00";
className = 'moderate';
break;
case '3':
case '3', 3:
color = "#d70d0d";
className = 'severe';
break;
@@ -1241,6 +1303,41 @@ export default {
// 关闭poup
onClose() {
this.isPopup = false;
},
getWeekResult() {
this.$toast.loading('数据加载中');
let reqUrl = 'https://dbmq.rzliot.com/heart/api/Data/GetWeekResult';
let reqParams = {
uid: this.uid/* '2023101521270090082 */,
type: this.emoType
};
axios.get(reqUrl, {
params: { ...reqParams },
/* headers: { 'AccessToken': this.$store.getters.ssjlToken } */
}).then(res => {
console.log("res", res);
const data = res.data.response;
this.weekList = data.map(item => {
return {
name: item.Name.replace('周报', '').replace(/-/g, ".").replace(/~/g, "-"),
recordId: item.RecordId,
summary: item.Summary,
summaryLevel: item.SummaryLevel,
type: this.emoType
}
});
this.$toast.success('数据加载完成');
})
},
onClickItem(recordId) {
this.$router.push({
name: 'psychologicalReport',
query: {
recordId: recordId,
name: 'depression',
isShowLeft: true
}
})
}
}
};


+ 0
- 21
src/views/health/psychological/report.scss ファイルの表示

@@ -1,21 +0,0 @@
.report{
height: 100vh;
width: 100%;
overflow: hidden;
background-color: #fff;
.main {
height: calc(100vh - 45px);
overflow: scroll;
padding: 5px 15px;
h5 {
font-size: 16px;
}
.overall-rating {
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-direction: column;
font-size: 14px;
}
}
}

+ 0
- 53
src/views/health/psychological/report.vue ファイルの表示

@@ -1,53 +0,0 @@
<!--
* @Date: 2023-10-30 11:30:22
* @LastEditors: JinxChen
* @LastEditTime: 2023-10-30 15:56:20
* @FilePath: \TelpoH5FrontendWeb\src\views\health\psychological\report.vue
* @description:
-->
<template>
<!-- 周/月报 -->
<div class="report">
<van-nav-bar title="心理监测周报" :border="true" :left-arrow="true" @click-left="onNavBack">
<template #left>
<van-icon name="arrow-left" size="24" style="padding: 0"/>
</template>
</van-nav-bar>
<div class="main">
<!-- 总评 -->
<div class="overall-rating">
<h5>本周总评:</h5>
<p>轻度抑郁倾向</p>
<p>监测次数: 20次</p>
<p>发发发发发个规格egg嘎嘎</p>
</div>
<!-- 趋势对比-饼状图 -->
<div class="pie-chart"></div>
<!-- 数据图-柱形图 -->
<div class="bar-chart "></div>
<!-- 建议 -->
<div class="advise"></div>
<!-- 概览 -->
<div class="overview"></div>
</div>
</div>
</template>

<script>
export default {
name:'',
data(){
return {

}
},
methods: {
onNavBack() {},

}
}
</script>

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

+ 305
- 0
src/views/health/psychological/report/index.scss ファイルの表示

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

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

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

.overall-rating {
padding: 23px 15px;
margin-bottom: 9px;

.con {
padding: 17px 18px;
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-direction: column;
font-size: 14px;
background: #FFFFFF;
border: 1px solid #535353;
box-shadow: 4px 5px 0px 0px #638EE4;
border-radius: 5px;

p {
font-size: 18px;
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: 12px;
}
}

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

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

.pie-chart-top {
display: flex;
justify-content: space-between;
align-items: flex-start;
padding: 23px 15px 16px 15px;

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

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

.count {
padding: 0 15px 5px 15px;
text-align: left;

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

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

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

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

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

.list {
flex-direction: column;

.item {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 12px;
padding: 9px 0;

.item-left {
display: flex;
justify-content: flex-start;
align-items: center;
padding-right: 10px;

.circle {
height: 12px;
width: 12px;
margin: 0 4px;
}

span {
font-size: 12px;
}

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

.item-right {
display: flex;
justify-content: center;
align-items: center;
}
}
}
}
}

.statistics {
position: relative;
padding: 0px 14px 5px 14px;

.list {
flex: 1;
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 16px;

.item {
@include center();
width: 58px;
/* height: px2rem(136); */
flex-direction: column;

.top {
font-size: 12px;
}

.middle {
font-size: 24px;
font-weight: bold;
padding: 5px;
}

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

.bar-chart {
height: 350px;
background-color: #fff;
padding: 0 5px;

.echart {
height: 350px;
padding: 0 5px;
}
}

.advice {
padding: 26px 15px 30px 15px;

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

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

.title {
font-size: 18px;
font-weight: bold;
color: #638EE4;
line-height: 18px;
padding-bottom: 13px;
}
}
}

.overview {
padding: 0 15px 16px 15px;

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

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

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

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

p {
font-size: 14px;
padding: 0;
color: #666666;

.day {
/* padding: 5px; */
font-size: 28px;
}

.day-text {
font-size: 12px
}
}
}
}
}
}
}
&.no-data {
@include center();
flex-direction: column;
p {
font-size: 16px;
}
}
}
}

+ 918
- 0
src/views/health/psychological/report/index.vue ファイルの表示

@@ -0,0 +1,918 @@
<!--
* @Date: 2023-10-30 11:30:22
* @LastEditors: JinxChen
* @LastEditTime: 2023-11-06 11:01:41
* @FilePath: \TelpoH5FrontendWeb\src\views\health\psychological\report\index.vue
* @description:
-->
<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"/>
</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.Total || '--' }}次</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>
</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>
</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/img/no_data_01.png" alt />
<p>暂无数据</p>
</div>
</div>
</template>

<script>
import { EmotionModel, PsyBaseUrl } from "@/config/models";
import { isNotNull} from "@/utils/index";
import axios from "axios";
import APICore from "@/api/core";
export default {
name:'',
data(){
return {
pieRightList: [
/* {
text: "无情绪倾向",
count: 12,
percentage: "80",
color: "#62BD48"
},
{
text: "轻度情绪倾向",
count: 2,
percentage: "80",
color: "#ffde00"
},
{
text: "中度情绪倾向",
count: 1,
percentage: "80",
color: "#ff8a00"
},
{
text: "重度情绪倾向",
count: 1,
percentage: "80",
color: "#d70d0d"
} */
],
statisticsList: [
/* { label: "最大值", value: "75", time: "08:15" },
{ label: "最小值", value: "40", time: "10:15" },
{ label: "最近值", value: "50", time: "18:15" } */
],
emotionList: [],
surveyTitle: '本周概览',
echarts: null,
// 路由传过来的情绪参数
emoName: null,
pieData: [],
xAxisData: [],
pieEcharts: null,
monitoringCount: '',
// 7天和30天最大数据列表
weekAndMonData: [],
defaultSeries: null,
defaultLegend: [
{
name: `轻度${this.emoName}倾向`,
icon: "rect",
itemStyle: {
color: "#ffde00"
},
textStyle: {
fontSize: 12
}
},
{
name: `中度${this.emoName}倾向`,
itemStyle: {
color: "#ff8a00"
},
icon: "rect",
textStyle: {
fontSize: 12
}
},
{
name: `重度${this.emoName}倾向`,
itemStyle: {
color: "#d70d0d",
},
icon: "rect",
textStyle: {
fontSize: 12
}
},
{
name: `无${this.emoName}倾向`,
icon: "rect",
itemStyle: {
color: "#62BD48"
},
textStyle: {
// 项目遗留问题,新项目不需重新转换文字大小
fontSize: 12
}
},
],
params: {},
weekResult: {},
}
},
created() {
this.initEchartText();
},
mounted() {
this.loadParams();
this.initEchart();
},
watch: {
// 监听数据发生变化 初始化各项图表
emotionData: {
handler(n, o) {
this.initEchart();
},
deep: true
},
xAxisData: {
handler(n, o) {
this.initEchart();
},
deep: true
},
pieData: {
handler(n, o) {
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: "#ffde00"
},
textStyle: {
fontSize: 12
}
},
{
name: `中度${this.emoName}倾向`,
itemStyle: {
color: "#ff8a00"
},
icon: "rect",
textStyle: {
fontSize: 12
}
},
{
name: `重度${this.emoName}倾向`,
itemStyle: {
color: "#d70d0d",
},
icon: "rect",
textStyle: {
fontSize: 12
}
},
{
name: `无${this.emoName}倾向`,
icon: "rect",
itemStyle: {
color: "#62BD48"
},
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: {
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";
let that = this;
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 reqUrl = 'https://dbmq.rzliot.com/heart/api/Data/GetWeekResultDetail';
let reqParams = {
recordId: this.params.recordId,
};
axios.get(reqUrl, {
params: { ...reqParams },
/* headers: { 'AccessToken': this.$store.getters.ssjlToken } */
}).then(res => {
console.log("res", res);
const data = res.data.response;
let chartData = data.ChartData ? (JSON.parse(data.ChartData)).filter(item => {return item.Key}) : [];
console.log("图表数据", chartData);
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.Count
),
text: `无${this.emoName}倾向`,
color: "#62BD48"
};
let Mild = {
count: data.Mild,
percentage: this.calcPercentage(
data.Mild,
data.Count
),
text: `轻度${this.emoName}倾向`,
color: "#ffde00"
};
let Moderate = {
count: data.Moderate,
percentage: this.calcPercentage(
data.Moderate,
data.Count
),
text: `中度${this.emoName}倾向`,
color: "#ff8a00"
};
let Severe = {
count: data.Severe,
percentage: this.calcPercentage(
data.Severe,
data.Count
),
text: `重度${this.emoName}倾向`,
color: "#d70d0d"
};
// 饼状图右边数据
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: "#62BD48"
};
let MildDay = {
days: data.MildDay,
text: `轻度${this.emoName}倾向`,
color: "#ffde00"
};
let ModerateDay = {
days: data.ModerateDay,
text: `中度${this.emoName}倾向`,
color: "#ff8a00"
};
let SevereDay = {
days: data.SevereDay,
text: `重度${this.emoName}倾向`,
color: "#d70d0d"
};
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 => {
console.log("item", item);
return item.Key ? this.$dayjs(item.Key.replace(/-/g, "/")).format(
"MM/DD"
) : item.key;
});
let emphasisStyle = {
itemStyle: {
shadowBlur: 10,
shadowColor: 'rgba(0,0,0,0.3)'
}
};
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.go(-1);
},
// 计算字体显示的颜色
calcColor(value) {
let color = "";
if (value <= 40) {
color = "#62BD48";
} else if (value > 40 && value <= 65) {
color = "#ffde00";
} else if (value > 65 && value <= 80) {
color = "#ff8a00";
} else if (value > 80) {
color = "#d70d0d";
} 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 = "#62BD48";
className = 'none';
break;
case '1', 1:
color = "#ffde00";
className = 'mild';
break;
case '2', 2:
color = "#ff8a00";
className = 'moderate';
break;
case '3', 3:
color = "#d70d0d";
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 "./index.scss";
</style>

+ 230
- 0
src/views/health/psychological/report/report-entry.vue ファイルの表示

@@ -0,0 +1,230 @@
<!--
* @Date: 2023-11-03 09:26:51
* @LastEditors: JinxChen
* @LastEditTime: 2023-11-04 10:38:00
* @FilePath: \TelpoH5FrontendWeb\src\views\health\psychological\report\report-entry.vue
* @description:
-->
<template>
<div class="report-main">
<van-nav-bar title="心理监测" :border="true" :left-arrow="true" @click-left="onNavBack">
<template #left>
<van-icon name="arrow-left" size="24" style="padding: 0" />
</template>
</van-nav-bar>
<div class="main">
<div class="tabs"></div>
<div class="content">
<div class="list" v-if="weekList">
<div
class="item"
v-for="(item, index) in weekList"
:key="index"
@click="onClickItem(item.recordId)"
>
<div class="left">
<img :src="weekImg" alt />
<div class="middle">
<div class="title">
<span>周报</span>
<p>{{ item.name }}</p>
</div>
<div class="overall">
<div class="left">
<span>总评</span>
<p>{{ item. summary}}</p>
</div>
</div>
<!-- <div class="trend">
<p>( <span>无抑郁倾向</span><span>5%</span>,<span>轻度抑郁倾向</span> <span>5%</span> )</p>
</div>-->
</div>
</div>

<div class="right">
<img :src="moreImg" alt />
</div>
</div>
</div>
<div class="list no-data" v-else>
<img src="../../../../assets/img/no_data_01.png" alt />
<p>暂无数据</p>
</div>
</div>
</div>
</div>
</template>

<script>
import { EmotionModel, PsyBaseUrl } from "@/config/models";
import axios from "axios";
export default {
name:'',
data(){
return {
active: 0,
tabImgUrl: require("@/assets/img/psychological/statistical_form.png"),
selectDownImg: require("@/assets/img/psychological/select_down.png"),
weekImg: require("@/assets/img/psychological/week_report.png"),
moreImg: require("@/assets/img/psychological/more.png"),
weekList: [],
uid: '',
emoName: '',
}
},
methods: {
onNavBack() {},
loadParams() {
let params = this.$route.query;
if (params) {
this.emoName = EmotionModel[params.name].name;
this.emoType = EmotionModel[params.name].type;
this.uid = params.uid;
}
},
onClickItem(recordId) {
this.$router.push({
name: 'psychologicalReport',
query: {
recordId: recordId,
name: 'depression',
isShowLeft: true
}
})
},
getWeekResult() {
this.$toast.loading('数据加载中');
let reqUrl = 'https://dbmq.rzliot.com/heart/api/Data/GetWeekResult';
let reqParams = {
uid: /* this.uid */'2023101521270090082',
type: this.emoType
};
axios.get(reqUrl, {
params: { ...reqParams },
/* headers: { 'AccessToken': this.$store.getters.ssjlToken } */
}).then(res => {
console.log("res", res);
const data = res.data.response;
this.weekList = data.map(item => {
return {
name: item.Name.replace('周报', ''),
recordId: item.RecordId,
summary: item.Summary,
type: this.emoType
}
});
this.$toast.success('数据加载完成');
})

}
},
mounted() {
this.loadParams();
this.getWeekResult();
}
}
</script>

<style scoped lang="scss">
.report-main {
height: 100vh;
width: 100%;
overflow: hidden;
background-color: #f5f5f5;
.main {
height: calc(100vh - 45px);
overflow: scroll;
.content {
position: relative;
.list {
.item {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 34px 15px;
background-color: #fff;
margin-bottom: 11px;
.left {
display: flex;
justify-content: flex-start;
align-items: flex-start;
img {
height: 25px;
width: 25px;
}
.middle {
.title,
.overall,
.trend {
display: flex;
justify-content: flex-start;
align-items: center;
padding-left: 13px;
span,
p {
font-size: 18px;
font-family: Source Han Sans CN;
font-weight: 400;
color: #8d8d8d;
line-height: 30px;
}
}
.title {
span {
padding-right: 20px;
}
p {
color: #282828;
}
}
.overall {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
.left {
p {
padding-left: 20px;
font-weight: bold;
}
}
.right {
img {
height: 15px;
width: 9px;
}
}
}
.trend {
align-items: flex-start;
text-align: left;
}
}
}
.right {
img {
width: 9px;
height: 15px;
}
}
}
&.no-data {
height: calc(100vh - 45px);
width: 100%;
@include center();
flex-direction: column;
img {
height: 110px;
width: 175px;
}
p {
color: #999;
font-size: 12px;
padding: 20px 0 65px 0;
}
}
}
}
}
}
</style>

読み込み中…
キャンセル
保存