Browse Source

新增心理量表

test
wzl 3 months ago
parent
commit
352ad6b86b
4 changed files with 1098 additions and 0 deletions
  1. +3
    -0
      src/router/index.js
  2. +319
    -0
      src/views/psychological-scale/detail.vue
  3. +427
    -0
      src/views/psychological-scale/index.vue
  4. +349
    -0
      src/views/psychological-scale/list.vue

+ 3
- 0
src/router/index.js View File

@@ -56,6 +56,9 @@ const routes = [
// 心理监测
{ path: '/PsychologicalModeling', name: 'PsychologicalModeling', component: resolve => require(['@/views/psychological-modeling'], resolve) },
{ path: '/PsychologicalQuestionnaire', name: 'PsychologicalQuestionnaire', component: resolve => require(['@/views/psychological-questionnaire'], resolve) },
{ path: '/PsychologicalScale', name: 'PsychologicalScale', component: resolve => require(['@/views/psychological-scale'], resolve) },
{ path: '/PsychologicalScaleDetail', name: 'PsychologicalScaleDetail', component: resolve => require(['@/views/psychological-scale/detail'], resolve) },
{ path: '/PsychologicalScaleList', name: 'PsychologicalScaleList', component: resolve => require(['@/views/psychological-scale/list'], resolve) },

// 健康-心理监测详情,抑郁,压力和疲劳
{ path: '/psychological', name: 'psychological', component: resolve => require(['@/views/health/psychological'], resolve) },


+ 319
- 0
src/views/psychological-scale/detail.vue View File

@@ -0,0 +1,319 @@
<template>
<div class="page">
<van-nav-bar
title="测评结果"
:border="true"
:left-arrow="true"
@click-left="onNavBack"
v-if="showLeftArrow"
>
<template #left>
<van-icon name="arrow-left" size="23" style="padding: 0" />返回
</template>
</van-nav-bar>
<div class="content">
<div class="result-title">您的测评结果为:</div>
<div
class="result"
:style="{ color: levels[`${resultLevel}`].color }"
>
{{ levels[`${resultLevel}`].title }}
</div>
<div class="result-label">
<span>您的焦虑得分:</span>
<div
class="result-color"
:style="{ background: levels[`${resultLevel}`].color }"
></div>
</div>
<div class="result-details">
<div
class="result-details-item"
v-for="(item, index) in showLevels"
:key="index"
:style="{ width: `${100 / showLevels.length}%` }"
>
<div
class="result-details-item-icon"
:style="{ background: item.color }"
></div>
<div
class="result-details-item-title"
:style="{
color: resultLevel == index + 1 ? 'black' : 'gray',
}"
>
{{ item.title }}
</div>
</div>
</div>
<div class="result-label">总体评分:</div>
<div class="result-content">{{ result.Explain }}</div>
<div class="result-label">结果解释:</div>
<div class="result-content">{{ result.Advice }}</div>
</div>
</div>
</template>

<script>
import axios from 'axios'
import APICore from '@/api/core'

export default {
name: 'PsychologicalScaleDetail',
data() {
return {
id: '',
uid: '',
isError: null, //是否是答题错误
showLeftArrow: false,
fromSsjl: this.$store.getters.fromSsjl,
result: {
Advice: '',
Explain: '',
ScaleName: '',
Score: 15,
Summary: '',
SummaryLevel: '-1',
Time: '',
},
levels: [
{
show: false,
color: '#dfe4ea',
title: '暂无测评结果',
},
{
color: '#60B977',
title: '没有抑郁症状',
},
{
color: '#FFB600',
title: '轻度抑郁',
},
{
color: '#CC0003',
title: '重度抑郁',
},
],
}
},
computed: {
resultLevel(){
return parseInt(this.result.SummaryLevel) + 1
},
showLevels() {
return this.levels.filter((item) => {
if (!(item.show === false)) {
return true
}
})
},
},
watch: {},
mounted() {
//页面标题
window.document.title = '测评结果'

//页面传参
let params = { ...this.$route.query }

if (params.id && params.uid) {
this.id = params.id
this.uid = params.uid

// 缓存从随手精灵传过来的token
this.$store.commit('ssjlToken', params.accessToken || '')
if (params.appType) {
this.$store.commit('appType', params.appType)
}
// 缓存从随手精灵传过来的标识
this.$store.commit('fromSsjl', params.fromSsjl)
// 是否显示 返回标签
if (params.showLeftArrow) {
this.showLeftArrow = true
}
this.fromUrl = params.fromUrl
console.log('fromUrl', this.fromUrl)

//初始化
this.init()
} else {
this.$toast('参数错误')
}
},
methods: {
async init() {
if (!this.$route.query.accessToken) {
// 如果当前url没有 accessToken, 获取token,并且存储到本地缓存里面
let authToken = await this.getAuth()
this.$store.commit('ssjlToken', authToken)
}

this.$toast.loading({
message: '',
forbidClick: true,
duration: 0,
})

let re = await this.api(
'/api/Question/GetScaleFillingRecord',
{
method: 'GET',
sslVerify: false,
withCredentials: false,
params: {
uid: this.uid,
},
},
this.$store.getters.ssjlToken
)
if (re.success) {
if (re.response && re.response.length) {
re.response.forEach((item) => {
if (item.Id === this.id) {
this.result = item
}
})
} else {
// this.$toast('暂无测评结果')
}
} else {
this.$toast(re.msg)
}
},
onNavBack() {
let fromSsjl = this.$store.getters.fromSsjl === "true";
if (fromSsjl) {
let baseUrl = this.fromUrl;
window.location.href = `${baseUrl}/#/${this.$route.query.fromMenu || "device"
}`;
} else {
window.history.go(-1);
}
},
// 获取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 {
that.$toast.fail(`${data.message}`)
reject('')
}
})
})
},
api(url, config, token) {
setTimeout(() => {
this.$toast.loading({
message: '',
forbidClick: true,
duration: 1500,
})
}, 100)
let baseUrl =
process.env.NODE_ENV === 'production'
? 'https://dbmq.rzliot.com/auth_heart'
: 'https://dbmq.rzliot.com/heart'
return new Promise((res) => {
axios({
url: `${baseUrl}${url}`,
...config,
// 增加请求头部 token
headers: {
AccessToken: token,
},
})
.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;

.content {
padding: 4vw;

.result-title {
font-size: 4vw;
text-align: center;
}
.result {
font-size: 6vw;
text-align: center;
font-weight: bold;
margin-top: 4vw;
}
.result-label {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 4.5vw;
font-weight: bold;
margin-top: 6vw;
}
.result-color {
width: 5.5vw;
height: 5.5vw;
border-radius: 1vw;
}
.result-details {
display: flex;
margin-top: 4vw;

.result-details-item {
.result-details-item-icon {
width: 100%;
height: 5.5vw;
}
.result-details-item-title {
font-weight: bold;
text-align: center;
margin-top: 2vw;
}
}
}
.result-content {
font-size: 3.6vw;
margin-top: 2vw;
}
}
}
</style>

+ 427
- 0
src/views/psychological-scale/index.vue View File

@@ -0,0 +1,427 @@
<template>
<div class="page" v-if="topic.length">
<div class="top">
<div class="schedule">
<div class="progress">
<van-progress
:percentage="
(select.length == 0 ? 0 : select.length / topic.length) * 100
"
stroke-width="10px"
color="#638ee4"
:show-pivot="false"
v-if="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',
{
error:
(isError && fromSsjl && item.Id == '6') ||
(isError && fromSsjl && item.Id == '8') ||
(isError && fromSsjl && item.Id == '11'),
},
]"
>
<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)"
:title-class="[
{
cellTitle:
(isError && fromSsjl && item.Id == '6') ||
(isError && fromSsjl && item.Id == '8') ||
(isError && fromSsjl && item.Id == '11'),
},
]"
>
<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.Id}`, idx)"
>
<template #right-icon>
<van-checkbox :name="ite.value" :ref="`checkboxes${item.Id}`" />
</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'
import APICore from '@/api/core'

export default {
name: 'PsychologicalScale',
data() {
return {
uid: '',
keyCode: '',
title: '',
topic: [], //题目列表
select: [],
isError: null, //是否是答题错误
fromSsjl: this.$store.getters.fromSsjl,
}
},
mounted() {
//页面标题
window.document.title = '测评'

//页面传参
let params = { ...this.$route.query }

if (params.uid) {
this.uid = params.uid

// 缓存从随手精灵传过来的token
this.$store.commit('ssjlToken', params.accessToken || '')
if (params.appType) {
this.$store.commit('appType', params.appType)
}
// 缓存从随手精灵传过来的标识
this.$store.commit('fromSsjl', params.fromSsjl)
// 是否显示 返回标签
this.showLeftArrow = this.$store.getters.fromSsjl === 'true'
this.fromUrl = params.fromUrl
console.log('fromUrl', this.fromUrl)

//初始化
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() {
if (!this.$route.query.accessToken) {
// 如果当前url没有 accessToken, 获取token,并且存储到本地缓存里面
let authToken = await this.getAuth()
this.$store.commit('ssjlToken', authToken)
}

let re = await this.api(
'/api/Question/GetScaleQuestion',
{
method: 'GET',
sslVerify: false,
withCredentials: false,
params: {
// uid: this.uid,
code: 'EPDS',
},
},
this.$store.getters.ssjlToken
)
if (re.success) {
if (
re.response &&
re.response.ScaleQuestionDetails &&
re.response.ScaleQuestionDetails.length
) {
let code = re.response.Code
this.title = re.response.Name
this.keyCode = re.response.Code

let temp = re.response.ScaleQuestionDetails

let topic = []
temp.forEach((item) => {
let tempt = { ...item }
if (!tempt.Type) {
tempt.Type = '单选题'
}
let a1 = tempt.Option.split('&')
let option = []
for (let index = 0; index < a1.length; index++) {
option.push({
label: a1[index],
value: index + 1,
})
}
tempt.Option = option
tempt.value = ''
topic.push(tempt)
})

this.topic = topic
} 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.Id, //问卷题目编号
value:
typeof item.select == 'object'
? item.select.join(',')
: item.select, //用户所选答案的 id
})
})
let re = await this.api(
'/api/Question/ScaleRsults',
{
method: 'POST',
sslVerify: false,
withCredentials: false,
data: temp,
},
this.$store.getters.ssjlToken
)
if (re.success && re.response) {
this.$toast('问卷提交成功', 3000)
this.isError = false
setTimeout(() => {
// 2023.09.25 使用此返回方法可能会导致页面返回异常,故使用路由跳转到指定页面
this.$router.replace({
name: 'PsychologicalScaleDetail',
query: {
id: re.response.Id,
uid: this.uid,
accessToken: this.$store.getters.ssjlToken,
},
})
}, 3000)
} else {
//this.$toast(re.msg);
this.$dialog.confirm({
message: re.msg,
showCancelButton: false,
})
this.isError = true
}
},
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)
}
},
// 获取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 {
that.$toast.fail(`${data.message}`)
reject('')
}
})
})
},
api(url, config, token) {
setTimeout(() => {
this.$toast.loading({
message: '',
forbidClick: true,
duration: 1500,
})
}, 100)
let baseUrl =
process.env.NODE_ENV === 'production'
? 'https://dbmq.rzliot.com/auth_heart'
: 'https://dbmq.rzliot.com/heart'
return new Promise((res) => {
axios({
url: `${baseUrl}${url}`,
...config,
// 增加请求头部 token
headers: {
AccessToken: token,
},
})
.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;
&.error {
color: red;
}
}
.van-cell {
.van-cell__title {
&.cellTitle {
color: red;
}
}
}
}
}

.button {
width: 75vw;
height: 14vw;
margin: 0 auto;
margin-top: 8vw;

.van-button--info {
background-color: #638ee4;
border: 1px solid #638ee4;
}
}
}
</style>

+ 349
- 0
src/views/psychological-scale/list.vue View File

@@ -0,0 +1,349 @@
<template>
<div class="page">
<van-nav-bar
title="我的测评"
:border="true"
:left-arrow="true"
@click-left="onNavBack"
v-if="showLeftArrow"
>
<template #left>
<van-icon name="arrow-left" size="23" style="padding: 0" />返回
</template>
</van-nav-bar>
<div class="content" v-if="result.length">
<div
class="item"
v-for="(item, index) in result"
:key="index"
@click="toDetail(item)"
>
<div class="left">
<div class="name">{{ item.ScaleName }}</div>
<div class="result">
<span>评测结果:</span>
<span>{{ item.Summary }}</span>
</div>
<div class="time">
{{ formateDate('yyyy年mm月dd日 HH:MM', item.Time) }}
</div>
</div>
<div class="right">
<div class="button">查看结果</div>
</div>
</div>
</div>
<div class="blank" v-else>暂无测评记录</div>
</div>
</template>

<script>
import axios from 'axios'
import APICore from '@/api/core'

export default {
name: 'PsychologicalScaleList',
data() {
return {
uid: '',
isError: null, //是否是答题错误
showLeftArrow: false,
fromSsjl: this.$store.getters.fromSsjl,
result: [],
}
},
computed: {
showLevels() {
return this.levels.filter((item) => {
if (!(item.show === false)) {
return true
}
})
},
},
watch: {},
mounted() {
//页面标题
window.document.title = '测评记录'

//页面传参
let params = { ...this.$route.query }

if (params.uid) {
this.uid = params.uid

// 缓存从随手精灵传过来的token
this.$store.commit('ssjlToken', params.accessToken || '')
if (params.appType) {
this.$store.commit('appType', params.appType)
}
// 缓存从随手精灵传过来的标识
this.$store.commit('fromSsjl', params.fromSsjl)
// 是否显示 返回标签
if (params.showLeftArrow) {
this.showLeftArrow = true
}
this.fromUrl = params.fromUrl
console.log('fromUrl', this.fromUrl)

//初始化
this.init()
} else {
this.$toast('参数错误')
}
},
methods: {
async init() {
if (!this.$route.query.accessToken) {
// 如果当前url没有 accessToken, 获取token,并且存储到本地缓存里面
let authToken = await this.getAuth()
this.$store.commit('ssjlToken', authToken)
}

this.$toast.loading({
message: '',
forbidClick: true,
duration: 0,
})

let re = await this.api(
'/api/Question/GetScaleFillingRecord',
{
method: 'GET',
sslVerify: false,
withCredentials: false,
params: {
uid: this.uid,
},
},
this.$store.getters.ssjlToken
)
if (re.success) {
if (re.response && re.response.length) {
this.result = re.response
} else {
// this.$toast('暂无测评结果')
}
} else {
this.$toast(re.msg)
}
},
toDetail(item) {
this.$router.push({
name: 'PsychologicalScaleDetail',
query: {
id: item.Id,
uid: this.uid,
accessToken: this.$store.getters.ssjlToken,
showLeftArrow: 1,
},
})
},
onNavBack() {
let fromSsjl = this.$store.getters.fromSsjl === 'true'
if (fromSsjl) {
let baseUrl = this.fromUrl
window.location.href = `${baseUrl}/#/${
this.$route.query.fromMenu || 'device'
}`
} else {
window.history.go(-1)
}
},
// 获取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 {
that.$toast.fail(`${data.message}`)
reject('')
}
})
})
},
api(url, config, token) {
setTimeout(() => {
this.$toast.loading({
message: '',
forbidClick: true,
duration: 1500,
})
}, 100)
let baseUrl =
process.env.NODE_ENV === 'production'
? 'https://dbmq.rzliot.com/auth_heart'
: 'https://dbmq.rzliot.com/heart'
return new Promise((res) => {
axios({
url: `${baseUrl}${url}`,
...config,
// 增加请求头部 token
headers: {
AccessToken: token,
},
})
.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)
})
})
},
formateDate(fmt = 'yyyy-mm-dd', date = '') {
if (!date) {
date = new Date()
}

try {
if (typeof date == 'string') {
date = date.replace(/-/g, '/').replace(/T/g, ' ')
if (date.indexOf('/') == -1) {
date = new Date(parseFloat(date))
}
date = new Date(date)
} else if (typeof date == 'number') {
date = new Date(date)
}
} catch (error) {
console.log('时间格式化出错', error)
date = new Date()
}

let ret
let weak = (function (date) {
let days = date.getDay()
let weekArrTxt = [
'星期天',
'星期一',
'星期二',
'星期三',
'星期四',
'星期五',
'星期六',
]
let weekArrTxt2 = [
'周日',
'周一',
'周二',
'周三',
'周四',
'周五',
'周六',
]
return [weekArrTxt[days], weekArrTxt2[days]]
})(date)
const opt = {
'y+': date.getFullYear().toString(), // 年
'm+': (date.getMonth() + 1).toString(), // 月
'd+': date.getDate().toString(), // 日
'H+': date.getHours().toString(), // 时
'M+': date.getMinutes().toString(), // 分
'S+': date.getSeconds().toString(), // 秒
// 有其他格式化字符需求可以继续添加,必须转化成字符串
'W+': weak[0],
'w+': weak[1],
}
for (let k in opt) {
ret = new RegExp('(' + k + ')').exec(fmt)
if (ret) {
fmt = fmt.replace(
ret[1],
ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, '0')
)
}
}
return fmt
},
},
}
</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;

.content {
padding: 2vw;

.item {
display: flex;
align-items: flex-end;
justify-content: space-between;
padding: 4vw;
margin-top: 2vw;
border-radius: 1vw;
background: white;

.left{

.name{
font-size: 4vw;
font-weight: bold;
}
.time{
color: gray;
margin-top: 4vw;
}
.result{
font-size: 3.8vw;
margin-top: 4vw;
}
}
.right{

.button{
color: #15C6BE;
padding: 2vw 3vw;
border-radius: 8vw;
border: 1px solid #15C6BE;

&:active{
background-color: rgba($color: #15C6BE, $alpha: 0.1);
}
}
}
}
}

.blank {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 80vh;
color: gray;
font-size: 5vw;
font-weight: bold;
letter-spacing: 5px;
}
}
</style>

Loading…
Cancel
Save