@@ -55,6 +55,7 @@ import { | |||||
Tabs, | Tabs, | ||||
Toast, | Toast, | ||||
ActionSheet, | ActionSheet, | ||||
Progress, | |||||
} from 'vant'; //按需加载vant组件 | } from 'vant'; //按需加载vant组件 | ||||
Vue | Vue | ||||
@@ -97,6 +98,7 @@ Vue | |||||
.use(Tabs) | .use(Tabs) | ||||
.use(Toast) | .use(Toast) | ||||
.use(ActionSheet) | .use(ActionSheet) | ||||
.use(Progress) | |||||
Vue.config.productionTip = false; | Vue.config.productionTip = false; | ||||
Vue.config.devtools = true; | Vue.config.devtools = true; | ||||
@@ -31,6 +31,11 @@ const routes = [ | |||||
{ path: '/cardActive', name: 'cardActive', component: resolve => require(['@/views/card-active'], resolve) }, | { path: '/cardActive', name: 'cardActive', component: resolve => require(['@/views/card-active'], resolve) }, | ||||
{ path: '/alarmDetails', name: 'alarmDetails', component: resolve => require(['@/views/alarm/alarm-details'], resolve) }, | { path: '/alarmDetails', name: 'alarmDetails', component: resolve => require(['@/views/alarm/alarm-details'], resolve) }, | ||||
// 心理监测 | |||||
{ path: '/PsychologicalModeling', name: 'PsychologicalModeling', component: resolve => require(['@/views/psychological-modeling'], resolve) }, | |||||
{ path: '/PsychologicalQuestionnaire', name: 'PsychologicalQuestionnaire', component: resolve => require(['@/views/psychological-questionnaire'], resolve) }, | |||||
]; | ]; | ||||
const router = new VueRouter({ | const router = new VueRouter({ | ||||
@@ -0,0 +1,286 @@ | |||||
<template> | |||||
<div class="page"> | |||||
<div class="tip"> | |||||
<div class="icon"> | |||||
<i class="iconfont icon-tishi"></i> | |||||
</div> | |||||
<div class="info"> | |||||
<div class="titie">温馨提醒:</div> | |||||
<div class="content"> | |||||
首次佩戴,需完成以下2步,建立情绪模型。完成初始化建模后,将为您计算抑郁、压力、疲劳分值。 | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div v-if="info"> | |||||
<div class="step"> | |||||
<div class="name">第一步</div> | |||||
<div class="title"> | |||||
<div class="text">连续佩戴两小时</div> | |||||
<div class="status success" v-if="info.progress === 1"> | |||||
<span class="icon" | |||||
><i class="iconfont icon-caozuochenggong"></i | |||||
></span> | |||||
<span>已完成</span> | |||||
</div> | |||||
<div class="status" v-else>待完成</div> | |||||
</div> | |||||
<div class="schedule"> | |||||
<van-progress | |||||
:percentage="info.progress" | |||||
stroke-width="10px" | |||||
color="#638ee4" | |||||
:show-pivot="false" | |||||
></van-progress> | |||||
</div> | |||||
<div class="sub_title"> | |||||
请连续佩戴不低于2小时,有助于为您输出更加精准的情绪分析指标。 | |||||
</div> | |||||
</div> | |||||
<div class="step"> | |||||
<div class="name">第二步</div> | |||||
<div class="title"> | |||||
<div class="text">情绪初始化评估</div> | |||||
<div class="status success" v-if="info.initScaleState === 1"> | |||||
<span class="icon" | |||||
><i class="iconfont icon-caozuochenggong"></i | |||||
></span> | |||||
<span>已完成</span> | |||||
</div> | |||||
<div class="status" v-else>待完成</div> | |||||
</div> | |||||
<div class="sub_title"> | |||||
完成一次“情绪初始化评估”,有助于建立您的个人情绪模型。 | |||||
</div> | |||||
</div> | |||||
<div class="button"> | |||||
<van-button | |||||
round | |||||
type="info" | |||||
style="width: 100%; height: 100%" | |||||
@click="toQuestion" | |||||
v-if="info.initScaleState !== 1" | |||||
>情绪初始化评估</van-button | |||||
> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
import axios from 'axios' | |||||
export default { | |||||
name: 'PsychologicalModeling', | |||||
data() { | |||||
return { | |||||
info: null, | |||||
} | |||||
}, | |||||
mounted() { | |||||
//页面标题 | |||||
window.document.title = '情绪初始化建模' | |||||
//页面传参 | |||||
let params = { ...this.$route.query } | |||||
if (params.uid) { | |||||
this.uid = params.uid | |||||
//初始化 | |||||
this.init() | |||||
} else { | |||||
this.$toast('参数错误') | |||||
} | |||||
}, | |||||
methods: { | |||||
async init() { | |||||
let re = await this.api('/api/Question/Progress', { | |||||
method: 'GET', | |||||
sslVerify: false, | |||||
withCredentials: false, | |||||
params: { | |||||
uid: this.uid, | |||||
}, | |||||
}) | |||||
if (re.success) { | |||||
if (re.response && re.response.state === -1) { | |||||
this.$toast('用户不存在或未绑定手表') | |||||
} else { | |||||
this.info = re.response | |||||
} | |||||
} else { | |||||
this.$toast(re.msg) | |||||
} | |||||
}, | |||||
toQuestion() { | |||||
this.$router.push(`/PsychologicalQuestionnaire?uid=${this.uid}`) | |||||
}, | |||||
api(url, config) { | |||||
let baseUrl = 'http://172.16.1.97:9291' | |||||
setTimeout(() => { | |||||
this.$toast.loading({ | |||||
message: '', | |||||
forbidClick: true, | |||||
duration: 0, | |||||
}) | |||||
}, 100) | |||||
return new Promise((res) => { | |||||
axios({ | |||||
url: `${baseUrl}${url}`, | |||||
...config, | |||||
}) | |||||
.then((re) => { | |||||
if (re) { | |||||
if (re.data) { | |||||
console.log(re.data) | |||||
res(re.data) | |||||
this.$toast.clear() | |||||
return | |||||
} | |||||
this.$toast(`信息获取失败-${re.status}`) | |||||
res(true) | |||||
this.$toast.clear() | |||||
return | |||||
} | |||||
this.$toast(`信息获取失败-${url}`) | |||||
res(true) | |||||
this.$toast.clear() | |||||
}) | |||||
.catch((e) => { | |||||
this.$toast(`信息获取失败-${url}`) | |||||
res(true) | |||||
this.$toast.clear() | |||||
console.log(e) | |||||
}) | |||||
}) | |||||
}, | |||||
}, | |||||
} | |||||
</script> | |||||
<style lang="scss" scoped> | |||||
@font-face { | |||||
font-family: 'iconfont'; /* Project id 2652084 */ | |||||
src: url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAQoAAsAAAAACFQAAAPaAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFQGYACDBgqEIIQDATYCJAMMCwgABCAFhGcHQRtqBxEVnBvJPhLjmMRz8aCJJho3wfN8ne+5817QmS/XTApqUAGT1kmpHaidloBWXGdzOaZE+Aj1S75l+ek70v5OL82zLE6hFEIiJEbx96dyFkjAnwUAJnXNTcUP1HiBAtaxhhUr2KsXyLuo1/rCrIx6BgFM6tACo12HbjZpk4bPmkIRGksqkFbKpPFjhxOWRnRLpRBGCEKXamQTATDWGo+AjeHn5RdRCYNBQGHt0mtM+1Hc+Zr+1VZ+0gf1Gl+CgIcbQABQQI2NmWVIu7MfKk7WQGHWKTUpDKIRjEkjySSEglIHt/zHM0CCWMoUTFVRGBclugwEvto8VnH9qyAIhIDrIApTOVMVOr2mNDQjKSPHeM4zz6ZrPrYDY3fjR7a4+xTrY15tvZVw5KkZtx/X+HznyRPHnvCeqZskVmTOjMmRnF1girdzz7F4ju3uiB/xc53CoFi1HdXMW9Vu1TonY+gTzqB98OucaHakkW3GjxWJhX9kQXymq/AjJ5sfbS5Hc9nm5+KfvW9ZiYfnRXbG8tzG6nK7+u265yW2Hv38lNG3PmqlJo7Hjv0enTXu0fJ0ouuAIf1WL94ysHiw9aA5vca2mth0ZPGOvtu99JioF7HtiBd95LA4E7Gj3qPSVmO6tC3erV1e54F9yvUsu3Bh2Z7l+lwiLGETNtvRp9ylmtsGlm7eieOF8GLvn+zifT/067/LLFd8TdeujrureHTFyFEf+hbPVft+SK96RrBXE7tqx8rt21XpUO2QwwZswmZvsZsOz8+pN3TsrzXZ143c71m5NwLL+4xyo30jdTbxttGdTvRcMG4rPzrU0SFdrfTjHqXWlOrxuHR1FdK1219m/7yFvU52Hh3x6th9I25U9b0QTS1XvFyq35thACTvqtuqZZiOq5kq9v9/w/jtj8cOTW/2P2xpAN5vbXsP+5NxDcwN4RfjFPjbqkFApFYhULpOcFsQQLEkk4cBmLYJfm81QBZvh6uzweUghMlOwSBEcVCEKYdpqhoEsIhCkDDNwaQ67VdbZPsIzBFdDKjEC4GQwRsM0rgKigw+mKa+ECCPHwTJ4A8mrqy2s6gkZs2oBC3oB9SGBudoJJR7QD92iqtiF+RY4wjkSVbM7HFAHmNGvPpCxIFj6mHHT8OuIwhMDRpJKpFQpqmre0liqJ+sYRCFgFgAzQOgxkAMOB8t+e87gHhGOhQMxC52JlKeyAdyEjIAtlcOoLYb6R254ikQBEdHORiiB9gpO9LZSQII9YMaEIOQUA2IB0pSgnJQZbK8un+5XYCJtaUSQ5Ro0kcqeo5kKhy8J7dhKXWs6skEAAA='); | |||||
} | |||||
.iconfont { | |||||
font-family: 'iconfont' !important; | |||||
// font-size: 16px; | |||||
font-style: normal; | |||||
-webkit-font-smoothing: antialiased; | |||||
-moz-osx-font-smoothing: grayscale; | |||||
} | |||||
.icon-caozuochenggong:before { | |||||
content: '\e60f'; | |||||
} | |||||
.icon-tishi:before { | |||||
content: '\e654'; | |||||
} | |||||
.page { | |||||
width: 100%; | |||||
min-height: 100%; | |||||
box-sizing: border-box; | |||||
font-size: 3.6vw; | |||||
text-align: left; | |||||
background: #f4f4f4; | |||||
padding-bottom: 30vw; | |||||
.tip { | |||||
display: flex; | |||||
font-size: 3.3vw; | |||||
padding: 6vw 4vw; | |||||
justify-content: space-between; | |||||
align-items: center; | |||||
background: white; | |||||
.icon { | |||||
overflow: hidden; | |||||
display: flex; | |||||
justify-content: center; | |||||
align-items: center; | |||||
width: 40px; | |||||
height: 40px; | |||||
color: #ff865a; | |||||
font-size: 6vw; | |||||
border-radius: 50%; | |||||
background: #fff5f1; | |||||
} | |||||
.info { | |||||
width: calc(100% - 50px); | |||||
line-height: 20px; | |||||
text-align: left; | |||||
.titie { | |||||
color: #ff865a; | |||||
} | |||||
.content { | |||||
color: gray; | |||||
} | |||||
} | |||||
} | |||||
.step { | |||||
margin-top: 3vw; | |||||
padding: 4vw 8vw; | |||||
padding-right: 4vw; | |||||
background: white; | |||||
.name { | |||||
display: flex; | |||||
align-items: center; | |||||
font-size: 3.8vw; | |||||
padding-bottom: 2vw; | |||||
&::before { | |||||
content: ''; | |||||
display: block; | |||||
width: 1vw; | |||||
height: 1vw; | |||||
border: 2px solid #638ee4; | |||||
border-radius: 50%; | |||||
margin-left: calc(-2vw - 4px); | |||||
margin-right: 1vw; | |||||
} | |||||
} | |||||
.title { | |||||
display: flex; | |||||
justify-content: space-between; | |||||
padding: 3vw 0; | |||||
.status { | |||||
color: #ff865a; | |||||
} | |||||
.success { | |||||
color: #638ee4; | |||||
.icon { | |||||
font-size: 4vw; | |||||
margin-right: 1vw; | |||||
} | |||||
} | |||||
} | |||||
.sub_title { | |||||
padding: 3vw 0; | |||||
color: gray; | |||||
} | |||||
} | |||||
.button { | |||||
position: fixed; | |||||
left: 0; | |||||
right: 0; | |||||
bottom: 15vw; | |||||
width: 75vw; | |||||
height: 14vw; | |||||
margin: auto; | |||||
.van-button--info { | |||||
background-color: #638ee4; | |||||
border: 1px solid #638ee4; | |||||
} | |||||
} | |||||
} | |||||
</style> |
@@ -0,0 +1,337 @@ | |||||
<template> | |||||
<div class="page" v-if="topic.length"> | |||||
<div class="top"> | |||||
<div class="schedule"> | |||||
<div class="progress"> | |||||
<van-progress | |||||
:percentage="(select.length / topic.length) * 100" | |||||
stroke-width="10px" | |||||
color="#638ee4" | |||||
:show-pivot="false" | |||||
v-if="select.length / topic.length" | |||||
></van-progress> | |||||
</div> | |||||
<div class="text"> | |||||
<span class="val">{{ select.length }}</span | |||||
>/<span class="total">{{ topic.length }}</span> | |||||
</div> | |||||
</div> | |||||
<div class="title">{{ title }}</div> | |||||
</div> | |||||
<div class="list_box"> | |||||
<div class="item" v-for="(item, index) in topic" :key="index"> | |||||
<div class="label"> | |||||
<span>{{ item.Title }}</span> | |||||
<span>({{ item.Type }})</span> | |||||
</div> | |||||
<van-radio-group | |||||
class="radio" | |||||
v-model="item.select" | |||||
v-if="item.Type == '单选题'" | |||||
> | |||||
<van-cell-group> | |||||
<van-cell | |||||
clickable | |||||
v-for="(ite, idx) in item.Option" | |||||
:key="idx" | |||||
:title="ite.label" | |||||
@click="onRadio(index, ite.value)" | |||||
> | |||||
<template #right-icon> | |||||
<van-radio :name="ite.value" /> | |||||
</template> | |||||
</van-cell> | |||||
</van-cell-group> | |||||
</van-radio-group> | |||||
<van-checkbox-group class="checkbox" v-model="item.select" v-else> | |||||
<van-cell-group> | |||||
<van-cell | |||||
v-for="(ite, idx) in item.Option" | |||||
clickable | |||||
:key="idx" | |||||
:title="ite.label" | |||||
@click="onCheckbox(`checkboxes${item.QId}`, idx)" | |||||
> | |||||
<template #right-icon> | |||||
<van-checkbox | |||||
:name="ite.value" | |||||
:ref="`checkboxes${item.QId}`" | |||||
/> | |||||
</template> | |||||
</van-cell> | |||||
</van-cell-group> | |||||
</van-checkbox-group> | |||||
</div> | |||||
</div> | |||||
<div class="button"> | |||||
<van-button | |||||
round | |||||
type="info" | |||||
:disabled="topic.length != select.length" | |||||
style="width: 100%; height: 100%" | |||||
@click="submit" | |||||
>提交问卷</van-button | |||||
> | |||||
</div> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
import axios from 'axios' | |||||
export default { | |||||
name: 'PsychologicalModeling', | |||||
data() { | |||||
return { | |||||
uid: '', | |||||
keyCode: '', | |||||
title: '', | |||||
topic: [], //题目列表 | |||||
select: [], | |||||
} | |||||
}, | |||||
mounted() { | |||||
//页面标题 | |||||
window.document.title = '情绪初始化评估' | |||||
//页面传参 | |||||
let params = { ...this.$route.query } | |||||
if (params.uid) { | |||||
this.uid = params.uid | |||||
//初始化 | |||||
this.init() | |||||
} else { | |||||
this.$toast('参数错误') | |||||
} | |||||
}, | |||||
watch: { | |||||
selects(val) { | |||||
let temp = JSON.parse(val) | |||||
let tempt = temp.filter((item) => { | |||||
if (item.select) { | |||||
return true | |||||
} | |||||
}) | |||||
this.select = tempt | |||||
}, | |||||
}, | |||||
computed: { | |||||
selects() { | |||||
return JSON.stringify(this.topic) | |||||
}, | |||||
}, | |||||
methods: { | |||||
async init() { | |||||
let re = await this.api('/api/Question/Get', { | |||||
method: 'GET', | |||||
sslVerify: false, | |||||
withCredentials: false, | |||||
params: { | |||||
// uid: this.uid, | |||||
}, | |||||
}) | |||||
if (re.success) { | |||||
if (re.response && re.response.length) { | |||||
let temp = re.response[0] | |||||
let code = temp.Code | |||||
this.title = temp.Memo | |||||
this.keyCode = temp.Code | |||||
let re1 = await this.api('/api/Question/GetQuestion', { | |||||
method: 'GET', | |||||
sslVerify: false, | |||||
withCredentials: false, | |||||
params: { | |||||
code: code, | |||||
}, | |||||
}) | |||||
if (re1.success) { | |||||
if (re1.response && re1.response.length) { | |||||
let topic = [] | |||||
re1.response.forEach((item) => { | |||||
let tempt = { ...item } | |||||
let a1 = tempt.Option.split('#&') | |||||
let a2 = tempt.Score.split('#&') | |||||
let option = [] | |||||
for (let index = 0; index < a1.length; index++) { | |||||
option.push({ | |||||
label: a1[index], | |||||
value: a2[index], | |||||
}) | |||||
} | |||||
tempt.Option = option | |||||
tempt.value = '' | |||||
topic.push(tempt) | |||||
}) | |||||
this.topic = topic | |||||
} else { | |||||
this.$toast('问卷暂无题目') | |||||
} | |||||
} else { | |||||
this.$toast(re1.msg) | |||||
} | |||||
} else { | |||||
this.$toast('问卷不存在') | |||||
} | |||||
} else { | |||||
this.$toast(re.msg) | |||||
} | |||||
}, | |||||
async submit() { | |||||
let temp = { | |||||
uid: this.uid, //客户端系统用户id | |||||
keyCode: this.keyCode, //问卷编号 | |||||
answer: [], | |||||
} | |||||
this.topic.forEach((item) => { | |||||
temp.answer.push({ | |||||
qid: item.QId, //问卷题目编号 | |||||
value: typeof item.select == 'object' ? item.select.join(',') : item.select, //用户所选答案的 id | |||||
}) | |||||
}) | |||||
let re = await this.api('/api/Question/Rsults', { | |||||
method: 'POST', | |||||
sslVerify: false, | |||||
withCredentials: false, | |||||
data: temp, | |||||
}) | |||||
if (re.success) { | |||||
this.$toast('问卷提交成功', 3000) | |||||
setTimeout(() => { | |||||
window.history.back(-1) | |||||
}, 3000) | |||||
} else { | |||||
this.$toast(re.msg) | |||||
} | |||||
}, | |||||
onRadio(index, value) { | |||||
let temp = { ...this.topic[index] } | |||||
temp.select = value | |||||
this.$set(this.topic, index, temp) | |||||
}, | |||||
onCheckbox(key, index) { | |||||
try { | |||||
this.$refs[`${key}`][index].toggle() | |||||
} catch (error) { | |||||
console.log(error) | |||||
} | |||||
}, | |||||
api(url, config) { | |||||
setTimeout(() => { | |||||
this.$toast.loading({ | |||||
message: '', | |||||
forbidClick: true, | |||||
duration: 0, | |||||
}) | |||||
}, 100) | |||||
let baseUrl = 'http://172.16.1.97:9291' | |||||
return new Promise((res) => { | |||||
axios({ | |||||
url: `${baseUrl}${url}`, | |||||
...config, | |||||
}) | |||||
.then((re) => { | |||||
if (re) { | |||||
if (re.data) { | |||||
console.log(re.data) | |||||
res(re.data) | |||||
this.$toast.clear() | |||||
return | |||||
} | |||||
this.$toast(`信息获取失败-${re.status}`) | |||||
res(true) | |||||
this.$toast.clear() | |||||
return | |||||
} | |||||
this.$toast(`信息获取失败-${url}`) | |||||
res(true) | |||||
this.$toast.clear() | |||||
}) | |||||
.catch((e) => { | |||||
this.$toast(`信息获取失败-${url}`) | |||||
res(true) | |||||
this.$toast.clear() | |||||
console.log(e) | |||||
}) | |||||
}) | |||||
}, | |||||
}, | |||||
} | |||||
</script> | |||||
<style lang="scss" scoped> | |||||
.page { | |||||
width: 100%; | |||||
min-height: 100%; | |||||
box-sizing: border-box; | |||||
font-size: 3.6vw; | |||||
text-align: left; | |||||
background: #f4f4f4; | |||||
padding-bottom: 8vw; | |||||
padding-top: 24vw; | |||||
.top { | |||||
box-sizing: border-box; | |||||
position: fixed; | |||||
top: 0; | |||||
display: flex; | |||||
flex-direction: column; | |||||
justify-content: space-between; | |||||
padding: 3vw; | |||||
width: 100vw; | |||||
height: 24vw; | |||||
background: white; | |||||
z-index: 99; | |||||
.schedule { | |||||
display: flex; | |||||
align-items: center; | |||||
.progress { | |||||
width: 85%; | |||||
} | |||||
.text { | |||||
width: 15%; | |||||
font-size: 4.5vw; | |||||
text-align: center; | |||||
.val { | |||||
font-size: 5vw; | |||||
font-weight: bold; | |||||
} | |||||
} | |||||
} | |||||
.title { | |||||
color: #638ee4; | |||||
} | |||||
} | |||||
.list_box { | |||||
width: 100%; | |||||
margin-top: 3vw; | |||||
.item { | |||||
margin-top: 3vw; | |||||
padding: 3vw; | |||||
background: white; | |||||
.label { | |||||
font-size: 4vw; | |||||
} | |||||
} | |||||
} | |||||
.button { | |||||
width: 75vw; | |||||
height: 14vw; | |||||
margin: 0 auto; | |||||
margin-top: 8vw; | |||||
.van-button--info { | |||||
background-color: #638ee4; | |||||
border: 1px solid #638ee4; | |||||
} | |||||
} | |||||
} | |||||
</style> |