update
init
This commit is contained in:
@@ -0,0 +1,356 @@
|
||||
<template>
|
||||
<div class="detail-container">
|
||||
<div class="detail-con">
|
||||
<div class="activity-con">
|
||||
<div :class="useStatus(details.state).class" class="status">{{ useStatus(details.state).name }}</div>
|
||||
<div class="title">
|
||||
<span class="title-status" v-if="details.userState === 1">已参加</span>
|
||||
<span class="title-con" :style="details.userState === 1 ? 'width: 70%' : 'width: 89%'">{{ details.examPlanName }}</span>
|
||||
</div>
|
||||
<div class="participate">
|
||||
<span>{{ details.questionCategory }}</span>
|
||||
<span v-if="details.userState === 1">已参与{{ details.actualJoinNumber }}人</span>
|
||||
</div>
|
||||
<div class="question-number"
|
||||
>共{{ details?.examPaperRule?.questionSum === null ? 0 : details?.examPaperRule?.questionSum }}道题 答题时长为{{
|
||||
details?.examPaperRule?.answerTime
|
||||
}}分钟</div
|
||||
>
|
||||
<div class="answerInfo">
|
||||
<div class="answer-item">
|
||||
<span>起止时间:</span>
|
||||
<span>{{ timeSplit(details.startTime) }} ~ {{ timeSplit(details.endTime) }}</span>
|
||||
</div>
|
||||
<div class="answer-item">
|
||||
<span>组织部门:</span>
|
||||
<span>{{ details.organizerDeptName }}</span>
|
||||
</div>
|
||||
<div class="answer-item head">
|
||||
<span>负责人:</span>
|
||||
<span>{{ details.managerName }}</span>
|
||||
<!-- <a href="tel:18719873644">打电话</a>-->
|
||||
<span :class="['contact', details.state !== '2' ? 'defaultImg' : 'no-contact']" @click="handlePhone"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="level-con">
|
||||
<div class="title">奖励等级标准</div>
|
||||
<div class="encourage" v-html="details.awardLevelStandard"></div>
|
||||
</div>
|
||||
<ranke-lists :listsInfo="listsInfo" :detailID="detailID" :allShow="true" />
|
||||
</div>
|
||||
<!-- 活动状态 state (状态0-未开始,1进行中,2-已结束)-->
|
||||
<div class="application-btn" v-if="['0', '1', '2'].includes(details.state)">
|
||||
<div :class="['btn', appBtnClass()]" @click="handleApplication">报名参加</div>
|
||||
</div>
|
||||
<dialog-overlay
|
||||
:show="dialogCon.show"
|
||||
:imgUrl="dialogCon.url"
|
||||
:okText="dialogCon.okText"
|
||||
@cancel="handleCancel"
|
||||
:cancelBtn="dialogCon.cancelBtn"
|
||||
@ok="handleOk"
|
||||
>
|
||||
<template #content>
|
||||
<div class="overlay-con">{{dialogCon.con}}</div>
|
||||
</template>
|
||||
</dialog-overlay>
|
||||
<van-action-sheet v-model:show="actionSheet" :actions="actions" @select="sheetChange" cancel-text="取消" close-on-click-action />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useStatus, timeSplit } from '/@/views/23-physical-questions/questionHooks';
|
||||
import rankeLists from '/@/views/23-physical-questions/components/rankeLists.vue';
|
||||
import dialogOverlay from '/@/views/23-physical-questions/components/dialogOverlay.vue';
|
||||
import tipsIcon from '/@/assets/images/questions/tips.png';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { activieDetailApi, rankeListApi } from '/@/views/23-physical-questions/questionApI';
|
||||
import { newPageParams, openPage } from '/@/hooks/openPage';
|
||||
|
||||
const actionSheet = ref(false);
|
||||
const actions = ref([]);
|
||||
const dialogCon = ref({
|
||||
show: false,
|
||||
url: tipsIcon,
|
||||
con: '',
|
||||
type: 1, // 1答题 2提示
|
||||
cancelBtn: true,
|
||||
okText: '开始答题',
|
||||
});
|
||||
const route = useRoute();
|
||||
const details = ref<any>({});
|
||||
const detailID = ref('');
|
||||
const listsInfo = ref({});
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
function getList() {
|
||||
activieDetailApi({
|
||||
id: route.query.id,
|
||||
}).then((res: any) => {
|
||||
if (res.code === 200) {
|
||||
let awardLevel = res.result.awardLevelStandard;
|
||||
res.result.awardLevelStandard = awardLevel !== null ? res.result?.awardLevelStandard.replace(/\n/g, '<br/>') : '';
|
||||
details.value = res.result;
|
||||
detailID.value = res.result.id;
|
||||
getRankeList(res.result.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
// 排名列表
|
||||
function getRankeList(id: string) {
|
||||
rankeListApi({
|
||||
examPlanId: id,
|
||||
}).then((res: any) => {
|
||||
if (res.code === 200) {
|
||||
listsInfo.value = res.result;
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 报名参加
|
||||
* @parmas 活动状态 state 0 未开始、state 1 进行中、 state 2 已结束
|
||||
* @parmas 参加状态 userState 1 已参加 、userState 0 未参加
|
||||
*/
|
||||
function handleApplication() {
|
||||
if (details.value.state === '1' && details.value.userState === 0) {
|
||||
let val = details.value;
|
||||
dialogCon.value.show = true;
|
||||
dialogCon.value.con = `共${val?.examPaperRule?.questionSum === null ? 0 : val?.examPaperRule?.questionSum}道题,答题时长为${
|
||||
val?.examPaperRule?.answerTime
|
||||
}分钟,是否确认开始答题?`;
|
||||
}
|
||||
}
|
||||
function handleCancel() {
|
||||
dialogCon.value.show = false;
|
||||
}
|
||||
function handleOk() {
|
||||
if (dialogCon.value.type === 1) {
|
||||
openPage(
|
||||
'/physical-answer',
|
||||
newPageParams({
|
||||
id: details.value.id,
|
||||
answerTime: details.value?.examPaperRule?.answerTime,
|
||||
affirmBack: 1,
|
||||
active: true,
|
||||
})
|
||||
);
|
||||
}
|
||||
dialogCon.value.show = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @parmas 活动状态 state 0 未开始 、活动状态 state 1 进行中、 state 2 已结束
|
||||
* @parmas 参加状态 userState 1 已参加 、userState 0 未参加
|
||||
*/
|
||||
function appBtnClass() {
|
||||
let text = '';
|
||||
if (details.value.state === '1') {
|
||||
if (details.value.userState === 0) {
|
||||
text = 'active-btn';
|
||||
} else {
|
||||
text = 'no-active-btn';
|
||||
}
|
||||
} else {
|
||||
text = 'no-active-btn';
|
||||
}
|
||||
return text;
|
||||
}
|
||||
// 打电话
|
||||
function handlePhone() {
|
||||
if (details.value.state !== '2') {
|
||||
actionSheet.value = true;
|
||||
actions.value = [{ name: details.value.managerPhone }];
|
||||
}
|
||||
}
|
||||
function sheetChange() {
|
||||
// const el = document.createElement('a');
|
||||
// el.href = `tel://${details.value.managerPhone}`;
|
||||
// document.body.appendChild(el);
|
||||
// el.click();
|
||||
// document.body.removeChild(el);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import '/@/assets/less/question.less';
|
||||
.detail-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
padding: 10px 20px;
|
||||
background-color: #f5f7fb;
|
||||
position: relative;
|
||||
.overlay-con{
|
||||
text-align: center;
|
||||
}
|
||||
.detail-con {
|
||||
width: 100%;
|
||||
height: calc(100vh - 60px);
|
||||
overflow-y: auto;
|
||||
.activity-con {
|
||||
width: 100%;
|
||||
background-color: #ffffff;
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
margin: 14px 0;
|
||||
.status {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 60px;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
border-top-right-radius: 16px;
|
||||
border-bottom-left-radius: 16px;
|
||||
}
|
||||
.progress-status {
|
||||
background-color: #f2742c;
|
||||
color: #ffffff;
|
||||
}
|
||||
.end-status {
|
||||
background-color: #dddddd;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.title-status {
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
background-color: rgba(82, 196, 26, 0.2);
|
||||
border-radius: 9px;
|
||||
color: #52c41a;
|
||||
font-size: 12px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.title-con {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
.participate {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
color: #999999;
|
||||
padding: 12px 0;
|
||||
font-size: 14px;
|
||||
span:nth-child(1) {
|
||||
width: 62%;
|
||||
}
|
||||
span:nth-child(2) {
|
||||
position: relative;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: -20px;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
background: url('/@/assets/images/questions/participateIcon.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.question-number {
|
||||
font-weight: 500;
|
||||
color: #999999;
|
||||
}
|
||||
.answerInfo {
|
||||
margin-top: 10px;
|
||||
padding: 14px;
|
||||
border-radius: 16px;
|
||||
background-color: #eff5ff;
|
||||
.answer-item {
|
||||
padding: 3px 0;
|
||||
> span:nth-child(1) {
|
||||
display: inline-block;
|
||||
width: 28%;
|
||||
color: #666666;
|
||||
}
|
||||
> span:nth-child(2) {
|
||||
color: #333333;
|
||||
}
|
||||
> span:nth-child(3) {
|
||||
padding-left: 14px;
|
||||
}
|
||||
}
|
||||
.head {
|
||||
position: relative;
|
||||
}
|
||||
.contact {
|
||||
position: absolute;
|
||||
right: 2px;
|
||||
bottom: 3px;
|
||||
width: 85px;
|
||||
height: 24px;
|
||||
}
|
||||
.defaultImg {
|
||||
background: url('/@/assets/images/questions/contact.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.no-contact {
|
||||
color: #666666;
|
||||
background: url('/@/assets/images/questions/no-contact.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.level-con {
|
||||
padding: 20px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 16px;
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.encourage {
|
||||
padding: 8px 0;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
.application-btn {
|
||||
width: 100%;
|
||||
height: 55px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.btn {
|
||||
width: 80%;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
border-radius: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.active-btn {
|
||||
background-color: #1a68ee;
|
||||
color: #ffffff;
|
||||
}
|
||||
.no-active-btn {
|
||||
background-color: #dddddd;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="less">
|
||||
@import '/@/assets/less/question.less';
|
||||
</style>
|
||||
@@ -0,0 +1,244 @@
|
||||
<template>
|
||||
<div class="answerActivity-container">
|
||||
<div class="activity-title">
|
||||
<div class="active-item" v-for="act in tagLists" :key="act.key">
|
||||
<span :class="activeTag === act.key ? 'active' : 'default'" @click="handleTags(act.key)">{{ act.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="activity-container" ref="activeRefs">
|
||||
<template v-if="lists.length > 0">
|
||||
<div class="activity-con" v-for="listItem in lists" @click="handleDetail(listItem)">
|
||||
<div :class="useStatus(listItem.state).class" class="status">{{ useStatus(listItem.state).name }}</div>
|
||||
<div class="title">
|
||||
<span class="title-status" v-if="listItem.userState === 1">已参加</span>
|
||||
<span class="title-con">{{ listItem.examPlanName }}</span>
|
||||
</div>
|
||||
<div class="participate">
|
||||
<span>{{ listItem.questionCategory }}</span>
|
||||
<span v-if="listItem.userState === 1">已参与{{ listItem.actualJoinNumber }}人</span>
|
||||
</div>
|
||||
<div class="question-number"
|
||||
>共{{ listItem.questionSum === null ? 0 : listItem.questionSum }}道题 答题时长为{{listItem.answerTime }}分钟</div
|
||||
>
|
||||
<div class="answerInfo">
|
||||
<div class="answer-item">
|
||||
<span>起止时间:</span>
|
||||
<span>{{ timeSplit(listItem.startTime) }} ~ {{ timeSplit(listItem.endTime) }}</span>
|
||||
</div>
|
||||
<div class="answer-item">
|
||||
<span>组织部门:</span>
|
||||
<span>{{ listItem.organizerDeptName }}</span>
|
||||
</div>
|
||||
<div class="answer-item">
|
||||
<span>负责人:</span>
|
||||
<span>{{ listItem.managerName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="answer-data" v-else>
|
||||
<Nodata />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useStatus, timeSplit } from '/@/views/23-physical-questions/questionHooks';
|
||||
import { activieListApi } from '/@/views/23-physical-questions/questionApI';
|
||||
import { showFailToast } from 'vant';
|
||||
import Nodata from '/@/views/23-physical-questions/components/noData.vue';
|
||||
import { newPageParams, openPage } from '/@/hooks/openPage';
|
||||
|
||||
const activeTag = ref(0);
|
||||
const tagLists = ref([
|
||||
{
|
||||
name: '全部活动',
|
||||
key: 0,
|
||||
},
|
||||
{
|
||||
name: '我参与的',
|
||||
key: 1,
|
||||
},
|
||||
]);
|
||||
const lists = ref([]);
|
||||
const activeRefs = ref(null);
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
function getList() {
|
||||
activieListApi({
|
||||
type: activeTag.value,
|
||||
}).then((res: any) => {
|
||||
if (res.code === 200) {
|
||||
lists.value = res.result.records;
|
||||
} else {
|
||||
showFailToast({
|
||||
message: res.message,
|
||||
forbidClick: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
function handleTags(active: number) {
|
||||
activeRefs.value.scrollTop = 0;
|
||||
activeTag.value = active;
|
||||
getList();
|
||||
}
|
||||
|
||||
function handleDetail(item: any) {
|
||||
openPage(
|
||||
'/physical-activityDetail',
|
||||
newPageParams({
|
||||
id: item.id,
|
||||
startNewActivity: -1,
|
||||
})
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import '/@/assets/less/question.less';
|
||||
.answerActivity-container {
|
||||
width: 100%;
|
||||
padding: 10px 20px;
|
||||
background-color: #f5f7fb;
|
||||
.activity-title {
|
||||
display: flex;
|
||||
margin-bottom: 5px;
|
||||
.active-item {
|
||||
margin: 0 10px;
|
||||
}
|
||||
.active {
|
||||
color: #333333;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 9px;
|
||||
background: linear-gradient(0deg, #1a68ee 0%, rgba(255, 255, 255, 0) 100%);
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
.default {
|
||||
font-weight: 500;
|
||||
color: #77849e;
|
||||
}
|
||||
}
|
||||
.activity-container {
|
||||
width: 100%;
|
||||
height: calc(100vh - 47px);
|
||||
overflow-y: auto;
|
||||
.answer-data {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
}
|
||||
.activity-con {
|
||||
width: 100%;
|
||||
background-color: #ffffff;
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
margin: 14px 0;
|
||||
.status {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 60px;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
border-top-right-radius: 16px;
|
||||
border-bottom-left-radius: 16px;
|
||||
}
|
||||
.progress-status {
|
||||
background-color: #f2742c;
|
||||
color: #ffffff;
|
||||
}
|
||||
.end-status {
|
||||
background-color: #dddddd;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.title-status {
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
background-color: rgba(82, 196, 26, 0.2);
|
||||
border-radius: 9px;
|
||||
color: #52c41a;
|
||||
font-size: 12px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.title-con {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
width: 70%;
|
||||
.text-over();
|
||||
}
|
||||
}
|
||||
.participate {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
color: #999999;
|
||||
padding: 12px 0;
|
||||
font-size: 14px;
|
||||
span:nth-child(1) {
|
||||
width: 62%;
|
||||
.text-over();
|
||||
}
|
||||
span:nth-child(2) {
|
||||
position: relative;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: -20px;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
background: url('/@/assets/images/questions/participateIcon.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.question-number {
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
}
|
||||
.answerInfo {
|
||||
margin-top: 10px;
|
||||
padding: 14px;
|
||||
border-radius: 16px;
|
||||
background-color: #eff5ff;
|
||||
.answer-item {
|
||||
padding: 3px 0;
|
||||
> span:nth-child(1) {
|
||||
display: inline-block;
|
||||
width: 70px;
|
||||
color: #666666;
|
||||
}
|
||||
> span:nth-child(2) {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div class="level-container">
|
||||
<div class="level-bg">
|
||||
<img :src="rankeTitle" />
|
||||
</div>
|
||||
<div class="level-list">
|
||||
<ranke-lists :listsInfo="listsInfo" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import rankeLists from '/@/views/23-physical-questions/components/rankeLists.vue';
|
||||
import rankeTitle from '/@/assets/images/questions/rankeTitle.png';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { rankeListApi } from '/@/views/23-physical-questions/questionApI';
|
||||
|
||||
const route = useRoute();
|
||||
const listsInfo = ref({});
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
function getList() {
|
||||
rankeListApi({
|
||||
examPlanId: route.query.id,
|
||||
}).then((res: any) => {
|
||||
if (res.code === 200) {
|
||||
listsInfo.value = res.result;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.level-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
overflow-y: auto;
|
||||
background-color: #f5f7fb;
|
||||
.level-bg {
|
||||
width: 100%;
|
||||
height: 234px;
|
||||
background: url("/@/assets/images/questions/ranke-bg.png") no-repeat;
|
||||
background-size: contain;
|
||||
img {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 50px;
|
||||
width: 60%;
|
||||
height: 43px;
|
||||
}
|
||||
}
|
||||
.level-list {
|
||||
width: 90%;
|
||||
height: calc(100vh - 120px);
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 110px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,299 @@
|
||||
<template>
|
||||
<div class="answer-home-container">
|
||||
<van-skeleton title :row="8" :loading="loading">
|
||||
<div class="times">倒计时:{{ formatTime }}</div>
|
||||
<div class="interval"></div>
|
||||
<div class="question">
|
||||
<question-card :item="questionItem" :ifAnswer="true" @selectOption="selectAnswer" />
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<answer-panel :list="list" :currentNo="currentIndex" :isEdit="true" @last="handleSheet" @next="handleSheet" @submit="handleSubmit" />
|
||||
</div>
|
||||
</van-skeleton>
|
||||
<dialog-overlay
|
||||
:show="dialogCon.show"
|
||||
:imgUrl="dialogCon.url"
|
||||
:okText="dialogCon.okText"
|
||||
:cancelBtn="dialogCon.canBtn"
|
||||
@cancel="handleCancel"
|
||||
@ok="handleOk"
|
||||
>
|
||||
<template #content>
|
||||
<div class="overlay-con">{{dialogCon.con}}</div>
|
||||
</template>
|
||||
</dialog-overlay>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, watch } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import questionCard from '/@/views/23-physical-questions/answer/questionCard.vue';
|
||||
import answerPanel from '/@/views/23-physical-questions/answer/answerPanel.vue';
|
||||
import dialogOverlay from '/@/views/23-physical-questions/components/dialogOverlay.vue';
|
||||
import tipsIcon from '/@/assets/images/questions/tips.png';
|
||||
import warnIcon from '/@/assets/images/questions/warn.png';
|
||||
import clockIcon from '/@/assets/images/questions/clock.png';
|
||||
import { convertTimeToSeconds, usePageAnswer, minuteConverSeconds, useCountdown } from '/@/views/23-physical-questions/questionHooks';
|
||||
import {
|
||||
destroyPage,
|
||||
newPageParams,
|
||||
openPage,
|
||||
refreshPage,
|
||||
setAnswerResult
|
||||
} from "/@/hooks/openPage";
|
||||
import {
|
||||
questionListApi,
|
||||
activieQuestionListApi,
|
||||
submitApi,
|
||||
activieSubmitApi,
|
||||
firstAidListApi,
|
||||
} from '/@/views/23-physical-questions/questionApI';
|
||||
import { showFailToast } from 'vant';
|
||||
import $bus from '/@/utils/mitt';
|
||||
import { useInterceptBack } from '/@/hooks/useInterceptAndroid';
|
||||
import { useLoading } from "/@/utils/compUtils";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const loading = ref(true);
|
||||
const dialogCon = ref({
|
||||
show: false,
|
||||
url: '',
|
||||
con: '',
|
||||
canBtn: true,
|
||||
type: 2, // 2退出 3 倒计时结束 4 提示
|
||||
okText: '',
|
||||
});
|
||||
const currentIndex = ref<number>(0);
|
||||
const questionItem = ref({});
|
||||
const list = ref<any>([]);
|
||||
const platform = sessionStorage.getItem('platform');
|
||||
const { formatTime, startTimer, stopTimer } = useCountdown(route.query.answerTime);
|
||||
const submitParams = ref<any>({
|
||||
paperId: '', // 考卷ID
|
||||
answerTimeSum: '', // 答题总耗时(单位:分钟)
|
||||
userSubmitAnswerDetailsDTOS: [], // 用户答案
|
||||
});
|
||||
const { loadingSpinner, loadingClose } = useLoading();
|
||||
|
||||
onMounted(() => {
|
||||
useInterceptBack(1, dropOut);
|
||||
if (platform !== null) {
|
||||
if (platform === 'C03') {
|
||||
getAidQuestion();
|
||||
} else {
|
||||
route.query.hasOwnProperty('active') ? getActiveQuestion() : getQuestion();
|
||||
}
|
||||
}
|
||||
});
|
||||
watch(formatTime, (newVal) => {
|
||||
if (convertTimeToSeconds(newVal) === 0) {
|
||||
dialogCon.value.show = true;
|
||||
dialogCon.value.con = '时间到,当前答题已结束。';
|
||||
dialogCon.value.canBtn = false;
|
||||
dialogCon.value.url = clockIcon;
|
||||
dialogCon.value.type = 2;
|
||||
dialogCon.value.okText = '确认';
|
||||
stopTimer();
|
||||
}
|
||||
});
|
||||
$bus.on('selectSheet', (index) => {
|
||||
let quItem = list.value[index];
|
||||
quItem['index'] = index;
|
||||
questionItem.value = quItem;
|
||||
currentIndex.value = index;
|
||||
});
|
||||
// 中途退出弹窗
|
||||
function dropOut() {
|
||||
dialogCon.value.show = true;
|
||||
dialogCon.value.con = '中途退出将不会保存您的答案,是否确定退出?';
|
||||
dialogCon.value.url = clockIcon;
|
||||
dialogCon.value.type = 3;
|
||||
dialogCon.value.okText = '退出答题';
|
||||
}
|
||||
// 获取随机试卷
|
||||
function getQuestion() {
|
||||
questionListApi({ questionCategoryId: route.query.id }).then((res: any) => {
|
||||
handlePaper(res);
|
||||
});
|
||||
}
|
||||
// 获取活动试卷
|
||||
function getActiveQuestion() {
|
||||
activieQuestionListApi({ examPlanId: route.query.id }).then((res: any) => {
|
||||
handlePaper(res);
|
||||
});
|
||||
}
|
||||
// 获取急救培训试卷
|
||||
function getAidQuestion() {
|
||||
firstAidListApi({ activityId: route.query.id }).then((res: any) => {
|
||||
handlePaper(res);
|
||||
});
|
||||
}
|
||||
// 试卷数据进行处理显示
|
||||
function handlePaper(res: any) {
|
||||
if (res.code === 200) {
|
||||
loading.value = false;
|
||||
if (res.result.examPaperQuestions.length === 0) {
|
||||
return false;
|
||||
}
|
||||
startTimer();
|
||||
res.result.examPaperQuestions.map((item: any) => {
|
||||
item['user_answer'] = '';
|
||||
});
|
||||
submitParams.value.paperId = res.result.id;
|
||||
list.value = res.result.examPaperQuestions;
|
||||
let quItem = list.value[0];
|
||||
quItem['index'] = currentIndex.value;
|
||||
questionItem.value = quItem;
|
||||
} else {
|
||||
dialogCon.value.show = true;
|
||||
dialogCon.value.con = res.message;
|
||||
dialogCon.value.url = tipsIcon;
|
||||
dialogCon.value.type = 4;
|
||||
dialogCon.value.canBtn = false;
|
||||
dialogCon.value.okText = '我知道了';
|
||||
}
|
||||
}
|
||||
// 上一题、下一题
|
||||
function handleSheet(type: string) {
|
||||
const { answer_item, c_index } = usePageAnswer(list.value, type, currentIndex.value);
|
||||
questionItem.value = answer_item;
|
||||
currentIndex.value = c_index;
|
||||
}
|
||||
// 改变用户选择选项样式
|
||||
function selectAnswer(answer: string, item: object) {
|
||||
let findIndex = list.value.findIndex((e) => e.id === item.id);
|
||||
list.value[findIndex].user_answer = answer;
|
||||
}
|
||||
function handleCancel() {
|
||||
dialogCon.value.show = false;
|
||||
}
|
||||
function handleOk() {
|
||||
dialogCon.value.show = false;
|
||||
let type = dialogCon.value.type;
|
||||
if (platform === 'C03') {
|
||||
if (type === 2) {
|
||||
// 倒计时时间到,点击确定提交
|
||||
handleSubmit();
|
||||
} else if (type === 3) {
|
||||
// 中途退出点击,退出答案按按钮,返回首页列表
|
||||
try {
|
||||
destroyPage();
|
||||
} catch {
|
||||
router.go(-1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (type === 2) {
|
||||
// 倒计时时间到,点击确定提交
|
||||
handleSubmit();
|
||||
} else if (type === 3 || type === 4) {
|
||||
// 1. type:3 中途退出点击,退出答案按按钮,返回上一个页面
|
||||
// 2. type:4 错误弹窗,返回上一个页面
|
||||
try {
|
||||
destroyPage();
|
||||
} catch {
|
||||
router.go(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 提交答案参数
|
||||
function setParams() {
|
||||
let answerList: { answer: string; questionId: string }[] = [];
|
||||
list.value.map((item: any) => {
|
||||
answerList.push({
|
||||
answer: item.user_answer,
|
||||
questionId: item.id,
|
||||
});
|
||||
});
|
||||
const totalTimer = minuteConverSeconds(route.query.answerTime); // 总时间(秒)
|
||||
const consumeTimer = convertTimeToSeconds(formatTime.value); // 未消耗时间(秒)
|
||||
const diffTimer = totalTimer - consumeTimer; // 已消耗时间(秒)
|
||||
const finalTimer = diffTimer =='0'?totalTimer:diffTimer;
|
||||
submitParams.value.answerTimeSum = finalTimer;
|
||||
submitParams.value.userSubmitAnswerDetailsDTOS = answerList;
|
||||
}
|
||||
async function handleSubmit() {
|
||||
loadingSpinner();
|
||||
await setParams();
|
||||
route.query.hasOwnProperty('active') ? await submitActivty() : await submitRound();
|
||||
}
|
||||
// 随机提交答案
|
||||
function submitRound() {
|
||||
submitApi(submitParams.value).then((res: any) => {
|
||||
result(res);
|
||||
});
|
||||
}
|
||||
// 活动提交答案
|
||||
function submitActivty() {
|
||||
activieSubmitApi(submitParams.value).then((res: any) => {
|
||||
result(res);
|
||||
});
|
||||
}
|
||||
// 提交答案提交后逻辑处理
|
||||
function result(res: any) {
|
||||
useInterceptBack(0);
|
||||
if (res.code === 200) {
|
||||
loadingClose();
|
||||
refreshPage();
|
||||
if (platform === 'C03') {
|
||||
const resParams = { ...res.result, activityId: route.query.id };
|
||||
setAnswerResult(JSON.stringify(resParams));
|
||||
stopTimer();
|
||||
} else {
|
||||
router.replace({
|
||||
path: '/physical-result',
|
||||
query: newPageParams(res.result),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
loadingClose();
|
||||
showFailToast({
|
||||
message: res.result,
|
||||
forbidClick: true,
|
||||
});
|
||||
}
|
||||
stopTimer();
|
||||
}
|
||||
onUnmounted(() => {
|
||||
stopTimer();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.answer-home-container {
|
||||
height: 100vh;
|
||||
background-color: #f5f7fb;
|
||||
position: relative;
|
||||
.overlay-con {
|
||||
text-align: center;
|
||||
}
|
||||
.times {
|
||||
color: #333333;
|
||||
padding: 20px 0 20px 0;
|
||||
text-align: center;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.interval {
|
||||
height: 10px;
|
||||
background-color: #f5f7fb;
|
||||
}
|
||||
.question {
|
||||
width: 100%;
|
||||
height: calc(100vh - 140px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
.bottom {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
:deep(.van-loading) {
|
||||
left: 45%;
|
||||
top: 40%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<div class="sheet-container">
|
||||
<div class="sheet">
|
||||
<span @click="openSheet"></span>
|
||||
<span> {{ currentNo + 1 }}/{{ list.length }}</span>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<div :class="['btn', useSheetButton(0, currentNo, isEdit, list).class]" @click="getSheet('last')">上一题</div>
|
||||
<div class="btn next" v-if="useSheetButton(1, currentNo, isEdit, list).ifShow" @click="submit">提交</div>
|
||||
<div
|
||||
:class="['btn', useSheetButton(2, currentNo, isEdit, list).class]"
|
||||
v-if="useSheetButton(2, currentNo, isEdit, list).ifShow"
|
||||
@click="getSheet('next')"
|
||||
>下一题</div
|
||||
>
|
||||
</div>
|
||||
<van-popup v-model:show="show" position="bottom" closeable close-icon-position="top-right">
|
||||
<answer-sheet :list="list" :isEdit="isEdit" />
|
||||
</van-popup>
|
||||
<dialog-overlay
|
||||
:show="dialogCon.show"
|
||||
:content="dialogCon.con"
|
||||
:imgUrl="dialogCon.url"
|
||||
:okText="dialogCon.okText"
|
||||
@cancel="handleCancel"
|
||||
@ok="dialogSubmit"
|
||||
>
|
||||
<template #content>
|
||||
<div class="overlay-con">{{dialogCon.con}}</div>
|
||||
</template>
|
||||
</dialog-overlay>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="answer-sheet" lang="ts">
|
||||
import { ref,onMounted } from 'vue';
|
||||
import answerSheet from '/@/views/23-physical-questions/answer/answerSheet.vue';
|
||||
import dialogOverlay from '/@/views/23-physical-questions/components/dialogOverlay.vue';
|
||||
import submitIcon from '/@/assets/images/questions/submit.png';
|
||||
import { useSheetButton } from '/@/views/23-physical-questions/questionHooks';
|
||||
import $bus from '/@/utils/mitt';
|
||||
|
||||
const show = ref(false);
|
||||
const emit = defineEmits(['last', 'next', 'submit']);
|
||||
|
||||
const props = defineProps({
|
||||
list: {
|
||||
type: Array,
|
||||
},
|
||||
currentNo: {
|
||||
type: Number,
|
||||
},
|
||||
// true 答题 false 回顾
|
||||
isEdit: {
|
||||
type: Boolean,
|
||||
},
|
||||
});
|
||||
const dialogCon = ref({
|
||||
show: false,
|
||||
url: submitIcon,
|
||||
con: '',
|
||||
okText: '提交答题',
|
||||
});
|
||||
onMounted(()=>{
|
||||
const platform = sessionStorage.getItem('platform') !== null ? sessionStorage.getItem('platform') : 'C01';
|
||||
if(platform === 'C03'){
|
||||
dialogCon.value.con = '请仔细确认答案,是否确认提交?'
|
||||
}else{
|
||||
dialogCon.value.con = '答题内容代表了您对该知识的掌握程度,请仔细确认答案,是否确认提交?'
|
||||
}
|
||||
})
|
||||
$bus.on('selectSheet', () => {
|
||||
show.value = false;
|
||||
});
|
||||
function getSheet(type: string) {
|
||||
if (type === 'last') {
|
||||
if (props.currentNo > 0) {
|
||||
emit('last', type);
|
||||
}
|
||||
} else {
|
||||
if (props.currentNo + 1 < props.list.length) {
|
||||
emit('next', type);
|
||||
}
|
||||
}
|
||||
}
|
||||
function submit() {
|
||||
dialogCon.value.show = true;
|
||||
}
|
||||
function openSheet() {
|
||||
show.value = true;
|
||||
}
|
||||
function handleCancel() {
|
||||
dialogCon.value.show = false;
|
||||
}
|
||||
// 弹窗提交答题
|
||||
function dialogSubmit() {
|
||||
dialogCon.value.show = false;
|
||||
emit('submit');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.sheet-container {
|
||||
background-color: #ffffff;
|
||||
padding: 10px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.overlay-con{
|
||||
text-align: center;
|
||||
}
|
||||
.sheet {
|
||||
width: 30%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
> span:nth-child(1) {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: url('/@/assets/images/questions/sheet.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
> span:nth-child(2) {
|
||||
padding-top: 5px;
|
||||
color: #333333;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
.btn-group {
|
||||
width: 70%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
.btn {
|
||||
width: 120px;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
text-align: center;
|
||||
border-radius: 18px;
|
||||
}
|
||||
.last {
|
||||
color: #1a68ee;
|
||||
background-color: rgba(26, 104, 238, 0.1);
|
||||
border: 1px solid #1a68ee;
|
||||
}
|
||||
.next {
|
||||
color: #ffffff;
|
||||
background-color: #1a68ee;
|
||||
}
|
||||
.disable {
|
||||
border: 1px solid #dddddd;
|
||||
color: #666666;
|
||||
background-color: #dddddd;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,137 @@
|
||||
<template>
|
||||
<div class="result-container">
|
||||
<div class="history-score">
|
||||
<div class="score-title">
|
||||
<div>本次得分</div>
|
||||
<div :style="{ color: useColor(info?.totalScore) }"
|
||||
><span>{{ info.totalScore }}</span
|
||||
>分</div
|
||||
>
|
||||
</div>
|
||||
<div class="score-info">
|
||||
<div class="info-item">
|
||||
<span>答题时长</span>
|
||||
<span>正确率</span>
|
||||
<span>答题数</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span>{{ useConvertTime(info?.answerTimeSum) }}</span>
|
||||
<span :style="{ color: useColor(amastery(info?.trueRate)) }">{{ amastery(info?.trueRate) }}%</span>
|
||||
<span>{{ info?.answerSum }}/{{ info?.questionSum }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="answerBtn" @click="handleReview">回顾答题</div>
|
||||
</div>
|
||||
<div class="history-title"> 答题历史</div>
|
||||
<div class="history-con">
|
||||
<record-list :list="lists" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script name="answer-result" setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import recordList from '/@/views/23-physical-questions/answer/recordList.vue';
|
||||
import { useColor, useConvertTime, amastery } from '/@/views/23-physical-questions/questionHooks';
|
||||
import { newPageParams, openPage } from '/@/hooks/openPage';
|
||||
import { historyListApi } from '/@/views/23-physical-questions/questionApI';
|
||||
import { showFailToast } from 'vant';
|
||||
|
||||
const route = useRoute();
|
||||
const lists = ref([]);
|
||||
const info = ref({});
|
||||
onMounted(() => {
|
||||
info.value = route.query;
|
||||
getLists();
|
||||
});
|
||||
function getLists() {
|
||||
historyListApi({}).then((res: any) => {
|
||||
if (res.code === 200) {
|
||||
lists.value = res.result.records;
|
||||
} else {
|
||||
showFailToast({
|
||||
message: res.message,
|
||||
forbidClick: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// 回顾答题
|
||||
function handleReview() {
|
||||
openPage(
|
||||
'/physical-review',
|
||||
newPageParams({
|
||||
id: info.value.userExamRecordId,
|
||||
})
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.result-container {
|
||||
width: 100%;
|
||||
padding: 10px 20px;
|
||||
background-color: #f5f7fb;
|
||||
.history-score {
|
||||
padding: 10px 20px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 16px;
|
||||
.score-title {
|
||||
text-align: center;
|
||||
> div:nth-child(1) {
|
||||
padding-top: 10px;
|
||||
}
|
||||
> div:nth-child(2) {
|
||||
padding: 10px 0;
|
||||
color: #52c41a;
|
||||
span {
|
||||
font-weight: bold;
|
||||
font-size: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.score-info {
|
||||
padding: 16px 0;
|
||||
border-radius: 16px;
|
||||
background-color: #eff5ff;
|
||||
.info-item:nth-child(1) {
|
||||
span {
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
.info-item:nth-child(2) {
|
||||
padding-top: 6px;
|
||||
span {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
.info-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
span {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
.answerBtn {
|
||||
width: 135px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
margin: 14px auto;
|
||||
text-align: center;
|
||||
border: 1px solid #1a68ee;
|
||||
background-color: rgba(26, 104, 238, 0.1);
|
||||
color: #1a68ee;
|
||||
border-radius: 16px;
|
||||
}
|
||||
}
|
||||
.history-title {
|
||||
padding: 12px 0;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,289 @@
|
||||
<template>
|
||||
<div class="review-container">
|
||||
<div class="review-info">
|
||||
<div class="score">得分:{{ questionItem.userScore }}</div>
|
||||
<div class="score">耗时:{{ useConvertTime(situation.answerTimeSum) }}</div>
|
||||
<div class="question">
|
||||
<span>{{ situation.yesAmount }}</span>
|
||||
<span>{{ situation.questionSum - situation.yesAmount }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="interval"></div>
|
||||
<div class="question-container">
|
||||
<question-card :item="questionItem" :ifAnswer="false" :questionType="questionType" />
|
||||
<div class="answer-tips" v-if="questionItem.isTrue === 4">
|
||||
<WarningFilled />
|
||||
<span>{{ questionItem.remark }}</span>
|
||||
</div>
|
||||
<div class="answer" v-else>
|
||||
<div class="answer-item">
|
||||
<span>答案:</span>
|
||||
<span :class="standStyle.class">{{ standStyle.text}}</span>
|
||||
</div>
|
||||
<div class="answer-item">
|
||||
<span>您的选择:</span>
|
||||
<span :class="answerStyle.class">{{ answerStyle.text }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="explain">
|
||||
<div class="title">答疑</div>
|
||||
<div class="con">{{ questionItem.answer ? questionItem.answer : '暂无' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<answer-panel :list="list" :currentNo="currentIndex" :isEdit="false" @last="handleSheet" @next="handleSheet" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="answer-review" lang="ts">
|
||||
import { onMounted, ref } from 'vue';
|
||||
import $bus from '/@/utils/mitt';
|
||||
import { useRoute } from 'vue-router';
|
||||
import questionCard from '/@/views/23-physical-questions/answer/questionCard.vue';
|
||||
import answerPanel from '/@/views/23-physical-questions/answer/answerPanel.vue';
|
||||
import { usePageAnswer, useConvertTime } from '/@/views/23-physical-questions/questionHooks';
|
||||
import { questionDetailApi } from '/@/views/23-physical-questions/questionApI';
|
||||
import { showFailToast } from 'vant';
|
||||
import { WarningFilled } from '@ant-design/icons-vue';
|
||||
|
||||
const route = useRoute();
|
||||
const currentIndex = ref(0);
|
||||
const questionItem = ref({});
|
||||
const situation = ref({});
|
||||
const list = ref([]);
|
||||
const questionType = ref('');
|
||||
const answerStyle = ref({
|
||||
class: '',
|
||||
text: '',
|
||||
});
|
||||
const standStyle = ref({
|
||||
class: '',
|
||||
text: '',
|
||||
});
|
||||
onMounted(() => {
|
||||
getLists();
|
||||
});
|
||||
$bus.on('selectSheet', (index) => {
|
||||
let quItem = list.value[index];
|
||||
quItem['index'] = index;
|
||||
questionItem.value = quItem;
|
||||
currentIndex.value = index;
|
||||
answerShow(questionItem.value);
|
||||
});
|
||||
|
||||
function getLists() {
|
||||
questionDetailApi({
|
||||
id: route.query.id,
|
||||
}).then(async (res: any) => {
|
||||
if (res.code === 200) {
|
||||
situation.value = res.result;
|
||||
questionType.value = res.result.questionCategoryId;
|
||||
list.value = res.result.userExamPaperRecordQuestionVOS;
|
||||
let quItem = list.value[0];
|
||||
quItem['index'] = currentIndex.value;
|
||||
questionItem.value = quItem;
|
||||
answerShow(questionItem.value);
|
||||
hanleAnswer();
|
||||
standardAnswer();
|
||||
} else {
|
||||
showFailToast({
|
||||
message: res.message,
|
||||
forbidClick: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 标准答案样式及内容
|
||||
*
|
||||
*/
|
||||
function standardAnswer() {
|
||||
let item = questionItem.value;
|
||||
let paramsClass = '',
|
||||
paramsText = '暂无';
|
||||
// 自我健康模块
|
||||
if (questionType.value === '2') {
|
||||
if (item.undefinedRealAnswer !== null) {
|
||||
let find = item.options.find((e: any) => e.id === item.undefinedRealAnswer);
|
||||
paramsText = find.optionNo;
|
||||
paramsClass = 'correct';
|
||||
}
|
||||
} else {
|
||||
if (item.real_answer !== '') {
|
||||
paramsClass = 'correct';
|
||||
paramsText = item.real_answer;
|
||||
}
|
||||
}
|
||||
standStyle.value.class = paramsClass;
|
||||
standStyle.value.text = paramsText;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户选择答案样式及内容
|
||||
*
|
||||
*/
|
||||
function hanleAnswer() {
|
||||
let item = questionItem.value;
|
||||
let paramsClass = '',
|
||||
paramsText = '未填写';
|
||||
// 自我健康模块
|
||||
if (questionType.value === '2') {
|
||||
if (item.undefinedRealAnswer !== null) {
|
||||
paramsClass = item.undefinedRealAnswer == item.userAnswer ? 'correct' : 'error';
|
||||
paramsText = item.user_answer;
|
||||
}
|
||||
} else {
|
||||
if (item.user_answer !== '') {
|
||||
paramsClass = item.real_answer === item.user_answer ? 'correct' : 'error';
|
||||
paramsText = item.user_answer;
|
||||
}
|
||||
}
|
||||
answerStyle.value.class = paramsClass;
|
||||
answerStyle.value.text = paramsText;
|
||||
}
|
||||
/**
|
||||
* real_answer 正确答案
|
||||
* user_answer 用户答案
|
||||
* @param currentItem 当前选中的题
|
||||
*/
|
||||
function answerShow(currentItem: any) {
|
||||
let { options, realAnswer, userAnswer,undefinedRealAnswer } = currentItem;
|
||||
let realList: any[] = [];
|
||||
let userList: any[] = [];
|
||||
let answerList: any[] = [];
|
||||
let userAnswerList: any[] = [];
|
||||
if (realAnswer) {
|
||||
realList = realAnswer.split(',');
|
||||
}
|
||||
if (userAnswer) {
|
||||
userList = userAnswer.split(',');
|
||||
}
|
||||
options.filter((item: any) => {
|
||||
realList.indexOf(item.id) > -1 ? answerList.push(item.optionNo) : '';
|
||||
userList.indexOf(item.id) > -1 ? userAnswerList.push(item.optionNo) : '';
|
||||
if (undefinedRealAnswer !== null) {
|
||||
let vis = undefinedRealAnswer.indexOf(item.id);
|
||||
item.isTrue = vis !== -1;
|
||||
}
|
||||
});
|
||||
currentItem['real_answer'] = answerList.length > 0 ? answerList.join(',') : '';
|
||||
currentItem['user_answer'] = userAnswerList.length > 0 ? userAnswerList.join(',') : '';
|
||||
questionItem.value = currentItem;
|
||||
hanleAnswer();
|
||||
standardAnswer();
|
||||
}
|
||||
// 上一题、下一题
|
||||
function handleSheet(type: string) {
|
||||
const { answer_item, c_index } = usePageAnswer(list.value, type, currentIndex.value);
|
||||
questionItem.value = answer_item;
|
||||
currentIndex.value = c_index;
|
||||
answerShow(questionItem.value);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.review-container {
|
||||
height: 100vh;
|
||||
background-color: #f5f7fb;
|
||||
position: relative;
|
||||
.review-info {
|
||||
padding: 16px 20px;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
.score {
|
||||
width: 25%;
|
||||
color: #333333;
|
||||
}
|
||||
.question {
|
||||
width: 50%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
span {
|
||||
width: 30%;
|
||||
text-align: right;
|
||||
}
|
||||
span:nth-child(1) {
|
||||
position: relative;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 21px;
|
||||
top: 3px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: url('/@/assets/images/questions/correct.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
span:nth-child(2) {
|
||||
position: relative;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 21px;
|
||||
top: 3px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: url('/@/assets/images/questions/error.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.question-container {
|
||||
padding-bottom: 30px;
|
||||
background-color: #ffffff;
|
||||
height: calc(100vh - 140px);
|
||||
overflow-y: auto;
|
||||
.answer-tips {
|
||||
margin: -10px 20px 10px 18px;
|
||||
padding: 10px;
|
||||
color: #1a68ee;
|
||||
background-color: #EFF5FF;
|
||||
border-radius: 8px;
|
||||
span{
|
||||
padding-left: 4px;
|
||||
}
|
||||
}
|
||||
.answer {
|
||||
display: flex;
|
||||
padding: 0 20px 15px 20px;
|
||||
.answer-item {
|
||||
.correct {
|
||||
color: #52c41a;
|
||||
}
|
||||
.error {
|
||||
color: #ed2a26;
|
||||
}
|
||||
}
|
||||
.answer-item:nth-child(2) {
|
||||
padding-left: 20px;
|
||||
}
|
||||
}
|
||||
.explain {
|
||||
margin: 0 20px;
|
||||
padding: 14px 20px;
|
||||
background-color: #eff5ff;
|
||||
border-radius: 16px;
|
||||
.title {
|
||||
color: #333333;
|
||||
}
|
||||
.con {
|
||||
color: #666666;
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.interval {
|
||||
height: 10px;
|
||||
background-color: #f5f7fb;
|
||||
}
|
||||
.bottom {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,138 @@
|
||||
<template>
|
||||
<div class="sheet-con">
|
||||
<div class="title">
|
||||
<span>答题卡</span>
|
||||
<span>已作答</span>
|
||||
<span>未作答</span>
|
||||
</div>
|
||||
<div class="sheet-answer">
|
||||
<div class="sheet-box" v-for="(item, index) in list" :key="item" @click="handleSheet(index)">
|
||||
<div :class="['number-item', isEdit && item.user_answer !== '' ? 'selected' : 'default', setStatus(item)]">
|
||||
<div class="text">{{ index + 1 }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="answer-sheet" lang="ts">
|
||||
import $bus from '/@/utils/mitt';
|
||||
|
||||
const props = defineProps({
|
||||
list: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
// true 答题 false 回顾
|
||||
isEdit: {
|
||||
type: Boolean,
|
||||
},
|
||||
});
|
||||
|
||||
function handleSheet(index: number) {
|
||||
$bus.emit('selectSheet', index);
|
||||
}
|
||||
|
||||
// 回顾答题卡样式设置
|
||||
function setStatus(item: any) {
|
||||
let statusClass = '';
|
||||
if (!props.isEdit) {
|
||||
if (item.userAnswer !== null && item.userAnswer !== '') {
|
||||
if (item.isTrue === 0) {
|
||||
statusClass = 'correct';
|
||||
} else {
|
||||
statusClass = 'error';
|
||||
}
|
||||
} else {
|
||||
statusClass = 'default';
|
||||
}
|
||||
}
|
||||
return statusClass;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.sheet-con {
|
||||
max-height: 350px;
|
||||
.title {
|
||||
padding: 15px 20px;
|
||||
> span:nth-child(1) {
|
||||
color: #333333;
|
||||
font-size: 15px;
|
||||
}
|
||||
> span:nth-child(2) {
|
||||
padding-left: 12%;
|
||||
color: #333333;
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 51%;
|
||||
top: 4%;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #1f91f2;
|
||||
background-color: rgba(31, 145, 242, 0.2);
|
||||
}
|
||||
}
|
||||
> span:nth-child(3) {
|
||||
padding-left: 12%;
|
||||
color: #333333;
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 51%;
|
||||
top: 4%;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
.sheet-answer {
|
||||
max-height: calc(350px - 55px);
|
||||
overflow-y: auto;
|
||||
padding: 0 10px 20px 10px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.sheet-box {
|
||||
width: 16.5%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
.number-item {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
margin: 12px 0;
|
||||
}
|
||||
}
|
||||
.default {
|
||||
border: 1px solid #999999;
|
||||
color: #333333;
|
||||
}
|
||||
.selected {
|
||||
border: 1px solid rgba(31, 145, 242, 1);
|
||||
color: #1f91f2;
|
||||
background-color: rgba(31, 145, 242, 0.2);
|
||||
}
|
||||
.correct {
|
||||
border: 1px solid rgba(82, 196, 26, 1);
|
||||
color: #52c41a;
|
||||
background-color: rgba(82, 196, 26, 0.2);
|
||||
}
|
||||
.error {
|
||||
border: 1px solid rgba(237, 42, 38, 1);
|
||||
color: #ed2a26;
|
||||
background-color: rgba(237, 42, 38, 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,273 @@
|
||||
<template>
|
||||
<div class="card-container">
|
||||
<div class="title">
|
||||
<div>{{ handleQuestionType() }}</div>
|
||||
<div>{{ item.index + 1 }}、{{ item.questionDesc }}</div>
|
||||
</div>
|
||||
<div class="option">
|
||||
<div
|
||||
v-for="(optItem, optIndex) in item.options"
|
||||
:key="optIndex"
|
||||
@click="answerItem(optItem, optItem.id)"
|
||||
:class="['option-item', ifAnswer && item.user_answer.indexOf(optItem.id) > -1 ? 'active' : '', !ifAnswer && showClassOption(optItem)]"
|
||||
>
|
||||
<div class="choose-icon correctBtn" v-if="!ifAnswer && correctIcon(optItem)"></div>
|
||||
<div class="choose-icon errorBtn" v-if="!ifAnswer && wrongIcon(optItem)"></div>
|
||||
<span class="option-number">{{ optItem.optionNo }}</span>
|
||||
<span class="option-name">{{ optItem.optionValue }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="question-card" lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
const selectClass = ref([]);
|
||||
const emit = defineEmits(['selectOption']);
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
},
|
||||
// true 答题 false 回顾
|
||||
ifAnswer: {
|
||||
type: Boolean,
|
||||
},
|
||||
questionType: {
|
||||
type: String,
|
||||
},
|
||||
});
|
||||
// 答案选项样式
|
||||
function showClassOption(val: any) {
|
||||
let text = '';
|
||||
// questionType 2 自我健康答题
|
||||
if (props.questionType === '2') {
|
||||
if (props.item.isTrue === 4) {
|
||||
// 用户已答题,没有标准答案
|
||||
if (props.item.userAnswer !== null) {
|
||||
let listAns = props.item.userAnswer.split(',');
|
||||
let findVis = listAns.find((e) => e === val.id);
|
||||
text = findVis !== undefined ? 'active' : '';
|
||||
}
|
||||
} else if ([0, 1, 2].includes(props.item.isTrue)) {
|
||||
// 自我健康答题 已答题,有标准答案
|
||||
text = optionStatus(val, 'undefinedRealAnswer');
|
||||
}
|
||||
} else {
|
||||
text = optionStatus(val, 'realAnswer');
|
||||
}
|
||||
return text;
|
||||
}
|
||||
/**
|
||||
* options背景样式
|
||||
* @param userAnswer
|
||||
* @param val
|
||||
* @param typeFileds 标准答案
|
||||
*/
|
||||
function optionStatus(val: object, typeFileds: string) {
|
||||
let text = '';
|
||||
const data = props.item;
|
||||
const ansList = data.userAnswer !== null ? data.userAnswer : [];
|
||||
const ifcon = ansList.indexOf(val.id);
|
||||
const same = ansList === props.item[typeFileds];
|
||||
if (ifcon !== -1) {
|
||||
if (val.isTrue && same) {
|
||||
text = 'correct';
|
||||
} else {
|
||||
if ((val.isTrue && !same) || !val.isTrue) {
|
||||
text = 'error';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (val.isTrue) text = 'correct';
|
||||
}
|
||||
// if (ifcon !== -1 && val.isTrue && same) {
|
||||
// text = 'correct';
|
||||
// } else if (ifcon !== -1 && val.isTrue && !same) {
|
||||
// text = 'error';
|
||||
// } else if (ifcon !== -1 && !val.isTrue) {
|
||||
// text = 'error';
|
||||
// } else if (ifcon === -1 && val.isTrue) {
|
||||
// text = 'correct';
|
||||
// }
|
||||
return text;
|
||||
}
|
||||
/**
|
||||
* 回答图标
|
||||
* @param val
|
||||
*/
|
||||
function correctIcon(val: any) {
|
||||
return showIcon(val, 'correct');
|
||||
}
|
||||
/**
|
||||
* 错误图标
|
||||
* @param val
|
||||
*/
|
||||
function wrongIcon(val: any) {
|
||||
return showIcon(val, 'wrong');
|
||||
}
|
||||
/**
|
||||
* 控制正确、错误图标显示
|
||||
* @param userAnswer 用户答案
|
||||
* @param val 选项options值
|
||||
* @param type correct 正确,wrong 错误
|
||||
*/
|
||||
function showIcon(val: object, type: string) {
|
||||
let vis = false;
|
||||
let data = props.item;
|
||||
let typeFileds = '';
|
||||
// 自我健康图标显示
|
||||
if (props.questionType === '2') {
|
||||
if (data.undefinedRealAnswer === null) return false;
|
||||
typeFileds = data.undefinedRealAnswer;
|
||||
} else {
|
||||
if (data.userAnswer === null) return false;
|
||||
typeFileds = data.realAnswer;
|
||||
}
|
||||
let listAns = data.userAnswer.split(',');
|
||||
let con = listAns.indexOf(val.id);
|
||||
const same = data.userAnswer === typeFileds;
|
||||
if (con !== -1) {
|
||||
if (val.isTrue) {
|
||||
if ((same && type === 'correct') || (!same && type === 'wrong')) {
|
||||
vis = true;
|
||||
}
|
||||
} else {
|
||||
if (type === 'wrong') {
|
||||
vis = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (con !== -1 && val.isTrue && same && type === 'correct') {
|
||||
// vis = true;
|
||||
// } else if (con !== -1 && val.isTrue && !same && type === 'wrong') {
|
||||
// vis = true;
|
||||
// } else if (con !== -1 && !val.isTrue && type === 'wrong') {
|
||||
// vis = true;
|
||||
// }
|
||||
return vis;
|
||||
}
|
||||
/**
|
||||
* 答题选中状态
|
||||
* @param options
|
||||
* @param index
|
||||
* DX 多选 DG 单选 PD 判断
|
||||
*/
|
||||
function answerItem(options: Object, id: String) {
|
||||
if (props.ifAnswer) {
|
||||
selectClass.value = [];
|
||||
if (props.item.type === 'DX') {
|
||||
if (props.item.user_answer !== '') {
|
||||
let val = props.item.user_answer.split(',');
|
||||
selectClass.value = val;
|
||||
}
|
||||
let valueIndex = selectClass.value.indexOf(id);
|
||||
if (valueIndex === -1) {
|
||||
selectClass.value.push(id);
|
||||
} else {
|
||||
selectClass.value.splice(valueIndex, 1);
|
||||
}
|
||||
} else if (props.item.type === 'DG' || props.item.type === 'PD') {
|
||||
selectClass.value = [];
|
||||
selectClass.value.push(id);
|
||||
}
|
||||
emit('selectOption', selectClass.value.join(','), props.item);
|
||||
}
|
||||
}
|
||||
function handleQuestionType() {
|
||||
let type = props.item.type;
|
||||
if (type === 'DG' || type === 'PD') {
|
||||
return '单选';
|
||||
} else if (type === 'DX') {
|
||||
return '多选';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.card-container {
|
||||
background-color: #ffffff;
|
||||
padding: 20px 18px;
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
> div:nth-child(1) {
|
||||
width: 48px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
background-color: rgba(26, 104, 238, 0.1);
|
||||
border-radius: 4px;
|
||||
color: #1a68ee;
|
||||
font-size: 13px;
|
||||
}
|
||||
> div:nth-child(2) {
|
||||
padding-left: 6px;
|
||||
width: 90%;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
.option {
|
||||
padding-top: 20px;
|
||||
.option-item {
|
||||
padding: 12px 10px;
|
||||
background-color: #f4f4f4;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 10px;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
display: flex;
|
||||
.option-number {
|
||||
display: inline-block;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
text-align: center;
|
||||
color: #333333;
|
||||
background-color: #ffffff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.option-name {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
.active {
|
||||
background-color: rgba(26, 104, 238, 0.2);
|
||||
color: #1f91f2;
|
||||
border: 1px solid #1a68ee;
|
||||
span:nth-child(1) {
|
||||
color: #1f91f2;
|
||||
}
|
||||
}
|
||||
.correct {
|
||||
background-color: rgba(82, 196, 26, 0.2);
|
||||
color: #52c41a;
|
||||
border: 1px solid #52c41a;
|
||||
}
|
||||
.error {
|
||||
background-color: rgba(237, 42, 38, 0.2);
|
||||
color: #ed2a26;
|
||||
border: 1px solid #ed2a26;
|
||||
}
|
||||
.choose-icon {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 12px;
|
||||
}
|
||||
.correctBtn {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
background: url('/@/assets/images/questions/correct.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.errorBtn {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
background: url('/@/assets/images/questions/error.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<div class="record-container">
|
||||
<div class="record-item" v-for="(record, index) in list" :key="index" @click="handleDetail(record)">
|
||||
<div class="time-con">
|
||||
<div class="timers">答题时间:{{ record.startAnswerTime }}</div>
|
||||
<div class="type">{{ record.questionCategory }} </div>
|
||||
</div>
|
||||
<div class="record-con title">
|
||||
<div>得分</div>
|
||||
<div>正确率</div>
|
||||
<div>耗时</div>
|
||||
<div>答题数</div>
|
||||
</div>
|
||||
<div class="record-con value">
|
||||
<div :style="{ color: useColor(record.totalScore) }">{{ record?.totalScore }}</div>
|
||||
<div :style="{ color: useColor(record.trueRate * 100) }">{{ trueRate(record.trueRate) }}%</div>
|
||||
<div>{{ useConvertTime(record.answerTimeSum) }}</div>
|
||||
<div>{{ record.answerSum }}/{{ record.questionSum }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="history-record" lang="ts">
|
||||
import { useColor, useConvertTime } from '/@/views/23-physical-questions/questionHooks';
|
||||
import { newPageParams, openPage } from '/@/hooks/openPage';
|
||||
const props = defineProps({
|
||||
list: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
});
|
||||
|
||||
function handleDetail(item: any) {
|
||||
openPage(
|
||||
'/physical-review',
|
||||
newPageParams({
|
||||
id: item.id,
|
||||
})
|
||||
);
|
||||
}
|
||||
function trueRate(val: Number) {
|
||||
return Math.round(val * 100);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.record-container {
|
||||
.record-item {
|
||||
border-radius: 16px;
|
||||
background-color: #ffffff;
|
||||
padding: 14px 15px;
|
||||
margin-bottom: 20px;
|
||||
.time-con {
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
padding: 0 0 10px 0;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.timers {
|
||||
color: #999999;
|
||||
}
|
||||
.type {
|
||||
color: #1a68ee;
|
||||
background-color: rgba(26, 104, 238, 0.1);
|
||||
border-radius: 5px;
|
||||
padding: 3px 6px;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
padding: 16px 0 5px 0;
|
||||
> div {
|
||||
color: #666666;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
.value {
|
||||
> div {
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
.record-con {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
>div{
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<div class="dialog-container">
|
||||
<van-overlay :show="show" :lock-scroll="false">
|
||||
<div class="wrapper">
|
||||
<img :src="imgUrl" />
|
||||
<div class="con">
|
||||
<slot name="content"></slot>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<div v-if="cancelBtn" class="overlay-btn overlay-cancelBtn" @click="handleCancel">{{ cancelText }}</div>
|
||||
<div class="overlay-btn overlay-okBtn" @click="handleOk">{{ okText }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-overlay>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const emit = defineEmits(['cancel', 'ok']);
|
||||
const props = defineProps({
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
imgUrl: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
okText: {
|
||||
type: String,
|
||||
default: '确认',
|
||||
},
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: '取消',
|
||||
},
|
||||
cancelBtn: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
function handleCancel() {
|
||||
emit('cancel');
|
||||
}
|
||||
function handleOk() {
|
||||
emit('ok');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import '/@/assets/less/question.less';
|
||||
.dialog-container {
|
||||
position: relative;
|
||||
.wrapper {
|
||||
position: absolute;
|
||||
top: 30%;
|
||||
left: 16%;
|
||||
width: 68%;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
img {
|
||||
position: absolute;
|
||||
top: -35px;
|
||||
left: 38%;
|
||||
width: 25%;
|
||||
}
|
||||
.con {
|
||||
padding: 40px 10px 34px 10px;
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
//line-height: 26px;
|
||||
}
|
||||
.btn-group {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<div class="history-container">
|
||||
<record-list v-if="lists.length > 0" :list="lists" />
|
||||
<div class="history-data" v-else>
|
||||
<NoData text="暂无答题记录" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import recordList from '/@/views/23-physical-questions/answer/recordList.vue';
|
||||
import NoData from '/@/views/23-physical-questions/components/noData.vue';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { historyListApi } from '/@/views/23-physical-questions/questionApI';
|
||||
import { showFailToast } from 'vant';
|
||||
|
||||
const route = useRoute();
|
||||
const lists = ref([]);
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
function getList() {
|
||||
historyListApi({
|
||||
questionCategoryId: route.query.id,
|
||||
}).then((res: any) => {
|
||||
if (res.code === 200) {
|
||||
lists.value = res.result.records;
|
||||
} else {
|
||||
showFailToast({
|
||||
message: res.msg,
|
||||
forbidClick: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.history-container {
|
||||
padding: 20px;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: #f5f7fb;
|
||||
overflow-y: auto;
|
||||
.history-data {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div class="no-container">
|
||||
<div class="nodata"></div>
|
||||
<div v-if="text" class="text">{{ text }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps } from 'vue';
|
||||
const props = defineProps({
|
||||
text: {
|
||||
type: String,
|
||||
default: '暂无数据',
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.no-container {
|
||||
width: 100%;
|
||||
padding: 30px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.nodata {
|
||||
width: 75%;
|
||||
margin: 0 auto;
|
||||
height: 200px;
|
||||
background: url('/@/assets/images/mergeQueImages/nodata.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.text {
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,227 @@
|
||||
<template>
|
||||
<div class="participate-con">
|
||||
<div class="participate-title">
|
||||
<span>参加人员</span>
|
||||
<span>共{{ listsInfo.number }}人参加</span>
|
||||
</div>
|
||||
<div class="personnel">
|
||||
<template v-if="listsInfo?.applyList?.records.length > 0">
|
||||
<div class="ranke-title">
|
||||
<div>
|
||||
<span>排名</span>
|
||||
<span>姓名</span>
|
||||
</div>
|
||||
<div>分数</div>
|
||||
</div>
|
||||
<div class="personnel-item my-bottom" v-if="listsInfo?.loginUserInfo !== null">
|
||||
<div class="icon">{{ listsInfo?.loginUserInfo?.ranking }}</div>
|
||||
<div class="sculpture">
|
||||
<img
|
||||
:src="getFileHttpUrl(listsInfo?.loginUserInfo?.avatar)|| 'https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'"
|
||||
onerror="this.src='https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'"
|
||||
/>
|
||||
</div>
|
||||
<div class="con">
|
||||
<div class="name">
|
||||
<span><span class="my">(我)</span>{{ listsInfo?.loginUserInfo?.userName }}</span>
|
||||
<span>{{ listsInfo?.loginUserInfo?.userDept }}</span>
|
||||
</div>
|
||||
<div class="ranke-time"
|
||||
>参加时间:{{ listsInfo?.loginUserInfo?.endAnswerTime !== null ? listsInfo?.loginUserInfo?.endAnswerTime : '--' }}</div
|
||||
>
|
||||
</div>
|
||||
<div class="score">
|
||||
<div>{{ listsInfo?.loginUserInfo?.totalScore ? listsInfo?.loginUserInfo?.totalScore : 0 }}分</div>
|
||||
<div class="ranke-time">耗时:{{ useConvertTime(listsInfo?.loginUserInfo?.answerTimeSum) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-item" v-if="listsInfo?.loginUserInfo !== null"></div>
|
||||
<div class="personnel-item" v-for="(ranke, rankeIndex) in listsInfo?.applyList?.records" :key="rankeIndex">
|
||||
<div class="icon" v-if="rankeIndex >= 3">{{ rankeIndex + 1 }}</div>
|
||||
<div class="icon" v-else :class="useRanke(rankeIndex) ? useRanke(rankeIndex) : ''"></div>
|
||||
<div class="sculpture">
|
||||
<img
|
||||
:src="getFileHttpUrl(ranke.avatar) || 'https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'"
|
||||
onerror="this.src='https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'"
|
||||
/>
|
||||
</div>
|
||||
<div class="con">
|
||||
<div class="name">
|
||||
<span>{{ ranke.userName }}</span>
|
||||
<span>{{ ranke.userDept }}</span>
|
||||
</div>
|
||||
<div class="ranke-time">参加时间:{{ ranke.endAnswerTime!==null?ranke.endAnswerTime:'--' }}</div>
|
||||
</div>
|
||||
<div class="score">
|
||||
<div>{{ ranke.totalScore ? ranke.totalScore : 0 }}分</div>
|
||||
<div class="ranke-time">耗时:{{ useConvertTime(ranke.answerTimeSum) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="personnel-look" v-if="allShow" @click="handleLook">查看全部</div>
|
||||
</template>
|
||||
<Nodata v-else />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps } from 'vue';
|
||||
import Nodata from '/@/views/23-physical-questions/components/noData.vue';
|
||||
import { useRanke } from '/@/views/23-physical-questions/questionHooks';
|
||||
import { useConvertTime } from '/@/views/23-physical-questions/questionHooks';
|
||||
import { newPageParams, openPage } from '/@/hooks/openPage';
|
||||
import { getFileHttpUrl } from '/@/utils/compUtils';
|
||||
|
||||
const props = defineProps({
|
||||
listsInfo: {
|
||||
type: Object,
|
||||
// eslint-disable-next-line vue/require-valid-default-prop
|
||||
default: {},
|
||||
},
|
||||
allShow: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
detailID: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
function handleLook() {
|
||||
openPage(
|
||||
'/physical-level',
|
||||
newPageParams({
|
||||
id: props.detailID,
|
||||
startNewActivity: -1,
|
||||
})
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.participate-con {
|
||||
margin-top: 20px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 16px;
|
||||
.participate-title {
|
||||
padding: 10px 20px;
|
||||
width: 100%;
|
||||
height: 42px;
|
||||
border-top-left-radius: 16px;
|
||||
border-top-right-radius: 16px;
|
||||
background: linear-gradient(180deg, rgba(26, 104, 238, 0.2) 0%, rgba(48, 160, 226, 0.2) 0%, rgba(255, 255, 255, 0) 100%);
|
||||
span:nth-child(1) {
|
||||
color: #333333;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
span:nth-child(2) {
|
||||
padding-left: 10px;
|
||||
color: #666666;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
.personnel {
|
||||
.ranke-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 2px 20px;
|
||||
color: #999999;
|
||||
div:nth-child(1) {
|
||||
span:nth-child(1) {
|
||||
margin-right: 10px;
|
||||
}
|
||||
span:nth-child(2) {
|
||||
padding-left: 10px;
|
||||
border-left: 1px solid #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
.personnel-item {
|
||||
width: 100%;
|
||||
padding: 10px 18px;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
.sculpture {
|
||||
width: 36px;
|
||||
height: 29px;
|
||||
margin-left: 8px;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
.ranke-one {
|
||||
background: url('/@/assets/images/questions/reanke1.png') no-repeat;
|
||||
background-size: contain;
|
||||
}
|
||||
.ranke-two {
|
||||
background: url('/@/assets/images/questions/reanke2.png') no-repeat;
|
||||
background-size: contain;
|
||||
}
|
||||
.ranke-three {
|
||||
background: url('/@/assets/images/questions/reanke3.png') no-repeat;
|
||||
background-size: contain;
|
||||
}
|
||||
.con {
|
||||
width: 66%;
|
||||
padding-left: 8px;
|
||||
.name {
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
word-break: break-all;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
span:nth-child(2) {
|
||||
padding-left: 10px;
|
||||
}
|
||||
.my {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
.ranke-time {
|
||||
padding-top: 6px;
|
||||
font-size: 13px;
|
||||
color: #999999;
|
||||
}
|
||||
.score {
|
||||
width: 28%;
|
||||
text-align: right;
|
||||
div:nth-child(1) {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
.my-bottom {
|
||||
border-bottom: none;
|
||||
}
|
||||
.my-item {
|
||||
width: 100%;
|
||||
height: 6px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.personnel-look {
|
||||
width: 100%;
|
||||
color: #1a68ee;
|
||||
padding: 14px 0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,242 @@
|
||||
<template>
|
||||
<div class="answer-container">
|
||||
<template v-if="lists.length > 0">
|
||||
<div class="answer-item" v-for="(answer, indexAns) in lists" :key="indexAns">
|
||||
<div class="answer-left">
|
||||
<div class="left-title">
|
||||
<div>{{ answer.questionCategoryName }}</div>
|
||||
<div>随机抽选{{ answer.questionSum }}道题,答题时间为{{ answer.answerTime }}分钟</div>
|
||||
</div>
|
||||
<div class="answer-btn">
|
||||
<div class="btn start" @click="handleStart(answer)">开始答题</div>
|
||||
<div class="btn history" @click="handleHistory(answer)">历史记录</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="answer-progress">
|
||||
<nut-circle-progress
|
||||
:progress="amastery(answer.know)"
|
||||
:stroke-width="progressInfo.width"
|
||||
:radius="progressInfo.radius"
|
||||
:color="useColor(amastery(answer.know))"
|
||||
>
|
||||
<div class="progress-con">
|
||||
<div>{{ amastery(answer.know) }}%</div>
|
||||
<div>掌握率</div>
|
||||
</div>
|
||||
</nut-circle-progress>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<Nodata v-else />
|
||||
<div class="unit-answering" @click="handleLook">
|
||||
<div class="unit-con">
|
||||
<div class="answering-con">
|
||||
<div class="unit-title">
|
||||
<div>{{ cardInfo.title }}</div>
|
||||
<div>{{ cardInfo.con }}</div>
|
||||
</div>
|
||||
<div class="unit-image"></div>
|
||||
</div>
|
||||
<div class="lookBtn">点击查看</div>
|
||||
</div>
|
||||
</div>
|
||||
<dialog-overlay
|
||||
:show="dialogCon.show"
|
||||
:content="dialogCon.con"
|
||||
:imgUrl="dialogCon.url"
|
||||
:okText="dialogCon.okText"
|
||||
@cancel="handleCancel"
|
||||
@ok="handleSubmit"
|
||||
>
|
||||
<template #content>
|
||||
<div class="overlay-con">{{ dialogCon.con }}</div>
|
||||
</template>
|
||||
</dialog-overlay>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import DialogOverlay from '/@/views/23-physical-questions/components/dialogOverlay.vue';
|
||||
import tipsIcon from '/@/assets/images/questions/tips.png';
|
||||
import { useColor, amastery } from './questionHooks';
|
||||
import { homeListApi } from '/@/views/23-physical-questions/questionApI';
|
||||
import { newPageParams, openPage } from '/@/hooks/openPage';
|
||||
import Nodata from '/@/views/23-physical-questions/components/noData.vue';
|
||||
|
||||
const dialogCon = ref({
|
||||
show: false,
|
||||
url: tipsIcon,
|
||||
con: '',
|
||||
okText: '开始答题',
|
||||
});
|
||||
const progressInfo = ref({
|
||||
width: '5',
|
||||
radius: '36',
|
||||
});
|
||||
const cardInfo = ref({
|
||||
title: '单位答题活动',
|
||||
con: '单位组织答题活动,获取一定积分,赢得超大奖励',
|
||||
});
|
||||
const lists = ref([]);
|
||||
const questDetail = ref({});
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
|
||||
function getList() {
|
||||
homeListApi({}).then((res: any) => {
|
||||
if (res.code === 200) {
|
||||
lists.value = res.result;
|
||||
}
|
||||
});
|
||||
}
|
||||
// 打开弹窗
|
||||
function handleStart(item: any) {
|
||||
questDetail.value = item;
|
||||
dialogCon.value.show = true;
|
||||
dialogCon.value.con = `共${item.questionSum}道题,答题时长为${item.answerTime}分钟,是否确认开始答题?`;
|
||||
}
|
||||
function handleCancel() {
|
||||
dialogCon.value.show = false;
|
||||
}
|
||||
// 进入答题
|
||||
function handleSubmit() {
|
||||
dialogCon.value.show = false;
|
||||
openPage(
|
||||
'/physical-answer',
|
||||
newPageParams({
|
||||
id: questDetail.value.questionCategoryId,
|
||||
answerTime: questDetail.value.answerTime,
|
||||
affirmBack: 1,
|
||||
})
|
||||
);
|
||||
}
|
||||
// 单位答题活动
|
||||
function handleLook() {
|
||||
openPage(
|
||||
'/physical-activity',
|
||||
newPageParams({
|
||||
startNewActivity: 2,
|
||||
})
|
||||
);
|
||||
}
|
||||
// 历史记录
|
||||
function handleHistory(item: any) {
|
||||
openPage(
|
||||
'/physical-history',
|
||||
newPageParams({
|
||||
id: item.questionCategoryId,
|
||||
})
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.answer-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
background-color: #f5f7fb;
|
||||
.overlay-con{
|
||||
text-align: center;
|
||||
}
|
||||
.answer-item {
|
||||
background-color: #ffffff;
|
||||
margin: 12px 0;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
border-radius: 16px;
|
||||
.answer-left {
|
||||
width: 80%;
|
||||
.left-title {
|
||||
> div:nth-child(1) {
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
font-size: 16px;
|
||||
}
|
||||
> div:nth-child(2) {
|
||||
color: #999999;
|
||||
font-size: 14px;
|
||||
padding-top: 3px;
|
||||
}
|
||||
}
|
||||
.answer-btn {
|
||||
display: flex;
|
||||
padding-top: 10px;
|
||||
.btn {
|
||||
width: 73px;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
text-align: center;
|
||||
border-radius: 5px;
|
||||
font-size: 13px;
|
||||
}
|
||||
.start {
|
||||
color: #ffffff;
|
||||
background-color: #1a68ee;
|
||||
}
|
||||
.history {
|
||||
color: #1a68ee;
|
||||
border: 1px solid #1a68ee;
|
||||
margin-left: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.answer-progress {
|
||||
width: 20%;
|
||||
.progress-con {
|
||||
font-size: 12px;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.unit-answering {
|
||||
width: 100%;
|
||||
height: 140px;
|
||||
border-radius: 16px;
|
||||
background-color: #1a68ee;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.unit-con {
|
||||
width: 96%;
|
||||
height: 98%;
|
||||
border-radius: 16px;
|
||||
background-color: #ffffff;
|
||||
padding: 20px;
|
||||
.answering-con {
|
||||
display: flex;
|
||||
.unit-title {
|
||||
flex: 1;
|
||||
> div:nth-child(1) {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
> div:nth-child(2) {
|
||||
font-size: 14px;
|
||||
color: #999999;
|
||||
padding-top: 2px;
|
||||
}
|
||||
}
|
||||
.unit-image {
|
||||
margin-top: 20px;
|
||||
width: 61px;
|
||||
height: 61px;
|
||||
background: url('/@/assets/images/questions/answer.png') no-repeat;
|
||||
background-size: contain;
|
||||
}
|
||||
}
|
||||
.lookBtn {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #1a68ee;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,41 @@
|
||||
import { get, post } from '/@/views/mobile/api/api';
|
||||
const prefix: string = import.meta.env.VITE_GLOB_APP_PREFIX || '';
|
||||
|
||||
// C01 体检答题 、 C02 癌症答题、 C03 急救培训
|
||||
const platform = sessionStorage.getItem('platform') !== null ? sessionStorage.getItem('platform') : 'C01';
|
||||
|
||||
//答题列表
|
||||
export const homeListApi = (params: any) => get(`${prefix}/user-exam/home`, params, platform);
|
||||
|
||||
// 获取随机答题数据
|
||||
export const questionListApi = (params: any) => get(`${prefix}/user-exam/answer`, params, platform);
|
||||
|
||||
// 获取急救培训答题
|
||||
export const firstAidListApi = (params: any) => get(`${prefix}/app/angiography/activity/start/answer`, params, platform);
|
||||
|
||||
// 答题详情
|
||||
export const questionDetailApi = (params: any) => get(`${prefix}/user-exam/answer/details`, params, platform);
|
||||
|
||||
// 随机提交答题
|
||||
export const submitApi = (params: any) => post(`${prefix}/user-exam/submit`, params, platform);
|
||||
|
||||
// 历史列表
|
||||
export const historyListApi = (params: any) => get(`${prefix}/user-exam/answer/page`, params, platform);
|
||||
|
||||
// 活动分类列表
|
||||
export const activieListApi = (params: any) => get(`${prefix}/user-plan/app/list`, params, platform);
|
||||
|
||||
// 活动分类详情
|
||||
export const activieDetailApi = (params: any) => get(`${prefix}/user-plan`, params, platform);
|
||||
|
||||
// 排行人员列表
|
||||
export const rankeListApi = (params: any) => get(`${prefix}/user-plan/app/api/join_num`, params, platform);
|
||||
|
||||
// 获取活动答题数据
|
||||
export const activieQuestionListApi = (params: any) => get(`${prefix}/user-plan/answer`, params, platform);
|
||||
|
||||
// 活动提交答题
|
||||
export const activieSubmitApi = (params: any) => post(`${prefix}/user-plan/submit`, params, platform);
|
||||
|
||||
// 用户报名
|
||||
export const registrationApi = (params: any) => get(`${prefix}/user-plan/apply`, params, platform);
|
||||
@@ -0,0 +1,184 @@
|
||||
import { computed, onBeforeUnmount, ref, watch } from 'vue';
|
||||
|
||||
export function useStatus(type: string) {
|
||||
const tagType = [
|
||||
{
|
||||
class: '',
|
||||
type: '0',
|
||||
name: '',
|
||||
},
|
||||
{
|
||||
class: 'progress-status',
|
||||
type: '1',
|
||||
name: '进行中',
|
||||
},
|
||||
{
|
||||
class: 'end-status',
|
||||
type: '2',
|
||||
name: '已结束',
|
||||
},
|
||||
];
|
||||
const isFind = tagType.find((item) => item.type === type);
|
||||
return isFind ? isFind : tagType[0];
|
||||
}
|
||||
// 排名图标样式
|
||||
export function useRanke(rankeIndex: number) {
|
||||
const rankeList = ['ranke-one', 'ranke-two', 'ranke-three'];
|
||||
// @ts-ignore
|
||||
const backIndex = rankeList.findIndex((item, index) => index === rankeIndex);
|
||||
return rankeList[backIndex];
|
||||
}
|
||||
export function usePageAnswer(list: never, type: string, currentIndex: number) {
|
||||
const answer: any = {
|
||||
answer_item: {},
|
||||
c_index: 0,
|
||||
};
|
||||
// @ts-ignore
|
||||
const findIndex = list.findIndex((e: any, findex: number) => findex === currentIndex);
|
||||
if (type === 'last') {
|
||||
answer.answer_item = list[findIndex - 1];
|
||||
answer.answer_item['index'] = findIndex - 1;
|
||||
answer.c_index = currentIndex - 1;
|
||||
} else {
|
||||
answer.answer_item = list[findIndex + 1];
|
||||
answer.answer_item['index'] = findIndex + 1;
|
||||
answer.c_index = currentIndex + 1;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param type last 上一题 next 下一题
|
||||
* @param currentNo 当前选中题下标
|
||||
* @param isEdit true 答题 false 回顾
|
||||
* @param list 全部题目
|
||||
*/
|
||||
export function useSheetButton(type: number, currentNo: number, isEdit: boolean, list: Array<any>) {
|
||||
const params = {
|
||||
class: '',
|
||||
ifShow: true,
|
||||
};
|
||||
switch (type) {
|
||||
case 0:
|
||||
if (currentNo === 0) {
|
||||
params.class = 'disable';
|
||||
} else if (currentNo + 1 <= list.length) {
|
||||
params.class = 'last';
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
params.ifShow = isEdit && currentNo + 1 === list.length;
|
||||
break;
|
||||
case 2:
|
||||
if (isEdit) {
|
||||
params.ifShow = currentNo + 1 < list.length;
|
||||
} else {
|
||||
params.ifShow = currentNo + 1 <= list.length;
|
||||
}
|
||||
params.class = currentNo + 1 < list.length ? 'next' : 'disable';
|
||||
break;
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
// 正确率字体颜色
|
||||
export function useColor(know: any) {
|
||||
const rate = Number(know);
|
||||
if (rate < 60) {
|
||||
return '#E60707';
|
||||
} else if (rate >= 60 && rate < 75) {
|
||||
return '#FE8700';
|
||||
} else if (rate >= 75) {
|
||||
return '#66C706';
|
||||
}
|
||||
}
|
||||
// 秒转为时、分、秒
|
||||
export function useConvertTime(seconds: any) {
|
||||
if (seconds === null || seconds === undefined) {
|
||||
return 0;
|
||||
}
|
||||
const hours = Math.floor(seconds / 3600);
|
||||
const minutes = Math.floor((seconds % 3600) / 60);
|
||||
const secs = seconds % 60;
|
||||
let text = '';
|
||||
if (hours !== 0) {
|
||||
isCountDigits(hours) ? (text += hours + ':') : (text += '0' + hours + ':');
|
||||
}
|
||||
isCountDigits(minutes) ? (text += minutes + ':') : (text += '0' + minutes + ':');
|
||||
isCountDigits(secs) ? (text += secs) : (text += '0' + secs);
|
||||
return text;
|
||||
}
|
||||
|
||||
function isCountDigits(val: number) {
|
||||
return val.toString().length > 1;
|
||||
}
|
||||
// 时分转换为秒
|
||||
export function convertTimeToSeconds(time: string) {
|
||||
const [minutes, seconds] = time.split(':');
|
||||
return parseInt(minutes, 10) * 60 + parseInt(seconds, 10);
|
||||
}
|
||||
|
||||
//分钟为秒
|
||||
export function minuteConverSeconds(val: number) {
|
||||
return val * 60;
|
||||
}
|
||||
|
||||
// 截取年月日
|
||||
export function timeSplit(val: string) {
|
||||
return !val ? '' : val.length > 10 ? val.substr(0, 10) : val;
|
||||
}
|
||||
|
||||
// 小数转百分率
|
||||
export function amastery(val: number) {
|
||||
let rate = 0;
|
||||
if (val > 0) {
|
||||
rate = Math.round(val * 100);
|
||||
}
|
||||
return rate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @params duration 时长
|
||||
*/
|
||||
export function useCountdown(duration: number) {
|
||||
// 分钟转为秒
|
||||
const timer = ref(minuteConverSeconds(duration));
|
||||
const isTimerRunning = ref(false);
|
||||
// 格式化时间
|
||||
const formatTime = computed(() => {
|
||||
const minutes = Math.floor(timer.value / 60);
|
||||
const seconds = timer.value % 60;
|
||||
return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
||||
});
|
||||
// 计时器逻辑
|
||||
let interval: any = null;
|
||||
const startTimer = () => {
|
||||
isTimerRunning.value = true;
|
||||
interval = setInterval(() => {
|
||||
timer.value--;
|
||||
}, 1000);
|
||||
};
|
||||
const stopTimer = () => {
|
||||
isTimerRunning.value = false;
|
||||
// timer.value = 0;
|
||||
clearInterval(interval);
|
||||
};
|
||||
|
||||
// 监听计时器状态变化
|
||||
watch(isTimerRunning, (newValue) => {
|
||||
if (!newValue) {
|
||||
clearInterval(interval);
|
||||
}
|
||||
});
|
||||
|
||||
// 在组件销毁前清除计时器
|
||||
onBeforeUnmount(() => {
|
||||
clearInterval(interval);
|
||||
});
|
||||
return {
|
||||
formatTime,
|
||||
startTimer,
|
||||
stopTimer,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,466 @@
|
||||
<template>
|
||||
<div class="traceability">
|
||||
<div class="header">
|
||||
<div class="header-font">
|
||||
<span>{{ type.title }}</span>
|
||||
<span>{{ type.sub }}</span>
|
||||
</div>
|
||||
<img :src="headerIcon" />
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="question-box" v-for="(quesItem, index) in questionList" :key="index">
|
||||
<div class="question-header">
|
||||
<div>{{ quesItem.name }}</div>
|
||||
<div v-if="qustType === '1'" @click="handleLookRes(quesItem)">查看最新检查结果</div>
|
||||
</div>
|
||||
<template v-for="(qus, quIndex) in quesItem.question">
|
||||
<div class="question-title" v-if="qus.isShow" :key="quIndex">
|
||||
<div class="title">
|
||||
<span class="tips">*</span>
|
||||
<div>
|
||||
<span>{{ quIndex + 1 }}、</span>
|
||||
<span>{{ qus.title }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="qus.inputType === 'radio'">
|
||||
<a-radio-group v-model:value="qus.answer" @change="(e) => changeRadio(index, e, qus.type)">
|
||||
<a-radio class="radioStyle" v-for="(optionItem, indexItem) in qus.options" :key="indexItem" :value="optionItem.value">
|
||||
{{ optionItem.name }}</a-radio
|
||||
>
|
||||
</a-radio-group>
|
||||
</template>
|
||||
<template v-if="qus.inputType === 'text'">
|
||||
<div class="error-box">
|
||||
<div class="error-item" v-for="(optionItem, optionIndex) in qus.options" :key="optionIndex">
|
||||
<van-field class="field-input" v-model="optionItem.remark" :label="optionItem.sizeMsg" />
|
||||
<van-field class="field-input" v-model="optionItem.position" :label="optionItem.positionMsg" />
|
||||
<van-icon
|
||||
v-if="optionIndex !== 0"
|
||||
class="deleteIcon"
|
||||
size="26"
|
||||
name="clear"
|
||||
color="#666666"
|
||||
@click="deleteICon(index, optionIndex)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="error-btn" @click="addInfo(index, qus.options, qus.type)">添加斑块信息</div>
|
||||
</template>
|
||||
<template v-if="qus.inputType === 'input'">
|
||||
<van-field type="number" class="field-answer" v-model="qus.answer" />
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-btn">
|
||||
<van-button class="btn" round type="primary" @click="handleSubmit">提交</van-button>
|
||||
</div>
|
||||
<van-overlay :show="popupShow">
|
||||
<div class="dialog">
|
||||
<img :src="resultIcon" />
|
||||
<div class="content-overlay">
|
||||
<div class="popup-title">{{ detailRes?.name }}</div>
|
||||
<div v-if="detailRes?.conclusion !== ''" class="popup-con">{{ detailRes?.conclusion }}</div>
|
||||
<div v-else class="no-date">暂无结果</div>
|
||||
</div>
|
||||
<van-icon class="closeIcon" name="close" color="#ffffff" size="36" @click="handleClose" />
|
||||
</div>
|
||||
</van-overlay>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import headerIcon from '/@/assets/images/traceability/headerImage.png';
|
||||
import resultIcon from '/@/assets/images/traceability/resultIcon.png';
|
||||
import { useTypeHeader } from '/@/views/23intervene/ImageTraceability/traceabilityHooks';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { showToast, showSuccessToast, showFailToast } from 'vant';
|
||||
import {
|
||||
getBehaviorSurveyApi,
|
||||
getEnvironmentSurveyApi,
|
||||
getSurveyApi,
|
||||
submitBehaviorSurveyApi,
|
||||
submitEnvironmentSurveyApi,
|
||||
submitSurveyApi,
|
||||
} from '/@/views/23intervene/ImageTraceability/tranceabilityApi';
|
||||
import { destroyPage } from '/@/hooks/openPage';
|
||||
import { useLoading } from '/@/utils/compUtils';
|
||||
|
||||
const questionList = ref([]);
|
||||
const submitParams = ref({});
|
||||
const popupShow = ref(false);
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const detailRes = ref({});
|
||||
const isEdit = ref(''); // 0 新增 1编辑
|
||||
const qustType = route.query?.traceabType;
|
||||
const type = useTypeHeader(qustType); // 1 影像溯源、2 行为溯源、 3环境溯源
|
||||
const { loadingSpinner, loadingClose } = useLoading();
|
||||
onMounted(() => {
|
||||
useTypeApi(qustType).getApi();
|
||||
});
|
||||
function useTypeApi(type: number) {
|
||||
const data = {
|
||||
1: {
|
||||
getApi: getSurvey,
|
||||
subApi: subSurvey,
|
||||
},
|
||||
2: {
|
||||
getApi: getBehavior,
|
||||
subApi: subBehavior,
|
||||
},
|
||||
3: {
|
||||
getApi: getEnvironment,
|
||||
subApi: subEnvironment,
|
||||
},
|
||||
};
|
||||
return data[type];
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param index
|
||||
* @param val 0 不存在异常、否, 1 存在异常、是
|
||||
* @param qustType 1 影像溯源、2 行为溯源、3环境溯源
|
||||
*/
|
||||
function changeRadio(index: number, val: number, field: string) {
|
||||
let data = val.target.value;
|
||||
let qusData = questionList.value;
|
||||
submitParams.value[field] = data;
|
||||
if (qustType === '1') {
|
||||
qusData[index].question[1].isShow = data === 1;
|
||||
if (data === 0) {
|
||||
let optionsList = qusData[index].question[1].options;
|
||||
if (optionsList.length > 1) {
|
||||
optionsList.splice(1, optionsList.length - 1);
|
||||
optionsList[0].size = '';
|
||||
optionsList[0].position = '';
|
||||
}
|
||||
}
|
||||
} else if (qustType === '2') {
|
||||
let qusList = qusData[index].question;
|
||||
if (qusList.length > 1) {
|
||||
qusList.filter((v: any) => {
|
||||
if (v.inputType === 'input') {
|
||||
if (v.answer !== '') {
|
||||
v.answer = '';
|
||||
}
|
||||
v.isShow = data === 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
questionList.value = qusData;
|
||||
}
|
||||
function addInfo(index: number, data: Array) {
|
||||
let dataParams = {
|
||||
remark: '',
|
||||
position: '',
|
||||
sizeMsg: data[0].sizeMsg,
|
||||
positionMsg: data[0].positionMsg,
|
||||
};
|
||||
questionList.value[index].question[1].options.push(dataParams);
|
||||
}
|
||||
function deleteICon(index: number, optionIndex: number) {
|
||||
questionList.value[index].question[1].options.splice(optionIndex, 1);
|
||||
}
|
||||
|
||||
function getParams() {
|
||||
questionList.value.map((quItem: any) => {
|
||||
quItem.question.map((item: any) => {
|
||||
if (item.inputType === 'text' && item.isShow) {
|
||||
submitParams.value[item.type] = item.options;
|
||||
}
|
||||
if (['radio', 'input'].includes(item.inputType) && item.isShow) {
|
||||
submitParams.value[item.type] = item.answer;
|
||||
}
|
||||
});
|
||||
});
|
||||
return submitParams.value;
|
||||
}
|
||||
// 影像
|
||||
async function getSurvey() {
|
||||
const { code, result } = await getSurveyApi({});
|
||||
getResult(code, result);
|
||||
}
|
||||
async function subSurvey() {
|
||||
const { code, result, message } = await submitSurveyApi(getParams());
|
||||
subResult(code, result, message);
|
||||
}
|
||||
|
||||
// 行为
|
||||
async function getBehavior() {
|
||||
const { code, result } = await getBehaviorSurveyApi({});
|
||||
getResult(code, result);
|
||||
}
|
||||
async function subBehavior() {
|
||||
const { code, result, message } = await submitBehaviorSurveyApi(getParams());
|
||||
subResult(code, result, message);
|
||||
}
|
||||
|
||||
// 环境
|
||||
async function getEnvironment() {
|
||||
const { code, result } = await getEnvironmentSurveyApi({});
|
||||
getResult(code, result);
|
||||
}
|
||||
async function subEnvironment() {
|
||||
const { code, result, message } = await submitEnvironmentSurveyApi(getParams());
|
||||
subResult(code, result, message);
|
||||
}
|
||||
function getResult(code: number, result: any) {
|
||||
if (code === 200) {
|
||||
isEdit.value = result.status;
|
||||
questionList.value = result.questionList;
|
||||
}
|
||||
}
|
||||
function subResult(code: number, result: any, message: string) {
|
||||
if (code === 200) {
|
||||
loadingClose();
|
||||
showSuccessToast('提交成功');
|
||||
try {
|
||||
destroyPage();
|
||||
} catch {
|
||||
router.go(-1);
|
||||
}
|
||||
} else {
|
||||
loadingClose();
|
||||
showFailToast(message);
|
||||
}
|
||||
}
|
||||
async function handleSubmit() {
|
||||
let vis = true;
|
||||
questionList.value.map((v: any) => {
|
||||
v.question.map((qusItem: any) => {
|
||||
if (qusItem.isShow && ['radio', 'input'].includes(qusItem.inputType)) {
|
||||
if (qusItem.answer === '') {
|
||||
vis = false;
|
||||
showToast('请填写完问卷');
|
||||
}
|
||||
}
|
||||
if (qusItem.isShow && qusItem.inputType === 'text') {
|
||||
qusItem.options.map((e: any) => {
|
||||
if (e.position === '' || e.remark === '') {
|
||||
vis = false;
|
||||
showToast('请填写异常信息');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
if (vis) {
|
||||
loadingSpinner();
|
||||
useTypeApi(qustType).subApi();
|
||||
}
|
||||
}
|
||||
async function handleLookRes(item: any) {
|
||||
popupShow.value = true;
|
||||
detailRes.value = item;
|
||||
}
|
||||
function handleClose() {
|
||||
popupShow.value = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.traceability {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: #f5f7fb;
|
||||
position: relative;
|
||||
.header {
|
||||
z-index: 4;
|
||||
width: 100%;
|
||||
height: 140px;
|
||||
position: relative;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.header-font {
|
||||
position: absolute;
|
||||
left: 7%;
|
||||
top: 22%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
span:nth-child(1) {
|
||||
font-size: 30px;
|
||||
color: #ffffff;
|
||||
}
|
||||
span:nth-child(2) {
|
||||
margin-top: -12px;
|
||||
color: rgba(255, 255, 255, 0.1);
|
||||
font-size: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.container {
|
||||
width: 100%;
|
||||
height: calc(100vh - 180px);
|
||||
overflow-y: auto;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 125px;
|
||||
z-index: 99;
|
||||
.question-box {
|
||||
margin-bottom: 18px;
|
||||
border-radius: 16px;
|
||||
background-color: #ffffff;
|
||||
.question-header {
|
||||
border-top-left-radius: 16px;
|
||||
border-top-right-radius: 16px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 43px;
|
||||
padding: 20px;
|
||||
background: linear-gradient(180deg, rgba(26, 104, 238, 0.2) 0%, rgba(48, 160, 226, 0.2) 0%, rgba(255, 255, 255, 0) 100%);
|
||||
> div:nth-child(1) {
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
font-weight: bold;
|
||||
}
|
||||
> div:nth-child(2) {
|
||||
color: #1a68ee;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
.question-title {
|
||||
padding: 20px;
|
||||
.title {
|
||||
color: #333b42;
|
||||
font-weight: bold;
|
||||
padding-bottom: 20px;
|
||||
position: relative;
|
||||
.tips {
|
||||
color: #ed2a26;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
left: -10px;
|
||||
}
|
||||
}
|
||||
.radioStyle {
|
||||
display: block;
|
||||
height: 40px;
|
||||
}
|
||||
.error-item {
|
||||
position: relative;
|
||||
margin-top: 12px;
|
||||
border-radius: 16px;
|
||||
& > .field-input:nth-child(1) {
|
||||
border-top-left-radius: 16px;
|
||||
border-top-right-radius: 16px;
|
||||
}
|
||||
& > .field-input:nth-child(2) {
|
||||
border-bottom-left-radius: 16px;
|
||||
border-bottom-right-radius: 16px;
|
||||
}
|
||||
& > .deleteIcon {
|
||||
position: absolute;
|
||||
right: -10px;
|
||||
top: -10px;
|
||||
z-index: 9;
|
||||
}
|
||||
:deep(.van-field__control:-webkit-autofill) {
|
||||
background-color: transparent;
|
||||
padding-left: 10px;
|
||||
transition: background-color 0s linear 3600s;
|
||||
}
|
||||
:deep(.van-field__control) {
|
||||
padding-left: 10px;
|
||||
}
|
||||
:deep(.van-cell) {
|
||||
background-color: #eff5ff;
|
||||
line-height: 38px;
|
||||
}
|
||||
:deep(.van-field__label) {
|
||||
font-weight: bold;
|
||||
}
|
||||
:deep(.van-cell__value) {
|
||||
height: 38px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
}
|
||||
.error-btn {
|
||||
text-align: center;
|
||||
color: #1a68ee;
|
||||
padding: 20px 0px;
|
||||
}
|
||||
.field-answer {
|
||||
border-bottom: 1px solid #eaecf1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.bottom-btn {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
height: 50px;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.btn {
|
||||
width: 80%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
background-color: #1a68ee;
|
||||
border-radius: 16px;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
:deep(.ant-radio-group) {
|
||||
width: 100%;
|
||||
}
|
||||
:deep(.van-overlay){
|
||||
z-index: 99;
|
||||
}
|
||||
.dialog {
|
||||
position: absolute;
|
||||
top: 30%;
|
||||
left: 11%;
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
img {
|
||||
position: absolute;
|
||||
top: -35px;
|
||||
left: 43%;
|
||||
width: 15%;
|
||||
}
|
||||
.content-overlay {
|
||||
background-color: #ffffff;
|
||||
border-radius: 16px;
|
||||
padding: 40px 20px 20px 20px;
|
||||
.popup-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.popup-con {
|
||||
font-size: 15px;
|
||||
line-height: 25px;
|
||||
max-height: 120px;
|
||||
overflow-y: auto;
|
||||
text-align: left;
|
||||
}
|
||||
.no-date {
|
||||
text-align: center;
|
||||
color: #999999;
|
||||
height: 120px;
|
||||
line-height: 120px;
|
||||
}
|
||||
}
|
||||
.closeIcon {
|
||||
position: relative;
|
||||
left: 45%;
|
||||
padding-top: 10%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,18 @@
|
||||
export function useTypeHeader(type: number) {
|
||||
const data = {
|
||||
1: {
|
||||
title: '影像溯源',
|
||||
sub: 'IMAGE TRACEABILITY',
|
||||
},
|
||||
2: {
|
||||
title: '行为溯源',
|
||||
sub: 'BEHAVIOR TRACEABILITY',
|
||||
},
|
||||
3: {
|
||||
title: '环境溯源',
|
||||
sub: 'ENVIRONMENTAL TRACEABILITY',
|
||||
},
|
||||
};
|
||||
// @ts-ignore
|
||||
return data[type];
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { get, post } from '/@/views/mobile/api/api';
|
||||
|
||||
const prefix: string = import.meta.env.VITE_GLOB_APP_PREFIX || '';
|
||||
|
||||
// 获取影像溯源
|
||||
export const getSurveyApi = (params: any) => get(`${prefix}/cancer/api/getImageSurvey`, params);
|
||||
|
||||
// 提交影像溯源
|
||||
export const submitSurveyApi = (params: any) => post(`${prefix}/cancer/api/postImageSurvey`, params);
|
||||
|
||||
// 获取行为溯源
|
||||
export const getBehaviorSurveyApi = (params: any) => get(`${prefix}/cancer/api/getBehaviorSurvey`, params);
|
||||
|
||||
// 提交行为溯源
|
||||
export const submitBehaviorSurveyApi = (params: any) => post(`${prefix}/cancer/api/postBehaviorSurvey`, params);
|
||||
|
||||
// 获取环境溯源
|
||||
export const getEnvironmentSurveyApi = (params: any) => get(`${prefix}/cancer/api/getEnvironmentSurvey`, params);
|
||||
|
||||
// 提交环境溯源
|
||||
export const submitEnvironmentSurveyApi = (params: any) => post(`${prefix}/cancer/api/postEnvironmentSurvey`, params);
|
||||
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<div class="vaccines-container">
|
||||
<div v-for="(qus, qusIndex) in question" :key="qusIndex">
|
||||
<template v-if="qus.isShow">
|
||||
<div class="qus-title">
|
||||
<span v-if="warnType === 0">{{ qus.indexNo }}、</span>
|
||||
<span>{{ qus.question }}</span>
|
||||
</div>
|
||||
<template v-if="qus.type === 0">
|
||||
<van-radio-group v-model="qus.userAnswer" shape="dot" @change="(e) => handleRadios(qusIndex, e)">
|
||||
<van-radio class="radioStyle" v-for="(opt, optIndex) in qus.optionList" :name="opt.optionCode" :key="optIndex">{{
|
||||
opt.option
|
||||
}}</van-radio>
|
||||
</van-radio-group>
|
||||
</template>
|
||||
<template v-if="qus.type === 1">
|
||||
<div class="time-box" @click="handleTimes(qus, qusIndex)">
|
||||
<div class="time-answer" v-if="qus.userAnswer !== '' || qus.userAnswer !== null">{{ qus.userAnswer }}</div>
|
||||
<div class="time-answer" v-else>{{ rangTime?.join('-') }}</div>
|
||||
<div class="time-pla" v-if="qus.userAnswer === '' || (qus.userAnswer === null && rangTime)">请选择接种时间 </div>
|
||||
<van-icon class="right-icon" color="#666666" name="arrow" />
|
||||
</div>
|
||||
<van-popup v-model:show="show" position="bottom">
|
||||
<van-date-picker
|
||||
v-model="rangTime"
|
||||
title="选择日期"
|
||||
:min-date="minDate"
|
||||
:max-date="new Date()"
|
||||
@cancel="show = false"
|
||||
@confirm="onConfirmPicker"
|
||||
/>
|
||||
</van-popup>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, defineProps, defineEmits } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
const props = defineProps({
|
||||
qusIndex: Number,
|
||||
question: Object,
|
||||
});
|
||||
const route = useRoute();
|
||||
const warnType = parseInt(route.query.warnType); // 0 疫苗+其他题 、 1 更新疫苗、 2 更新其他题
|
||||
const emit = defineEmits(['radios', 'picker']);
|
||||
let show = ref(false);
|
||||
let rangTime = ref([]);
|
||||
let vanIndex = ref('');
|
||||
let vanParmas = ref({});
|
||||
let minDate = new Date(1990, 0, 1);
|
||||
function handleRadios(index: number, value: string) {
|
||||
emit('radios', props.qusIndex, index, value);
|
||||
}
|
||||
function onConfirmPicker(e: any) {
|
||||
rangTime.value = e.selectedValues;
|
||||
emit('picker', vanParmas.value.questionCode, vanIndex.value, rangTime.value);
|
||||
show.value = false;
|
||||
}
|
||||
function handleTimes(vanData: any, val: number) {
|
||||
vanIndex.value = val;
|
||||
vanParmas.value = vanData;
|
||||
show.value = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.vaccines-container {
|
||||
width: 100%;
|
||||
.qus-title {
|
||||
padding: 10px 0;
|
||||
}
|
||||
.radioStyle {
|
||||
height: 30px;
|
||||
}
|
||||
.time-answer {
|
||||
padding: 10px 0;
|
||||
font-size: 15px;
|
||||
color: #333333;
|
||||
}
|
||||
.right-icon {
|
||||
padding-left: 6px;
|
||||
}
|
||||
.time-pla {
|
||||
color: #666666;
|
||||
}
|
||||
.time-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,318 @@
|
||||
<template>
|
||||
<div class="warning-container">
|
||||
<div class="warn-con">
|
||||
<div class="warn-header" v-if="warnType === 0">
|
||||
<div class="header-font">
|
||||
<span>免疫预警</span>
|
||||
<span>IMMUNE WARNING</span>
|
||||
</div>
|
||||
<img :src="headerIcon" />
|
||||
</div>
|
||||
<div :class="warnType === 0 ? 'warn-box' : 'vancc-box'">
|
||||
<div class="vancc-title" v-if="warnType === 1">
|
||||
<div>疫苗信息</div>
|
||||
<div>请填写疫苗接种信息,评估您的细菌·病毒预警情况</div>
|
||||
</div>
|
||||
<div class="ques-item" v-for="(qus, qusIndex) in quesList" :key="qusIndex">
|
||||
<div :class="warnType === 0 ? '' : 'vancc'" v-if="qus.hasChildren && [0, 1].includes(warnType)">
|
||||
<div class="qus-title">{{ qus.question }}</div>
|
||||
<Vaccines
|
||||
v-if="qus.hasChildren"
|
||||
:question="qus.childrenQuestions"
|
||||
:qusIndex="qusIndex"
|
||||
@radios="changeRadios"
|
||||
@picker="handlePicker"
|
||||
/>
|
||||
</div>
|
||||
<template v-if="qus.isShow && [0, 2].includes(warnType) && !qus.hasChildren">
|
||||
<div class="qus-title">{{ qus.indexNo }}、{{ qus.question }}</div>
|
||||
<van-radio-group v-model="qus.userAnswer" shape="dot">
|
||||
<van-radio class="radioStyle" v-for="(opt, optIndex) in qus.optionList" :name="opt.optionCode" :key="optIndex">{{
|
||||
opt.option
|
||||
}}</van-radio>
|
||||
</van-radio-group>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-btn">
|
||||
<van-button class="btn" round type="primary" @click="handleSubmit">提交</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { getQuestionList, setQuestion } from '/@/views/23intervene/ImmuneWarning/warningApi.ts';
|
||||
import Vaccines from '/@/views/23intervene/ImmuneWarning/Vaccines.vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import headerIcon from '/@/assets/images/traceability/headerImage.png';
|
||||
import { showSuccessToast, showFailToast } from 'vant';
|
||||
import { destroyPage } from '/@/hooks/openPage';
|
||||
import { useLoading } from '/@/utils/compUtils';
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
let quesList = ref([]);
|
||||
const warnType = parseInt(route.query.warnType); // 0 疫苗+其他题 、 1 更新疫苗、 2 更新其他题
|
||||
const { loadingSpinner, loadingClose } = useLoading();
|
||||
const subParams = ref({
|
||||
optionList: [],
|
||||
submitType: '',
|
||||
surveyCode: '',
|
||||
});
|
||||
interface quesItem {
|
||||
hasChildren: Boolean;
|
||||
childrenQuestions: Array;
|
||||
questionCode: String;
|
||||
optionList: Array;
|
||||
isShow: Boolean;
|
||||
meaning: String;
|
||||
userAnswer: String;
|
||||
type: Number;
|
||||
}
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
function setListIndex(data: any) {
|
||||
let indexNo = 0;
|
||||
const list = data.map((item: any) => {
|
||||
if (item.hasChildren) {
|
||||
indexNo = 0;
|
||||
item.childrenQuestions.map((childrenItem: any) => {
|
||||
if (childrenItem.isShow) {
|
||||
indexNo++;
|
||||
childrenItem['indexNo'] = indexNo;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (item.isShow) {
|
||||
indexNo++;
|
||||
item['indexNo'] = indexNo;
|
||||
}
|
||||
}
|
||||
return item;
|
||||
});
|
||||
return list;
|
||||
}
|
||||
function setShowQuestion(vanList: any) {
|
||||
vanList.map((data: any) => {
|
||||
if (data.hasChildren) {
|
||||
const user_answer = data.childrenQuestions[0].userAnswer;
|
||||
if (['10', '12', '11'].includes(data.questionCode)) {
|
||||
data.childrenQuestions.map((item: any) => {
|
||||
if (user_answer !== null || user_answer !== '') {
|
||||
if (['10.1', '12.1'].includes(item.questionCode)) {
|
||||
data.childrenQuestions[1].isShow = user_answer === 'A';
|
||||
}
|
||||
if (item.questionCode === '11.1') {
|
||||
const showNo = [1, 2, 3];
|
||||
showNo.map((itemNo: number) => {
|
||||
data.childrenQuestions[itemNo].isShow = user_answer === 'A';
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
return vanList;
|
||||
}
|
||||
async function getList() {
|
||||
const { code, result } = await getQuestionList({});
|
||||
if (code === 200) {
|
||||
let data_index = await setShowQuestion(result.questionList);
|
||||
quesList.value = await setListIndex(data_index);
|
||||
subParams.value.surveyCode = result.surveyCode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param qusIndex
|
||||
* @param childIndex 子集下标
|
||||
* @param value 单选题值
|
||||
*/
|
||||
function changeRadios(qusIndex: number, childIndex: number, value: string) {
|
||||
let new_quesList: quesItem[] = quesList.value;
|
||||
if (new_quesList[qusIndex].hasChildren) {
|
||||
let childList = new_quesList[qusIndex].childrenQuestions;
|
||||
if (['10.1', '12.1'].includes(childList[childIndex].questionCode)) {
|
||||
if (value === 'B') {
|
||||
childList[1].userAnswer = '';
|
||||
}
|
||||
childList[1].isShow = value === 'A';
|
||||
}
|
||||
if (childList[childIndex].questionCode === '11.1') {
|
||||
const showNo = [1, 2, 3];
|
||||
showNo.map((itemNo: number) => {
|
||||
childList[itemNo].isShow = value === 'A';
|
||||
if (value === 'B') {
|
||||
childList[itemNo].userAnswer = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
quesList.value = setListIndex(new_quesList);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param questionCode 编号
|
||||
* @param childIndex 子集下标
|
||||
* @param value 时间
|
||||
*/
|
||||
function handlePicker(questionCode: string, childIndex: number, value: string) {
|
||||
let new_quesList: quesItem[] = quesList.value;
|
||||
new_quesList.map((item: any) => {
|
||||
if (item.hasChildren && item.childrenQuestions !== null) {
|
||||
const chiCode = item.childrenQuestions[childIndex];
|
||||
if (chiCode && questionCode === chiCode.questionCode) {
|
||||
item.childrenQuestions[childIndex].userAnswer = value.join('-');
|
||||
}
|
||||
}
|
||||
});
|
||||
quesList.value = setListIndex(new_quesList);
|
||||
}
|
||||
function getParams() {
|
||||
let list: quesItem[] = [];
|
||||
quesList.value.map((item: any) => {
|
||||
if (item.hasChildren) {
|
||||
item.childrenQuestions.map((childrenItem: any) => {
|
||||
if ([0, 1].includes(warnType)) {
|
||||
list.push(answerSame(childrenItem));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if ([0, 2].includes(warnType)) {
|
||||
list.push(answerSame(item));
|
||||
}
|
||||
}
|
||||
});
|
||||
subParams.value.optionList = list;
|
||||
subParams.value.submitType = warnType;
|
||||
return subParams.value;
|
||||
}
|
||||
function answerSame(item: quesItem) {
|
||||
let paramsItem = {
|
||||
questionCode: item.questionCode,
|
||||
userOptionCode: item.userAnswer,
|
||||
};
|
||||
if (item.isShow) {
|
||||
if (item.type === 0) {
|
||||
let meanFind = item.optionList.find((e: any) => e.optionCode === item.userAnswer);
|
||||
paramsItem.meaning = meanFind.meaning;
|
||||
} else {
|
||||
delete paramsItem.meaning;
|
||||
}
|
||||
}
|
||||
return paramsItem;
|
||||
}
|
||||
async function handleSubmit() {
|
||||
loadingSpinner();
|
||||
const { code, result, message } = await setQuestion(getParams());
|
||||
if (code === 200) {
|
||||
loadingClose();
|
||||
showSuccessToast('提交成功');
|
||||
try {
|
||||
destroyPage();
|
||||
} catch {
|
||||
router.go(-1);
|
||||
}
|
||||
} else {
|
||||
loadingClose();
|
||||
showFailToast(message);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.warning-container {
|
||||
background-color: #f5f7fb;
|
||||
.warn-con {
|
||||
width: 100%;
|
||||
.warn-header {
|
||||
z-index: 4;
|
||||
width: 100%;
|
||||
height: 140px;
|
||||
position: relative;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.header-font {
|
||||
position: absolute;
|
||||
left: 7%;
|
||||
top: 22%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
span:nth-child(1) {
|
||||
font-size: 30px;
|
||||
color: #ffffff;
|
||||
}
|
||||
span:nth-child(2) {
|
||||
margin-top: -12px;
|
||||
color: rgba(255, 255, 255, 0.1);
|
||||
font-size: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.warn-box {
|
||||
height: calc(100vh - 190px);
|
||||
overflow-y: auto;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
.vancc-box {
|
||||
background-color: #fff;
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
height: calc(100vh - 60px);
|
||||
overflow-y: auto;
|
||||
.vancc-title {
|
||||
div:nth-child(1) {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
div:nth-child(2) {
|
||||
padding: 4px 0;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
.ques-item {
|
||||
width: 100%;
|
||||
.vancc {
|
||||
padding: 10px 12px;
|
||||
background-color: #f1f1f1;
|
||||
border-radius: 16px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.qus-title {
|
||||
padding: 10px 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
.radioStyle {
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.bottom-btn {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.btn {
|
||||
width: 80%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
background-color: #1a68ee;
|
||||
border-radius: 16px;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,7 @@
|
||||
import { get, post } from '/@/views/mobile/api/api';
|
||||
|
||||
const prefix: string = import.meta.env.VITE_GLOB_APP_PREFIX || '';
|
||||
|
||||
export const getQuestionList = (params: any) => get(`${prefix}/cancer/immune/survey/info`, params);
|
||||
|
||||
export const setQuestion = (params: any) => post(`${prefix}/cancer/immune/survey/submit`, params);
|
||||
@@ -0,0 +1,3 @@
|
||||
export function changeRadio(){
|
||||
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
<template>
|
||||
<div class="home-perediction">
|
||||
<div class="container" v-if="type === 1">
|
||||
<van-collapse v-model="activeNames" ref="collapse">
|
||||
<div class="con-box" v-for="(item, index) in tableData" :key="index">
|
||||
<van-collapse-item>
|
||||
<template #title>
|
||||
<div class="header">
|
||||
<span class="name">{{ item.name }}</span>
|
||||
<span @click="checkStatus(item.vis, index)">
|
||||
{{ item.vis ? '收起' : '展开' }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<a-table
|
||||
v-if="item.list.length > 0"
|
||||
:columns="index === 1 ? columns1 : columns"
|
||||
:data-source="item.list"
|
||||
:pagination="false"
|
||||
/>
|
||||
<Nodata v-else />
|
||||
</van-collapse-item>
|
||||
</div>
|
||||
</van-collapse>
|
||||
<div class="cancer-box">
|
||||
<div class="header">
|
||||
<span class="name">癌症信号预判</span>
|
||||
<span class="info" @click="goPeredic">修改问卷信息</span>
|
||||
</div>
|
||||
<div class="cancer-con" v-if="cancerList.length > 0">
|
||||
<div
|
||||
class="cance-width"
|
||||
v-for="(canItem, canIndex) in cancerList"
|
||||
:key="canIndex"
|
||||
:style="{ padding: canIndex % 2 === 0 ? '0 10px 10px 0' : '0 0 10px 0' }"
|
||||
>
|
||||
<div :class="['cancer-item', canItem.classBg]">
|
||||
<div class="icon"></div>
|
||||
<div class="title">{{ canItem.name }}</div>
|
||||
<div class="grade" v-if="canItem.grade !== null">{{ canItem.grade }}</div>
|
||||
<div v-else class="tips">缺少必要指标无法计算</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cance-tips">
|
||||
<span class="con">存在未体检的指标数据,如需正常计算相关癌症风险,请前往做相关检查 </span>
|
||||
<span class="tipsLook" @click="handleTips">查看指标</span>
|
||||
</div>
|
||||
</div>
|
||||
<Nodata v-else />
|
||||
<div v-if="isAbnormal !== ''" class="bottom-btn" @click="handleWarn">干预提示</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="no-date" v-else>
|
||||
<img :src="home" />
|
||||
<div class="tips">请先进行信号预判问卷填写</div>
|
||||
<div class="bottom-btn" @click="goPeredic">去填写</div>
|
||||
</div>
|
||||
<dialog-overlay
|
||||
:show="dialogCon.show"
|
||||
:content="dialogCon.con"
|
||||
:imgUrl="dialogCon.url"
|
||||
:okText="dialogCon.okText"
|
||||
:cancelBtn="dialogCon.canBtn"
|
||||
@ok="handleOk"
|
||||
>
|
||||
<template #content>
|
||||
<div class="overlay-container">
|
||||
<template v-if="overlayType === '1'">
|
||||
<div class="title">癌症风险计算所需体检指标</div>
|
||||
<div class="overlay-con">
|
||||
<div class="con-item" v-for="(item, index) in overlayList" :key="index"
|
||||
><span>{{ index + 1 }}</span
|
||||
><span>{{ item.name }}</span></div
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="overlayType === '2'">
|
||||
<span v-if="isAbnormal === 0" style="color: #52c41a">您的癌症信号正常请继续保持!</span>
|
||||
<span v-else style="color: #ed2a26">您的癌症信号异常请及时就诊!</span>
|
||||
<!-- {{ // isAbnormal === 0 ? '您的癌症信号正常请继续保持!' : '您的癌症信号异常请及时就诊!' }}-->
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</dialog-overlay>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, nextTick } from 'vue';
|
||||
import home from '/@/assets/images/traceability/homePrediction.png';
|
||||
import signal from '/@/assets/images/traceability/no-signal.png';
|
||||
import warnIcon from '/@/assets/images/questions/warn.png';
|
||||
import dialogOverlay from '/@/views/23-physical-questions/components/dialogOverlay.vue';
|
||||
import Nodata from '/@/views/23-physical-questions/components/noData.vue';
|
||||
import { getHomeListApi } from '/@/views/23intervene/signalPrediction/predictionApi.ts';
|
||||
import { columns, columns1 } from '/@/views/23intervene/signalPrediction/signalHooks.ts';
|
||||
import { newPageParams, openPage } from '/@/hooks/openPage';
|
||||
const type = ref(0);
|
||||
const activeNames = ref(['1']);
|
||||
const collapse = ref(null);
|
||||
const tableData = ref([
|
||||
{
|
||||
name: '表象信号',
|
||||
list: [],
|
||||
vis: true,
|
||||
},
|
||||
{
|
||||
name: '检验信号',
|
||||
list: [],
|
||||
vis: true,
|
||||
},
|
||||
{
|
||||
name: '检查信号',
|
||||
list: [],
|
||||
vis: true,
|
||||
},
|
||||
]);
|
||||
const overlayType = ref('');
|
||||
const cancerList = ref([]);
|
||||
const overlayList = ref([]);
|
||||
const dialogCon = ref({
|
||||
show: false,
|
||||
url: warnIcon,
|
||||
con: '',
|
||||
canBtn: false,
|
||||
okText: '我知道了',
|
||||
});
|
||||
const isAbnormal = ref(''); // 0 正常、 1 异常
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
async function getList() {
|
||||
const { code, result } = await getHomeListApi({});
|
||||
if (code === 200) {
|
||||
if (result.appearanceList !== null && result.checkList !== null) {
|
||||
type.value = 1;
|
||||
nextTick(() => {
|
||||
collapse.value.toggleAll(true);
|
||||
});
|
||||
}
|
||||
tableData.value[0].list = result.appearanceList !== null ? result.appearanceList : [];
|
||||
tableData.value[1].list = result.inspectionList !== null ? result.inspectionList : [];
|
||||
tableData.value[2].list = result.checkList !== null ? result.checkList : [];
|
||||
isAbnormal.value = result.isAbnormal;
|
||||
if (result.cancerList !== null) {
|
||||
const barColor = {
|
||||
1: 'lowBg',
|
||||
2: 'centerBg',
|
||||
3: 'highBg',
|
||||
};
|
||||
result.cancerList.map((v: any) => {
|
||||
v['classBg'] = v.code !== null ? barColor[v.code] : '';
|
||||
});
|
||||
}
|
||||
cancerList.value = result.cancerList !== null ? result.cancerList : [];
|
||||
}
|
||||
}
|
||||
function handleWarn() {
|
||||
dialogCon.value.show = true;
|
||||
// dialogCon.value.con = isAbnormal.value === 0 ? '您的癌症信号正常请继续保持!' : '您的癌症信号异常请及时就诊!';
|
||||
overlayType.value = '2';
|
||||
}
|
||||
function handleTips() {
|
||||
dialogCon.value.show = true;
|
||||
// dialogCon.value.con = '';
|
||||
overlayType.value = '1';
|
||||
let data = tableData.value[1].list;
|
||||
overlayList.value = data.filter((v: any) => {
|
||||
return v.result === null;
|
||||
});
|
||||
}
|
||||
function goPeredic() {
|
||||
openPage('/signal-prediction', newPageParams({}));
|
||||
}
|
||||
function checkStatus(status: Boolean, index: Number) {
|
||||
tableData.value[index].vis = !status;
|
||||
}
|
||||
function handleOk() {
|
||||
dialogCon.value.show = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.home-perediction {
|
||||
height: 100%;
|
||||
background-color: #f5f7fb;
|
||||
overflow-y: auto;
|
||||
:deep(.ant-table-thead > tr > th) {
|
||||
background: rgba(26, 104, 238, 0.2);
|
||||
}
|
||||
:deep(.ant-table-tbody > tr > td) {
|
||||
border: 1px solid #f0f0f0;
|
||||
}
|
||||
.container {
|
||||
.con-box {
|
||||
background-color: #ffffff;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.name {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
.info {
|
||||
color: #1a68ee;
|
||||
position: relative;
|
||||
padding-left: 20px;
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 5px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background: url('/@/assets/images/traceability/edit.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.min-height {
|
||||
max-height: 0;
|
||||
transition: max-height 0.5s ease-out;
|
||||
overflow: hidden;
|
||||
}
|
||||
.max-height {
|
||||
transition: max-height 0.5s ease-out;
|
||||
max-height: 600px;
|
||||
}
|
||||
.cancer-box {
|
||||
margin-top: 20px;
|
||||
background-color: #ffffff;
|
||||
padding: 20px;
|
||||
.cancer-con {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
padding-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
.cance-width {
|
||||
width: 50%;
|
||||
.cancer-item {
|
||||
width: 100%;
|
||||
height: 110px;
|
||||
border-radius: 10px;
|
||||
background: url('/@/assets/images/traceability/defaultBg.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
position: relative;
|
||||
.title {
|
||||
padding: 16px;
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
font-weight: bold;
|
||||
}
|
||||
.grade {
|
||||
padding-left: 16px;
|
||||
}
|
||||
.tips {
|
||||
padding: 0 16px;
|
||||
color: #999999;
|
||||
}
|
||||
.icon {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 16px;
|
||||
width: 22px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
.lowBg {
|
||||
background: url('/@/assets/images/traceability/lowBg.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
.grade {
|
||||
color: #52c41a;
|
||||
}
|
||||
}
|
||||
.centerBg {
|
||||
background: url('/@/assets/images/traceability/centerBg.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
.grade {
|
||||
color: #ff7421;
|
||||
}
|
||||
.icon {
|
||||
background: url('/@/assets/images/traceability/centerIcon.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
.highBg {
|
||||
background: url('/@/assets/images/traceability/highBg.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
.grade {
|
||||
color: #ed2a26;
|
||||
}
|
||||
.icon {
|
||||
background: url('/@/assets/images/traceability/highBgIcon.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.cance-tips {
|
||||
padding: 20px 0;
|
||||
.con {
|
||||
color: #999999;
|
||||
}
|
||||
.tipsLook {
|
||||
color: #1a68ee;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.no-date {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 55%;
|
||||
img {
|
||||
width: 46%;
|
||||
}
|
||||
.tips {
|
||||
font-size: 16px;
|
||||
padding: 10px 0 20px 0;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
.bottom-btn {
|
||||
width: 28%;
|
||||
height: 38px;
|
||||
line-height: 38px;
|
||||
background-color: #1a68ee;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
border-radius: 30px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.overlay-container {
|
||||
.title {
|
||||
color: #333333;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.overlay-con {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
.con-item {
|
||||
padding: 8px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
span:nth-child(1) {
|
||||
display: inline-block;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
border: 1px solid #bdbdbd;
|
||||
border-radius: 50%;
|
||||
font-size: 16px;
|
||||
color: #b6b6b6;
|
||||
}
|
||||
span:nth-child(2) {
|
||||
padding-left: 10px;
|
||||
width: 90%;
|
||||
display: inline-block;
|
||||
text-decoration: underline 4px rgba(26, 104, 238, 0.4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,277 @@
|
||||
<template>
|
||||
<div class="prediction-container">
|
||||
<div class="prediction-header">
|
||||
<div class="header-font">
|
||||
<span>信号预判</span>
|
||||
<span>SIGNAL PREDICTION</span>
|
||||
</div>
|
||||
<img :src="headerIcon" />
|
||||
</div>
|
||||
<div class="prediction-con">
|
||||
<div class="con-title"></div>
|
||||
<div class="container">
|
||||
<div class="question-box" v-for="(quesItem, index) in questionList" :key="index">
|
||||
<template v-for="(qus, quIndex) in quesItem.question">
|
||||
<div class="question-title" v-if="qus.isShow" :key="quIndex">
|
||||
<div class="title">
|
||||
<span class="tips">*</span>
|
||||
<div>
|
||||
<span>{{ qus.index_type }}、</span>
|
||||
<span>{{ qus.title }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="qus.inputType === 'radio'">
|
||||
<a-radio-group v-model:value="qus.answer" @change="(e) => changeRadio(index, e, qus.type, qus.options)">
|
||||
<a-radio
|
||||
class="radioStyle"
|
||||
v-for="(optionItem, indexItem) in qus.options"
|
||||
:key="indexItem"
|
||||
:value="optionItem.value"
|
||||
>
|
||||
{{ optionItem.name }}</a-radio
|
||||
>
|
||||
</a-radio-group>
|
||||
</template>
|
||||
<template v-if="qus.inputType === 'input'">
|
||||
<div class="input-box">
|
||||
<div class="field-answer">
|
||||
<van-field type="number" v-model="qus.answer" @blur="changeInpput(qus.answer, index, quIndex)" />
|
||||
</div>
|
||||
<div class="input-unit">{{ qus.unit }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-btn">
|
||||
<van-button class="btn" round type="primary" @click="handleSubmit">提交</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import headerIcon from '/@/assets/images/traceability/headerImage.png';
|
||||
import { getSignalApi, postSignalApi } from '/@/views/23intervene/signalPrediction/predictionApi.ts';
|
||||
import { showFailToast, showSuccessToast, showToast, showLoadingToast } from 'vant';
|
||||
import { destroyPage } from '/@/hooks/openPage';
|
||||
import {useLoading} from '/@/utils/compUtils';
|
||||
import { useRouter } from 'vue-router';
|
||||
let questionList = ref({});
|
||||
let submitParams = ref({});
|
||||
const router = useRouter();
|
||||
const { loadingSpinner, loadingClose } = useLoading();
|
||||
getList();
|
||||
async function getList() {
|
||||
const { code, result } = await getSignalApi({});
|
||||
if (code === 200) {
|
||||
questionList.value = changeIndex(result.questionList);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 添加自定义问卷序号
|
||||
*/
|
||||
function changeIndex(data: Array) {
|
||||
let indexInit = 0;
|
||||
const list = data.map((v: any) => {
|
||||
v.question.map((item: any) => {
|
||||
if (item.isShow) {
|
||||
indexInit++;
|
||||
item['index_type'] = indexInit;
|
||||
}
|
||||
});
|
||||
return v;
|
||||
});
|
||||
return list;
|
||||
}
|
||||
/**
|
||||
* radio 跳题,给提交对象赋值
|
||||
* @param index
|
||||
* @param value radio 选中值
|
||||
* @param field 提交时所需参数
|
||||
* @param options 选中题的选项
|
||||
*/
|
||||
async function changeRadio(index: number, value: number, field: string, options: object) {
|
||||
let datas = questionList.value;
|
||||
let radioVal = value.target.value;
|
||||
let optionItem = options.find((e: { value: any }) => e.value === 1);
|
||||
if (optionItem.showCode !== '') {
|
||||
let codeList = optionItem.showCode.split(',');
|
||||
codeList.map((code: any) => {
|
||||
datas.map((item: any) => {
|
||||
if (code == item.questionCode) {
|
||||
if (item.question[0].answer !== '') {
|
||||
item.question[0].answer = '';
|
||||
}
|
||||
item.question[0].isShow = radioVal === 1;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
submitParams.value[field] = radioVal;
|
||||
questionList.value = changeIndex(datas);
|
||||
}
|
||||
// 限制input输入负数
|
||||
function changeInpput(value: string, index: number, qusIndex: number) {
|
||||
if (Number(value) < 0) {
|
||||
showToast('不能输入负数');
|
||||
questionList.value[index].question[qusIndex].answer = '';
|
||||
}
|
||||
}
|
||||
function getParams() {
|
||||
questionList.value.map((quItem: any) => {
|
||||
quItem.question.map((item: any) => {
|
||||
if (['radio', 'input'].includes(item.inputType) && item.isShow) {
|
||||
submitParams.value[item.type] = item.answer;
|
||||
}
|
||||
});
|
||||
});
|
||||
return submitParams.value;
|
||||
}
|
||||
async function handleSubmit() {
|
||||
let vis = true;
|
||||
questionList.value.map((v: any) => {
|
||||
v.question.map((qusItem: any) => {
|
||||
if (qusItem.isShow && ['radio', 'input'].includes(qusItem.inputType)) {
|
||||
if (qusItem.answer === '') {
|
||||
vis = false;
|
||||
showToast('请填写完问卷');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
if (vis) {
|
||||
loadingSpinner();
|
||||
const { code, result, message } = await postSignalApi(getParams());
|
||||
if (code === 200) {
|
||||
loadingClose();
|
||||
showSuccessToast('提交成功');
|
||||
try {
|
||||
destroyPage();
|
||||
} catch {
|
||||
router.go(-1);
|
||||
}
|
||||
} else {
|
||||
loadingClose();
|
||||
showFailToast(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.prediction-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: #f5f7fb;
|
||||
position: relative;
|
||||
.prediction-header {
|
||||
z-index: 4;
|
||||
width: 100%;
|
||||
height: 140px;
|
||||
position: relative;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.header-font {
|
||||
position: absolute;
|
||||
left: 7%;
|
||||
top: 22%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
span:nth-child(1) {
|
||||
font-size: 30px;
|
||||
color: #ffffff;
|
||||
}
|
||||
span:nth-child(2) {
|
||||
margin-top: -12px;
|
||||
color: rgba(255, 255, 255, 0.1);
|
||||
font-size: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.prediction-con {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 125px;
|
||||
z-index: 99;
|
||||
border-radius: 16px;
|
||||
background-color: #ffffff;
|
||||
.con-title {
|
||||
width: 100%;
|
||||
height: 34px;
|
||||
background: linear-gradient(180deg, rgba(26, 104, 238, 0.2) 0%, rgba(48, 160, 226, 0.2) 0%, rgba(255, 255, 255, 0) 100%);
|
||||
}
|
||||
.container {
|
||||
width: 100%;
|
||||
height: calc(100vh - 220px);
|
||||
overflow-y: auto;
|
||||
.question-box {
|
||||
.question-title {
|
||||
padding: 10px 20px;
|
||||
.title {
|
||||
color: #333b42;
|
||||
font-weight: bold;
|
||||
padding-bottom: 10px;
|
||||
position: relative;
|
||||
.tips {
|
||||
color: #ed2a26;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
left: -10px;
|
||||
}
|
||||
}
|
||||
.radioStyle {
|
||||
display: block;
|
||||
height: 32px;
|
||||
}
|
||||
.input-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.field-answer {
|
||||
width: 40%;
|
||||
}
|
||||
:deep(.van-cell) {
|
||||
border: 1px solid #e6e6ea;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.input-unit {
|
||||
width: 20%;
|
||||
padding-left: 10px;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.bottom-btn {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
height: 50px;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.btn {
|
||||
width: 80%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
background-color: #1a68ee;
|
||||
border-radius: 16px;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,9 @@
|
||||
import { get, post } from '/@/views/mobile/api/api';
|
||||
|
||||
const prefix: string = import.meta.env.VITE_GLOB_APP_PREFIX || '';
|
||||
|
||||
export const getHomeListApi = (params: any) => get(`${prefix}/cancer/signal/app/index`, params);
|
||||
|
||||
export const getSignalApi = (params: any) => get(`${prefix}/cancer/signal/app/getSurvey`, params);
|
||||
|
||||
export const postSignalApi = (params: any) => post(`${prefix}/cancer/signal/app/postSurvey`, params);
|
||||
@@ -0,0 +1,70 @@
|
||||
import { h } from 'vue';
|
||||
function resColor(data: any) {
|
||||
let color = '';
|
||||
if (data.resultText !== null) {
|
||||
color = data.isError === 1 ? 'red' : '';
|
||||
}
|
||||
return h('span', { style: { color } }, data.resultText !== null ? data.resultText : '-');
|
||||
}
|
||||
// @ts-ignore
|
||||
export const columns = [
|
||||
{
|
||||
title: '信号名称',
|
||||
dataIndex: 'name',
|
||||
width: 110,
|
||||
},
|
||||
{
|
||||
title: '结果',
|
||||
dataIndex: 'result',
|
||||
width: 60,
|
||||
customRender: ({ record }) => {
|
||||
return resColor(record);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '单位',
|
||||
dataIndex: 'unit',
|
||||
width: 60,
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
dataIndex: 'updateTime',
|
||||
width: 110,
|
||||
customRender: ({ record }) => {
|
||||
return record.updateTime !== null ? record.updateTime : '-';
|
||||
},
|
||||
},
|
||||
];
|
||||
export const columns1 = [
|
||||
{
|
||||
title: '指标名称',
|
||||
dataIndex: 'name',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '结果',
|
||||
dataIndex: 'result',
|
||||
width: 70,
|
||||
customRender: ({ record }) => {
|
||||
return resColor(record);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '单位',
|
||||
dataIndex: 'unit',
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
title: '参考范围',
|
||||
dataIndex: 'referenceRange',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
dataIndex: 'updateTime',
|
||||
width: 110,
|
||||
customRender: ({ record }) => {
|
||||
return record.updateTime !== null ? record.updateTime : '-';
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,272 @@
|
||||
<template>
|
||||
<div class="outer-d">
|
||||
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||
<div style="height: 100%; overflow: auto">
|
||||
<template v-if="list.length > 0">
|
||||
<van-list
|
||||
v-model:loading="loading"
|
||||
:finished="finished"
|
||||
@load="onLoad"
|
||||
:finished-text="list.length > 0 ? '没有更多了' : ''"
|
||||
v-model:error="error"
|
||||
error-text="请求失败,点击重新加载"
|
||||
>
|
||||
<template v-for="it in vellArray" :key="`collapse${it}`">
|
||||
<van-collapse v-model="activeNames">
|
||||
<van-collapse-item :title="it" :name="it">
|
||||
<template v-for="item in list" :key="item">
|
||||
<div
|
||||
class="van-collapse-item-d"
|
||||
v-if="moment(item.endAnswerTime).format('YYYY').indexOf(it) !== -1"
|
||||
:title="item"
|
||||
@click="toReports(item)"
|
||||
>
|
||||
<div> 评估时间:{{ moment(item.endAnswerTime).format('YYYY-MM-DD HH:mm:ss') }} </div>
|
||||
<table>
|
||||
<tr>
|
||||
<th class="table-left">主题</th>
|
||||
<th class="table-right">模块</th>
|
||||
</tr>
|
||||
<tr v-for="(t, index) in item.categoryList || []" :key="`category${index}`" class="tbody-tr">
|
||||
<td class="table-left" v-if="count[index] != 0" :rowspan="count[index]">{{
|
||||
t.modelName || '-'
|
||||
}}</td>
|
||||
<td class="table-right">{{ t.questionCategory || '-' }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
</van-collapse-item>
|
||||
</van-collapse>
|
||||
</template>
|
||||
</van-list>
|
||||
</template>
|
||||
<div v-if="list.length === 0 && finished" class="empty-d">
|
||||
<!-- <van-empty description="暂无数据" />-->
|
||||
<Empty :url="emptyIcon" :imageSize="[200, 160]" />
|
||||
</div>
|
||||
</div>
|
||||
</van-pull-refresh>
|
||||
<van-back-top />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { getAnswerPageApi } from '/@/views/23psychology/psychic/psychologyApi';
|
||||
import moment from 'moment';
|
||||
import Empty from '/@/components/Empty.vue';
|
||||
import emptyIcon from '/@/assets/images/interveneEmpty.png';
|
||||
import { useRouter } from 'vue-router';
|
||||
const activeNames = ref<any[]>([]);
|
||||
const list = ref<any[]>([]); // 列表
|
||||
const refreshing = ref(false); // 刷新状态
|
||||
const loading = ref(false); // loading 状态
|
||||
const finished = ref(false); // 是否完成
|
||||
const error = ref(false); // 是否报错
|
||||
const vellArray = ref<any[]>([]);
|
||||
const pageInfo = ref({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
});
|
||||
const router = useRouter();
|
||||
const count = ref<any[]>([]);
|
||||
const dataIndex = ref(0);
|
||||
function toReports(item: any) {
|
||||
router.push({
|
||||
path: '/answer-report',
|
||||
query: { id: item.id },
|
||||
});
|
||||
}
|
||||
|
||||
function getRowspan(list: any[]) {
|
||||
list.map((item, index) => {
|
||||
if (index === 0) {
|
||||
dataIndex.value = index;
|
||||
count.value[index] = 1;
|
||||
} else {
|
||||
if (list[index - 1].modelId === item.modelId) {
|
||||
count.value[dataIndex.value] = parseInt(count.value[dataIndex.value]) + 1;
|
||||
count.value[index] = 0;
|
||||
} else {
|
||||
dataIndex.value = index;
|
||||
count.value[index] = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
console.log(count.value);
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
if (refreshing.value) {
|
||||
list.value = [];
|
||||
vellArray.value = [];
|
||||
activeNames.value = [];
|
||||
refreshing.value = false;
|
||||
finished.value = false;
|
||||
error.value = false;
|
||||
loading.value = true;
|
||||
pageInfo.value.pageNo = 1;
|
||||
}
|
||||
if (finished.value) return;
|
||||
getAnswerPageApi(pageInfo.value)
|
||||
.then((res: any) => {
|
||||
if (res.success) {
|
||||
error.value = false;
|
||||
if (res.result.length > 0) {
|
||||
res.result.map((item: any) => {
|
||||
if (vellArray.value.length === 0) {
|
||||
vellArray.value = [new Date(item.endAnswerTime).getFullYear()];
|
||||
} else {
|
||||
if (vellArray.value[vellArray.value.length - 1] !== new Date(item.endAnswerTime).getFullYear()) {
|
||||
vellArray.value.push(new Date(item.endAnswerTime).getFullYear());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
activeNames.value = vellArray.value;
|
||||
if (res.result.length < pageInfo.value.pageSize || res.result.length === 0) {
|
||||
finished.value = true;
|
||||
} else {
|
||||
pageInfo.value.pageNo += 1;
|
||||
}
|
||||
getRowspan(res.result[0].categoryList);
|
||||
list.value = list.value.concat(res.result);
|
||||
} else {
|
||||
error.value = true;
|
||||
}
|
||||
loading.value = false;
|
||||
})
|
||||
.catch(() => {
|
||||
error.value = true;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
const onRefresh = () => {
|
||||
refreshing.value = true;
|
||||
onLoad();
|
||||
};
|
||||
onLoad();
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.empty-d {
|
||||
height: 90%;
|
||||
padding-top: 50%;
|
||||
}
|
||||
:deep(.van-cell__title) {
|
||||
background-color: #f5f7fb;
|
||||
flex: none !important;
|
||||
}
|
||||
:deep(.van-cell) {
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
font-size: 16px;
|
||||
padding-bottom: 5px !important;
|
||||
color: rgba(119, 132, 158, 1);
|
||||
background-color: #f5f7fb !important;
|
||||
}
|
||||
:deep(.van-collapse-item__content) {
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
padding: 0 10px 0 15px;
|
||||
background-color: #f5f7fb !important;
|
||||
}
|
||||
:deep(.van-collapse-item) {
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
:deep(.van-hairline--top-bottom) {
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.outer-d {
|
||||
height: 100%;
|
||||
background-color: #f5f7fb;
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.van-collapse-item-d {
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
font-size: 16px;
|
||||
background: #ffffff;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.middle-d {
|
||||
padding: 10px 0 0;
|
||||
> div {
|
||||
border-radius: 5px;
|
||||
padding: 10px 17px;
|
||||
border: 1px solid rgba(230, 230, 234, 1);
|
||||
margin-bottom: 10px;
|
||||
> :nth-child(1) {
|
||||
color: #21bebd;
|
||||
font-size: 19px;
|
||||
margin-right: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
> :nth-child(2) {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-d {
|
||||
border: 1px solid rgba(224, 224, 224, 1);
|
||||
border-bottom: none;
|
||||
.bottom-d-item {
|
||||
display: flex;
|
||||
border-bottom: 1px solid rgba(224, 224, 224, 1);
|
||||
> div {
|
||||
padding: 10px 17px;
|
||||
}
|
||||
> :nth-child(1) {
|
||||
background-color: #f0f0f0;
|
||||
width: 40%;
|
||||
color: #000000;
|
||||
}
|
||||
> :nth-child(2) {
|
||||
text-align: right;
|
||||
width: 60%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
margin-top: 10px;
|
||||
color: #586275;
|
||||
//font-size: 16px;
|
||||
//font-weight: bold;
|
||||
border-top: 1px solid #E0E0E0;
|
||||
border-left: 1px solid #E0E0E0;
|
||||
.tbody-tr{
|
||||
font-size: 15px;
|
||||
}
|
||||
.table-left {
|
||||
width: 45%;
|
||||
}
|
||||
.table-right {
|
||||
width: 55%;
|
||||
}
|
||||
th {
|
||||
background-color: #c6eeee;
|
||||
}
|
||||
th,
|
||||
td {
|
||||
padding: 10px 20px;
|
||||
border-right: 1px solid #e0e0e0;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,300 @@
|
||||
<template>
|
||||
<div class="outer-d">
|
||||
<div v-if="state == 2">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||
<div style="color: #586275; font-size: 15px"> 评估时间:{{ moment(time).format('YYYY-MM-DD HH:mm') }} </div>
|
||||
<span style="color: #3390ff; font-size: 15px" @click="handleDetails"> 查看答题详情 </span>
|
||||
</div>
|
||||
<div v-if="specialReport" class="item-d">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||
<span style="color: #333b42; font-size: 16px; font-weight: bold">专题心理知识</span>
|
||||
<span style="color: #21bebd; font-weight: bold">
|
||||
总分:{{ specialReport?.totalScore || 0 }} <span style="margin-left: 10px">得分:{{ specialReport?.userScore || 0 }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<table-item
|
||||
:list="specialReport.reportInfo ? specialReport.reportInfo : []"
|
||||
:count="specialReportCount"
|
||||
:field-list="['modelName', 'questionCategory', 'score', 'grade']"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="specialReport?.gradeList && specialReport?.gradeList.length > 0" class="grade-d">
|
||||
<div style="color: #000000; font-size: 16px">等级说明</div>
|
||||
<div v-for="(item, index) in specialReport?.gradeList" :key="`gradeList-${index}`">
|
||||
<div>
|
||||
{{ item?.min }}-{{ item?.max }} <span style="margin-left: 5px">{{ item?.grade }}</span></div
|
||||
>
|
||||
<div>{{ item?.prompt }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="allReport" class="item-d">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||
<span style="color: #333b42; font-size: 16px; font-weight: bold">综合心理知识</span>
|
||||
<span style="color: #21bebd; font-weight: bold">
|
||||
总分:{{ allReport?.totalScore || 0 }} <span style="margin-left: 10px">得分:{{ allReport?.userScore || 0 }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<table-item
|
||||
:list="allReport.reportInfo ? allReport.reportInfo : []"
|
||||
:count="allReportCount"
|
||||
:field-list="['modelName', 'questionCategory', 'score', 'grade']"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="allReport?.gradeList && allReport?.gradeList.length > 0" class="grade-d">
|
||||
<div style="color: #000000; font-size: 16px">等级说明</div>
|
||||
<div v-for="(item, index) in allReport?.gradeList" :key="`gradeList-${index}`">
|
||||
<div>
|
||||
{{ item?.min }}-{{ item?.max }} <span style="margin-left: 5px">{{ item?.grade }}</span></div
|
||||
>
|
||||
<div>{{ item?.prompt }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="problemReport" class="item-d">
|
||||
<div>
|
||||
<span style="color: #333b42; font-size: 16px; font-weight: bold">心理问题</span>
|
||||
</div>
|
||||
<div>
|
||||
<table-item :list="problemReport ? problemReport : []" class="problem-report">
|
||||
<template #list-th-slot>
|
||||
<th>分类</th>
|
||||
<th>等级</th>
|
||||
<th>指导语</th>
|
||||
</template>
|
||||
<template #list-td-slot="data">
|
||||
<td>{{ data?.questionCategory || '-' }}</td>
|
||||
<td>{{ data?.score || '-' }}分{{ data?.grade ? `(${data?.grade})` : '' }}</td>
|
||||
<td>{{ data?.prompt || '-' }}</td>
|
||||
</template>
|
||||
</table-item>
|
||||
</div>
|
||||
</div>
|
||||
<div class="knowledge-list-d" v-if="knowledgeList.length > 0">
|
||||
<span>知识推荐</span>
|
||||
<div v-for="(item, index) in knowledgeList" :key="`knowledgeList${index}`">
|
||||
<van-divider v-if="index !== 0" :style="{ backgroundColor: '#EAECF1' }" />
|
||||
<div class="knowledge-list-item-d" @click="toDetails(item?.id)">
|
||||
<div> <img :src="getFileHttpUrl(item?.banner as string)" alt="" /> </div>
|
||||
<div>
|
||||
<div style="color: #333333; font-weight: bold">{{ item?.knowledgeName }} </div>
|
||||
<div style="color: #666666; font-size: 14px">{{ item?.description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="loading-outer" v-else>
|
||||
<van-loading v-if="state == 0" color="#1989fa" />
|
||||
<div v-else>
|
||||
<img :src="answerReportEmpty" alt="" />
|
||||
<div style="text-align: center; margin-top: 10px">
|
||||
<span style="font-size: 16px; color: #586275"> 答题结果正在计算中... </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import answerReportEmpty from '/@/assets/images/psychiology/answerReportEmpty.png';
|
||||
import { getAnswerReportApi, getKnowledgeApi } from '/@/views/23psychology/psychic/psychologyApi';
|
||||
import TableItem from '/@/views/23psychology/answer/answerReport/tableItem.vue';
|
||||
import { ref } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import moment from 'moment/moment';
|
||||
import { getFileHttpUrl } from '/@/utils/compUtils.ts';
|
||||
// 1825837438048186370
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const state = ref(0);
|
||||
const time = ref(null);
|
||||
const specialReport = ref({});
|
||||
const specialReportCount = ref<any[]>([]);
|
||||
const allReport = ref({});
|
||||
const allReportCount = ref<any[]>([]);
|
||||
const problemReport = ref({});
|
||||
const knowledgeList = ref<any[]>([]);
|
||||
const apiInterval = ref<any>(null);
|
||||
const intervalCount = ref(1);
|
||||
let idRecord = ref('');
|
||||
|
||||
function init() {
|
||||
getAnswerReportApi({ id: route.query.id })
|
||||
.then((res: any) => {
|
||||
if (res.success) {
|
||||
time.value = res.result.endAnswerTime;
|
||||
state.value = res.result.state;
|
||||
specialReport.value = res.result.specialReport;
|
||||
specialReportCount.value = res.result.specialReport ? preList(res.result.specialReport.reportInfo) : [];
|
||||
allReport.value = res.result.allReport;
|
||||
allReportCount.value = res.result.allReport ? preList(res.result.allReport.reportInfo) : [];
|
||||
problemReport.value = res.result.problemReport;
|
||||
idRecord.value = res.result.id;
|
||||
if (res.result.state == '2') {
|
||||
getKnowledge(res.result.id);
|
||||
}
|
||||
if (!apiInterval.value && res.result.state == '1' && intervalCount.value < 10) {
|
||||
apiInterval.value = setInterval(() => {
|
||||
intervalCount.value++;
|
||||
init();
|
||||
}, 5000);
|
||||
}
|
||||
if (res.result.state == '2' || intervalCount.value >= 10) {
|
||||
apiInterval.value && clearInterval(apiInterval.value);
|
||||
}
|
||||
} else {
|
||||
state.value = 1;
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
state.value = 1;
|
||||
});
|
||||
}
|
||||
|
||||
function getKnowledge(id: string) {
|
||||
getKnowledgeApi({ recordId: id, pageNo: 1, pageSize: 999 })
|
||||
.then((res: any) => {
|
||||
console.log(res);
|
||||
if (res.success) {
|
||||
knowledgeList.value = res.result;
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
function toDetails(id: string) {
|
||||
router.push({
|
||||
path: '/knowledge-detail',
|
||||
query: {
|
||||
id: id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function preList(list: any[]) {
|
||||
let dataIndex = 0;
|
||||
let count: any[] = [];
|
||||
list.map((item, index) => {
|
||||
if (index === 0) {
|
||||
dataIndex = index;
|
||||
count[index] = 1;
|
||||
} else {
|
||||
if (list[index - 1].modelId === item.modelId) {
|
||||
count[dataIndex] = parseInt(count[dataIndex]) + 1;
|
||||
count[index] = 0;
|
||||
} else {
|
||||
dataIndex = index;
|
||||
count[index] = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
console.log(count);
|
||||
return [];
|
||||
}
|
||||
function handleDetails() {
|
||||
router.push({
|
||||
path: '/ps-answerDetails',
|
||||
query: {
|
||||
idRecord: idRecord.value,
|
||||
},
|
||||
});
|
||||
}
|
||||
init();
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.outer-d {
|
||||
padding: 10px;
|
||||
overflow: auto;
|
||||
}
|
||||
.outer-d,
|
||||
.loading-outer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f5f7fb;
|
||||
}
|
||||
.loading-outer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 30%;
|
||||
}
|
||||
}
|
||||
.item-d {
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
background-color: #ffffff;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.empty-d {
|
||||
height: 90%;
|
||||
padding-top: 50%;
|
||||
}
|
||||
.problem-report {
|
||||
td,
|
||||
th {
|
||||
&:nth-child(1) {
|
||||
width: 32%;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
width: 28%;
|
||||
}
|
||||
&:nth-child(3) {
|
||||
width: 40%;
|
||||
}
|
||||
}
|
||||
th {
|
||||
background-color: #c6eeee;
|
||||
}
|
||||
th,
|
||||
td {
|
||||
padding: 10px;
|
||||
border-right: 1px solid #e0e0e0;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
}
|
||||
|
||||
.grade-d {
|
||||
background-color: #f3f5f9;
|
||||
color: #77849e;
|
||||
margin-top: 10px;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
div {
|
||||
padding: 3px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.knowledge-list-d {
|
||||
background-color: #ffffff;
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-top: 10px;
|
||||
.knowledge-list-item-d {
|
||||
padding: 20px 0;
|
||||
display: flex;
|
||||
> div {
|
||||
height: 115px;
|
||||
overflow: hidden;
|
||||
&:nth-child(1) {
|
||||
width: 40%;
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
&:nth-child(2) {
|
||||
padding: 0 10px;
|
||||
width: 60%;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 5;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,145 @@
|
||||
<template>
|
||||
<div class="outer-d">
|
||||
<template v-if="info">
|
||||
<div class="img-bottom-d">
|
||||
<div class="img-header">
|
||||
<div class="header-img">
|
||||
<img :src="getFileHttpUrl(info?.banner)" alt="" />
|
||||
</div>
|
||||
<div class="header-con">
|
||||
<div class="header-name"> {{ info?.knowledgeName }}</div>
|
||||
<div class="header-container">
|
||||
<div :class="['header-des', extendType ? '' : 'expand']"> {{ info?.description }}</div>
|
||||
<span class="header-expand" @click="changeExpand">
|
||||
{{ extendType ? '收起' : '展开' }}
|
||||
<van-icon v-if="!extendType" name="arrow-down" color="#1A68EE" />
|
||||
<van-icon v-else name="arrow-up" color="#1A68EE" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-item-d">
|
||||
<div> 主要内容 </div>
|
||||
<div v-if="info?.content" v-html="info?.content"> </div>
|
||||
<div class="nodata" v-else>暂无数据</div>
|
||||
</div>
|
||||
<div class="bottom-item-d">
|
||||
<div> 推荐理由 </div>
|
||||
<div v-if="info?.recommendReason" v-html="info?.recommendReason"> </div>
|
||||
<div class="nodata" v-else>暂无</div>
|
||||
</div>
|
||||
<div class="bottom-item-d">
|
||||
<div> 具体帮助 </div>
|
||||
<div v-if="info?.help" v-html="info?.help"> </div>
|
||||
<div class="nodata" v-else>暂无</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div v-if="empty || !info" class="empty-d">
|
||||
<Empty :url="emptyIcon" :imageSize="[200, 160]" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useRoute } from 'vue-router';
|
||||
import { getKnowledgeDetailApi } from '/@/views/23psychology/psychic/psychologyApi';
|
||||
import { ref } from 'vue';
|
||||
import emptyIcon from '/@/assets/images/interveneEmpty.png';
|
||||
import Empty from '/@/components/Empty.vue';
|
||||
import { getFileHttpUrl } from '/@/utils/compUtils.ts';
|
||||
|
||||
const route = useRoute();
|
||||
const empty = ref(false);
|
||||
const info = ref<any>(null);
|
||||
let extendType = ref(false);
|
||||
let headerHieght = ref(120);
|
||||
|
||||
function init() {
|
||||
getKnowledgeDetailApi({ id: route.query.id })
|
||||
.then((res: any) => {
|
||||
if (res.success) {
|
||||
info.value = res.result;
|
||||
} else {
|
||||
empty.value = true;
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
empty.value = true;
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
function changeExpand() {
|
||||
extendType.value = !extendType.value;
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.outer-d {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: #f5f7fb;
|
||||
position: relative;
|
||||
.img-bottom-d {
|
||||
padding: 20px;
|
||||
.img-header {
|
||||
display: flex;
|
||||
padding: 16px;
|
||||
margin-bottom: 20px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 10px;
|
||||
.expand {
|
||||
height: 125px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.header-expand {
|
||||
color: #1a68ee;
|
||||
}
|
||||
.header-img {
|
||||
width: 35%;
|
||||
height: 170px;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.header-con {
|
||||
padding-left: 15px;
|
||||
width: 65%;
|
||||
.header-name {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
.header-des {
|
||||
color: #666666;
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.bottom-item-d {
|
||||
padding: 16px;
|
||||
margin-bottom: 20px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 10px;
|
||||
.nodata{
|
||||
color:#666666;
|
||||
}
|
||||
> div {
|
||||
&:nth-child(1) {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
padding-bottom: 10px;
|
||||
color: #333333;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
font-size: 14px;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.empty-d {
|
||||
height: 90%;
|
||||
padding-top: 50%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<table>
|
||||
<tr>
|
||||
<slot name="list-th-slot">
|
||||
<th class="table-left">模块</th>
|
||||
<th class="table-right">分类</th>
|
||||
<th class="table-right">计分</th>
|
||||
<th class="table-right">等级</th>
|
||||
</slot>
|
||||
</tr>
|
||||
<tr v-for="(t, index) in props.list" :key="`category${index}`">
|
||||
<slot name="list-td-slot" v-bind="t || {}">
|
||||
<td v-if="props.count?.[index] != 0 || !props.count?.[index]" :rowspan="props.count?.[index] ? props.count?.[index] : 1">
|
||||
{{ t[props.fieldList[0]] || '-' }}
|
||||
</td>
|
||||
<td>{{ t[props.fieldList[1]] || '-' }}</td>
|
||||
<td>{{ t[props.fieldList[2]] || '-' }}</td>
|
||||
<td>{{ t[props.fieldList[3]] || '-' }}</td>
|
||||
</slot>
|
||||
</tr>
|
||||
</table>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
count: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
fieldList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
table {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
margin-top: 10px;
|
||||
color: #586275;
|
||||
//font-size: 16px;
|
||||
font-weight: bold;
|
||||
border-top: 1px solid #e0e0e0;
|
||||
border-left: 1px solid #e0e0e0;
|
||||
td,
|
||||
th {
|
||||
&:nth-child(1) {
|
||||
width: 32%;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
width: 28%;
|
||||
}
|
||||
&:nth-child(3) {
|
||||
width: 20%;
|
||||
}
|
||||
&:nth-child(4) {
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
th {
|
||||
background-color: #c6eeee;
|
||||
}
|
||||
th,
|
||||
td {
|
||||
padding: 10px;
|
||||
border-right: 1px solid #e0e0e0;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,200 @@
|
||||
<template>
|
||||
<div class="outer-d">
|
||||
<div class="top-tip">请选择此次答题类别,可一次选择多个类别</div>
|
||||
<div class="middle-d">
|
||||
<template v-if="!isEmpty">
|
||||
<template v-for="(item, index) in list" :key="`topic${index}`">
|
||||
<template v-if="item?.childrenList && item?.childrenList.length > 0">
|
||||
<div class="topic-item-d">
|
||||
<div class="topic-item-d-title-one" style="margin-bottom: 10px">
|
||||
<img v-if="item.id.indexOf('A01') > -1" :src="chooseTopicItem" alt="" />
|
||||
<img v-if="item.id.indexOf('B01') > -1" :src="comprehensive" alt="" />
|
||||
<img v-if="item.id.indexOf('C01') > -1" :src="chooseTopicItemLast" alt="" />
|
||||
{{ item?.category }}{{ item.chidrenList }}
|
||||
</div>
|
||||
<template v-if="item?.id.indexOf('C01') === -1">
|
||||
<topic-item :list="item?.childrenList" @update-value="changeValue" :count="index + ''" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<van-checkbox-group v-model="checked" shape="square" style="width: 100%">
|
||||
<div style="display: flex; flex-wrap: wrap">
|
||||
<div
|
||||
:key="`topic${index}-${index}-${c}`"
|
||||
class="check-item-d"
|
||||
:class="[checked.includes(t.id as string) ? 'checked-item' : '']"
|
||||
v-for="(t, c) in item.childrenList"
|
||||
:style="{
|
||||
width: t.id.indexOf('B01') !== -1 ? '100%' : '46%',
|
||||
marginLeft: t.id.indexOf('B01') === -1 && c % 2 !== 0 ? '6%' : '0',
|
||||
}"
|
||||
>
|
||||
<van-checkbox :name="t.id"> {{ t?.category }}</van-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</van-checkbox-group>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="no-data">
|
||||
<Empty :url="emptyIcon" :imageSize="[200, 160]" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="bottom-button">
|
||||
<van-button class="btn" round type="primary" @click="toAnswer" :disabled="isEmpty"> 开始答题 </van-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { getCategoryApi } from '/@/views/23psychology/psychic/psychologyApi';
|
||||
import chooseTopicItem from '/@/assets/images/psychiology/chooseTopicItem.png';
|
||||
import chooseTopicItemLast from '/@/assets/images/psychiology/chooseTopicItemLast.png';
|
||||
import comprehensive from '/@/assets/images/psychiology/comprehensive.png';
|
||||
import { showFailToast } from 'vant';
|
||||
import { ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import store from '/@/store';
|
||||
import TopicItem from '/@/views/23psychology/answer/chooseTopic/topicItem.vue';
|
||||
import emptyIcon from '/@/assets/images/interveneEmpty.png';
|
||||
import Empty from '/@/components/Empty.vue';
|
||||
import { newPageParams, openPage } from '/@/hooks/openPage';
|
||||
|
||||
const list = ref<any[]>([]);
|
||||
const checked = ref<any[]>([]);
|
||||
const checkedJson = ref<any>({});
|
||||
const isEmpty = ref(true);
|
||||
const router = useRouter();
|
||||
|
||||
function getCategory() {
|
||||
getCategoryApi({})
|
||||
.then((res: any) => {
|
||||
if (res.success) {
|
||||
list.value = preTree(res.result || []);
|
||||
} else {
|
||||
showFailToast(res.messgae);
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
function toAnswer() {
|
||||
let list: any[] = [];
|
||||
for (const c in checkedJson.value) {
|
||||
list = list.concat(checkedJson.value[c]);
|
||||
}
|
||||
if (checked.value.concat(list).length === 0) return showFailToast('请至少选择一个类别');
|
||||
store.commit('setQuestionList', checked.value.concat(list));
|
||||
openPage(
|
||||
'/ps-selfAnswer',
|
||||
newPageParams({
|
||||
affirmBack: 1,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function preTree(d: any[]) {
|
||||
const dg = (data: any[]) => {
|
||||
if (data.length === 0) return [];
|
||||
return data.filter((item) => {
|
||||
if (item.childrenList && item.childrenList.length > 0) {
|
||||
item.childrenList = dg(item.childrenList);
|
||||
return 1 === 1;
|
||||
} else {
|
||||
if (item.questionSum && item.id.indexOf('C01') !== -1 ? item.questionSum >= 1 : item.questionSum >= 5 && isEmpty) {
|
||||
isEmpty.value = false;
|
||||
}
|
||||
return item.questionSum && item.id.indexOf('C01') !== -1 ? item.questionSum >= 1 : item.questionSum >= 5;
|
||||
}
|
||||
});
|
||||
};
|
||||
console.log(dg(d));
|
||||
return dg(d);
|
||||
}
|
||||
|
||||
function changeValue(v: any) {
|
||||
checkedJson.value = { ...checkedJson.value, ...v };
|
||||
console.log(checkedJson.value);
|
||||
}
|
||||
|
||||
getCategory();
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.outer-d {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.no-data {
|
||||
width: 100%;
|
||||
padding-top: 50%;
|
||||
}
|
||||
|
||||
.top-tip {
|
||||
color: #21bebd;
|
||||
background-color: #eefffe;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.middle-d {
|
||||
background-color: #f5f7fb;
|
||||
padding: 10px;
|
||||
overflow: auto;
|
||||
height: calc(100% - 111px);
|
||||
|
||||
.topic-item-d {
|
||||
background: #ffffff;
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
.topic-item-d-title-one {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.check-item-d {
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
border: 1px solid #f3f5f9;
|
||||
}
|
||||
}
|
||||
|
||||
.check-item-d {
|
||||
background: #f3f5f9;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-button {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
background-color: #ffffff;
|
||||
.btn {
|
||||
background-color: #21bebd;
|
||||
border: 1px solid #21bebd;
|
||||
}
|
||||
button {
|
||||
width: 80%;
|
||||
margin-left: 10%;
|
||||
}
|
||||
}
|
||||
.checked-item {
|
||||
background-color: #eefffe !important;
|
||||
border: 1px solid #21bebd !important;
|
||||
}
|
||||
:deep(.van-checkbox__icon--checked .van-icon) {
|
||||
color: #ffffff !important;
|
||||
background-color: #21bebd !important;
|
||||
border-color: #21bebd !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<van-checkbox-group v-model="checked" shape="square" style="width: 100%" @change="changeChecked">
|
||||
<div style="display: flex; flex-wrap: wrap; justify-content: space-between">
|
||||
<template v-for="(t, c) in props.list">
|
||||
<template v-if="t?.childrenList && t?.childrenList.length > 0">
|
||||
<div style="margin: 10px 0 0; font-size: 16px; width: 100%"> {{ c + 1 }}、{{ t?.category }} </div>
|
||||
<topic-item :list="t?.childrenList" @update-value="updateValueInfo" :count="props.count + '-' + c" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<div
|
||||
class="check-item-d"
|
||||
:style="{
|
||||
width: t?.parentId === 'B01' && !t?.childrenList ? '100%' : '46%',
|
||||
backgroundColor: t?.childrenList && t?.childrenList.length > 0 ? '#ffffff !important' : '',
|
||||
borderColor: t?.childrenList && t?.childrenList.length > 0 ? '' : '',
|
||||
}"
|
||||
:class="[checked.includes(t.id as string) ? 'checked-item' : '']"
|
||||
>
|
||||
<van-checkbox :name="t.id">
|
||||
{{ `${t.id.indexOf('B01') !== -1 && t?.parentId === 'B01' ? c + 1 + '、' : ''}${t?.category}` }}
|
||||
</van-checkbox>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</van-checkbox-group>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { union } from 'lodash-es';
|
||||
|
||||
const props = defineProps({
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
count: {
|
||||
type: String,
|
||||
default: () => '',
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['updateValue']);
|
||||
|
||||
const checked = ref<any[]>([]);
|
||||
const checkedJson = ref<any>({});
|
||||
|
||||
function changeChecked() {
|
||||
emit('updateValue', { ...{ [props.count]: checked.value }, ...checkedJson.value });
|
||||
}
|
||||
|
||||
function updateValueInfo(v: any) {
|
||||
checkedJson.value = v;
|
||||
emit('updateValue', { ...{ [props.count]: checked.value }, ...checkedJson.value });
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.topic-item-d {
|
||||
background: #ffffff;
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
.topic-item-d-title-one {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.check-item-d {
|
||||
background: #f3f5f9;
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
width: 46%;
|
||||
border: 1px solid #f3f5f9;
|
||||
}
|
||||
}
|
||||
.checked-item {
|
||||
background-color: #eefffe !important;
|
||||
border: 1px solid #eefffe !important;
|
||||
}
|
||||
:deep(.van-checkbox__icon--checked .van-icon) {
|
||||
color: #ffffff !important;
|
||||
background-color: #21bebd !important;
|
||||
border-color: #21bebd !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,339 @@
|
||||
<template>
|
||||
<div class="answer-container">
|
||||
<div class="plan-music" v-if="ifActive">
|
||||
<div class="time">倒计时:{{ formatTime }}</div>
|
||||
<div class="bg-music">
|
||||
<img :src="playIcon" v-if="isOpenMusic" alt="" @click="handleMusic('stop')" />
|
||||
<img :src="stopIcon" alt="" v-else @click="handleMusic('play')" />
|
||||
<span>背景音乐</span>
|
||||
<audio loop ref="audioPlayer" :src="audioUrl"></audio>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="q-content"
|
||||
:style="{ height: ifActive ? 'calc(100vh - 100px)' : 'calc(100vh - 60px)' }"
|
||||
v-if="quesParams?.paperQuestionList.length > 0"
|
||||
id="psychlolgy_plan"
|
||||
>
|
||||
<AnswerCon :list="quesParams?.paperQuestionList" isEdit @change="handelChange" />
|
||||
</div>
|
||||
<div class="no-data" v-else>
|
||||
<Empty :url="emptyIcon" :imageSize="[200, 160]" />
|
||||
</div>
|
||||
<div class="bottom-btn">
|
||||
<van-button class="btn" type="primary" :disabled="quesParams?.paperQuestionList.length === 0" @click="handleSubmit">提交</van-button>
|
||||
</div>
|
||||
<Overlay :show="show">
|
||||
<template #content>
|
||||
<div class="overlay-block">
|
||||
<div class="block-top">时间到,当前答题已结束。</div>
|
||||
<div class="block-bottom" @click="handleSubmit">我知道了</div>
|
||||
</div>
|
||||
</template>
|
||||
</Overlay>
|
||||
<Overlay :show="backOver">
|
||||
<template #content>
|
||||
<div class="overlay-block">
|
||||
<div class="block-top">中途退出将不会保存您的答案,是否确定退出?</div>
|
||||
<div class="out-btn">
|
||||
<div class="backBtn canel-out" @click="backOver = false">取消</div>
|
||||
<div class="backBtn sure-out" @click="backAnswer">退出答题</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Overlay>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, watch } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { getQuesApi, submitQuesApi, getPlanQuesApi, submitPlanQuesApi } from '/@/views/23psychology/answer/questionAnswer/questionAnswer.api';
|
||||
import AnswerCon from '/@/views/23psychology/answer/questionAnswer/components/AnswerCon.vue';
|
||||
import Empty from '/@/components/Empty.vue';
|
||||
import emptyIcon from '/@/assets/images/interveneEmpty.png';
|
||||
import store from '/@/store';
|
||||
import playIcon from '/@/assets/images/psychiology/answer/playIcon.png';
|
||||
import stopIcon from '/@/assets/images/psychiology/answer/stopIcon.png';
|
||||
import { showSuccessToast, showFailToast, showToast } from 'vant';
|
||||
import { useLoading } from '/@/utils/compUtils';
|
||||
import { getFileUrl } from '/@/hooks/fileUrl';
|
||||
import { useCountdown } from '/@/views/23psychology/answer/questionAnswer/questionAnswerHook';
|
||||
import { convertTimeToSeconds, minuteConverSeconds } from '/@/views/23-physical-questions/questionHooks';
|
||||
import Overlay from '/@/views/components/overlay/Overlay.vue';
|
||||
import { useInterceptBack } from '/@/hooks/useInterceptAndroid';
|
||||
import { destroyPage } from '/@/hooks/openPage';
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const { loadingSpinner, loadingClose } = useLoading();
|
||||
const ifActive = route.query.hasOwnProperty('type');
|
||||
let show = ref(false);
|
||||
let audioPlayer = ref(null);
|
||||
let audioUrl = ref('');
|
||||
let timerOver = ref(false);
|
||||
let backOver = ref(false);
|
||||
let quesParams = ref({
|
||||
paperQuestionList: [],
|
||||
});
|
||||
let isOpenMusic = ref(false);
|
||||
const { formatTime, startTimer, stopTimer } = useCountdown(ifActive ? route.query.answerTime : -1);
|
||||
watch(formatTime, (newVal) => {
|
||||
if (ifActive && convertTimeToSeconds(newVal) === 0) {
|
||||
show.value = true;
|
||||
stopTimer();
|
||||
}
|
||||
});
|
||||
onMounted(() => {
|
||||
useInterceptBack(1, dropOut);
|
||||
document.title = ifActive ? '活动答题' : '自主答题';
|
||||
ifActive ? getPlanList() : getList();
|
||||
});
|
||||
function dropOut() {
|
||||
backOver.value = true;
|
||||
}
|
||||
async function getList() {
|
||||
loadingSpinner();
|
||||
try {
|
||||
let queCode = store.getters.getQuestionList;
|
||||
const { code, result } = await getQuesApi(queCode);
|
||||
if (code === 200) {
|
||||
startTimer();
|
||||
quesParams.value = result;
|
||||
}
|
||||
} catch (e) {
|
||||
} finally {
|
||||
loadingClose();
|
||||
}
|
||||
}
|
||||
// 活动问卷
|
||||
async function getPlanList() {
|
||||
loadingSpinner();
|
||||
try {
|
||||
const { code, result } = await getPlanQuesApi({
|
||||
planId: route.query.planId,
|
||||
});
|
||||
if (code === 200) {
|
||||
startTimer();
|
||||
quesParams.value = result;
|
||||
audioUrl.value = getFileUrl(result.planMusicUrl);
|
||||
}
|
||||
} catch (e) {
|
||||
} finally {
|
||||
loadingClose();
|
||||
}
|
||||
}
|
||||
function handelChange(data: any) {
|
||||
quesParams.value.paperQuestionList = data;
|
||||
}
|
||||
function subTip() {
|
||||
let userAnswerList: { answer: any; questionId: any }[] = [];
|
||||
let data = quesParams.value.paperQuestionList;
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
let item = data[i];
|
||||
if (!item.userAnswer) {
|
||||
showToast('请完成所有题目');
|
||||
let errorItem = document.getElementById('psychlolgy_plan');
|
||||
errorItem.scrollTop = document.getElementById('psychology_' + item.questionId).offsetTop - 35;
|
||||
break;
|
||||
} else {
|
||||
userAnswerList.push({
|
||||
answer: item.userAnswer,
|
||||
questionId: item.questionId,
|
||||
});
|
||||
}
|
||||
}
|
||||
return userAnswerList;
|
||||
}
|
||||
function handleSubmit() {
|
||||
let userAnswerList: any[] = [];
|
||||
let data = quesParams.value.paperQuestionList;
|
||||
if (show.value) {
|
||||
// 时间到,不需要拦截
|
||||
data.map((item: any) => {
|
||||
userAnswerList.push({
|
||||
answer: item.userAnswer,
|
||||
questionId: item.questionId,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// 在规定时间内,拦截填写完
|
||||
userAnswerList = subTip();
|
||||
}
|
||||
if (userAnswerList.length !== data.length) return false;
|
||||
loadingSpinner();
|
||||
try {
|
||||
const params = {
|
||||
paperId: quesParams.value.paperId,
|
||||
answerTimeSum: hanleAnswerTime(),
|
||||
userSubmitAnswerDetailsDTOS: userAnswerList,
|
||||
};
|
||||
console.log(params);
|
||||
timerOver.value = false;
|
||||
stopTimer();
|
||||
ifActive ? planSubmit(params) : slefSubmit(params);
|
||||
} catch (e) {
|
||||
} finally {
|
||||
loadingClose();
|
||||
}
|
||||
}
|
||||
function hanleAnswerTime() {
|
||||
if (ifActive) {
|
||||
const totalTimer = minuteConverSeconds(route.query.answerTime); // 总时间(秒)
|
||||
const consumeTimer = convertTimeToSeconds(formatTime.value); // 未消耗时间(秒)
|
||||
const diffTimer = totalTimer - consumeTimer; // 已消耗时间(秒)
|
||||
const finalTimer = diffTimer == '0' ? totalTimer : diffTimer;
|
||||
return finalTimer;
|
||||
} else {
|
||||
return convertTimeToSeconds(formatTime.value);
|
||||
}
|
||||
}
|
||||
function backAnswer() {
|
||||
backOver.value = false;
|
||||
try {
|
||||
destroyPage();
|
||||
} catch {
|
||||
router.go(-1);
|
||||
}
|
||||
}
|
||||
async function slefSubmit(params: any) {
|
||||
const res = await submitQuesApi(params);
|
||||
hanleResult(res);
|
||||
}
|
||||
async function planSubmit(params: any) {
|
||||
const res = await submitPlanQuesApi(params);
|
||||
hanleResult(res);
|
||||
}
|
||||
function hanleResult({ code, result }) {
|
||||
useInterceptBack(0);
|
||||
if (code === 200) {
|
||||
showSuccessToast('答题成功');
|
||||
router.replace({
|
||||
path: '/answer-Report',
|
||||
query: {
|
||||
id: result,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
showFailToast('答题失败!');
|
||||
}
|
||||
}
|
||||
// 活动时播放背景音乐
|
||||
function handleMusic(type: string) {
|
||||
if(audioUrl.value==='') return showToast('暂无音乐资源!')
|
||||
if (audioPlayer.value) {
|
||||
if (type == 'play') {
|
||||
isOpenMusic.value = true;
|
||||
audioPlayer.value.play();
|
||||
} else {
|
||||
isOpenMusic.value = false;
|
||||
audioPlayer.value.pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
onUnmounted(() => {
|
||||
// 清除用户选择题型
|
||||
store.commit('setQuestionList', []);
|
||||
stopTimer();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import url('/@/views/23psychology/components/psychology.less');
|
||||
.answer-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: @con-bg;
|
||||
.overlay-block {
|
||||
width: 80%;
|
||||
height: 170px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-items: center;
|
||||
.block-top {
|
||||
width: 100%;
|
||||
height: 70%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 15px;
|
||||
color: #333333;
|
||||
padding: 0 30px;
|
||||
text-align: center;
|
||||
}
|
||||
.block-bottom {
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
border-radius: 0 0 8px 8px;
|
||||
color: #ffffff;
|
||||
background-color: @primary-color;
|
||||
}
|
||||
.out-btn {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
.backBtn {
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
}
|
||||
.canel-out {
|
||||
background-color: #e6e6ea;
|
||||
color: #333333;
|
||||
border-bottom-left-radius: 8px;
|
||||
}
|
||||
.sure-out {
|
||||
color: #ffffff;
|
||||
background-color: @primary-color;
|
||||
border-bottom-right-radius: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.plan-music {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 10px 20px;
|
||||
background-color: #eefffe;
|
||||
.time {
|
||||
color: #21bebd;
|
||||
}
|
||||
.bg-music {
|
||||
color: #21bebd;
|
||||
font-size: 15px;
|
||||
img {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.q-content {
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
padding: 20px;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
.no-data {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-top: 50%;
|
||||
}
|
||||
.bottom-btn {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
height: 50px;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.btn {
|
||||
.bottom-button();
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,212 @@
|
||||
<template>
|
||||
<div class="question-box">
|
||||
<div class="question-item" v-for="(item, index) in list" :key="index" :id="'psychology_' + item.questionId">
|
||||
<div class="question-title" v-if="item.disabledCategory">
|
||||
<div class="one-title" v-if="showTitle(item.categoryList).one.text">
|
||||
<img :src="showTitle(item.categoryList).one.icon" />
|
||||
<span>{{ showTitle(item.categoryList).one.text }}</span>
|
||||
</div>
|
||||
<div class="subtitle" v-if="showTitle(item.categoryList).two">{{ showTitle(item.categoryList).two }}</div>
|
||||
<div class="three-title" v-if="showTitle(item.categoryList).three">{{ showTitle(item.categoryList).three }}</div>
|
||||
</div>
|
||||
<div class="question-operate">
|
||||
<div class="question-top">
|
||||
<span class="tips">*</span>
|
||||
<span>{{ index + 1 }}、</span>
|
||||
<span>{{ item.questionDesc }}</span>
|
||||
<span>【{{ questionType(item.type) }}】</span>
|
||||
</div>
|
||||
<div class="options-content">
|
||||
<div
|
||||
v-for="(optionItem, optionIndex) in item.options"
|
||||
:class="['optionItem', optionClass(isEdit, item, optionItem, item.options)]"
|
||||
:key="optionIndex"
|
||||
@click="handleChange(optionItem, item.type, index)"
|
||||
>
|
||||
<span>{{ optionItem.optionNo }}.</span>
|
||||
<span>{{ optionItem.optionValue }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!isEdit && item.realAnswer!==''" class="answer-con">
|
||||
<div class="standard">
|
||||
<span class="label">答案:</span>
|
||||
<span :class="answerText(item, item.options, 'realAnswer') === '暂无' ? '' : 'correct-color'">{{
|
||||
answerText(item, item.options, 'realAnswer')
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="standard">
|
||||
<span class="label">您的选择:</span>
|
||||
<span :class="userAnswerClass(item, item.options)">{{ answerText(item, item.options, 'userAnswer') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps, defineEmits, ref } from 'vue';
|
||||
import {
|
||||
questionType,
|
||||
showTitle,
|
||||
answerText,
|
||||
userAnswerClass,
|
||||
optionClass,
|
||||
} from '/@/views/23psychology/answer/questionAnswer/questionAnswerHook';
|
||||
const emit = defineEmits(['change']);
|
||||
const props = defineProps({
|
||||
list: {
|
||||
type: Array,
|
||||
// eslint-disable-next-line vue/require-valid-default-prop
|
||||
default: [],
|
||||
},
|
||||
isEdit: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: 'title',
|
||||
},
|
||||
});
|
||||
let userList = ref([]);
|
||||
function handleChange(optionItem: never, type: string, index: number) {
|
||||
if (!props.isEdit) return false;
|
||||
const data = props.list as any[];
|
||||
// 单选,判断
|
||||
if (type === 'DG' || type === 'PD') {
|
||||
data[index].userAnswer = optionItem.optionId;
|
||||
}
|
||||
// 多选
|
||||
if (type === 'DX') {
|
||||
if (userList.value.includes(optionItem.optionId)) {
|
||||
let index = userList.value.indexOf(optionItem.optionId);
|
||||
userList.value.splice(index, 1);
|
||||
} else {
|
||||
userList.value.push(optionItem.optionId);
|
||||
}
|
||||
data[index].userAnswer = userList.value.join(',');
|
||||
}
|
||||
emit('change', data);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import url('/@/views/23psychology/components/psychology.less');
|
||||
.question-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f4f4f4;
|
||||
.question-item {
|
||||
width: 100%;
|
||||
.question-title {
|
||||
width: 100%;
|
||||
background-color: #ffffff;
|
||||
.one-title {
|
||||
background-color: #c8f5f5;
|
||||
padding: 16px 10px;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
img {
|
||||
width: 28px;
|
||||
}
|
||||
span {
|
||||
color: #333333;
|
||||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
.subtitle {
|
||||
padding: 5px 25px 5px 15px;
|
||||
display: inline-block;
|
||||
background: url('/@/assets/images/psychiology/answer/titleBg.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
color: #ffffff;
|
||||
position: relative;
|
||||
}
|
||||
.three-title {
|
||||
padding: 10px 20px 10px 35px;
|
||||
position: relative;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 18px;
|
||||
top: 14px;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
border-radius: 50%;
|
||||
background-color: @primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.question-operate {
|
||||
padding: 10px 20px;
|
||||
background-color: #ffffff;
|
||||
.question-top {
|
||||
position: relative;
|
||||
.tips {
|
||||
color: #ed2a26;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
left: -8px;
|
||||
}
|
||||
}
|
||||
.options-content {
|
||||
padding: 10px 0;
|
||||
span:nth-child(2) {
|
||||
padding-left: 4px;
|
||||
}
|
||||
.optionItem {
|
||||
padding: 10px 20px;
|
||||
margin: 10px 0;
|
||||
border-radius: 6px;
|
||||
background-color: #f4f4f4;
|
||||
color: #77849e;
|
||||
border: 1px solid #f4f4f4;
|
||||
}
|
||||
.select-item {
|
||||
background-color: #eefffe;
|
||||
color: @primary-color;
|
||||
border: 1px solid @primary-color;
|
||||
}
|
||||
.error-item {
|
||||
background-color: rgba(237, 42, 38, 0.2);
|
||||
color: #ed2a26;
|
||||
border: 1px solid #ed2a26;
|
||||
}
|
||||
.correct-item {
|
||||
background-color: rgba(82, 196, 26, 0.2);
|
||||
color: #52c41a;
|
||||
border: 1px solid #52c41a;
|
||||
}
|
||||
}
|
||||
.answer-con {
|
||||
display: flex;
|
||||
background-color: #eff5ff;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
.standard {
|
||||
.label {
|
||||
color: #333333;
|
||||
}
|
||||
.correct-color {
|
||||
color: #52c41a;
|
||||
}
|
||||
.error-color {
|
||||
color: #ed2a26;
|
||||
}
|
||||
}
|
||||
.standard:nth-child(2) {
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,379 @@
|
||||
<template>
|
||||
<div class="outer-d">
|
||||
<div class="title">
|
||||
<div>答题时长:{{ useConvertTime(quesParams?.answerTimeSum) || '-' }}</div>
|
||||
<div>答题时间:{{ quesParams?.endAnswerTime || '-' }}</div>
|
||||
</div>
|
||||
<div class="container" v-if="quesParams.paperQuestionList !== null && quesParams.paperQuestionList.length > 0">
|
||||
<div class="top-button" id="resultCon">
|
||||
<div class="ps-two">
|
||||
<div class="ps-two-title">
|
||||
<div class="name">心理知识</div>
|
||||
<div class="score">
|
||||
<span>总分:{{ quesParams.paperScore }}</span>
|
||||
<span>得分:{{ quesParams.totalScore }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabs-con">
|
||||
<div class="tabs-bg">
|
||||
<div
|
||||
v-for="(item, index) in tabList"
|
||||
:class="['tabs-item', index === active ? 'active' : '']"
|
||||
:key="index"
|
||||
@click="onClickTab(item.value)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ps-two-container" v-for="(item, index) in quesParams.paperQuestionList" :key="index">
|
||||
<template v-if="item.questionCategoryId.indexOf('A01') > -1 || item.questionCategoryId.indexOf('B01') > -1">
|
||||
<div class="question-title" v-if="item.disabledCategory">
|
||||
<div class="one-title-no" v-if="showTitle(item.categoryList).one.text">
|
||||
<img :src="showTitle(item.categoryList).one.icon" />
|
||||
<span>{{ showTitle(item.categoryList).one.text }}</span>
|
||||
</div>
|
||||
<div class="subtitle" v-if="showTitle(item.categoryList).two">{{ showTitle(item.categoryList).two }}</div>
|
||||
<div class="three-title" v-if="showTitle(item.categoryList).three">{{ showTitle(item.categoryList).three }}</div>
|
||||
</div>
|
||||
<div class="question-operate">
|
||||
<div class="question-top">
|
||||
<span class="tips">*</span>
|
||||
<span>{{ index + 1 }}、</span>
|
||||
<span>{{ item.questionDesc }}</span>
|
||||
<span>【{{ questionType(item.type) }}】</span>
|
||||
</div>
|
||||
<div class="options-content">
|
||||
<div
|
||||
v-for="(optionItem, optionIndex) in item.options"
|
||||
:class="['optionItem', optionClass(false, item, optionItem, item.options)]"
|
||||
:key="optionIndex"
|
||||
>
|
||||
<span>{{ optionItem.optionNo }}.</span>
|
||||
<span>{{ optionItem.optionValue }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="item.realAnswer !== ''" class="answer-con">
|
||||
<div class="standard">
|
||||
<span class="label">答案:</span>
|
||||
<span :class="answerText(item, item.options, 'realAnswer') === '暂无' ? '' : 'correct-color'">{{
|
||||
answerText(item, item.options, 'realAnswer')
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="standard">
|
||||
<span class="label">您的选择:</span>
|
||||
<span :class="userAnswerClass(item, item.options)">{{ answerText(item, item.options, 'userAnswer') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ps-three">
|
||||
<div class="ps-two-container" v-for="(item, index) in quesParams.paperQuestionList" :key="index">
|
||||
<template v-if="item.questionCategoryId.indexOf('C01') > -1">
|
||||
<div class="question-title" v-if="item.disabledCategory">
|
||||
<div class="one-title-no one-title-bg" v-if="showTitle(item.categoryList).one.text">
|
||||
<img :src="showTitle(item.categoryList).one.icon" />
|
||||
<span>{{ showTitle(item.categoryList).one.text }}</span>
|
||||
</div>
|
||||
<div class="subtitle" v-if="showTitle(item.categoryList).two">{{ showTitle(item.categoryList).two }}</div>
|
||||
<div class="three-title" v-if="showTitle(item.categoryList).three">{{ showTitle(item.categoryList).three }}</div>
|
||||
</div>
|
||||
<div class="question-operate">
|
||||
<div class="question-top">
|
||||
<span class="tips">*</span>
|
||||
<span>{{ index + 1 }}、</span>
|
||||
<span>{{ item.questionDesc }}</span>
|
||||
<span>【{{ questionType(item.type) }}】</span>
|
||||
</div>
|
||||
<div class="options-content">
|
||||
<div
|
||||
v-for="(optionItem, optionIndex) in item.options"
|
||||
:class="['optionItem', optionClass(false, item, optionItem, item.options)]"
|
||||
:key="optionIndex"
|
||||
>
|
||||
<span>{{ optionItem.optionNo }}.</span>
|
||||
<span>{{ optionItem.optionValue }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="no-data" v-else>
|
||||
<Empty :url="emptyIcon" :imageSize="[200, 160]" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { getAnswerDetailsApi } from '/@/views/23psychology/answer/questionAnswer/questionAnswer.api';
|
||||
import {
|
||||
questionType,
|
||||
showTitle,
|
||||
answerText,
|
||||
userAnswerClass,
|
||||
optionClass,
|
||||
} from '/@/views/23psychology/answer/questionAnswer/questionAnswerHook';
|
||||
import { useConvertTime } from '/@/views/23-physical-questions/questionHooks';
|
||||
import Empty from '/@/components/Empty.vue';
|
||||
import emptyIcon from '/@/assets/images/interveneEmpty.png';
|
||||
const route = useRoute();
|
||||
let active = ref(0);
|
||||
let tabList = ref([
|
||||
{
|
||||
label: '全部',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: '我的错题',
|
||||
value: 1,
|
||||
},
|
||||
]);
|
||||
let quesParams = ref({
|
||||
paperQuestionList: [],
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
getDetails();
|
||||
});
|
||||
async function getDetails() {
|
||||
const { code, result } = await getAnswerDetailsApi({
|
||||
id: route.query.idRecord,
|
||||
type: active.value,
|
||||
});
|
||||
if (code === 200) {
|
||||
quesParams.value = result;
|
||||
}
|
||||
}
|
||||
function onClickTab(val: number) {
|
||||
active.value = val;
|
||||
if (quesParams.value.paperQuestionList !== null && quesParams.value.paperQuestionList.length > 0) {
|
||||
document.getElementById('resultCon').scrollTop = 0;
|
||||
}
|
||||
getDetails();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import url('/@/views/23psychology/components/psychology.less');
|
||||
.outer-d {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: @con-bg;
|
||||
position: relative;
|
||||
overflow-y: hidden;
|
||||
padding: 20px;
|
||||
.container {
|
||||
width: 100%;
|
||||
height: calc(100% - 80px);
|
||||
margin-top: 20px;
|
||||
overflow-y: auto;
|
||||
.ps-two {
|
||||
background-color: #ffffff;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.ps-three {
|
||||
background-color: #ffffff;
|
||||
border-radius: 10px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.ps-two-title {
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background-color: #c8f5f5;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
.name {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
}
|
||||
.score {
|
||||
color: #21bebd;
|
||||
span:nth-child(1) {
|
||||
padding-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.question-title {
|
||||
width: 100%;
|
||||
background-color: #ffffff;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
.one-title-no {
|
||||
padding: 16px 10px;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
img {
|
||||
width: 28px;
|
||||
}
|
||||
span {
|
||||
color: #333333;
|
||||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
.one-title-bg {
|
||||
background-color: #c8f5f5;
|
||||
}
|
||||
.subtitle {
|
||||
padding: 5px 25px 5px 15px;
|
||||
display: inline-block;
|
||||
background: url('/@/assets/images/psychiology/answer/titleBg.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
color: #ffffff;
|
||||
position: relative;
|
||||
}
|
||||
.three-title {
|
||||
padding: 10px 20px 10px 35px;
|
||||
position: relative;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 18px;
|
||||
top: 14px;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
border-radius: 50%;
|
||||
background-color: @primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.question-operate {
|
||||
padding: 10px 20px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 10px;
|
||||
.question-top {
|
||||
position: relative;
|
||||
.tips {
|
||||
color: #ed2a26;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
left: -8px;
|
||||
}
|
||||
}
|
||||
.options-content {
|
||||
padding: 10px 0;
|
||||
span:nth-child(2) {
|
||||
padding-left: 4px;
|
||||
}
|
||||
.optionItem {
|
||||
padding: 10px 20px;
|
||||
margin: 10px 0;
|
||||
border-radius: 6px;
|
||||
background-color: #f4f4f4;
|
||||
color: #77849e;
|
||||
border: 1px solid #f4f4f4;
|
||||
}
|
||||
.select-item {
|
||||
background-color: #eefffe;
|
||||
color: @primary-color;
|
||||
border: 1px solid @primary-color;
|
||||
}
|
||||
.error-item {
|
||||
background-color: rgba(237, 42, 38, 0.2);
|
||||
color: #ed2a26;
|
||||
border: 1px solid #ed2a26;
|
||||
}
|
||||
.correct-item {
|
||||
background-color: rgba(82, 196, 26, 0.2);
|
||||
color: #52c41a;
|
||||
border: 1px solid #52c41a;
|
||||
}
|
||||
}
|
||||
.answer-con {
|
||||
display: flex;
|
||||
background-color: #eff5ff;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
.standard {
|
||||
.label {
|
||||
color: #333333;
|
||||
}
|
||||
.correct-color {
|
||||
color: #52c41a;
|
||||
}
|
||||
.error-color {
|
||||
color: #ed2a26;
|
||||
}
|
||||
}
|
||||
.standard:nth-child(2) {
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
background: linear-gradient(180deg, #21bebd 0%, #87d8d7 100%);
|
||||
padding: 10px 13px;
|
||||
border-radius: 10px;
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-items: center;
|
||||
position: relative;
|
||||
div {
|
||||
padding: 2px 0;
|
||||
}
|
||||
&:after {
|
||||
content: '';
|
||||
width: 76px;
|
||||
height: 52px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: url('/@/assets/images/psychiology/answer/timer.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
.tabs-con {
|
||||
width: 100%;
|
||||
height: 64px;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.tabs-bg {
|
||||
width: 90%;
|
||||
height: 45px;
|
||||
padding: 20px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #e8ebf2;
|
||||
border-radius: 5px;
|
||||
.tabs-item {
|
||||
width: 48%;
|
||||
margin: 0 auto;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
color: #77849e;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.active {
|
||||
background-color: #ffffff;
|
||||
color: #252535;
|
||||
}
|
||||
}
|
||||
}
|
||||
.no-data {
|
||||
height: 100%;
|
||||
padding-top: 50%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,17 @@
|
||||
import { get, post } from '/@/views/mobile/api/api';
|
||||
const prefix: string = import.meta.env.VITE_GLOB_APP_PREFIX || '';
|
||||
|
||||
// 获取自主问卷
|
||||
export const getQuesApi = (params: any) => post(`${prefix}/api/psychology/answer/paper`, params, 'C01', { isArray: true });
|
||||
|
||||
//自主问卷提交
|
||||
export const submitQuesApi = (params: any) => post(`${prefix}/api/psychology/answer/submit`, params);
|
||||
|
||||
// 获取活动问卷
|
||||
export const getPlanQuesApi = (params: any) => get(`${prefix}/api/psychology/answer/plan/answer`, params);
|
||||
|
||||
// 自主问卷提交
|
||||
export const submitPlanQuesApi = (params: any) => post(`${prefix}/api/psychology/answer/plan/submit`, params);
|
||||
|
||||
// 答题详情、
|
||||
export const getAnswerDetailsApi = (params: any) => get(`${prefix}/api/psychology/answer/details`, params);
|
||||
@@ -0,0 +1,133 @@
|
||||
import chooseTopicItem from '/@/assets/images/psychiology/chooseTopicItem.png';
|
||||
import comprehensive from '/@/assets/images/psychiology/comprehensive.png';
|
||||
import chooseTopicItemLast from '/@/assets/images/psychiology/chooseTopicItemLast.png';
|
||||
import { computed, onBeforeUnmount, ref, watch } from 'vue';
|
||||
import { minuteConverSeconds } from '/@/views/23-physical-questions/questionHooks';
|
||||
export function questionType(type: string) {
|
||||
const typeParams = {
|
||||
DG: '单选题',
|
||||
DX: '多选题',
|
||||
PD: '单选题',
|
||||
};
|
||||
// @ts-ignore
|
||||
return typeParams[type];
|
||||
}
|
||||
function iconback(text: string) {
|
||||
let icon = chooseTopicItem;
|
||||
if (text.indexOf('专题') > -1) {
|
||||
icon = chooseTopicItem;
|
||||
} else if (text.indexOf('综合') > -1) {
|
||||
icon = comprehensive;
|
||||
} else if (text.indexOf('心理') > -1) {
|
||||
icon = chooseTopicItemLast;
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
export function showTitle(list: any) {
|
||||
let oneText = '',
|
||||
twoText = '',
|
||||
threeTwo = '';
|
||||
if (list.length === 3) {
|
||||
oneText = list[0];
|
||||
twoText = list[1];
|
||||
threeTwo = list[2];
|
||||
}
|
||||
if (list.length === 2) {
|
||||
oneText = list[0];
|
||||
twoText = list[1];
|
||||
}
|
||||
if (list.length === 1) {
|
||||
twoText = list[0];
|
||||
}
|
||||
return {
|
||||
one: {
|
||||
icon: iconback(oneText),
|
||||
text: oneText,
|
||||
},
|
||||
two: twoText,
|
||||
three: threeTwo,
|
||||
};
|
||||
}
|
||||
export function useCountdown(duration: number) {
|
||||
// 分钟转为秒
|
||||
const timer = ref(duration === -1 ? 0 : minuteConverSeconds(duration));
|
||||
const isTimerRunning = ref(false);
|
||||
// 格式化时间
|
||||
const formatTime = computed(() => {
|
||||
const minutes = Math.floor(timer.value / 60);
|
||||
const seconds = timer.value % 60;
|
||||
return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
||||
});
|
||||
// 计时器逻辑
|
||||
let interval: any = null;
|
||||
const startTimer = () => {
|
||||
isTimerRunning.value = true;
|
||||
interval = setInterval(() => {
|
||||
duration === -1 ? timer.value++ : timer.value--;
|
||||
}, 1000);
|
||||
};
|
||||
const stopTimer = () => {
|
||||
isTimerRunning.value = false;
|
||||
if (duration === -1) timer.value = 0;
|
||||
clearInterval(interval);
|
||||
};
|
||||
|
||||
// 监听计时器状态变化
|
||||
watch(isTimerRunning, (newValue) => {
|
||||
if (!newValue) {
|
||||
clearInterval(interval);
|
||||
}
|
||||
});
|
||||
|
||||
// 在组件销毁前清除计时器
|
||||
onBeforeUnmount(() => {
|
||||
clearInterval(interval);
|
||||
});
|
||||
return {
|
||||
formatTime,
|
||||
startTimer,
|
||||
stopTimer,
|
||||
};
|
||||
}
|
||||
// 标准答案内容
|
||||
export function answerText(item: any, optionList: Array, fields: string) {
|
||||
if (item[fields] !== '') {
|
||||
const userAnswer = item[fields].split(',');
|
||||
const same = optionList.filter((item: any) => userAnswer.includes(item.optionId));
|
||||
const answer = same.map((item: any) => item.optionNo).join(',');
|
||||
return answer;
|
||||
}
|
||||
return '暂无';
|
||||
}
|
||||
// 用户选择样式
|
||||
export function userAnswerClass(item: any) {
|
||||
if (item.realAnswer === '' || item.realAnswer === null) return false;
|
||||
return item.realAnswer === item.userAnswer ? 'correct-color' : 'error-color';
|
||||
}
|
||||
//
|
||||
export function optionClass(isEdit: Boolean, item: any, optionItem: any, optionList: any) {
|
||||
let optionClass = '';
|
||||
if (isEdit) {
|
||||
optionClass = item.userAnswer !== null && item.userAnswer.split(',').includes(optionItem.optionId) ? 'select-item' : '';
|
||||
} else {
|
||||
if (item.userAnswer === null || item.userAnswer === '') {
|
||||
optionClass = '';
|
||||
}else{
|
||||
const vis = optionList.some((e: any) => e.isTrue);
|
||||
if (vis) {
|
||||
// 有正确答题
|
||||
const userAnswer = item.userAnswer.split(',');
|
||||
if (userAnswer.includes(optionItem.optionId)) {
|
||||
optionItem.isTrue ? (optionClass = 'correct-item') : (optionClass = 'error-item');
|
||||
}
|
||||
} else {
|
||||
// 无正确答案,使用默认样式显示用户选项
|
||||
if (optionItem.optionId === item.userAnswer) {
|
||||
optionClass = 'select-item';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return optionClass;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { get, post } from '/@/views/mobile/api/api';
|
||||
|
||||
const prefix: string = import.meta.env.VITE_GLOB_APP_PREFIX || '';
|
||||
//通过id 获取列表
|
||||
export const getPlanRecord = (params: any) => get(`${prefix}/api/psychology/answer/plan/record`, params);
|
||||
@@ -0,0 +1,327 @@
|
||||
<template>
|
||||
<div class="box">
|
||||
<div class="top-img">
|
||||
<img :src="RankingListPng" alt="" />
|
||||
</div>
|
||||
<div class="ranking-box">
|
||||
<div class="ranking-top">
|
||||
<div class="left">
|
||||
<span class="one">
|
||||
排行榜
|
||||
<span class="under"></span>
|
||||
</span>
|
||||
<span>(共{{ list?.joinUserList.length }}人参加)</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<img :src="RankingPng" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="ranking-center">
|
||||
<span style="width: 12%" v-if="list?.showRanking">排名</span>
|
||||
<span style="flex: 1; text-align: left">用户</span>
|
||||
<span style="text-align: right">分数</span>
|
||||
</div>
|
||||
<div class="ranking-bottom">
|
||||
<div class="me ranking" v-if="meList?.selfRecord">
|
||||
<!-- -->
|
||||
<div class="fraction" v-if="meList?.showRanking">{{ meList?.selfRecord.ranking }}</div>
|
||||
<div class="picture">
|
||||
<img
|
||||
:src="getFileHttpUrl(meList?.selfRecord.avatar) || 'https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'"
|
||||
onerror="this.src='https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<div class="personal">
|
||||
<div class="top">
|
||||
<div class="top-left">
|
||||
<span>{{ meList?.selfRecord.userName }}</span>
|
||||
<span class="my">(我)</span>
|
||||
<span class="line"></span>
|
||||
<span class="dept">{{ meList?.selfRecord.deptName }}</span>
|
||||
</div>
|
||||
<div class="top-right">
|
||||
<span>{{ meList?.selfRecord.userScore }}</span>
|
||||
<span>分</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<span>{{ meList?.selfRecord.endAnswerTime }}</span>
|
||||
<span>耗时:{{ getTimeStr(meList?.selfRecord.answerTimeSum, 'mm') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||
<div style="height: 100%; overflow: auto">
|
||||
<van-list
|
||||
v-model:loading="loading"
|
||||
:finished="finished"
|
||||
:finished-text="list?.joinUserList && list?.joinUserList.length > 0 ? '没有更多了' : ''"
|
||||
@load="onLoad"
|
||||
v-model:error="error"
|
||||
error-text="请求失败,点击重新加载"
|
||||
>
|
||||
<template v-if="list?.joinUserList && list?.joinUserList.length > 0">
|
||||
<div v-for="(item, index) in list?.joinUserList" :key="index" class="ranking">
|
||||
<div class="fraction" v-if="list?.showRanking">
|
||||
<span v-if="index == 0" class="medal gold">
|
||||
<img :src="GoldPng" alt="" />
|
||||
</span>
|
||||
<span v-else-if="index == 1" class="medal silver">
|
||||
<img :src="SilverPng" alt="" />
|
||||
</span>
|
||||
<span v-else-if="index == 2" class="medal bronze">
|
||||
<img :src="BronzePng" alt="" />
|
||||
</span>
|
||||
<span v-else>{{ index + 1 }}</span>
|
||||
</div>
|
||||
<div class="picture">
|
||||
<img
|
||||
:src="getFileHttpUrl(item.avatar) || 'https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'"
|
||||
onerror="this.src='https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<div class="personal">
|
||||
<div class="top">
|
||||
<div class="top-left">
|
||||
<span>{{ item.userName }}</span>
|
||||
<span class="line"></span>
|
||||
<span class="dept">{{ item.deptName }}</span>
|
||||
</div>
|
||||
<div class="top-right">
|
||||
<span>{{ item.userScore }}</span>
|
||||
<span>分</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<span>{{ item.endAnswerTime }}</span>
|
||||
<span>耗时:{{ getTimeStr(item.answerTimeSum, 'mm') }}</span>
|
||||
</div>
|
||||
</div></div
|
||||
>
|
||||
</template>
|
||||
</van-list>
|
||||
</div>
|
||||
</van-pull-refresh>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { getFileHttpUrl, getTimeStr } from '/@/utils/compUtils.ts';
|
||||
import RankingListPng from '/@/assets/images/psychiology/answer/ranking_list.png';
|
||||
import RankingPng from '/@/assets/images/psychiology/answer/ranking.png';
|
||||
import GoldPng from '/@/assets/images/psychiology/answer/gold.png';
|
||||
import SilverPng from '/@/assets/images/psychiology/answer/silver.png';
|
||||
import BronzePng from '/@/assets/images/psychiology/answer/bronze.png';
|
||||
import { getPlanRecord } from '/@/views/23psychology/answer/rankingList/rankingList.api';
|
||||
import { showFailToast } from 'vant';
|
||||
import { useRoute } from 'vue-router';
|
||||
const route = useRoute();
|
||||
const list = ref<any[]>([]); // 列表
|
||||
const refreshing = ref(false); // 刷新状态
|
||||
const loading = ref(false); // loading 状态
|
||||
const finished = ref(false); // 是否完成
|
||||
const error = ref(false); // 是否报错
|
||||
const meList = ref<any>();
|
||||
const pageInfo = ref({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
});
|
||||
async function getMeList() {
|
||||
const data = await getPlanRecord({ planId: route.query.planId });
|
||||
console.log(data.result.selfRecord, 123);
|
||||
meList.value = data.result;
|
||||
}
|
||||
getMeList();
|
||||
function onLoad() {
|
||||
if (refreshing.value) {
|
||||
list.value = [];
|
||||
refreshing.value = false;
|
||||
finished.value = false;
|
||||
error.value = false;
|
||||
loading.value = true;
|
||||
pageInfo.value.pageNo = 1;
|
||||
}
|
||||
loading.value = true;
|
||||
getPlanRecord({ planId: route.query.planId, ...pageInfo.value })
|
||||
.then((res) => {
|
||||
const { success, result, message } = res;
|
||||
if (success) {
|
||||
list.value = result;
|
||||
if (result.joinUserList.length === 0 || result.joinUserList.length < pageInfo.value.pageSize) {
|
||||
finished.value = true;
|
||||
} else {
|
||||
pageInfo.value.pageNo += 1;
|
||||
}
|
||||
} else {
|
||||
error.value = true;
|
||||
showFailToast(message);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
error.value = true;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
function onRefresh() {
|
||||
refreshing.value = true;
|
||||
onLoad();
|
||||
}
|
||||
onLoad();
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.box {
|
||||
height: 100vh;
|
||||
position: relative;
|
||||
background: #eff2f5;
|
||||
.top-img {
|
||||
height: 150px;
|
||||
background: #21bebd;
|
||||
position: relative;
|
||||
img {
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
bottom: 40px;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
.ranking-box {
|
||||
background: #fff;
|
||||
height: calc(100vh - 140px);
|
||||
position: absolute;
|
||||
width: calc(100% - 32px);
|
||||
top: 120px;
|
||||
margin: 0 16px;
|
||||
border-radius: 8px;
|
||||
padding: 16px 0;
|
||||
.ranking-top {
|
||||
position: relative;
|
||||
padding: 0 16px;
|
||||
.left {
|
||||
.one {
|
||||
display: inline-block;
|
||||
font-size: 25px;
|
||||
font-style: oblique;
|
||||
color: #252535;
|
||||
font-weight: bold;
|
||||
transform: translateX(0) skewX(-10deg);
|
||||
transform-origin: 0 0;
|
||||
position: relative;
|
||||
.under {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 15px;
|
||||
bottom: 5px;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
background: linear-gradient(180deg, transparent, #21bebd);
|
||||
}
|
||||
}
|
||||
}
|
||||
.right {
|
||||
position: absolute;
|
||||
top: -80px;
|
||||
right: 0;
|
||||
height: 120px;
|
||||
width: 150px;
|
||||
img {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.ranking-center {
|
||||
display: flex;
|
||||
padding: 0 16px;
|
||||
span {
|
||||
width: 15%;
|
||||
text-align: center;
|
||||
color: #77849e;
|
||||
}
|
||||
}
|
||||
.ranking-bottom {
|
||||
height: calc(100% - 60px);
|
||||
.ranking {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #eaecf1;
|
||||
.fraction {
|
||||
width: 12%;
|
||||
text-align: center;
|
||||
.medal {
|
||||
width: 72px;
|
||||
height: 42px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: -16px;
|
||||
img {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
.gold {
|
||||
background: linear-gradient(90deg, #fffcf7 0%, #ffedcc 100%);
|
||||
}
|
||||
.silver {
|
||||
background: linear-gradient(90deg, #fdfdfd 0%, #eaeaea 100%);
|
||||
}
|
||||
.bronze {
|
||||
background: linear-gradient(90deg, #fdfdfd 0%, #ffe0c9 100%);
|
||||
}
|
||||
}
|
||||
.picture {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 50%;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
.personal {
|
||||
flex: 1;
|
||||
margin-left: 10px;
|
||||
.top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.top-left {
|
||||
.line {
|
||||
display: inline-block;
|
||||
width: 1px;
|
||||
height: 10px;
|
||||
margin: 0 8px;
|
||||
background: #e6e6ea;
|
||||
}
|
||||
.dept {
|
||||
color: #77849e;
|
||||
}
|
||||
.my {
|
||||
padding-left: 5px;
|
||||
color: #21bebd;
|
||||
}
|
||||
}
|
||||
}
|
||||
.bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: #b6b6b6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<div class="outer-d">
|
||||
<div class="top-button">
|
||||
<van-tabs v-model:active="active" type="card" sticky>
|
||||
<van-tab title="全部">
|
||||
<task-list status="0" />
|
||||
</van-tab>
|
||||
<van-tab title="已参加">
|
||||
<task-list status="1" />
|
||||
</van-tab>
|
||||
<van-back-top />
|
||||
</van-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import TaskList from '/@/views/23psychology/answer/task/taskList.vue';
|
||||
|
||||
const active = ref();
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.outer-d {
|
||||
background-color: #f5f7fb;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
div {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:deep(.van-tabs__wrap) {
|
||||
background-color: #fff;
|
||||
padding: 10px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
:deep(.van-tab--card) {
|
||||
border: none;
|
||||
}
|
||||
|
||||
:deep(.van-tabs__nav--card) {
|
||||
height: auto;
|
||||
border-width: 2px;
|
||||
border-color: #e8ebf2ff !important;
|
||||
}
|
||||
|
||||
:deep(.van-tab--active) {
|
||||
color: #252535 !important;
|
||||
background-color: #ffffff !important;
|
||||
}
|
||||
|
||||
:deep(.van-tab--card) {
|
||||
color: #77849eff;
|
||||
background-color: #f3f5f8;
|
||||
padding: 10px 0;
|
||||
}
|
||||
:deep(.van-tabs__content) {
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
.top-button {
|
||||
height: 100%;
|
||||
:deep(.van-tabs) {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
:deep(.van-tabs__content) {
|
||||
height: calc(100% - 64px) !important;
|
||||
}
|
||||
:deep(.van-tab__panel) {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,171 @@
|
||||
<template>
|
||||
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||
<div style="height: 100%; overflow: auto">
|
||||
<van-list
|
||||
v-model:loading="loading"
|
||||
:finished="finished"
|
||||
:finished-text="list.length > 0 ? '没有更多了' : ''"
|
||||
@load="onLoad"
|
||||
v-model:error="error"
|
||||
error-text="请求失败,点击重新加载"
|
||||
>
|
||||
<template v-if="list.length > 0">
|
||||
<div v-for="it in list" :key="`collapse${it}`">
|
||||
<div class="top" v-if="it" @click.native="toDetail(it)">
|
||||
<div class="time">
|
||||
<div>
|
||||
<van-icon name="clock-o" size="16" color="#21BEBD" />
|
||||
<span> {{ moment(it?.startTime).format('YYYY.MM.DD') }} ~ {{ moment(it?.endTime).format('MM.DD') }}</span>
|
||||
</div>
|
||||
<div :style="{ color: it?.status == 0 ? '#F36510' : '#52C41A' }">
|
||||
{{ it?.userState == 1 ? '已参加' : '' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="title">
|
||||
<img :src="it?.state == '1' ? isProgressPng : isOverPng" alt="" />
|
||||
<span>{{ it?.planName }}</span>
|
||||
</div>
|
||||
<div :style="{ marginBottom: it?.questionCategory ? '10px' : '0' }">
|
||||
<span
|
||||
style="color: #21bebd; margin-right: 5px"
|
||||
v-for="item in it?.questionCategory ? it?.questionCategory.split(',') : []"
|
||||
>
|
||||
#{{ item }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="info">
|
||||
已参加{{ it?.actualJoinNumber || 0 }}人
|
||||
<span style="color: #b6b6b6; margin-left: 30px">
|
||||
共{{ it?.questionSum }}道题
|
||||
<span style="margin-left: 10px"> 答题时长为{{ it?.maxLimitTime }}分钟 </span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="no-data" v-if="list.length === 0 && finished">
|
||||
<Empty :url="emptyIcon" :imageSize="[200, 160]" />
|
||||
</div>
|
||||
</van-list>
|
||||
</div>
|
||||
</van-pull-refresh>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { getPlanListApi } from '/@/views/23psychology/psychic/psychologyApi';
|
||||
import { showFailToast } from 'vant';
|
||||
import { useRouter } from 'vue-router';
|
||||
import isProgressPng from '/@/assets/images/psychiology/isProgress.png';
|
||||
import isOverPng from '/@/assets/images/psychiology/isOver.png';
|
||||
import moment from 'moment';
|
||||
import Empty from '/@/components/Empty.vue';
|
||||
import emptyIcon from '/@/assets/images/interveneEmpty.png';
|
||||
|
||||
const props = defineProps({
|
||||
status: {
|
||||
type: String,
|
||||
default: () => '0',
|
||||
},
|
||||
});
|
||||
|
||||
const list = ref<any[]>([]); // 列表
|
||||
const refreshing = ref(false); // 刷新状态
|
||||
const loading = ref(false); // loading 状态
|
||||
const finished = ref(false); // 是否完成
|
||||
const error = ref(false); // 是否报错
|
||||
const pageInfo = ref({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
function toDetail(it: any) {
|
||||
router.push({
|
||||
path: '/taskDetails',
|
||||
query: { id: it?.id },
|
||||
});
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
if (refreshing.value) {
|
||||
list.value = [];
|
||||
refreshing.value = false;
|
||||
finished.value = false;
|
||||
error.value = false;
|
||||
loading.value = true;
|
||||
pageInfo.value.pageNo = 1;
|
||||
}
|
||||
loading.value = true;
|
||||
getPlanListApi({ ...pageInfo.value, type: props.status })
|
||||
.then((res) => {
|
||||
const { success, result, message: msg } = res;
|
||||
if (success) {
|
||||
list.value = result;
|
||||
if (result.length === 0 || result.length < pageInfo.value.pageSize) {
|
||||
finished.value = true;
|
||||
} else {
|
||||
pageInfo.value.pageNo += 1;
|
||||
}
|
||||
} else {
|
||||
error.value = true;
|
||||
showFailToast(msg);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
error.value = true;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
function onRefresh() {
|
||||
refreshing.value = true;
|
||||
onLoad();
|
||||
}
|
||||
onLoad();
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.no-data {
|
||||
width: 100%;
|
||||
padding-top: 50%;
|
||||
}
|
||||
.top {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
margin-top: 20px;
|
||||
.time {
|
||||
font-size: 15px;
|
||||
border-bottom: 1px solid #eaecf1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 15px;
|
||||
span {
|
||||
margin-left: 8px;
|
||||
color: #77849e;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
padding: 15px;
|
||||
.title {
|
||||
font-size: 17px;
|
||||
color: #252535;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
img {
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
margin-right: 7px;
|
||||
}
|
||||
}
|
||||
.info {
|
||||
font-size: 14px;
|
||||
color: #77849e;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,244 @@
|
||||
<template>
|
||||
<div class="ranking-list">
|
||||
<div class="title">
|
||||
<div class="left">
|
||||
<div class="name">心理知识排名</div>
|
||||
<div class="number">共{{ planRecordList?.joinNumber }}人参加</div>
|
||||
</div>
|
||||
<div class="right">总分:{{ planRecordList?.totalScore }}</div>
|
||||
</div>
|
||||
<div class="title-bottom">
|
||||
<span style="width: 12%" v-if="planRecordList?.showRanking">排名</span>
|
||||
<span style="flex: 1; text-align: left">用户</span>
|
||||
<span style="text-align: right">分数</span>
|
||||
</div>
|
||||
<div class="me ranking" v-if="planRecordList?.selfRecord">
|
||||
<!-- -->
|
||||
<div class="fraction" v-if="planRecordList?.showRanking">{{ planRecordList?.selfRecord.ranking }}</div>
|
||||
<div class="picture">
|
||||
<img
|
||||
:src="getFileHttpUrl(planRecordList?.selfRecord.avatar) || 'https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'"
|
||||
onerror="this.src='https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<div class="personal">
|
||||
<div class="top">
|
||||
<div class="top-left">
|
||||
<span>{{ planRecordList?.selfRecord.userName }}</span>
|
||||
<span class="my">(我)</span>
|
||||
<span class="line"></span>
|
||||
<span class="dept">{{ planRecordList?.selfRecord.deptName }}</span>
|
||||
</div>
|
||||
<div class="top-right">
|
||||
<span>{{ planRecordList?.selfRecord.userScore }}</span>
|
||||
<span>分</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<span>{{ planRecordList?.selfRecord.endAnswerTime }}</span>
|
||||
<span>耗时:{{ getTimeStr(planRecordList?.selfRecord.answerTimeSum, 'mm') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ranking" v-for="(item, index) in planRecordList?.joinUserList" :key="index">
|
||||
<div class="fraction" v-if="planRecordList?.showRanking">
|
||||
<span v-if="index == 0" class="medal gold">
|
||||
<img :src="GoldPng" alt="" />
|
||||
</span>
|
||||
<span v-else-if="index == 1" class="medal silver">
|
||||
<img :src="SilverPng" alt="" />
|
||||
</span>
|
||||
<span v-else-if="index == 2" class="medal bronze">
|
||||
<img :src="BronzePng" alt="" />
|
||||
</span>
|
||||
<span v-else>{{ index + 1 }}</span>
|
||||
</div>
|
||||
<div class="picture">
|
||||
<img
|
||||
:src="getFileHttpUrl(item.avatar) || 'https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'"
|
||||
onerror="this.src='https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<div class="personal">
|
||||
<div class="top">
|
||||
<div class="top-left">
|
||||
<span>{{ item.userName }}</span>
|
||||
<span class="line"></span>
|
||||
<span class="dept">{{ item.deptName }}</span>
|
||||
</div>
|
||||
<div class="top-right">
|
||||
<span>{{ item.userScore }}</span>
|
||||
<span>分</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<span>{{ item.endAnswerTime }}</span>
|
||||
<span>耗时:{{ getTimeStr(item.answerTimeSum, 'mm') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="openMore" v-if="planRecordList?.joinUserList">
|
||||
<span type="default" @click="goRanking()">查看全部</span>
|
||||
</div>
|
||||
<div v-if="!planRecordList?.joinUserList">
|
||||
<Empty :url="emptyIcon" :imageSize="[200, 160]" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { getFileHttpUrl, getTimeStr } from '/@/utils/compUtils.ts';
|
||||
import GoldPng from '/@/assets/images/psychiology/answer/gold.png';
|
||||
import SilverPng from '/@/assets/images/psychiology/answer/silver.png';
|
||||
import BronzePng from '/@/assets/images/psychiology/answer/bronze.png';
|
||||
import Empty from '/@/components/Empty.vue';
|
||||
import emptyIcon from '/@/assets/images/interveneEmpty.png';
|
||||
import { useRouter } from 'vue-router';
|
||||
const router = useRouter();
|
||||
const props = defineProps({
|
||||
id: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
planRecordList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
function goRanking() {
|
||||
router.push({
|
||||
path: '/ranking-list',
|
||||
query: { planId: props.id },
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.ranking-list {
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
padding-bottom: 0;
|
||||
.title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.name {
|
||||
font-weight: bold;
|
||||
font-size: 17px;
|
||||
color: #333333;
|
||||
}
|
||||
.number {
|
||||
font-weight: 500;
|
||||
margin-left: 10px;
|
||||
font-size: 14px;
|
||||
color: #77849e;
|
||||
}
|
||||
}
|
||||
.right {
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
color: #21bebd;
|
||||
}
|
||||
}
|
||||
.title-bottom {
|
||||
display: flex;
|
||||
span {
|
||||
width: 15%;
|
||||
text-align: center;
|
||||
color: #77849e;
|
||||
}
|
||||
}
|
||||
.me {
|
||||
padding: 16px 0px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
.ranking {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #eaecf1;
|
||||
.fraction {
|
||||
width: 12%;
|
||||
text-align: center;
|
||||
.medal {
|
||||
width: 72px;
|
||||
height: 42px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: -16px;
|
||||
img {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
.gold {
|
||||
background: linear-gradient(90deg, #fffcf7 0%, #ffedcc 100%);
|
||||
}
|
||||
.silver {
|
||||
background: linear-gradient(90deg, #fdfdfd 0%, #eaeaea 100%);
|
||||
}
|
||||
.bronze {
|
||||
background: linear-gradient(90deg, #fdfdfd 0%, #ffe0c9 100%);
|
||||
}
|
||||
}
|
||||
.picture {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 50%;
|
||||
background: pink;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
.personal {
|
||||
flex: 1;
|
||||
margin-left: 10px;
|
||||
.top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.top-left {
|
||||
.line {
|
||||
display: inline-block;
|
||||
width: 1px;
|
||||
height: 10px;
|
||||
margin: 0 8px;
|
||||
background: #e6e6ea;
|
||||
}
|
||||
.dept {
|
||||
color: #77849e;
|
||||
}
|
||||
.my {
|
||||
padding-left: 5px;
|
||||
color: #21bebd;
|
||||
}
|
||||
}
|
||||
}
|
||||
.bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: #b6b6b6;
|
||||
}
|
||||
}
|
||||
}
|
||||
.openMore {
|
||||
padding: 10px 0;
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
span {
|
||||
color: #21bebd;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,6 @@
|
||||
import { get, post } from '/@/views/mobile/api/api';
|
||||
|
||||
const prefix: string = import.meta.env.VITE_GLOB_APP_PREFIX || '';
|
||||
//通过id 获取列表
|
||||
export const getPlan = (params: any) => get(`${prefix}/api/psychology/answer/plan`, params);
|
||||
export const getPlanRecord = (params: any) => get(`${prefix}/api/psychology/answer/plan/record`, params);
|
||||
@@ -0,0 +1,285 @@
|
||||
<template>
|
||||
<div class="progress" v-if="planList">
|
||||
<div class="top">
|
||||
<div class="time">
|
||||
<div>
|
||||
<van-icon name="clock-o" size="16" color="#21BEBD" />
|
||||
<!-- <span> 2024.05.20 ~ 05.28</span>-->
|
||||
<span> {{ `${planList.startTime} ~ ${dayjs(planList.endTime).format('MM-DD')}` }}</span>
|
||||
</div>
|
||||
<div class="state" v-if="planList?.userState == 1">已参加</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="title">
|
||||
<img :src="planList?.state == '1' ? isProgressPng : isOverPng" alt="" />
|
||||
<span>{{ planList?.planName }}</span>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="classification">
|
||||
<span v-for="(item, index) in planList?.questionCategory.split(',')" :key="index">#{{ item }}</span>
|
||||
</div>
|
||||
<div class="details">
|
||||
<span class="number">已参加{{ planList?.actualJoinNumber }}人</span>
|
||||
<span class="information">共{{ planList?.questionSum }}道题 答题时长为{{ planList?.maxLimitTime }}分钟</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="illustrate">
|
||||
<span>活动说明:</span>
|
||||
<span class="explain">{{ planList?.description || '--' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="center" v-if="planList?.userState == 1">
|
||||
<span>答题时长: {{ getTimeStr(planRecordList?.selfRecord.answerTimeSum, 'mm') }}</span>
|
||||
<span>答题时间: {{ planRecordList?.selfRecord.endAnswerTime }}</span>
|
||||
<van-button class="btn" size="small" @click="goReport(planList)">答题报告</van-button>
|
||||
<img :src="timePng" alt="" />
|
||||
</div>
|
||||
<div class="bottom" :style="{ background: planList?.userState == 1 ? '' : '#fff' }">
|
||||
<RankingList :id="route.query.id" :planRecordList="planRecordList" v-if="planRecordList" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer" v-if="planList && planList?.userState == '0'">
|
||||
<van-button
|
||||
type="primary"
|
||||
:class="planList?.state == 1 ? 'footer-true-btn' : 'footer-false-btn'"
|
||||
:disabled="planList?.state != 1"
|
||||
@click="show = true"
|
||||
>
|
||||
开始答题
|
||||
</van-button>
|
||||
</div>
|
||||
<van-overlay :show="show" @click="show = false">
|
||||
<div class="wrapper" @click.stop>
|
||||
<div class="block">
|
||||
<div class="block-top"> 共{{ planList?.questionSum }}道题,答题时长为{{ planList?.maxLimitTime }}分钟,是否确认开始答题? </div>
|
||||
<div class="block-bottom">
|
||||
<van-button class="close-btn" @click="show = false">取消</van-button>
|
||||
<van-button class="go-answer" @click="goAnswer(planList)">开始答题</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-overlay>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { getPlan, getPlanRecord } from '/@/views/23psychology/answer/taskDetails/taskDetails.api.ts';
|
||||
|
||||
import isProgressPng from '/@/assets/images/psychiology/isProgress.png';
|
||||
import isOverPng from '/@/assets/images/psychiology/isOver.png';
|
||||
import timePng from '/@/assets/images/psychiology/answer/time.png';
|
||||
import RankingList from '/@/views/23psychology/answer/taskDetails/components/rankingList.vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { getTimeStr } from '/@/utils/compUtils.ts';
|
||||
import { newPageParams, openPage } from '/@/hooks/openPage';
|
||||
import dayjs from 'dayjs';
|
||||
const router = useRouter();
|
||||
let planList = ref();
|
||||
let planRecordList = ref();
|
||||
const show = ref(false);
|
||||
const route = useRoute();
|
||||
onMounted(async () => {
|
||||
const data = await getPlan({ id: route.query.id });
|
||||
const planData = await getPlanRecord({ planId: route.query.id });
|
||||
planList.value = data.result;
|
||||
planRecordList.value = planData.result;
|
||||
});
|
||||
function goAnswer(value: any) {
|
||||
show.value = false;
|
||||
openPage(
|
||||
'/ps-selfAnswer',
|
||||
newPageParams({
|
||||
planId: value?.id,
|
||||
type: 1,
|
||||
answerTime: value.maxLimitTime,
|
||||
affirmBack: 1,
|
||||
})
|
||||
);
|
||||
}
|
||||
function goReport(value: any) {
|
||||
router.push({
|
||||
path: '/answer-Report',
|
||||
query: { id: value?.paperId },
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.progress {
|
||||
padding: 16px;
|
||||
background: #eaecf1;
|
||||
min-height: 100vh;
|
||||
.top {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
.time {
|
||||
height: 50px;
|
||||
font-size: 15px;
|
||||
border-bottom: 1px solid #eaecf1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
justify-content: space-between;
|
||||
span {
|
||||
margin-left: 8px;
|
||||
color: #77849e;
|
||||
}
|
||||
.state {
|
||||
color: #21bebd;
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
padding: 15px;
|
||||
border-bottom: 1px solid #eaecf1;
|
||||
.title {
|
||||
font-size: 17px;
|
||||
color: #252535;
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
img {
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
margin-right: 7px;
|
||||
}
|
||||
}
|
||||
.info {
|
||||
font-size: 14px;
|
||||
color: #252535;
|
||||
.classification {
|
||||
color: #21bebd;
|
||||
margin-bottom: 5px;
|
||||
span {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
.details {
|
||||
.number {
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
color: #77849e;
|
||||
}
|
||||
.information {
|
||||
margin-left: 20px;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
color: #b6b6b6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.illustrate {
|
||||
padding: 15px;
|
||||
color: #252535;
|
||||
|
||||
line-height: 26px;
|
||||
font-size: 15px;
|
||||
.explain {
|
||||
font-weight: 500;
|
||||
color: #77849e;
|
||||
}
|
||||
}
|
||||
}
|
||||
.center {
|
||||
height: 110px;
|
||||
background: linear-gradient(180deg, #21bebd 0%, #87d8d7 100%);
|
||||
border-radius: 10px;
|
||||
margin: 16px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: space-around;
|
||||
color: #fff;
|
||||
padding: 10px 20px;
|
||||
position: relative;
|
||||
font-size: 14px;
|
||||
.btn {
|
||||
border-radius: 5px;
|
||||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
color: #21bebd;
|
||||
line-height: 21px;
|
||||
}
|
||||
img {
|
||||
display: inline-block;
|
||||
width: 78px;
|
||||
position: absolute;
|
||||
right: 5%;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
.bottom {
|
||||
margin-top: 16px;
|
||||
border-radius: 8px;
|
||||
.title {
|
||||
font-weight: bold;
|
||||
font-size: 17px;
|
||||
color: #333b42;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.footer-true-btn {
|
||||
width: 70%;
|
||||
border-radius: 20px;
|
||||
background: #21bebd;
|
||||
border-color: #21bebd;
|
||||
}
|
||||
.footer-false-btn {
|
||||
width: 70%;
|
||||
border-radius: 20px;
|
||||
color: #fff;
|
||||
background: #b6b6b6;
|
||||
border-color: #b6b6b6;
|
||||
}
|
||||
}
|
||||
.wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.block {
|
||||
width: 80%;
|
||||
height: 170px;
|
||||
background-color: #fff;
|
||||
/* border: 8px; */
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.block-top {
|
||||
flex: 1;
|
||||
height: 40px;
|
||||
font-size: 15px;
|
||||
color: #333333;
|
||||
line-height: 28px;
|
||||
text-align: center;
|
||||
padding: 32px 42px;
|
||||
}
|
||||
.block-bottom {
|
||||
.close-btn {
|
||||
width: 50%;
|
||||
border: none;
|
||||
background: #e6e6ea;
|
||||
border-radius: 0 0 0 8px;
|
||||
}
|
||||
.go-answer {
|
||||
width: 50%;
|
||||
border: none;
|
||||
background: #21bebd;
|
||||
border-radius: 0 0 8px 0;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,258 @@
|
||||
<template>
|
||||
<div class="question-box">
|
||||
<template v-for="(qus, quIndex) in list">
|
||||
<div class="question-title" :id="surveyCode + 'psychlolgy_' + qus.type" v-if="!hiden.includes(qus?.questionCode)" :key="quIndex">
|
||||
<div class="title">
|
||||
<span class="tips" v-if="ifRequire">*</span>
|
||||
<div class="title-con">
|
||||
<!-- <span class="qus-title">{{ quIndex + 1 }}、</span>-->
|
||||
<span class="qus-title">{{ qus.title }}</span>
|
||||
<span class="que-type">【{{ questionType(qus.inputType) }}】</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 单选 -->
|
||||
<template v-if="qus.inputType === 'radio'">
|
||||
<div v-for="(item, index) in qus.options" :key="'info' + index">
|
||||
<div :class="[qus.answer == item.value + '' ? 'blue-b' : 'red-g']" class="item-div" @click="handleRadio(item, quIndex)">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 多选 -->
|
||||
<template v-if="qus.inputType === 'check'">
|
||||
<div v-for="(item, index) in qus.options" :key="'info' + index">
|
||||
<div
|
||||
:class="[qus.answer.split(',').includes(item.value + '') ? 'blue-b' : 'red-g']"
|
||||
class="item-div"
|
||||
@click="handleCheck(item, quIndex)"
|
||||
>
|
||||
{{ item.name }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 填空题单个内容 -->
|
||||
<template v-if="qus.inputType === 'text'">
|
||||
<div v-if="qus.type == 'actualSleepTime'">
|
||||
<div class="input-box">
|
||||
<div class="field-answer">
|
||||
<van-field
|
||||
:type="qus.tfNumber ? 'number' : ''"
|
||||
v-model="qus.answer"
|
||||
placeholder="请输入"
|
||||
@input="(e) => handleChange(e, quIndex, qus)"
|
||||
@blur="(e) => handleBlurText(e, quIndex, qus)"
|
||||
/>
|
||||
</div>
|
||||
<!-- <div class="input-unit">{{ qus.unit }}</div>-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-box" v-else>
|
||||
<div class="field-answer">
|
||||
<van-field
|
||||
:type="qus.tfNumber ? 'number' : ''"
|
||||
v-model="qus.answer"
|
||||
placeholder="请输入"
|
||||
@blur="(e) => handleBlurText(e, quIndex, qus)"
|
||||
/>
|
||||
</div>
|
||||
<!-- <div class="input-unit">{{ qus.unit }}</div>-->
|
||||
</div>
|
||||
</template>
|
||||
<!-- 填空题多个内容 -->
|
||||
<template v-if="qus.inputType === 'inputs'">
|
||||
<slot name="inputs" v-bind="{ data: qus }"></slot>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { defineProps, defineExpose, defineEmits } from 'vue';
|
||||
import { questionType } from '/@/views/23psychology/components/answerTemplateHooks';
|
||||
import { showToast } from 'vant';
|
||||
const emit = defineEmits(['radios', 'check', 'inputClear']);
|
||||
let checkList = ref<any[]>([]);
|
||||
const props = defineProps({
|
||||
list: {
|
||||
type: Array,
|
||||
},
|
||||
dataIndex: {
|
||||
type: Number,
|
||||
},
|
||||
ifRequire: {
|
||||
type: Boolean,
|
||||
},
|
||||
hiden: {
|
||||
type: Object,
|
||||
},
|
||||
surveyCode: {
|
||||
type: String,
|
||||
default: () => '',
|
||||
},
|
||||
});
|
||||
function handleBlurText(e: any, index: number, chilData: any) {
|
||||
let data: any[] = props.list as any[];
|
||||
let value = e.target.value;
|
||||
if (chilData.hasOwnProperty('tfNumberRange')) {
|
||||
if (value < 0 || value > 100) {
|
||||
showToast(`请输入${chilData.tfNumberRange.min}-${chilData.tfNumberRange.max}任意一个数字`);
|
||||
data[index].answer = '';
|
||||
emit('inputClear', { dataIndex: props.dataIndex, childData: data });
|
||||
}
|
||||
}
|
||||
}
|
||||
function handleChange(e: any, index: number, chilData: any) {
|
||||
let data: any[] = props.list as any[];
|
||||
let value;
|
||||
if (e.target.value > 24) {
|
||||
value = 24;
|
||||
} else {
|
||||
value = parseInt(e.target.value);
|
||||
}
|
||||
|
||||
if (chilData.hasOwnProperty('tfNumber')) {
|
||||
if (value <= 0 || value >= 24) {
|
||||
showToast(`请输入0到24内任意一个数字`);
|
||||
data[index].answer = value.toString().substring(0, 2);
|
||||
emit('inputClear', { dataIndex: props.dataIndex, childData: data });
|
||||
}
|
||||
}
|
||||
}
|
||||
// 单选
|
||||
function handleRadio(item: any, index: number) {
|
||||
let data: any[] = props.list as any[];
|
||||
data[index].answer = item.value;
|
||||
emit('radios', { dataIndex: props.dataIndex, childData: data, hidenParams: handleJumpQues(item, index) });
|
||||
}
|
||||
// 多选
|
||||
function handleCheck(item: any, index: number) {
|
||||
let data: any[] = props.list as any[];
|
||||
let userAnswer = data[index].answer !== '' ? data[index].answer.split(',').map(Number) : [];
|
||||
if (userAnswer.includes(item.value)) {
|
||||
let index = userAnswer.indexOf(item.value);
|
||||
userAnswer.splice(index, 1);
|
||||
} else {
|
||||
userAnswer.push(item.value);
|
||||
}
|
||||
data[index].answer = userAnswer.join(',');
|
||||
emit('check', { dataIndex: props.dataIndex, childData: data });
|
||||
}
|
||||
// 跳题
|
||||
function handleJumpQues(qusItem: any, index: number) {
|
||||
let data: any[] = props.list as any[];
|
||||
if (qusItem.hasOwnProperty('hideCode')) {
|
||||
const numericArray = qusItem.hideCode !== '' ? qusItem.hideCode.split(',').map(Number) : [];
|
||||
return {
|
||||
[data[index].type]: numericArray,
|
||||
};
|
||||
}
|
||||
}
|
||||
// 滚动
|
||||
function setScrollInto() {
|
||||
const list: any[] = props.list as [];
|
||||
let vis = '';
|
||||
let ind = null;
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (list[i].answer === '' && props.ifRequire) {
|
||||
ind = list[i].type;
|
||||
vis = props.surveyCode + 'psychlolgy_' + ind;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return vis;
|
||||
}
|
||||
defineExpose({
|
||||
setScrollInto,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import url('/@/views/23psychology/components/psychology.less');
|
||||
.question-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.question-title {
|
||||
padding: 10px 20px;
|
||||
.title {
|
||||
color: #333b42;
|
||||
font-weight: bold;
|
||||
padding-bottom: 10px;
|
||||
position: relative;
|
||||
.tips {
|
||||
color: #ed2a26;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
left: -10px;
|
||||
}
|
||||
.title-con {
|
||||
.qus-title {
|
||||
font-size: 15px;
|
||||
}
|
||||
.que-type {
|
||||
padding-left: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.item-div {
|
||||
margin: 10px 0;
|
||||
padding: 10px 20px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.red-g {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
.blue-b {
|
||||
background-color: #d2f2f3;
|
||||
border: 1px solid @primary-color;
|
||||
color: @primary-color;
|
||||
}
|
||||
.radioStyle {
|
||||
display: block;
|
||||
height: 32px;
|
||||
}
|
||||
.radios {
|
||||
height: 28px;
|
||||
}
|
||||
:deep(.van-checkbox__label) {
|
||||
height: 70%;
|
||||
}
|
||||
.checksInput-box {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
.options-name {
|
||||
width: 90%;
|
||||
height: 100%;
|
||||
}
|
||||
.checksInput-answer {
|
||||
width: 100%;
|
||||
}
|
||||
:deep(.van-cell) {
|
||||
border-bottom: 1px solid #e6e6ea;
|
||||
}
|
||||
}
|
||||
.input-box {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 6px 0;
|
||||
.field-answer {
|
||||
width: 100%;
|
||||
}
|
||||
:deep(.van-cell) {
|
||||
border: 1px solid #e6e6ea;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.input-unit {
|
||||
width: 20%;
|
||||
padding-left: 10px;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,100 @@
|
||||
// 判断有几个下划线
|
||||
function countUnderscores(str: string) {
|
||||
const matches = str.match(/_/g);
|
||||
return matches ? matches.length : 0;
|
||||
}
|
||||
// inputs类型添加fieldOptions字段
|
||||
export function addInputFieldOption(quesList: Array<any>) {
|
||||
const hideParams: any = {};
|
||||
quesList.map((item) => {
|
||||
item.childrenQuestions.map((quesItem: any) => {
|
||||
if (quesItem.inputType === 'inputs') {
|
||||
quesItem['fieldOptions'] = setFieldOptions(quesItem);
|
||||
}
|
||||
if (quesItem.inputType === 'radio') {
|
||||
const findItem = quesItem.options.find((e: any) => {
|
||||
if (e?.hideCode && quesItem.answer !== '') {
|
||||
return [quesItem.answer].includes(e.value);
|
||||
}
|
||||
});
|
||||
if (findItem) {
|
||||
const findHide = findItem?.hideCode.split(',').map(Number);
|
||||
hideParams[quesItem.type] = findHide;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
return { quesList, hideParams };
|
||||
}
|
||||
// 设置一个题多个填空,内容回显及添加字段
|
||||
function setFieldOptions(data: any) {
|
||||
const number = countUnderscores(data.textInfo);
|
||||
const options = {};
|
||||
const answerOption = data.answer !== '' ? data.answer.split(',') : [];
|
||||
for (let i = 0; i < number; i++) {
|
||||
const fieldValue = answerOption.length > 0 ? answerOption[i] : '';
|
||||
// @ts-ignore
|
||||
options[data.type + i] = fieldValue;
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交问卷数据
|
||||
* answerContent 问卷+answer
|
||||
* queCode 问卷code
|
||||
* answerDetail type+answer [{"type":"smoke",answer:"444"}]
|
||||
* @param type
|
||||
* @param list
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
*/
|
||||
export function setSubmitData(type: string, list: Array<any>, startTime: string, endTime: string) {
|
||||
const questList: Array<any> = [];
|
||||
let baseQues: Array<any> = [];
|
||||
list.map((item) => {
|
||||
const answerDetailList: Array<any> = [];
|
||||
item.questionList.map((quesItem: any) => {
|
||||
quesItem.childrenQuestions.map((childItem: any) => {
|
||||
if (childItem.inputType === 'inputs') {
|
||||
const fieldList = Object.values(childItem.fieldOptions);
|
||||
const filterArray = fieldList.filter(Boolean);
|
||||
childItem.answer = filterArray.length > 0 ? filterArray.join(',') : '';
|
||||
}
|
||||
answerDetailList.push({
|
||||
type: childItem.type,
|
||||
answer: childItem.answer,
|
||||
});
|
||||
});
|
||||
});
|
||||
questList.push({
|
||||
answerContent: JSON.stringify(item),
|
||||
queCode: item.surveyCode,
|
||||
answerDetail: JSON.stringify(answerDetailList),
|
||||
});
|
||||
baseQues = answerDetailList;
|
||||
});
|
||||
let backParams = undefined;
|
||||
if (type === 'base') {
|
||||
backParams = {
|
||||
answerContent: JSON.stringify(baseQues),
|
||||
};
|
||||
} else {
|
||||
backParams = {
|
||||
questList,
|
||||
task: '',
|
||||
startTime,
|
||||
endTime,
|
||||
};
|
||||
}
|
||||
return backParams;
|
||||
}
|
||||
export function questionType(type: string) {
|
||||
const queType: any = {
|
||||
radio: '单选题',
|
||||
check: '多选题',
|
||||
text: '填空题',
|
||||
inputs: '填空题',
|
||||
};
|
||||
return queType[type];
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
@primary-color:#21BEBD;
|
||||
@con-bg:#f5f7fb;
|
||||
@font-primary-color:#333333;
|
||||
@font-sub-color:#586275;
|
||||
.bottom-button(@width:70%,@height:40px,@color:#ffffff,@bg:@primary-color,@borderRadius:20px) {
|
||||
width: @width;
|
||||
height: @height;
|
||||
line-height: @height;
|
||||
background-color: @bg;
|
||||
border:1px solid @bg;
|
||||
border-radius: @borderRadius;
|
||||
color: @color;
|
||||
text-align: center;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export function reportsStatus(type: number) {
|
||||
const params = {
|
||||
0: 'low-type',
|
||||
1: 'centre-type',
|
||||
2: 'tall-type',
|
||||
};
|
||||
return params(type);
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
<template>
|
||||
<div class="ps-container">
|
||||
<div class="ps-top-bg"></div>
|
||||
<div class="ps-con">
|
||||
<div class="ps-top-text" ref="psText">{{ quesParams.tips }}</div>
|
||||
<div class="answer-container" :style="psTextHeight" v-if="quesParams.questionList.length > 0">
|
||||
<div class="question-type" v-for="(item, index) in quesParams.questionList" :key="index">
|
||||
<div class="type-title">{{ item.name }}</div>
|
||||
<answer-template
|
||||
:list="item.childrenQuestions"
|
||||
:dataIndex="index"
|
||||
:hiden="getHide()"
|
||||
:ifRequire="false"
|
||||
ref="psychology"
|
||||
@radios="getRadios"
|
||||
@check="getRadios"
|
||||
>
|
||||
<template #inputs="{ data }">
|
||||
<div class="input-box" v-for="(value, key, index) in data.fieldOptions" :key="index">
|
||||
<div class="field-answer">
|
||||
<van-field v-model="data.fieldOptions[key]" :type="data?.tfNumber ? 'number' : ''" placeholder="请输入" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</answer-template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="no-data" v-else>
|
||||
<Empty :url="emptyIcon" :imageSize="[200, 160]" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-btn">
|
||||
<van-button class="btn" type="primary" :disabled="quesParams.questionList.length === 0" @click="handleSubmit">提交</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, nextTick } from 'vue';
|
||||
import AnswerTemplate from '/@/views/23psychology/components/AnswerTemplate.vue';
|
||||
import { setSubmitData, addInputFieldOption } from '/@/views/23psychology/components/answerTemplateHooks';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { getBaseQuesApi, submitBaseQuesApi } from '/@/views/23psychology/psychic/psychologyApi';
|
||||
import { showFailToast, showSuccessToast } from 'vant';
|
||||
import { destroyPage } from '/@/hooks/openPage';
|
||||
import { useLoading } from '/@/utils/compUtils';
|
||||
import Empty from '/@/components/Empty.vue';
|
||||
import emptyIcon from '/@/assets/images/interveneEmpty.png';
|
||||
const { loadingSpinner, loadingClose } = useLoading();
|
||||
const router = useRouter();
|
||||
let psText = ref(null);
|
||||
let psTextHeight = ref({});
|
||||
let psychology = ref(null);
|
||||
let quesParams = ref({
|
||||
questionList: [],
|
||||
result: [],
|
||||
tips: '',
|
||||
});
|
||||
onMounted(() => {
|
||||
getQuestion();
|
||||
});
|
||||
|
||||
const hide = ref({});
|
||||
function getHide() {
|
||||
let result: any[] = [];
|
||||
if (Object.keys(hide.value).length === 0) return [];
|
||||
for (let i = 0; i < Object.keys(hide.value).length; i++) {
|
||||
result = result.concat(hide.value[Object.keys(hide.value)[i]]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
async function getQuestion() {
|
||||
const { code, result } = await getBaseQuesApi({ type: 1 });
|
||||
if (code === 200) {
|
||||
quesParams.value.result = result;
|
||||
const { quesList, hideParams } = addInputFieldOption(result[0].questionList);
|
||||
hide.value = { ...hideParams };
|
||||
quesParams.value.questionList = quesList;
|
||||
quesParams.value.tips = result[0].surveyDesc;
|
||||
nextTick(() => {
|
||||
let psHeight = `height:calc(100% - ${psText.value.offsetHeight}px)`;
|
||||
psTextHeight.value = psHeight;
|
||||
});
|
||||
}
|
||||
}
|
||||
function handleSubmit() {
|
||||
loadingSpinner();
|
||||
let params = setSubmitData('base', quesParams.value.result, '', '');
|
||||
submitBaseQuesApi(params).then((res: any) => {
|
||||
if (res.code === 200) {
|
||||
loadingClose();
|
||||
destroyPage();
|
||||
showSuccessToast('提交成功!');
|
||||
router.go(-1);
|
||||
} else {
|
||||
loadingClose();
|
||||
showFailToast('提交失败!');
|
||||
}
|
||||
});
|
||||
}
|
||||
function getRadios({ dataIndex, childData, hidenParams }) {
|
||||
hide.value = { ...hide.value, ...hidenParams };
|
||||
quesParams.value.questionList[dataIndex].childrenQuestions = childData;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import url('/@/views/23psychology/components/psychology.less');
|
||||
.ps-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: @con-bg;
|
||||
position: relative;
|
||||
.ps-top-bg {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
background: linear-gradient(180deg, @primary-color 20%, rgba(84, 236, 203, 0) 100%);
|
||||
}
|
||||
.ps-con {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
right: 20px;
|
||||
width: 90%;
|
||||
height: calc(100vh - 90px);
|
||||
background-color: #ffffff;
|
||||
padding: 20px;
|
||||
border-radius: 20px;
|
||||
.ps-top-text {
|
||||
width: 100%;
|
||||
color: #586275;
|
||||
line-height: 26px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.answer-container {
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
.question-type {
|
||||
margin: 30px 0;
|
||||
.type-title {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
color: @font-primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.no-data {
|
||||
height: 100%;
|
||||
padding-top: 50%;
|
||||
}
|
||||
.input-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 6px 0;
|
||||
.field-answer {
|
||||
width: 100%;
|
||||
}
|
||||
:deep(.van-cell) {
|
||||
border: 1px solid #e6e6ea;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.input-unit {
|
||||
width: 20%;
|
||||
padding-left: 10px;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
.bottom-btn {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
height: 50px;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.btn {
|
||||
.bottom-button();
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,250 @@
|
||||
<template>
|
||||
<div class="scale-container">
|
||||
<div class="scale-con" id="scaleBox" v-if="list.length > 0">
|
||||
<div class="scale-item" v-for="(item, index) in list" :id="item.surveyCode" :key="index">
|
||||
<div class="scale-title">
|
||||
<div>{{ item.surveyName }}</div>
|
||||
<div>{{ item.surveyDesc }}</div>
|
||||
</div>
|
||||
<div class="qus-con">
|
||||
<div
|
||||
class="qus-item"
|
||||
v-for="(quChilds, childsIndex) in item.questionList"
|
||||
:id="item.surveyCode + '-a-' + index + '-b-'"
|
||||
:key="childsIndex"
|
||||
>
|
||||
<div class="children-title" v-if="quChilds.name">{{ quChilds?.name }}</div>
|
||||
<answer-template
|
||||
:hiden="[]"
|
||||
:survey-code="item.surveyCode + '-a-' + index + '-b-'"
|
||||
:dataIndex="index"
|
||||
:list="quChilds?.childrenQuestions"
|
||||
:ref="
|
||||
(el) => {
|
||||
psychologyScale[index + '-' + childsIndex] = el;
|
||||
}
|
||||
"
|
||||
:ifRequire="true"
|
||||
@inputClear="handleInputClear"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="no-data" v-else>
|
||||
<Empty :url="emptyIcon" :imageSize="[200, 160]" />
|
||||
</div>
|
||||
<div class="bottom-btn">
|
||||
<van-button class="btn" type="primary" :disabled="list.length === 0" @click="handleSubmit">提交</van-button>
|
||||
</div>
|
||||
<Overlay :show="backOver">
|
||||
<template #content>
|
||||
<div class="overlay-block">
|
||||
<div class="block-top">中途退出将不会保存您的答案,是否确定退出?</div>
|
||||
<div class="out-btn">
|
||||
<div class="backBtn canel-out" @click="backOver = false">取消</div>
|
||||
<div class="backBtn sure-out" @click="backAnswer">退出答题</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Overlay>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import AnswerTemplate from '/@/views/23psychology/components/AnswerTemplate.vue';
|
||||
import { getBaseQuesApi, submitQuesApi } from '/@/views/23psychology/psychic/psychologyApi';
|
||||
import { setSubmitData } from '/@/views/23psychology/components/answerTemplateHooks';
|
||||
import { showFailToast, showSuccessToast, showToast } from 'vant';
|
||||
import Empty from '/@/components/Empty.vue';
|
||||
import emptyIcon from '/@/assets/images/interveneEmpty.png';
|
||||
import Overlay from '/@/views/components/overlay/Overlay.vue';
|
||||
import moment from 'moment';
|
||||
import { useLoading } from '/@/utils/compUtils';
|
||||
import { useInterceptBack } from '/@/hooks/useInterceptAndroid';
|
||||
import { destroyPage } from '/@/hooks/openPage';
|
||||
const { loadingSpinner, loadingClose } = useLoading();
|
||||
|
||||
let psychologyScale = ref({});
|
||||
let backOver = ref(false);
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const startTime = moment(new Date()).format('YYYY-MM-DD HH:mm:ss');
|
||||
let list = ref([]);
|
||||
|
||||
onMounted(() => {
|
||||
useInterceptBack(1, dropOut);
|
||||
getQuestion(route.query?.codes);
|
||||
});
|
||||
function dropOut() {
|
||||
backOver.value = true;
|
||||
}
|
||||
function backAnswer() {
|
||||
backOver.value = false;
|
||||
try {
|
||||
destroyPage();
|
||||
} catch {
|
||||
router.go(-1);
|
||||
}
|
||||
}
|
||||
async function getQuestion(codes: string) {
|
||||
const { code, result } = await getBaseQuesApi({ type: codes });
|
||||
if (code === 200) {
|
||||
list.value = result;
|
||||
}
|
||||
}
|
||||
function handleInputClear({ dataIndex, childData }) {
|
||||
list.value[dataIndex].childrenQuestions = childData;
|
||||
}
|
||||
function handleSubmit() {
|
||||
let dataParams = Object.entries(psychologyScale.value);
|
||||
for (const value in dataParams) {
|
||||
let [key, element] = dataParams[value];
|
||||
const t: string = element.setScrollInto();
|
||||
if (t) {
|
||||
showToast('请完成所有题目');
|
||||
return (document.getElementById('scaleBox').scrollTop =
|
||||
document.getElementById(t.substring(0, t.indexOf('-a-'))).offsetTop + document.getElementById(t).offsetTop);
|
||||
break;
|
||||
}
|
||||
}
|
||||
loadingSpinner();
|
||||
let endTime = moment(new Date()).format('YYYY-MM-DD HH:mm:ss');
|
||||
let params = setSubmitData('others', list.value, startTime, endTime);
|
||||
useInterceptBack(0);
|
||||
submitQuesApi({ ...params, taskId: route.query.taskId }).then((res: any) => {
|
||||
if (res.code === 200) {
|
||||
loadingClose();
|
||||
showSuccessToast('提交成功!');
|
||||
router.replace({
|
||||
path: '/ps-result',
|
||||
query: {
|
||||
id: res.message,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
loadingClose();
|
||||
showFailToast('提交失败!');
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import url('/@/views/23psychology/components/psychology.less');
|
||||
.scale-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: @con-bg;
|
||||
position: relative;
|
||||
.overlay-block {
|
||||
width: 80%;
|
||||
height: 170px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-items: center;
|
||||
.block-top {
|
||||
width: 100%;
|
||||
height: 70%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 15px;
|
||||
color: #333333;
|
||||
padding: 0 30px;
|
||||
text-align: center;
|
||||
}
|
||||
.block-bottom {
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
border-radius: 0 0 8px 8px;
|
||||
color: #ffffff;
|
||||
background-color: @primary-color;
|
||||
}
|
||||
.out-btn {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
.backBtn {
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
}
|
||||
.canel-out {
|
||||
background-color: #e6e6ea;
|
||||
color: #333333;
|
||||
border-bottom-left-radius: 8px;
|
||||
}
|
||||
.sure-out {
|
||||
color: #ffffff;
|
||||
background-color: @primary-color;
|
||||
border-bottom-right-radius: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.scale-con {
|
||||
width: 100%;
|
||||
height: calc(100vh - 60px);
|
||||
overflow-y: auto;
|
||||
padding: 20px;
|
||||
scroll-behavior: smooth;
|
||||
.scale-item {
|
||||
margin: 20px 0;
|
||||
border-radius: 12px;
|
||||
position: relative;
|
||||
.scale-title {
|
||||
padding: 20px;
|
||||
background-color: #c8f5f5;
|
||||
border-top-left-radius: 12px;
|
||||
border-top-right-radius: 12px;
|
||||
div:nth-child(1) {
|
||||
font-weight: bold;
|
||||
color: @font-primary-color;
|
||||
font-size: 16px;
|
||||
}
|
||||
div:nth-child(2) {
|
||||
color: @font-sub-color;
|
||||
padding-top: 8px;
|
||||
}
|
||||
}
|
||||
.qus-con {
|
||||
margin-top: -6px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 12px;
|
||||
.qus-item {
|
||||
margin: 20px 0;
|
||||
.children-title {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
padding: 20px 0;
|
||||
color: @font-primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.no-data {
|
||||
width: 100%;
|
||||
height: calc(100vh - 60px);
|
||||
padding-top: 50%;
|
||||
}
|
||||
.bottom-btn {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
height: 50px;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.btn {
|
||||
.bottom-button();
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,164 @@
|
||||
<template>
|
||||
<div class="evaluation-container">
|
||||
<div class="top-bg">
|
||||
<div class="top-con">
|
||||
<div>自主评估</div>
|
||||
<div>请选择此次测评的量表,可一次选择多个量表</div>
|
||||
</div>
|
||||
<div class="top-icon"></div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<template v-if="list.length > 0">
|
||||
<div class="con-item" v-for="(item, index) in list">
|
||||
<div class="number">{{ index + 1 }}</div>
|
||||
<div class="con-left">
|
||||
<div class="name">{{ item.name }}</div>
|
||||
<div class="describe">{{ item.describe }}</div>
|
||||
</div>
|
||||
<van-checkbox shape="square" checked-color="#21BEBD" v-model="item.checked" />
|
||||
</div>
|
||||
</template>
|
||||
<div class="no-data" v-else>
|
||||
<Empty :url="emptyIcon" :imageSize="[200, 160]" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-btn">
|
||||
<van-button class="btn" :disabled="list.length === 0" type="primary" @click="start">开始测评</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { getCodeApi } from '/@/views/23psychology/psychic/psychologyApi';
|
||||
import { showToast } from 'vant';
|
||||
import Empty from '/@/components/Empty.vue';
|
||||
import emptyIcon from '/@/assets/images/interveneEmpty.png';
|
||||
import { newPageParams, openPage } from '/@/hooks/openPage';
|
||||
const router = useRouter();
|
||||
let list = ref([]);
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
async function getList() {
|
||||
const { code, result: result } = await getCodeApi();
|
||||
if (code === 200) {
|
||||
list.value = result;
|
||||
}
|
||||
}
|
||||
function start() {
|
||||
let filterCheck = list.value.filter((e) => e?.checked);
|
||||
if (filterCheck.length === 0) {
|
||||
showToast('请选择测评量表');
|
||||
return;
|
||||
}
|
||||
const codesList = filterCheck.map((item) => item?.code);
|
||||
openPage(
|
||||
'/scale-questionnaire',
|
||||
newPageParams({
|
||||
codes: codesList.join(','),
|
||||
affirmBack: 1,
|
||||
})
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import url('/@/views/23psychology/components/psychology.less');
|
||||
.evaluation-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: @con-bg;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
.top-bg {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
background: linear-gradient(180deg, @primary-color 20%, rgba(84, 236, 203, 0) 100%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: start;
|
||||
position: relative;
|
||||
margin-bottom: 20px;
|
||||
.top-con {
|
||||
width: 65%;
|
||||
padding-top: 24px;
|
||||
padding-left: 40px;
|
||||
color: #ffffff;
|
||||
div:nth-child(1) {
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
}
|
||||
div:nth-child(2) {
|
||||
padding-top: 6px;
|
||||
}
|
||||
}
|
||||
.top-icon {
|
||||
position: absolute;
|
||||
right: 45px;
|
||||
bottom: 70px;
|
||||
width: 80px;
|
||||
height: 76px;
|
||||
background: url('/@/assets/images/psychiology/scaleIcon.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
width: 90%;
|
||||
height: calc(100% - 200px);
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
right: 20px;
|
||||
top: 125px;
|
||||
overflow-y: auto;
|
||||
.con-item:nth-child(1) {
|
||||
margin-top: 15px;
|
||||
}
|
||||
.con-item {
|
||||
padding: 20px;
|
||||
margin: 15px 0;
|
||||
background-color: #ffffff;
|
||||
border-radius: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.number {
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
color: @primary-color;
|
||||
}
|
||||
.con-left {
|
||||
width: 80%;
|
||||
.name {
|
||||
color: @font-primary-color;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
.describe {
|
||||
color: @font-sub-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.no-data {
|
||||
height: 100%;
|
||||
padding-top: 50%;
|
||||
}
|
||||
.bottom-btn {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
height: 50px;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.btn {
|
||||
.bottom-button(70%);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,122 @@
|
||||
<template>
|
||||
<div v-for="(item, index) in dataValue" :key="index">
|
||||
<div class="que">
|
||||
<div class="que-title"> ({{ index + 1 }}) {{ item.queName }}({{ item.queCode }})</div>
|
||||
<div class="infomation">{{ item.description }}</div>
|
||||
<van-button
|
||||
type="primary"
|
||||
:color="states !== '1' ? '#B6B6B6' : '#21BEBD'"
|
||||
class="btn"
|
||||
v-if="!item.result"
|
||||
@click="goWrite(item)"
|
||||
:disabled="states !== '1'"
|
||||
>填写</van-button
|
||||
>
|
||||
<div style="color: #21bebd" v-if="item.result">已填写</div>
|
||||
</div>
|
||||
<div class="over" v-if="item.result" @click="goViewHistory(item)">
|
||||
<div>
|
||||
<div class="time">评估时间:{{ item?.date }}</div>
|
||||
<div class="comment" :style="{ color: item.queColor }">{{ item?.result }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<img :src="BackPng" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import BackPng from '/@/assets/images/psychiology/back.png';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { newPageParams, openPage } from '/@/hooks/openPage';
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const props = defineProps({
|
||||
dataValue: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
states: {
|
||||
type: String,
|
||||
default: '0',
|
||||
},
|
||||
});
|
||||
function goViewHistory(record: any) {
|
||||
router.push({
|
||||
path: '/ps-result',
|
||||
query: {
|
||||
id: record.totalId,
|
||||
},
|
||||
});
|
||||
}
|
||||
function goWrite(record: any) {
|
||||
openPage(
|
||||
'/scale-questionnaire',
|
||||
newPageParams({
|
||||
codes: record?.queCode,
|
||||
taskId: route.query.id,
|
||||
affirmBack: 1,
|
||||
})
|
||||
);
|
||||
// router.push({
|
||||
// path: '/scale-questionnaire',
|
||||
// query: {
|
||||
// codes: record?.queCode,
|
||||
// taskId: route.query.id,
|
||||
// affirmBack: 1,
|
||||
// },
|
||||
// });
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.que {
|
||||
background: #ffffff;
|
||||
border-radius: 5px;
|
||||
padding: 16px;
|
||||
border: 1px solid #e6e6ea;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.btn {
|
||||
width: 73px;
|
||||
height: 29px;
|
||||
background: #21bebd;
|
||||
border-radius: 4px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.que-title {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
}
|
||||
.infomation {
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
color: #586275;
|
||||
line-height: 30px;
|
||||
}
|
||||
.over {
|
||||
background: #f3f5f9;
|
||||
border-radius: 10px;
|
||||
padding: 16px;
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.time {
|
||||
font-size: 14px;
|
||||
color: #586275;
|
||||
line-height: 21px;
|
||||
}
|
||||
.comment {
|
||||
font-weight: bold;
|
||||
margin-top: 8px;
|
||||
font-size: 16px;
|
||||
color: #ed2a26;
|
||||
line-height: 26px;
|
||||
}
|
||||
img {
|
||||
display: inline-block;
|
||||
width: 6px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,5 @@
|
||||
import { get } from '/@/views/mobile/api/api';
|
||||
|
||||
const prefix: string = import.meta.env.VITE_GLOB_APP_PREFIX || '';
|
||||
//通过id 获取列表
|
||||
export const getPlanById = (params: any) => get(`${prefix}/app/psychology/psychologyPlan/queryById`, params);
|
||||
@@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<div class="progress" v-if="infoData">
|
||||
<div class="top">
|
||||
<div class="time">
|
||||
<van-icon name="clock-o" size="16" color="#21BEBD" />
|
||||
<span> {{ infoData?.startTime }} ~ {{ infoData?.endTime }}</span>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="title">
|
||||
<img :src="infoData.state == '1' ? isProgressPng : isOverPng" alt="" />
|
||||
<span>{{ infoData?.planName }}</span>
|
||||
</div>
|
||||
<div class="info">{{ infoData?.description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom" v-if="dataValue">
|
||||
<div class="title">测评量表</div>
|
||||
<Questionnaire :dataValue="dataValue" :states="infoData.state"></Questionnaire>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import isProgressPng from '/@/assets/images/psychiology/isProgress.png';
|
||||
import isOverPng from '/@/assets/images/psychiology/isOver.png';
|
||||
import Questionnaire from '/@/views/23psychology/psychic/progress/components/questionnaire.vue';
|
||||
import { getPlanById } from '/@/views/23psychology/psychic/progress/progress.api';
|
||||
import { useRoute } from 'vue-router';
|
||||
const dataValue = ref([]);
|
||||
|
||||
const infoData = ref();
|
||||
const route = useRoute();
|
||||
onMounted(async () => {
|
||||
const data = await getPlanById({ id: route.query.id });
|
||||
infoData.value = data.result;
|
||||
dataValue.value = infoData.value.queList;
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.progress {
|
||||
padding: 16px;
|
||||
background: #eaecf1;
|
||||
min-height: 100vh;
|
||||
.top {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
.time {
|
||||
height: 50px;
|
||||
font-size: 15px;
|
||||
border-bottom: 1px solid #eaecf1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
span {
|
||||
margin-left: 8px;
|
||||
color: #77849e;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
padding: 15px;
|
||||
.title {
|
||||
font-size: 17px;
|
||||
color: #252535;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
img {
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
margin-right: 7px;
|
||||
}
|
||||
}
|
||||
.info {
|
||||
font-size: 14px;
|
||||
color: #252535;
|
||||
}
|
||||
}
|
||||
}
|
||||
.bottom {
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
margin-top: 16px;
|
||||
border-radius: 8px;
|
||||
.title {
|
||||
font-weight: bold;
|
||||
font-size: 17px;
|
||||
color: #333b42;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,33 @@
|
||||
import { get, post } from '/@/views/mobile/api/api';
|
||||
const prefix: string = import.meta.env.VITE_GLOB_APP_PREFIX || '';
|
||||
|
||||
// 获取问卷
|
||||
export const getBaseQuesApi = (params: any) => get(`${prefix}/api/psychology/psychologyEvaluateBase/getPsychologyEvaluateQuestion`, params);
|
||||
|
||||
// 获取量表
|
||||
export const getCodeApi = (params: any) => get(`${prefix}/psychology/psychologyPlan/getQueCode`, params);
|
||||
|
||||
// 量表提交问卷
|
||||
export const submitQuesApi = (params: any) => post(`${prefix}/api/psychology/psychologyEvaluateBase/submitPsychologyEvaluate`, params);
|
||||
|
||||
// 自主评估历史
|
||||
export const selectPsychologyEvaluateListApi = (params: any) =>
|
||||
get(`${prefix}/api/psychology/psychologyEvaluateBase/selectPsychologyEvaluateList`, params);
|
||||
export const selectPsychologyEvaluateInfoApi = (params: any) =>
|
||||
get(`${prefix}/api/psychology/psychologyEvaluateBase/selectPsychologyEvaluateInfo`, params);
|
||||
export const psychologyPlanListApi = (params: any) => get(`${prefix}/app/psychology/psychologyPlan/list`, params);
|
||||
|
||||
// 基础问卷提交
|
||||
export const submitBaseQuesApi = (params: any) => post(`${prefix}/api/psychology/psychologyEvaluateBase/addOrUpdatePsychologyEvaluateBase`, params);
|
||||
// 心理-知识答题-自主答题-选择题型
|
||||
export const getCategoryApi = (params: any) => get(`${prefix}/api/psychology/answer/category`, params);
|
||||
// 心理-知识答题-自主答题-活动列表
|
||||
export const getPlanListApi = (params: any) => get(`${prefix}/api/psychology/answer/plan/list`, params);
|
||||
// 心理-知识答题-自主答题-答题历史
|
||||
export const getAnswerPageApi = (params: any) => get(`${prefix}/api/psychology/answer/page`, params);
|
||||
// 心理-知识答题-自主答题-答题报告
|
||||
export const getAnswerReportApi = (params: any) => get(`${prefix}/api/psychology/answer/report`, params);
|
||||
// 心理-知识答题-自主答题-知识推荐
|
||||
export const getKnowledgeApi = (params: any) => get(`${prefix}/api/psychology/answer/knowledge/page`, params);
|
||||
// 心理-知识答题-自主答题-知识推荐详情
|
||||
export const getKnowledgeDetailApi = (params: any) => get(`${prefix}/api/psychology/answer/knowledge`, params);
|
||||
@@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<div class="report-container">
|
||||
<SingleReport v-if="info.hasOwnProperty('signleModule')" :list="info?.signleModule" />
|
||||
<report-more v-else :empty="empty" :info="info" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import SingleReport from '/@/views/23psychology/psychic/report/SingleReport.vue';
|
||||
import { selectPsychologyEvaluateInfoApi } from '/@/views/23psychology/psychic/psychologyApi';
|
||||
import { showFailToast } from 'vant';
|
||||
import { ref } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import ReportMore from '/@/views/23psychology/psychic/report/reportMore.vue';
|
||||
|
||||
const info = ref({});
|
||||
const empty = ref(false);
|
||||
const route = useRoute();
|
||||
function init() {
|
||||
selectPsychologyEvaluateInfoApi({ totalId: route.query.id })
|
||||
.then((res: any) => {
|
||||
if (res.success) {
|
||||
info.value = res.result;
|
||||
} else {
|
||||
showFailToast(res.message);
|
||||
empty.value = true;
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
empty.value = true;
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import url('/@/views/23psychology/components/psychology.less');
|
||||
.report-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: @con-bg;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<div class="single-container">
|
||||
<div class="report-item" v-for="(item, index) in props.list || []" :key="index">
|
||||
<div class="name">{{ item.moduleName }}</div>
|
||||
<div class="time">评估时间:{{ item.createTime ? item.createTime : '-' }}</div>
|
||||
<div style="display: flex; justify-content: center; margin-top: 10px" v-if="item.moduleName.indexOf('睡眠') === -1">
|
||||
<div>
|
||||
<div class="five-pointed-star-bottom" :style="{ backgroundColor: hexToRgb(item.color) }">
|
||||
<div class="five-pointed-star" style="color: #ffffff" :style="{ backgroundColor: item.color }">
|
||||
<span> {{ item?.score === '-' ? item?.score : parseFloat(item.score) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="five-pointed-star-text" :style="{ color: item.color }">{{ item.rating }}</div>
|
||||
<div class="name">指导建议</div>
|
||||
<div class="tips">{{ item.suggest }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps } from 'vue';
|
||||
const props = defineProps({
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
function hexToRgb(hex: string) {
|
||||
// 移除十六进制颜色代码中的'#'
|
||||
let sanitizedHex = hex ? hex.replace('#', '') : '';
|
||||
|
||||
// 解析红、绿、蓝值
|
||||
let r = parseInt(sanitizedHex.substring(0, 2), 16);
|
||||
let g = parseInt(sanitizedHex.substring(2, 4), 16);
|
||||
let b = parseInt(sanitizedHex.substring(4, 6), 16);
|
||||
|
||||
return `rgb(${r}, ${g}, ${b}, 0.2)`;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.five-pointed-star-bottom {
|
||||
position: relative;
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
clip-path: polygon(50% 0%, 100% 35%, 80% 90%, 20% 90%, 0% 35%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.five-pointed-star-text {
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
padding: 10px 0;
|
||||
}
|
||||
.five-pointed-star {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
clip-path: polygon(50% 0%, 100% 35%, 80% 90%, 20% 90%, 0% 35%);
|
||||
> span {
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 2%;
|
||||
}
|
||||
}
|
||||
.name {
|
||||
font-size: 17px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.time {
|
||||
font-size: 16px;
|
||||
color: rgba(88, 98, 117, 1);
|
||||
}
|
||||
.time,.tips{
|
||||
padding-top: 4px;
|
||||
}
|
||||
.single-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.report-item {
|
||||
margin-top: 20px;
|
||||
padding: 20px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 12px;
|
||||
}
|
||||
.report-item:nth-child(1) {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,226 @@
|
||||
<template>
|
||||
<div class="outer-d">
|
||||
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||
<div style="height: 100%; overflow: auto">
|
||||
<template v-if="list.length > 0">
|
||||
<van-list
|
||||
v-model:loading="loading"
|
||||
:finished="finished"
|
||||
@load="onLoad"
|
||||
:finished-text="list.length > 0 ? '没有更多了' : ''"
|
||||
v-model:error="error"
|
||||
error-text="请求失败,点击重新加载"
|
||||
>
|
||||
<template v-for="it in vellArray" :key="`collapse${it}`">
|
||||
<van-collapse v-model="activeNames">
|
||||
<van-collapse-item :title="it" :name="it">
|
||||
<template v-for="item in list" :key="item">
|
||||
<div
|
||||
class="van-collapse-item-d"
|
||||
v-if="moment(item.createTime).format('YYYY').indexOf(it) !== -1"
|
||||
:title="item"
|
||||
@click="toReports(item)"
|
||||
>
|
||||
<div class="timer"> 评估时间:{{ moment(item.createTime).format('YYYY-MM-DD HH:mm:ss') }} </div>
|
||||
<!-- <div class="middle-d" v-if="item?.queModules && item?.queModules.length > 0">-->
|
||||
<!-- <div v-for="(t, i) in item?.queModules || []" :key="`queModules${i}`">-->
|
||||
<!-- <span>{{ i + 1 }}</span>-->
|
||||
<!-- <span>{{ t || '-' }}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<div class="bottom-d" v-if="item?.list && item?.list.length > 0">
|
||||
<div class="bottom-d-item" v-for="(t, i) in item?.list || []" :key="`list${i}`">
|
||||
<div>{{ t.moduleName || '-' }}</div>
|
||||
<div>{{ t.rating || '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</van-collapse-item>
|
||||
</van-collapse>
|
||||
</template>
|
||||
</van-list>
|
||||
</template>
|
||||
<div v-if="list.length === 0 && finished" class="empty-d">
|
||||
<!-- <van-empty description="暂无数据" />-->
|
||||
<Empty :url="emptyIcon" :imageSize="[200, 160]" />
|
||||
</div>
|
||||
</div>
|
||||
</van-pull-refresh>
|
||||
<van-back-top />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { selectPsychologyEvaluateListApi } from '/@/views/23psychology/psychic/psychologyApi';
|
||||
import moment from 'moment';
|
||||
import Empty from '/@/components/Empty.vue';
|
||||
import emptyIcon from '/@/assets/images/interveneEmpty.png';
|
||||
import { useRouter } from 'vue-router';
|
||||
const activeNames = ref<any[]>([]);
|
||||
const list = ref<any[]>([]); // 列表
|
||||
const refreshing = ref(false); // 刷新状态
|
||||
const loading = ref(false); // loading 状态
|
||||
const finished = ref(false); // 是否完成
|
||||
const error = ref(false); // 是否报错
|
||||
const vellArray = ref<any[]>([]);
|
||||
const pageInfo = ref({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
});
|
||||
const router = useRouter();
|
||||
function toReports(item: any) {
|
||||
router.push({
|
||||
path: '/ps-result',
|
||||
query: { id: item.totalId },
|
||||
});
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
if (refreshing.value) {
|
||||
list.value = [];
|
||||
vellArray.value = [];
|
||||
activeNames.value = [];
|
||||
refreshing.value = false;
|
||||
finished.value = false;
|
||||
error.value = false;
|
||||
loading.value = true;
|
||||
pageInfo.value.pageNo = 1;
|
||||
}
|
||||
if (finished.value) return;
|
||||
selectPsychologyEvaluateListApi(pageInfo.value)
|
||||
.then((res: any) => {
|
||||
if (res.success) {
|
||||
error.value = false;
|
||||
if (res.result.length > 0) {
|
||||
res.result.map((item: any) => {
|
||||
if (vellArray.value.length === 0) {
|
||||
vellArray.value = [new Date(item.createTime).getFullYear()];
|
||||
} else {
|
||||
if (vellArray.value[vellArray.value.length - 1] !== new Date(item.createTime).getFullYear()) {
|
||||
vellArray.value.push(new Date(item.createTime).getFullYear());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
activeNames.value = vellArray.value;
|
||||
if (res.result.length < pageInfo.value.pageSize || res.result.length === 0) {
|
||||
finished.value = true;
|
||||
} else {
|
||||
pageInfo.value.pageNo += 1;
|
||||
}
|
||||
list.value = list.value.concat(res.result);
|
||||
} else {
|
||||
error.value = true;
|
||||
}
|
||||
loading.value = false;
|
||||
})
|
||||
.catch(() => {
|
||||
error.value = true;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
const onRefresh = () => {
|
||||
refreshing.value = true;
|
||||
onLoad();
|
||||
};
|
||||
onLoad();
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.empty-d {
|
||||
height: 90%;
|
||||
padding-top: 50%;
|
||||
}
|
||||
:deep(.van-cell__title) {
|
||||
background-color: #f5f7fb;
|
||||
flex: none !important;
|
||||
}
|
||||
:deep(.van-cell) {
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
font-size: 16px;
|
||||
padding-bottom: 5px !important;
|
||||
color: rgba(119, 132, 158, 1);
|
||||
background-color: #f5f7fb !important;
|
||||
}
|
||||
:deep(.van-collapse-item__content) {
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
padding: 0 10px 0 15px;
|
||||
background-color: #f5f7fb !important;
|
||||
}
|
||||
:deep(.van-collapse-item) {
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
:deep(.van-hairline--top-bottom) {
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.outer-d {
|
||||
height: 100%;
|
||||
background-color: #f5f7fb;
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.van-collapse-item-d {
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
font-size: 15px;
|
||||
background: #ffffff;
|
||||
margin-bottom: 10px;
|
||||
.timer{
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
//.middle-d {
|
||||
// padding: 10px 0 0;
|
||||
// > div {
|
||||
// border-radius: 5px;
|
||||
// padding: 10px 17px;
|
||||
// border: 1px solid rgba(230, 230, 234, 1);
|
||||
// margin-bottom: 10px;
|
||||
// > :nth-child(1) {
|
||||
// color: #21bebd;
|
||||
// font-size: 19px;
|
||||
// margin-right: 10px;
|
||||
// font-weight: bold;
|
||||
// }
|
||||
// > :nth-child(2) {
|
||||
// color: #000000;
|
||||
// font-weight: bold;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
.bottom-d {
|
||||
border: 1px solid rgba(224, 224, 224, 1);
|
||||
border-bottom: none;
|
||||
.bottom-d-item {
|
||||
display: flex;
|
||||
border-bottom: 1px solid rgba(224, 224, 224, 1);
|
||||
> div {
|
||||
padding: 10px 17px;
|
||||
font-size: 15px;
|
||||
}
|
||||
> :nth-child(1) {
|
||||
background-color: #f0f0f0;
|
||||
width: 40%;
|
||||
color: #333333;
|
||||
}
|
||||
> :nth-child(2) {
|
||||
text-align: right;
|
||||
width: 60%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,163 @@
|
||||
<template>
|
||||
<div class="outer-d" v-if="props.info?.questionCodeList">
|
||||
<div>
|
||||
<div class="van-collapse-item-d">
|
||||
<div style="color: rgba(88, 98, 117, 1); font-size: 16px">
|
||||
评估时间:{{ moment(info?.createTime).format('YYYY-MM-DD HH:mm:ss') }}
|
||||
</div>
|
||||
<!-- <div style="font-size: 16px; font-weight: bold; color: #000000; padding: 10px 0 12px"> 测评量表 </div>-->
|
||||
<!-- <div class="middle-d">-->
|
||||
<!-- <div v-for="(item, i) in props.info?.questionCodeList || []" :key="`questionCodeList${i}`">-->
|
||||
<!-- <span>{{ i + 1 }}</span>-->
|
||||
<!-- <span>{{ item }}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="props.info?.moduleList">
|
||||
<div class="van-collapse-item-d">
|
||||
<div style="font-size: 16px; font-weight: bold; color: #000000; padding: 10px 0 12px"> 分析模块 </div>
|
||||
<div class="table-outer-d">
|
||||
<div class="table-th">
|
||||
<div>模块名称</div>
|
||||
<div>计分</div>
|
||||
<div>等级</div>
|
||||
</div>
|
||||
<div v-for="(item, i) in props.info?.moduleList || []" :key="`moduleList${i}`" class="table-td">
|
||||
<div>{{ item?.moduleName || '-' }}</div>
|
||||
<div>{{ item?.score === '-' ? item?.score : parseFloat(item.score) }}</div>
|
||||
<div>{{ item?.rating || '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="props.info?.moduleSuggestList">
|
||||
<div class="van-collapse-item-d">
|
||||
<div style="font-size: 16px; font-weight: bold; color: #000000; padding: 10px 0 0"> 指导意见 </div>
|
||||
<div class="suggest-d" v-for="(item, i) in props.info?.moduleSuggestList || []" :key="`moduleSuggestList${i}`">
|
||||
<div :style="{ color: item?.color || '' }">{{ item?.rating || '-' }}</div>
|
||||
<div>{{ item?.suggest || '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="props.empty" class="empty-d">
|
||||
<van-empty description="暂无数据" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import moment from 'moment';
|
||||
|
||||
const props = defineProps({
|
||||
info: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
empty: {
|
||||
type: Boolean,
|
||||
default: () => false,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.empty-d {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.outer-d {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: #f5f7fb;
|
||||
}
|
||||
|
||||
.van-collapse-item-d {
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
background: #ffffff;
|
||||
margin-bottom: 10px;
|
||||
//.middle-d {
|
||||
// > div {
|
||||
// border-radius: 5px;
|
||||
// padding: 10px 17px;
|
||||
// border: 1px solid rgba(230, 230, 234, 1);
|
||||
// margin-bottom: 10px;
|
||||
// > :nth-child(1) {
|
||||
// color: #21bebd;
|
||||
// font-size: 19px;
|
||||
// margin-right: 10px;
|
||||
// font-weight: bold;
|
||||
// }
|
||||
// > :nth-child(2) {
|
||||
// color: #000000;
|
||||
// font-weight: bold;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
.table-outer-d {
|
||||
> div {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
border: 1px solid #e0e0e0ff;
|
||||
> div {
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
.table-th {
|
||||
background-color: rgba(240, 240, 240, 1);
|
||||
> div {
|
||||
border-right: 1px solid #e0e0e0ff;
|
||||
width: calc(100% / 3);
|
||||
text-align: center;
|
||||
color: #333333;
|
||||
&:nth-child(3) {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
.table-td {
|
||||
border-top: none;
|
||||
border-right: none;
|
||||
&:nth-child(1) {
|
||||
border-top: 1px solid #e0e0e0ff;
|
||||
}
|
||||
> div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-right: 1px solid #e0e0e0ff;
|
||||
width: calc(100% / 3);
|
||||
text-align: center;
|
||||
&:nth-child(3) {
|
||||
justify-content: flex-start;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.suggest-d {
|
||||
background-color: #f3f5f9ff;
|
||||
border-radius: 20px;
|
||||
padding: 20px;
|
||||
margin-top: 10px;
|
||||
&:nth-child(1) {
|
||||
margin-top: 0;
|
||||
}
|
||||
> div {
|
||||
&:nth-child(1) {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
font-size: 14px;
|
||||
color: #77849eff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<div class="outer-d">
|
||||
<div class="top-button">
|
||||
<van-tabs v-model:active="active" type="card" sticky>
|
||||
<van-tab title="全部">
|
||||
<task-list />
|
||||
</van-tab>
|
||||
<van-tab title="已完成">
|
||||
<task-list status="1" />
|
||||
</van-tab>
|
||||
<van-back-top />
|
||||
</van-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import TaskList from '/@/views/23psychology/psychic/task/taskList.vue';
|
||||
|
||||
const active = ref();
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.outer-d {
|
||||
background-color: #f5f7fb;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
div {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:deep(.van-tabs__wrap) {
|
||||
background-color: #fff;
|
||||
padding: 10px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
:deep(.van-tab--card) {
|
||||
border: none;
|
||||
}
|
||||
|
||||
:deep(.van-tabs__nav--card) {
|
||||
height: auto;
|
||||
border-width: 2px;
|
||||
border-color: #e8ebf2ff !important;
|
||||
}
|
||||
|
||||
:deep(.van-tab--active) {
|
||||
color: #252535 !important;
|
||||
background-color: #ffffff !important;
|
||||
}
|
||||
|
||||
:deep(.van-tab--card) {
|
||||
color: #77849eff;
|
||||
background-color: #f3f5f8;
|
||||
padding: 10px 0;
|
||||
}
|
||||
:deep(.van-tabs__content) {
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
.top-button {
|
||||
height: 100%;
|
||||
:deep(.van-tabs) {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
:deep(.van-tabs__content) {
|
||||
height: calc(100% - 64px) !important;
|
||||
}
|
||||
:deep(.van-tab__panel) {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,171 @@
|
||||
<template>
|
||||
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||
<div style="height: 100%; overflow: auto">
|
||||
<van-list
|
||||
v-model:loading="loading"
|
||||
:finished="finished"
|
||||
:finished-text="list.length > 0 ? '没有更多了' : ''"
|
||||
@load="onLoad"
|
||||
v-model:error="error"
|
||||
error-text="请求失败,点击重新加载"
|
||||
>
|
||||
<tempalte v-if="list.length > 0">
|
||||
<div v-for="it in list" :key="`collapse${it}`">
|
||||
<div class="top" v-if="it" @click.native="toDetail(it)">
|
||||
<div class="time">
|
||||
<div>
|
||||
<van-icon name="clock-o" size="16" color="#21BEBD" />
|
||||
<span> {{ moment(it?.startTime).format('YYYY.MM.DD') }} ~ {{ moment(it?.endTime).format('MM.DD') }}</span>
|
||||
</div>
|
||||
<div :style="{ color: it?.status == 0 ? '#F36510' : '#52C41A' }">
|
||||
{{ it?.status == 0 ? '待测评' : '已完成' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="title">
|
||||
<img :src="it?.state == '1' ? isProgressPng : isOverPng" alt="" />
|
||||
<span>{{ it?.planName }}</span>
|
||||
</div>
|
||||
<div class="info">已参加{{ it?.actualAttendNumber || 0 }}人</div>
|
||||
<div style="display: flex; justify-content: space-between; padding-top: 10px">
|
||||
<span style="color: #252535"> 共包含{{ it?.queCode ? it?.queCode.split(',').length : 0 }}张量表 </span>
|
||||
<span style="color: #21bebd"> {{ it?.queSum || 0 }}/{{ it?.queCode ? it?.queCode.split(',').length : 0 }} </span>
|
||||
</div>
|
||||
<div style="margin-top: 10px">
|
||||
<van-progress
|
||||
color="#21BEBD"
|
||||
stroke-width="8"
|
||||
pivot-text=""
|
||||
:percentage="parseInt(((it?.queSum || 0) / (it?.queCode ? it?.queCode.split(',').length : 0)) * 100)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</tempalte>
|
||||
<div class="no-data" v-if="list.length === 0 && finished">
|
||||
<Empty :url="emptyIcon" :imageSize="[200, 160]" />
|
||||
</div>
|
||||
</van-list>
|
||||
</div>
|
||||
</van-pull-refresh>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { psychologyPlanListApi } from '/@/views/23psychology/psychic/psychologyApi';
|
||||
import { showFailToast } from 'vant';
|
||||
import { useRouter } from 'vue-router';
|
||||
import isProgressPng from '/@/assets/images/psychiology/isProgress.png';
|
||||
import isOverPng from '/@/assets/images/psychiology/isOver.png';
|
||||
import moment from 'moment';
|
||||
import Empty from '/@/components/Empty.vue';
|
||||
import emptyIcon from '/@/assets/images/interveneEmpty.png';
|
||||
|
||||
const props = defineProps({
|
||||
status: {
|
||||
type: String,
|
||||
default: () => '',
|
||||
},
|
||||
});
|
||||
|
||||
const list = ref<any[]>([]); // 列表
|
||||
const refreshing = ref(false); // 刷新状态
|
||||
const loading = ref(false); // loading 状态
|
||||
const finished = ref(false); // 是否完成
|
||||
const error = ref(false); // 是否报错
|
||||
const pageInfo = ref({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
function toDetail(it: any) {
|
||||
router.push({
|
||||
path: '/psychology-progress',
|
||||
query: { id: it?.id },
|
||||
});
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
if (refreshing.value) {
|
||||
list.value = [];
|
||||
refreshing.value = false;
|
||||
finished.value = false;
|
||||
error.value = false;
|
||||
loading.value = true;
|
||||
pageInfo.value.pageNo = 1;
|
||||
}
|
||||
loading.value = true;
|
||||
psychologyPlanListApi({ ...pageInfo.value, status: props.status })
|
||||
.then((res) => {
|
||||
const { success, result, message: msg } = res;
|
||||
if (success) {
|
||||
list.value = result.records;
|
||||
if (pageInfo.value.pageNo === result.current) {
|
||||
finished.value = true;
|
||||
} else {
|
||||
pageInfo.value.pageNo += 1;
|
||||
}
|
||||
} else {
|
||||
error.value = true;
|
||||
showFailToast(msg);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
error.value = true;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
function onRefresh() {
|
||||
refreshing.value = true;
|
||||
onLoad();
|
||||
}
|
||||
|
||||
onLoad();
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.no-data {
|
||||
width: 100%;
|
||||
padding-top: 50%;
|
||||
}
|
||||
.top {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
margin-top: 20px;
|
||||
.time {
|
||||
font-size: 15px;
|
||||
border-bottom: 1px solid #eaecf1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 15px;
|
||||
span {
|
||||
margin-left: 8px;
|
||||
color: #77849e;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
padding: 15px;
|
||||
.title {
|
||||
font-size: 17px;
|
||||
color: #252535;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
img {
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
margin-right: 7px;
|
||||
}
|
||||
}
|
||||
.info {
|
||||
font-size: 14px;
|
||||
color: #77849e;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<div class="down-container">
|
||||
<div class="ios" @click="down('ios')"></div>
|
||||
<div class="android" @click="down('android')"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { showToast } from 'vant';
|
||||
function isType() {
|
||||
let userAgent = navigator.userAgent || navigator.vendor || window.opera;
|
||||
if (userAgent.match(/iPad/i) || userAgent.match(/iPhone/i) || userAgent.match(/iPod/i)) {
|
||||
return 'ios';
|
||||
} else if (userAgent.match(/Android/i)) {
|
||||
return 'android';
|
||||
}
|
||||
}
|
||||
function androidLoad() {
|
||||
window.open('https://api.cqygjk.com/health-system/api/anon/sys/toAppDown?pkg=com.sw.healthyclients&type=1');
|
||||
}
|
||||
function iosLoad() {
|
||||
// 响应App store
|
||||
const appID = '6483208440';
|
||||
const link = 'itms-apps://itunes.apple.com/app/id' + appID;
|
||||
window.location.href = 'https://api.cqygjk.com/health-system/api/anon/sys/toAppDown?pkg=com.escortUP.EscortProject&type=2';
|
||||
}
|
||||
function down(type: string) {
|
||||
if (isType() === 'ios') {
|
||||
if (type === 'ios') {
|
||||
iosLoad();
|
||||
} else {
|
||||
showToast('请选择IOS安装包进行下载!');
|
||||
}
|
||||
} else {
|
||||
if (type === 'ios') {
|
||||
showToast('请选择Android安装包进行下载!');
|
||||
} else {
|
||||
androidLoad();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.down-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url('/@/assets/images/download/bg.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.android {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background: url('/@/assets/images/download/android.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
margin-top: 14%;
|
||||
}
|
||||
.ios {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background: url('/@/assets/images/download/ios.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<div class="drink-box">
|
||||
<div class="text">
|
||||
<a-select v-model:value="beerInfo.beerValue" :placeholder="'请选择'" :options="beerType" @change="changeTime"></a-select>
|
||||
<a-input type="number" v-model:value="beerInfo.valueTime" placeholder="请输入" :min="0" suffix="次/周" @change="changeTime" />
|
||||
<a-input type="number" v-model:value="beerInfo.valueMach" placeholder="请输入" :min="0" suffix="两/次" @change="changeTime" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
const props = defineProps({
|
||||
beerKeys: String,
|
||||
beerInfo: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
beerValue: '',
|
||||
valueTime: '',
|
||||
valueMach: '',
|
||||
};
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const beerType = ref([
|
||||
{
|
||||
label: '红酒',
|
||||
value: 'wine',
|
||||
},
|
||||
{
|
||||
label: '黄酒',
|
||||
value: 'yellowWine',
|
||||
},
|
||||
{
|
||||
label: '啤酒',
|
||||
value: 'beer',
|
||||
},
|
||||
{
|
||||
label: '白酒',
|
||||
value: 'liquors',
|
||||
},
|
||||
{
|
||||
label: '其他',
|
||||
value: 'otherWine',
|
||||
},
|
||||
]);
|
||||
const beerInfo = ref({
|
||||
beerKeys: props.beerKeys,
|
||||
beerValue: props.beerInfo?.beerValue,
|
||||
valueTime: props.beerInfo?.valueTime,
|
||||
valueMach: props.beerInfo?.valueMach,
|
||||
});
|
||||
const emit = defineEmits(['change']);
|
||||
function changeTime() {
|
||||
emit('change', beerInfo.value);
|
||||
}
|
||||
function changeMach() {}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.drink-box {
|
||||
.text {
|
||||
:deep(.ant-select) {
|
||||
margin: 10px;
|
||||
height: 54px;
|
||||
padding: 5px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 5px;
|
||||
background: #117474;
|
||||
border: 1px solid #72bcbc;
|
||||
color: #83cdcd;
|
||||
}
|
||||
:deep(.ant-select-selector) {
|
||||
background: #117474;
|
||||
border: none;
|
||||
}
|
||||
:deep(.ant-select-arrow) {
|
||||
color: #83cdcd;
|
||||
}
|
||||
:deep(.ant-input-affix-wrapper) {
|
||||
color: #83cdcd;
|
||||
border: 1px solid #72bcbc;
|
||||
}
|
||||
:deep(.ant-input) {
|
||||
color: #83cdcd;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<!-- <div>-->
|
||||
<!-- <div>-->
|
||||
<!-- <span>{{ topicTitle }}(单选)</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- <a-radio-group v-model:value="checkedList" @change="changeVal">-->
|
||||
<!-- <template v-for="(item, index) in topicInfo" :key="'info' + index">-->
|
||||
<!-- <div>-->
|
||||
<!-- <a-radio :value="item.value">{{ item.title }}{{ item.value }}</a-radio>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- </a-radio-group>-->
|
||||
<div>
|
||||
<span style="font-size: 16px; margin-left: 10px; font-weight: bold; color: #ffffff">{{ topicTitle }}</span>
|
||||
<template v-for="(item, index) in topicInfo" :key="'info' + index">
|
||||
<div :class="[checkedListC !== item.code + '' ? 'red-g' : 'blue-b']" class="item-div" @click="clickD(item)"> {{ item.title }}</div>
|
||||
</template>
|
||||
</div>
|
||||
<!-- </div>-->
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watchEffect } from 'vue';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
|
||||
const emit = defineEmits(['changeRVal', 'smoking']);
|
||||
|
||||
const props = defineProps({
|
||||
dataIndex: propTypes.array.def([]), // 下标
|
||||
pVal: propTypes.string.def(''), // 返回值
|
||||
pCVal: propTypes.string.def(''), // 返回值
|
||||
topicTitle: propTypes.string.def(''), // 题目
|
||||
topicInfo: propTypes.array.def([]), // 选项
|
||||
orderNo: propTypes.number.def(0), // 选项
|
||||
});
|
||||
|
||||
// 单选的值
|
||||
const checkedList = ref<string>(props.pVal);
|
||||
const checkedListC = ref<string>(props.pCVal);
|
||||
|
||||
const clickD = (item: object) => {
|
||||
if (item.code + '' === checkedListC.value) {
|
||||
checkedList.value = '';
|
||||
checkedListC.value = '';
|
||||
} else {
|
||||
checkedList.value = item.value;
|
||||
checkedListC.value = item.code + '';
|
||||
}
|
||||
emit('changeRVal', { dataIndex: props.dataIndex, answer: checkedList.value, answerCode: checkedListC.value });
|
||||
|
||||
if (props.orderNo === 8 && sessionStorage.getItem('type') === '0') {
|
||||
emit('smoking', { dataIndex: props.dataIndex, answer: checkedList.value, answerCode: checkedListC.value });
|
||||
}
|
||||
};
|
||||
// const checkedList = ref<number>(props.pVal);
|
||||
//
|
||||
// const changeVal = (e: any) => {
|
||||
// checkedList.value = e?.target?.value ?? e;
|
||||
// emit('changeRVal', { dataIndex: props.dataIndex, checkedList });
|
||||
// };
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.red-g {
|
||||
border: 1px solid #72bcbc;
|
||||
color: #83cdcd;
|
||||
}
|
||||
.blue-b {
|
||||
border: 2px solid #bffeff;
|
||||
color: #bffeff;
|
||||
}
|
||||
.item-div {
|
||||
margin: 10px;
|
||||
height: 54px;
|
||||
padding: 5px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 5px;
|
||||
background: #117474;
|
||||
}
|
||||
.toolbar {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,3 @@
|
||||
import { get, post } from '/@/views/mobile/api/api';
|
||||
|
||||
export const surveySubmit = (params) => post(`health-archives/archives/app/smoking/survey/submit`, params);
|
||||
@@ -0,0 +1,275 @@
|
||||
<template>
|
||||
<div class="box" ref="box">
|
||||
<div class="title">
|
||||
<span class="line line-left"></span>
|
||||
<span class="name">吸烟</span>
|
||||
<span class="line line-right"></span>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div>
|
||||
<radio-topic
|
||||
ref="radioTopic"
|
||||
topicTitle="1、吸烟状况?"
|
||||
@changeRVal="changeRVal"
|
||||
:topicInfo="[
|
||||
{ title: '吸烟', code: 0 },
|
||||
{ title: '不吸烟', code: 1 },
|
||||
{ title: '已戒烟', code: 2 },
|
||||
]"
|
||||
/>
|
||||
</div>
|
||||
<div class="text">
|
||||
<span style="font-size: 16px; margin-left: 10px; font-weight: bold; color: #ffffff">2、每日根数?</span>
|
||||
<a-input type="number" v-model:value="roots" placeholder="请输入" :min="0" suffix="根/每天" @change="changeSmokeNum" />
|
||||
</div>
|
||||
<div class="text">
|
||||
<span style="font-size: 16px; margin-left: 10px; font-weight: bold; color: #ffffff">3、开始吸烟年龄?</span>
|
||||
<a-input type="number" v-model:value="smokingAge" placeholder="请输入" :min="0" suffix="岁" @change="changeAgeNum" />
|
||||
</div>
|
||||
<div>
|
||||
<radio-topic
|
||||
ref="radioTopic"
|
||||
topicTitle="4、和您在一起工作的人是否有人吸烟?"
|
||||
@changeRVal="changePassive"
|
||||
:topicInfo="[
|
||||
{ title: '是', code: 1 },
|
||||
{ title: '否', code: 0 },
|
||||
]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title">
|
||||
<span class="line line-left"></span>
|
||||
<span class="name">饮酒</span>
|
||||
<span class="line line-right"></span>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div>
|
||||
<radio-topic
|
||||
ref="radioTopic"
|
||||
topicTitle="1、饮酒状况?"
|
||||
@changeRVal="changeDrink"
|
||||
:topicInfo="[
|
||||
{ title: '饮酒', code: 0 },
|
||||
{ title: '不饮酒', code: 1 },
|
||||
{ title: '已戒酒', code: 2 },
|
||||
]"
|
||||
/>
|
||||
</div>
|
||||
<div class="text">
|
||||
<span style="font-size: 16px; margin-left: 10px; font-weight: bold; color: #ffffff">2、饮酒种类以及频次?</span>
|
||||
<div v-for="(item, index) in Object.keys(beerArr)" :key="index">
|
||||
<div class="beer">
|
||||
<span class="beer-one">种类{{ index + 1 }}</span>
|
||||
<span class="beer-two" @click="handleAddBeer" v-if="index == 0">
|
||||
<plus-circle-outlined />
|
||||
添加种类
|
||||
</span>
|
||||
<span class="beer-two" v-if="index !== 0" @click="handledeleteBeer(item)"><close-circle-filled /> </span>
|
||||
</div>
|
||||
<DrinkType :key="`beer-${item}`" :beerKeys="item" :beerInfo="beerArr[item]" @change="(e) => preData(e, item)"></DrinkType>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<a-button class="sub-btn" @click="handleSubmit">提交</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { PlusCircleOutlined, CloseCircleFilled } from '@ant-design/icons-vue';
|
||||
import RadioTopic from '/@/views/archivesManage/smokeOrDrink/components/radio.vue';
|
||||
import DrinkType from '/@/views/archivesManage/smokeOrDrink/components/drinkType.vue';
|
||||
import { ref } from 'vue';
|
||||
import { surveySubmit } from '/@/views/archivesManage/smokeOrDrink/index.ts';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { showToast, showConfirmDialog } from 'vant';
|
||||
const roots = ref();
|
||||
const smokingAge = ref();
|
||||
const radioTopic = ref();
|
||||
const box = ref();
|
||||
const beerArr = ref<any>({
|
||||
'1arr': {
|
||||
beerValue: '',
|
||||
valueTime: '',
|
||||
valueMach: '',
|
||||
},
|
||||
});
|
||||
const beerNum = ref(1);
|
||||
function changeSmokeNum() {
|
||||
if (roots.value < 0) {
|
||||
roots.value = 0;
|
||||
}
|
||||
}
|
||||
function changeAgeNum() {
|
||||
if (smokingAge.value < 0) {
|
||||
smokingAge.value = 0;
|
||||
}
|
||||
}
|
||||
const smokingStatus = ref();
|
||||
function changeRVal(data: object) {
|
||||
console.log(data);
|
||||
smokingStatus.value = data.answerCode;
|
||||
}
|
||||
const passiveSmoking = ref();
|
||||
function changePassive(data: object) {
|
||||
console.log(data);
|
||||
console.log(data.answerCode);
|
||||
passiveSmoking.value = data.answerCode;
|
||||
}
|
||||
const drinkStatus = ref();
|
||||
function changeDrink(data: object) {
|
||||
drinkStatus.value = data.answerCode;
|
||||
}
|
||||
function preData(i, v) {
|
||||
beerArr.value[i?.beerKeys] = i;
|
||||
}
|
||||
function handleAddBeer() {
|
||||
beerNum.value++;
|
||||
beerArr.value[beerNum.value + 'arr'] = {};
|
||||
}
|
||||
async function handleSubmit() {
|
||||
if (!smokingStatus.value || !roots.value || !smokingAge.value || !passiveSmoking.value || !drinkStatus.value) {
|
||||
return showToast('问卷未填写完整');
|
||||
}
|
||||
|
||||
const result = {};
|
||||
for (const key in beerArr.value) {
|
||||
const item = beerArr.value[key];
|
||||
const value = item.beerValue;
|
||||
if (!value) {
|
||||
return showToast('问卷未填写完整');
|
||||
}
|
||||
if (!result[value]) {
|
||||
result[value] = { frequency: 0, drinkUnit: 0 };
|
||||
}
|
||||
result[value].frequency += parseInt(item.valueTime);
|
||||
result[value].drinkUnit += parseInt(item.valueMach);
|
||||
}
|
||||
const params = {
|
||||
smokingStatus: smokingStatus.value,
|
||||
roots: roots.value,
|
||||
smokingAge: smokingAge.value,
|
||||
passiveSmoking: passiveSmoking.value,
|
||||
drinkStatus: drinkStatus.value,
|
||||
...result,
|
||||
};
|
||||
showConfirmDialog({
|
||||
message: '保证问卷填写真实,并确认提交?',
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
getContainer: box.value,
|
||||
})
|
||||
.then(async () => {
|
||||
// on confirm
|
||||
await surveySubmit(params);
|
||||
})
|
||||
.catch(() => {
|
||||
// on cancel
|
||||
});
|
||||
// await surveySubmit(params);
|
||||
}
|
||||
function handledeleteBeer(value) {
|
||||
let b = beerArr.value;
|
||||
delete b[value];
|
||||
beerArr.value = b;
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.box {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
background: #117474;
|
||||
padding: 0 0 15%;
|
||||
:deep(.van-dialog) {
|
||||
background: #117474;
|
||||
}
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.name {
|
||||
width: 39px;
|
||||
font-weight: bold;
|
||||
font-size: 21px;
|
||||
color: #bffeff;
|
||||
white-space: nowrap;
|
||||
margin: 0 10px;
|
||||
}
|
||||
.line {
|
||||
display: inline-block;
|
||||
width: 125px;
|
||||
height: 2px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
.line-left {
|
||||
background: linear-gradient(-90deg, #bffeff 0%, rgba(191, 254, 255, 0) 100%);
|
||||
}
|
||||
.line-right {
|
||||
background: linear-gradient(90deg, #bffeff 0%, rgba(191, 254, 255, 0) 100%);
|
||||
}
|
||||
}
|
||||
.content {
|
||||
width: 90%;
|
||||
background: #0c5a5a;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #72bcbc;
|
||||
margin: 10px auto;
|
||||
min-height: 100px;
|
||||
padding: 10px;
|
||||
.text {
|
||||
:deep(.ant-input-affix-wrapper) {
|
||||
background: #117474;
|
||||
height: 54px;
|
||||
margin: 10px;
|
||||
height: 54px;
|
||||
padding: 5px 10px;
|
||||
width: 95%;
|
||||
border-radius: 5px;
|
||||
}
|
||||
:deep(.ant-input) {
|
||||
background: #117474;
|
||||
color: #bffeff;
|
||||
}
|
||||
:deep(.ant-input-suffix) {
|
||||
color: #bffeff;
|
||||
}
|
||||
}
|
||||
.beer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 10px;
|
||||
.beer-one {
|
||||
color: #ffffff;
|
||||
}
|
||||
.beer-two {
|
||||
color: #bffeff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
height: 7%;
|
||||
background: #0d5a5a;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px 0;
|
||||
.sub-btn {
|
||||
width: 80%;
|
||||
height: 90%;
|
||||
color: #117474;
|
||||
background: #cfffff;
|
||||
border-radius: 23px;
|
||||
}
|
||||
:deep(.ant-btn:hover, .ant-btn:focus) {
|
||||
color: #117474;
|
||||
background: #cfffff;
|
||||
border-color: #cfffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,8 @@
|
||||
import { get, post } from '/@/views/mobile/api/api';
|
||||
const prefix: string = import.meta.env.VITE_GLOB_APP_PREFIX || '';
|
||||
|
||||
export const homeApi = (params) => get(`${prefix}/api/health-diabetes/diabetes/glucose/home`, params);
|
||||
// 历史记录
|
||||
export const recordApi = (params) => get(`${prefix}/api/health-diabetes/diabetes/glucose/record`, params);
|
||||
// 录入血糖
|
||||
export const fillApi = (params) => post(`${prefix}/api/health-diabetes/diabetes/glucose/fill`, params);
|
||||
@@ -0,0 +1,355 @@
|
||||
<template>
|
||||
<div class="bloodGlucose">
|
||||
<div class="bloodGlucose-1">
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<img src="../../assets/images/health-interventions/blood.png" alt="" />
|
||||
</div>
|
||||
血糖
|
||||
</div>
|
||||
<div :class="descColor">{{ homeInfo.latest.desc !== '' ? homeInfo.latest.desc : '--' }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<span>{{ homeInfo.latest.value }}</span>
|
||||
mmol/L
|
||||
</div>
|
||||
<div>{{ homeInfo.latest.time !== null ? homeInfo.latest.time : '--' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bloodGlucose-2">
|
||||
<div>指标解析</div>
|
||||
<div>{{ homeInfo.latest.analyze !== '' ? homeInfo.latest.analyze : '暂无数据' }}</div>
|
||||
</div>
|
||||
<div class="bloodGlucose-3">
|
||||
<div>
|
||||
<div>近7次记录</div>
|
||||
<div @click="openMoreRecord">更多记录 ></div>
|
||||
</div>
|
||||
<div>
|
||||
<div ref="chartRef"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="vaccine-button">
|
||||
<div class="button-text" @click="openManualEntry">手动录入</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import * as echarts from 'echarts';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { homeApi } from './blood';
|
||||
import { newPageParams, openPage } from '/@/hooks/openPage';
|
||||
let homeInfo = ref({
|
||||
latest: {
|
||||
desc: '',
|
||||
value: '',
|
||||
time: '',
|
||||
analyze: '',
|
||||
},
|
||||
lineCharts: {
|
||||
x: [],
|
||||
y: [],
|
||||
},
|
||||
});
|
||||
let descColor = ref('');
|
||||
onMounted(() => {
|
||||
getHomeInfo();
|
||||
});
|
||||
const getHomeInfo = () => {
|
||||
homeApi({}).then((res: any) => {
|
||||
if (res.code === 200) {
|
||||
let { x, y } = res.result.lineCharts;
|
||||
homeInfo.value = res.result;
|
||||
setChart(x, y);
|
||||
setStatus(res.result);
|
||||
}
|
||||
});
|
||||
};
|
||||
// 血压颜色状态
|
||||
function setStatus(val: object) {
|
||||
let desc = val?.latest?.desc;
|
||||
if (desc !== '') {
|
||||
switch (desc) {
|
||||
case '偏高':
|
||||
descColor.value = 'highColor';
|
||||
break;
|
||||
case '正常':
|
||||
descColor.value = 'normalColor';
|
||||
break;
|
||||
case '偏低':
|
||||
descColor.value = 'lowColor';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 打开更多记录
|
||||
const openMoreRecord = () => {
|
||||
openPage('/bloodGlucoseMoreRecord', newPageParams());
|
||||
};
|
||||
|
||||
// 打开手动录入
|
||||
const openManualEntry = () => {
|
||||
openPage('/bloodGlucoseManualEntry', newPageParams());
|
||||
};
|
||||
|
||||
const chartRef = ref<HTMLElement>();
|
||||
const myChart = ref<any>();
|
||||
const setChart = (xData, yData) => {
|
||||
myChart.value = echarts.init(chartRef.value!);
|
||||
myChart.value.setOption({
|
||||
graphic: {
|
||||
type: 'text',
|
||||
left: 'center',
|
||||
top: 'center',
|
||||
silent: true,
|
||||
invisible: xData.length > 0, // 有数据就隐藏
|
||||
style: {
|
||||
fill: '#999',
|
||||
text: '暂无数据',
|
||||
fontSize: '15',
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xData,
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#E0E0E0',
|
||||
},
|
||||
},
|
||||
axisTick: {
|
||||
lineStyle: {
|
||||
color: '#E0E0E0',
|
||||
},
|
||||
},
|
||||
axisLabel: {
|
||||
textStyle: {
|
||||
color: '#333333',
|
||||
},
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
top: '5%',
|
||||
left: '5%',
|
||||
right: '5%',
|
||||
bottom: 0,
|
||||
containLabel: true,
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
show: true,
|
||||
textStyle: {
|
||||
color: '#333333',
|
||||
},
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#E0E0E0',
|
||||
},
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: yData,
|
||||
type: 'line',
|
||||
symbol: 'circle',
|
||||
symbolSize: 0,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
lineStyle: {
|
||||
color: '#13C2C2',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import '../../assets/less/index';
|
||||
.normalColor {
|
||||
color: #74b84e;
|
||||
}
|
||||
.lowColor {
|
||||
color: #13c4c4;
|
||||
}
|
||||
.highColor {
|
||||
color: #c93432;
|
||||
}
|
||||
.bloodGlucose {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
overflow-y: scroll;
|
||||
padding: 10px 15px 0;
|
||||
box-sizing: border-box;
|
||||
background-color: @card-gray;
|
||||
|
||||
.bloodGlucose-1 {
|
||||
width: 100%;
|
||||
padding: 15px 15px 12px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 10px;
|
||||
background-color: @card-fff;
|
||||
|
||||
> div:first-of-type {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
margin-bottom: 12px;
|
||||
justify-content: space-between;
|
||||
|
||||
> div:first-of-type {
|
||||
color: #333333;
|
||||
height: 30px;
|
||||
font-size: 13px;
|
||||
line-height: 30px;
|
||||
display: flex;
|
||||
|
||||
> div {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
margin-right: 5px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
height: 30px;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
line-height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
width: 100%;
|
||||
height: 18px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
|
||||
> div:first-of-type {
|
||||
height: 18px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
|
||||
> span {
|
||||
color: #333333;
|
||||
font-size: 17px;
|
||||
font-weight: bold;
|
||||
margin-right: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
color: #999999;
|
||||
height: 18px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
line-height: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bloodGlucose-2 {
|
||||
width: 100%;
|
||||
padding: 20px 15px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 10px;
|
||||
background-color: @card-fff;
|
||||
|
||||
> div:first-of-type {
|
||||
width: 100%;
|
||||
height: 13px;
|
||||
font-size: 13px;
|
||||
font-weight: bolder;
|
||||
color: #333333;
|
||||
line-height: 26px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
width: 100%;
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.bloodGlucose-3 {
|
||||
width: 100%;
|
||||
border-radius: 10px;
|
||||
padding: 22px 0 25px;
|
||||
margin-bottom: 25px;
|
||||
background-color: @card-fff;
|
||||
|
||||
> div:first-of-type {
|
||||
width: 100%;
|
||||
height: 14px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 20px;
|
||||
justify-content: space-between;
|
||||
|
||||
> div:first-of-type {
|
||||
color: #333333;
|
||||
height: 14px;
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
color: #999999;
|
||||
height: 14px;
|
||||
font-size: 12px;
|
||||
line-height: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
width: 100%;
|
||||
height: 240px;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.vaccine-button {
|
||||
height: 40px;
|
||||
.button-text {
|
||||
height: 40px;
|
||||
flex: 1;
|
||||
.flex-center();
|
||||
margin: 0 10%;
|
||||
.footerButton();
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,241 @@
|
||||
<template>
|
||||
<div class="manualEntry">
|
||||
<div class="manua-container">
|
||||
<div class="manualEntry-1">
|
||||
<div>
|
||||
<div>测量时间</div>
|
||||
<div>
|
||||
<div>
|
||||
<div class="year" @click="openTime(1)">{{ picker.time === '' ? '请选择年月日' : picker.time }}</div>
|
||||
<div class="time" @click="openTime(2)">{{ picker.divisionTime === '' ? '请选择时分' : picker.divisionTime }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>血糖</div>
|
||||
<div>
|
||||
<div>
|
||||
<van-field type="number" placeholder="请输入血糖" v-model="manuaNum" @update:model-value="handleInput" />
|
||||
</div>
|
||||
<div>mmol/L</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="manualEntry-2">
|
||||
<p>空腹血糖标准值:3.9-6.1mmol/L</p>
|
||||
<p>餐后2小时血糖标准值:3.9-7.8mmol/L</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="vaccine-button">
|
||||
<div class="button-text" @click="handleSave">保存</div>
|
||||
</div>
|
||||
<van-popup :show="picker.show" round position="bottom">
|
||||
<van-date-picker
|
||||
v-if="timeType === 1"
|
||||
title="选择日期"
|
||||
:maxDate="picker.maxDate"
|
||||
@cancel="picker.show = false"
|
||||
@confirm="onConfirmPicker"
|
||||
/>
|
||||
<van-time-picker v-else title="选择时间" @cancel="picker.show = false" @confirm="onDivision" />
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { fillApi } from './blood';
|
||||
import { showSuccessToast, showFailToast } from 'vant';
|
||||
import moment from 'moment';
|
||||
import { useLoading } from '/@/utils/compUtils';
|
||||
import { destroyPage } from '/@/hooks/openPage';
|
||||
|
||||
const picker = ref({
|
||||
show: false,
|
||||
time: '',
|
||||
divisionTime: '',
|
||||
maxDate: new Date(),
|
||||
});
|
||||
const { loadingSpinner, loadingClose } = useLoading();
|
||||
const router = useRouter();
|
||||
const manuaNum = ref('');
|
||||
const timeType = ref();
|
||||
onMounted(() => {
|
||||
let today = new Date();
|
||||
let year = moment(today).format('YYYY');
|
||||
let month = moment(today).format('MM');
|
||||
let days = moment(today).format('DD');
|
||||
console.log(year, month, days);
|
||||
picker.value.maxDate = new Date(year, month, days);
|
||||
});
|
||||
function onConfirmPicker(e: { selectedValues: any }) {
|
||||
let value = e.selectedValues;
|
||||
picker.value.time = `${value[0]}-${value[1]}-${value[2]}`;
|
||||
picker.value.show = false;
|
||||
}
|
||||
function onDivision(e: { selectedValues: any }) {
|
||||
let value = e.selectedValues;
|
||||
picker.value.divisionTime = `${value[0]}:${value[1]}`;
|
||||
picker.value.show = false;
|
||||
}
|
||||
function handleInput(value: number) {
|
||||
manuaNum.value = value;
|
||||
}
|
||||
function handleSave() {
|
||||
let { time, divisionTime } = picker.value;
|
||||
if (time === '') {
|
||||
showFailToast({
|
||||
message: '请选择年月日',
|
||||
forbidClick: true,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (divisionTime === '') {
|
||||
showFailToast({
|
||||
message: '请选择时分',
|
||||
forbidClick: true,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (manuaNum.value === '') {
|
||||
showFailToast({
|
||||
message: '请输入血糖',
|
||||
forbidClick: true,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
loadingSpinner();
|
||||
fillApi({
|
||||
fillValue: manuaNum.value,
|
||||
createTime: `${time} ${divisionTime}`,
|
||||
}).then((res: any) => {
|
||||
if (res.code === 200) {
|
||||
showSuccessToast('保存成功');
|
||||
loadingClose();
|
||||
try {
|
||||
destroyPage();
|
||||
} catch {
|
||||
router.go(-1);
|
||||
}
|
||||
} else {
|
||||
showFailToast({
|
||||
message: res.data.msg,
|
||||
forbidClick: true,
|
||||
});
|
||||
loadingClose();
|
||||
}
|
||||
});
|
||||
}
|
||||
function openTime(type: number) {
|
||||
timeType.value = type;
|
||||
picker.value.show = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import '../../assets/less/index';
|
||||
|
||||
.manualEntry {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
padding-top: 10px;
|
||||
overflow-y: scroll;
|
||||
box-sizing: border-box;
|
||||
background-color: @card-gray;
|
||||
.manua-container {
|
||||
height: calc(100vh - 60px);
|
||||
.manualEntry-1 {
|
||||
width: 100%;
|
||||
padding: 0 15px;
|
||||
margin-bottom: 12px;
|
||||
box-sizing: border-box;
|
||||
background-color: @card-fff;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
> div:first-of-type {
|
||||
width: 100px;
|
||||
color: #333333;
|
||||
height: 50px;
|
||||
font-size: 14px;
|
||||
line-height: 50px;
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
flex: 1;
|
||||
width: 0;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
> div {
|
||||
color: #333333;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
line-height: 50px;
|
||||
font-size: 14px;
|
||||
|
||||
&:first-of-type {
|
||||
flex: 1;
|
||||
}
|
||||
.time {
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-size: 14px;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
//.arrow:after {
|
||||
// position: absolute;
|
||||
// right: 0;
|
||||
// top: 0;
|
||||
// bottom: 0;
|
||||
// width: 10px;
|
||||
// height: 10px;
|
||||
// border-left: 2px solid #b6b6b6;
|
||||
// border-top: 2px solid #b6b6b6;
|
||||
// transform: rotate(135deg);
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.manualEntry-2 {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
|
||||
> p {
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
color: #999999;
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.vaccine-button {
|
||||
height: 40px;
|
||||
.button-text {
|
||||
height: 40px;
|
||||
flex: 1;
|
||||
.flex-center();
|
||||
margin: 0 10%;
|
||||
.footerButton();
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div class="MoreRecord">
|
||||
<template v-if="list.length > 0">
|
||||
<div class="list" v-for="(item, index) in list" :key="index">
|
||||
<div class="times">{{ item.createTime }}</div>
|
||||
<div class="item">
|
||||
<div>
|
||||
<div>血糖</div>
|
||||
<div>{{ item.fillValue }}<span>mmo/L</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<van-empty v-else description="暂无数据" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { recordApi } from './blood';
|
||||
const list = ref([]);
|
||||
getHistory();
|
||||
function getHistory() {
|
||||
recordApi({}).then((res: any) => {
|
||||
list.value = res.result.records;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import '../../assets/less/index';
|
||||
|
||||
.MoreRecord {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
overflow-y: scroll;
|
||||
background-color: @card-gray;
|
||||
|
||||
.list {
|
||||
width: 100%;
|
||||
|
||||
.times {
|
||||
color: #999999;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
font-size: 12px;
|
||||
line-height: 32px;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
background-color: @card-fff;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
|
||||
> div {
|
||||
color: #333333;
|
||||
height: 50px;
|
||||
font-size: 14px;
|
||||
line-height: 50px;
|
||||
|
||||
> span {
|
||||
color: #999999;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<van-overlay :show="show">
|
||||
<div class="wrapper" @click.stop>
|
||||
<slot name="content"></slot>
|
||||
</div>
|
||||
</van-overlay>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps } from 'vue';
|
||||
const props = defineProps({
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,100 @@
|
||||
<template>
|
||||
<div class="common-res" :style="content[status].style">
|
||||
<div class="doctor-img">
|
||||
<img class="img" :src="doctorImg" alt="" />
|
||||
</div>
|
||||
<div class="res-card">
|
||||
<div class="res-text">您的测评结果</div>
|
||||
<div class="status" :style="content[status].statusStyle">{{ content[status].text }} </div>
|
||||
<div class="">测试时间:2023-09-11</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
const doctorImg = new URL('/@/assets/images/disease-warning/doctor.png', import.meta.url).href;
|
||||
const props = defineProps({
|
||||
status: Number,
|
||||
});
|
||||
const content = {
|
||||
0: {
|
||||
style: `background: rgba(82, 196, 26, 0.2)`,
|
||||
statusStyle: 'color: #52c41a',
|
||||
text: '正常',
|
||||
},
|
||||
1: {
|
||||
style: `background:rgba(250, 219, 20, 0.2)`,
|
||||
statusStyle: 'color:#FADB14',
|
||||
text: '低危',
|
||||
},
|
||||
2: {
|
||||
style: `background: rgba(212, 136, 6, 0.2)`,
|
||||
statusStyle: 'color: #D48806',
|
||||
text: '中危',
|
||||
},
|
||||
3: {
|
||||
style: `background: rgba(237, 42, 38, 0.2)`,
|
||||
statusStyle: 'color: #ED2A26',
|
||||
text: '中高危',
|
||||
},
|
||||
4: {
|
||||
style: `background-color: rgba(237, 42, 38, 0.2);`,
|
||||
statusStyle: 'color: #ED2A26',
|
||||
text: '高危',
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.common-res {
|
||||
height: 210px;
|
||||
position: relative;
|
||||
background: rgba(82, 196, 26, 0.2);
|
||||
|
||||
.doctor-img {
|
||||
position: absolute;
|
||||
top: 20%;
|
||||
left: 5%;
|
||||
bottom: 0;
|
||||
width: 35%;
|
||||
|
||||
.img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.res-card {
|
||||
position: absolute;
|
||||
top: 35px;
|
||||
right: 20px;
|
||||
width: 195px;
|
||||
height: 130px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
color: #999999;
|
||||
background: #ffffff;
|
||||
border-radius: 16px;
|
||||
|
||||
.res-text {
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.status {
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
color: #52c41a;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.time {
|
||||
white-space: nowrap;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div class="common-title" v-text="text"></div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
text: String,
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.common-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.common-title:before {
|
||||
content: '';
|
||||
left: 0;
|
||||
top: 25%;
|
||||
position: absolute;
|
||||
width: 3px;
|
||||
height: 50%;
|
||||
background: #21bebe;
|
||||
border-radius: 2px;
|
||||
}
|
||||
</style>
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
<template>
|
||||
<div class="disease-assessment-result">
|
||||
<div class="result-container">
|
||||
<CommonRes :status="resStatus" />
|
||||
<div class="result-con">
|
||||
<div>
|
||||
<CommonTit text="评估结果" />
|
||||
<div class="text-area">{{ resultObj.conclusionInfo.resultDesc }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<CommonTit text="改善建议" />
|
||||
<div class="text-area" v-for="(item, index) in resultObj.conclusionInfo.tips" :key="index">{{ item }} </div>
|
||||
</div>
|
||||
<div>
|
||||
<CommonTit text="主要危险因素" class="text-area" />
|
||||
<div>
|
||||
<div
|
||||
class="danger-val"
|
||||
:style="{ display: item.name != null && item.field != 'assessDate' && item.name != '' ? 'flex' : 'none' }"
|
||||
v-for="(item, index) in resultObj.tableInfo.fields"
|
||||
:key="index"
|
||||
>
|
||||
<div class="img-box">
|
||||
<div class="img"></div>
|
||||
<div class="font-333">{{ item.name }}</div>
|
||||
</div>
|
||||
<div class="font-666"> {{ item.value }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-btn" v-if="!route.query.history">
|
||||
<div class="common-btn history-btn" @click="historicalEvaluation">历史测评</div>
|
||||
<div class="common-btn again-btn font-fff" @click="aginSelfClick">再测一次</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import CommonTit from './components/commonTit.vue';
|
||||
import CommonRes from './components/commonRes.vue';
|
||||
|
||||
import { get } from '/@/views/mobile/api/api';
|
||||
import subjectUrl from '/@/views/health/subjectType';
|
||||
import { showFailToast } from 'vant';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const templateNo = ref('');
|
||||
const resultObj = ref({
|
||||
conclusionInfo: {},
|
||||
tableInfo: {},
|
||||
});
|
||||
const resStatus = ref(0); // 评估样式及文字
|
||||
handleGetRestule();
|
||||
function handleGetRestule() {
|
||||
templateNo.value = route.query.templateNo;
|
||||
let params = { resultId: route.query.resultId };
|
||||
let findItem = subjectUrl.getSubject.find((e) => e.templateNo === templateNo.value);
|
||||
if (findItem !== undefined) {
|
||||
get(findItem.url, params).then((res) => {
|
||||
handleResult(res);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function handleResult(res: any) {
|
||||
if (res.code === 200) {
|
||||
if (res.data.conclusionInfo.resources != null) {
|
||||
// res.data.conclusionInfo.resources.map((item)=>{
|
||||
// item.path = urlProcessor(item.path)
|
||||
// })
|
||||
}
|
||||
resultObj.value = res.data;
|
||||
resStatus.value = res.data.graphInfo.resultLevel;
|
||||
} else {
|
||||
showFailToast({
|
||||
message: res.msg,
|
||||
forbidClick: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 历史记录
|
||||
function historicalEvaluation() {
|
||||
let temNo = templateNo.value;
|
||||
let url = '';
|
||||
let params = {
|
||||
path: '',
|
||||
query: { templateNo: temNo, templateName: route.query.templateName+'记录' },
|
||||
};
|
||||
if (temNo === 500 || temNo === 400) {
|
||||
url = '/anxiety-history';
|
||||
} else {
|
||||
url = '/health-history';
|
||||
}
|
||||
params.path = url;
|
||||
router.push(params);
|
||||
}
|
||||
|
||||
// 再测一次
|
||||
function aginSelfClick() {
|
||||
router.push({
|
||||
path: '/health-subject',
|
||||
query: {
|
||||
templateNo: templateNo.value,
|
||||
templateName: route.query.templateName,
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
@import '/@/assets/less/index';
|
||||
|
||||
.disease-assessment-result {
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
.result-container {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.result-con {
|
||||
padding: 16px;
|
||||
|
||||
.text-area {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.danger-val {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 14px 0;
|
||||
border-bottom: #e0e0e0 1px solid;
|
||||
font-size: 14px;
|
||||
|
||||
.dangerShow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.img-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
vertical-align: middle;
|
||||
margin-right: 10px;
|
||||
background: url('/@/assets/images/disease-warning/heart.png') no-repeat;
|
||||
background-size: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.danger-val:last-child {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-btn {
|
||||
margin: 12px 30px 12px 30px;
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
box-sizing: border-box;
|
||||
justify-content: space-between;
|
||||
font-size: 16px;
|
||||
|
||||
.common-btn {
|
||||
flex: 1;
|
||||
height: 40px;
|
||||
white-space: nowrap;
|
||||
.flex-center();
|
||||
border-radius: 35px;
|
||||
}
|
||||
|
||||
.history-btn {
|
||||
background: #ffffff;
|
||||
border: 1px solid #999999;
|
||||
}
|
||||
|
||||
.again-btn {
|
||||
.qs-btn();
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<div id="adjustmentSuggestion">
|
||||
<div>
|
||||
<div>
|
||||
<div>食物种类</div>
|
||||
<div>
|
||||
<p v-for="item in adjustmentSuggestion.foodType">{{ item }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>碳水</div>
|
||||
<div>
|
||||
<p>{{ adjustmentSuggestion.cho }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>脂肪</div>
|
||||
<div>
|
||||
<p>{{ adjustmentSuggestion.fat }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>蛋白质</div>
|
||||
<div>
|
||||
<p>{{ adjustmentSuggestion.pro }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>维生素、矿物质和膳食纤维</div>
|
||||
<div>
|
||||
<p>{{ adjustmentSuggestion.other }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getSuggestionsDietaryAdjustment } from '/@/api/index';
|
||||
|
||||
import { defineComponent, onMounted, reactive, toRefs } from 'vue';
|
||||
import { showFailToast } from 'vant';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const state = reactive({
|
||||
adjustmentSuggestion: {},
|
||||
});
|
||||
|
||||
const getGetSuggestionsDietaryAdjustment = () => {
|
||||
let params = {};
|
||||
getSuggestionsDietaryAdjustment(params)
|
||||
.then((res) => {
|
||||
state.adjustmentSuggestion = res.data;
|
||||
})
|
||||
.catch((err) => {
|
||||
showFailToast({
|
||||
message: err.msg,
|
||||
forbidClick: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getGetSuggestionsDietaryAdjustment();
|
||||
});
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#adjustmentSuggestion {
|
||||
width: 100%;
|
||||
background-color: #ffffff;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
padding: 20px 15px 0;
|
||||
box-sizing: border-box;
|
||||
border-radius: 15px 15px 0 0;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
|
||||
> div:first-of-type {
|
||||
color: #252535;
|
||||
font-size: 16px;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding: 0 10px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 12px;
|
||||
background-color: #eef0f4;
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
width: 100%;
|
||||
padding: 0 12px;
|
||||
box-sizing: border-box;
|
||||
|
||||
p {
|
||||
color: #77849e;
|
||||
width: 100%;
|
||||
line-height: 20px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,412 @@
|
||||
<template>
|
||||
<div id="dailyPaper">
|
||||
<div>
|
||||
<div>评估日期:{{ dailyPaper.date }}</div>
|
||||
<div>
|
||||
<div class="header-info">
|
||||
<div class="header">
|
||||
<span>姓名:{{ dailyPaper.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="margin-bottom: 10px">性别:{{ dailyPaper.sex === '1' ? '女' : '男' }}</div>
|
||||
<div style="margin-bottom: 10px">年龄:{{ dailyPaper.age }}岁</div>
|
||||
<div style="margin-bottom: 10px">身高:{{ dailyPaper.height }}m</div>
|
||||
<div>体重:{{ dailyPaper.weight }}kg</div>
|
||||
<div>腰围:{{ dailyPaper.waistline }}cm</div>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div class="title">测验目的与意义</div>
|
||||
<div class="meaning">
|
||||
该问卷包括监测数据和随访数据,针对膳食数据监测和运动数据监测有效的对体重进行管理,体重管理不仅是减重,还包括调整饮食、运动和心理行为,重塑生活方式,以达到改善健康状况的目的。
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="title">测验结果</div>
|
||||
<div class="card-item">
|
||||
<div>指标信息</div>
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
>BMI:<span>{{ dailyPaper.bmi }}kg/㎡</span></div
|
||||
>
|
||||
<div>{{ dailyPaper.habitusType }}</div>
|
||||
</div>
|
||||
<template v-if="dailyPaper.indexVo">
|
||||
<div>
|
||||
<div
|
||||
>血压:<span>收缩压:{{ dailyPaper.indexVo.systolicPressure }}mmHg</span></div
|
||||
>
|
||||
<div>{{ dailyPaper.indexVo.pressureStatus }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
>   <span>舒张压:{{ dailyPaper.indexVo.diastolicPressure }}mmHg</span></div
|
||||
>
|
||||
<div></div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-item" v-if="dailyPaper.dietVo">
|
||||
<div>膳食数据</div>
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
>当日总能量摄入量:<span>{{ dailyPaper.dietVo.foodTotalEnergy }}kcal</span></div
|
||||
>
|
||||
<div v-if="dailyPaper.dietVo.totalEnergyStatus">{{ dailyPaper.dietVo.totalEnergyStatus }}</div>
|
||||
<div v-else>--</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
>碳水化合物供能占比:<span>{{ dailyPaper.dietVo.cho }}%</span></div
|
||||
>
|
||||
<div>{{ dailyPaper.dietVo.choStatus }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
>蛋白质供能占比:<span>{{ dailyPaper.dietVo.pro }}%</span></div
|
||||
>
|
||||
<div>{{ dailyPaper.dietVo.proStatus }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
>脂肪供能占比:<span>{{ dailyPaper.dietVo.fat }}%</span></div
|
||||
>
|
||||
<div>{{ dailyPaper.dietVo.fatStatus }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-item" v-if="dailyPaper.sportVo">
|
||||
<div>运动数据</div>
|
||||
<div>
|
||||
<div>
|
||||
<div>身体活动水平分级</div>
|
||||
<div v-if="dailyPaper.sportVo.physicalActivityLevel === '1'">低</div>
|
||||
<div v-if="dailyPaper.sportVo.physicalActivityLevel === '2'">中</div>
|
||||
<div v-if="dailyPaper.sportVo.physicalActivityLevel === '3'">高</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
>当日运动消耗:<span>{{ dailyPaper.sportVo.totalSportConsume }}kcal</span></div
|
||||
>
|
||||
<div v-if="dailyPaper.sportVo.totalSportConsumeStatus">{{ dailyPaper.sportVo.totalSportConsumeStatus }}</div>
|
||||
<div v-else>--</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="sport_name">运动情况:</div>
|
||||
<div v-if="dailyPaper.sportVo.detailVoList && dailyPaper.sportVo.detailVoList.length === 0">--</div>
|
||||
</div>
|
||||
<div class="sport_container" v-if="dailyPaper.sportVo.detailVoList && dailyPaper.sportVo.detailVoList.length > 0">
|
||||
<div class="item" v-for="item in dailyPaper.sportVo.detailVoList">
|
||||
<span>{{ item.exerciseModeTrans }}</span>
|
||||
<span>{{ item.exerciseTime }}分钟</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-item" v-if="dailyPaper.sportVo">
|
||||
<div>能量消耗</div>
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
>基础代谢率(BMR):<span>{{ dailyPaper.sportVo.bmr }}kcal</span></div
|
||||
>
|
||||
<div>--</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
>当日工作消耗:<span>{{ dailyPaper.sportVo.totalWorkConsume }}kcal</span></div
|
||||
>
|
||||
<div>--</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
>当日总消耗热量:<span>{{ dailyPaper.sportVo.totalEnergyConsume }}kcal</span></div
|
||||
>
|
||||
<div>--</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-item" v-if="dailyPaper.desValue">
|
||||
<div>吃动平衡评估结果</div>
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
>每日能量剩余量(DES):<span>{{ dailyPaper.desValue }}kcal</span></div
|
||||
>
|
||||
<div class="result-warp">{{ dailyPaper.desDesc }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { monitoringReportsOneDay } from '/@/api/index';
|
||||
|
||||
import { defineComponent, onMounted, reactive, toRefs } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import { showFailToast } from 'vant';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const route = useRoute();
|
||||
const state = reactive({
|
||||
dailyPaper: {},
|
||||
circleWidth: '0',
|
||||
});
|
||||
|
||||
const getMonitoringReportsOneDay = () => {
|
||||
let params = {
|
||||
date: route.query.times,
|
||||
};
|
||||
monitoringReportsOneDay(params)
|
||||
.then((res) => {
|
||||
state.dailyPaper = res.data;
|
||||
})
|
||||
.catch((err) => {
|
||||
showFailToast({
|
||||
message: err.msg,
|
||||
forbidClick: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getMonitoringReportsOneDay();
|
||||
});
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#dailyPaper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f5f7fb;
|
||||
|
||||
> div:nth-of-type(1) {
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
box-sizing: border-box;
|
||||
|
||||
> div:first-of-type {
|
||||
height: 14px;
|
||||
font-size: 14px;
|
||||
color: #77849e;
|
||||
line-height: 14px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
width: 100%;
|
||||
border-radius: 15px;
|
||||
box-sizing: border-box;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0 3px 8px 0 rgba(37, 37, 53, 0.1);
|
||||
.status-bg1 {
|
||||
background-color: rgba(255, 79, 68, 0.14);
|
||||
.status-font {
|
||||
color: #ff4f44;
|
||||
}
|
||||
.circle-border {
|
||||
border: 1px solid #ff4f44;
|
||||
}
|
||||
}
|
||||
.status-bg2 {
|
||||
background-color: rgba(255, 214, 51, 0.14);
|
||||
.status-font {
|
||||
color: #ffc833;
|
||||
}
|
||||
.circle-border {
|
||||
border: 1px solid #ffc833;
|
||||
}
|
||||
}
|
||||
.status-bg3 {
|
||||
background-color: rgba(48, 205, 155, 0.14);
|
||||
.status-font {
|
||||
color: #2ac79f;
|
||||
}
|
||||
.circle-border {
|
||||
border: 1px solid #2ac79f;
|
||||
}
|
||||
}
|
||||
.header-info {
|
||||
color: #252535;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
border-radius: 15px;
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-left: 20px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
.header-status {
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
height: 10px;
|
||||
border-radius: 10px;
|
||||
background-image: linear-gradient(to right, rgba(255, 79, 68, 1), rgba(255, 214, 51, 1), rgba(42, 199, 159, 1));
|
||||
position: relative;
|
||||
.circle-seat {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
}
|
||||
.status-name {
|
||||
padding-top: 14px;
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
color: #333333;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
padding: 10px 20px 20px 20px;
|
||||
> div {
|
||||
flex: 0 0 33.333333%;
|
||||
color: #77849e;
|
||||
height: 14px;
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-of-type(2) {
|
||||
width: 100%;
|
||||
padding: 20px 15px 0;
|
||||
box-sizing: border-box;
|
||||
background-color: #ffffff;
|
||||
border-radius: 15px 15px 0 0;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
//margin-bottom: 24px;
|
||||
padding: 20px 0 30px 0;
|
||||
> .title {
|
||||
color: #252535;
|
||||
width: 100%;
|
||||
height: 16px;
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
> .meaning {
|
||||
width: 100%;
|
||||
color: #77849e;
|
||||
font-size: 13px;
|
||||
line-height: 22px;
|
||||
text-indent: 2em;
|
||||
}
|
||||
.sport_name {
|
||||
color: #252535 !important;
|
||||
}
|
||||
> .card-item {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
> div:first-of-type {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
color: #252535;
|
||||
font-size: 16px;
|
||||
padding: 0 10px;
|
||||
line-height: 40px;
|
||||
box-sizing: border-box;
|
||||
background-color: #eef0f4;
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
width: 100%;
|
||||
padding: 25px 12px;
|
||||
box-sizing: border-box;
|
||||
background-color: #f5f7fb;
|
||||
border-radius: 0 0 8px 8px;
|
||||
|
||||
.sport_container {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
height: auto;
|
||||
flex-direction: column;
|
||||
.item {
|
||||
padding: 8px 0;
|
||||
font-size: 13px;
|
||||
span {
|
||||
display: inline-block;
|
||||
color: #77849e;
|
||||
width: 50%;
|
||||
text-align: right;
|
||||
&:first-of-type {
|
||||
color: #252535;
|
||||
}
|
||||
&:last-of-type {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
> div {
|
||||
height: 14px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 15px;
|
||||
> div:first-of-type {
|
||||
color: #252535;
|
||||
height: 14px;
|
||||
font-size: 13px;
|
||||
line-height: 14px;
|
||||
> span {
|
||||
color: #77849e;
|
||||
}
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
color: #77849e;
|
||||
height: 14px;
|
||||
font-size: 13px;
|
||||
line-height: 14px;
|
||||
}
|
||||
.result-warp {
|
||||
width: 22%;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<div id="dietarySciencePopularization">
|
||||
<img src="../../../assets/images/living/dietarySciencePopularization.jpg" alt="">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {defineComponent} from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#dietarySciencePopularization {
|
||||
width: 100%;
|
||||
background-color: #F5F7FB;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,607 @@
|
||||
<template>
|
||||
<div id="healthIndependent">
|
||||
<div>
|
||||
<div>
|
||||
<div class="icon"></div>
|
||||
<div class="userInfor">
|
||||
<div>
|
||||
<div>{{ healthManage.name }}</div>
|
||||
<div>{{ healthManage.typeOfPopulation }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
><span>{{ healthManage.sex === '1' ? '女' : '男' }}</span
|
||||
>{{ healthManage.age }}岁
|
||||
</div>
|
||||
<div @click="openFileEntry()">健康档案 <img src="../../../assets/images/living/more.png" alt="" /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="home-right"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div>健康监测</div>
|
||||
<div>
|
||||
<div>今日监测</div>
|
||||
<div>
|
||||
<img v-if="healthManage.inToday === 1" src="../../../assets/images/living/healthIndependentC.png" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<template v-if="healthManage.lastDate"> 上次监测时间:{{ healthManage.lastDate }} </template>
|
||||
</div>
|
||||
<div class="entry" @click="openPsychologicalEvaluationList">
|
||||
历史数据
|
||||
<van-icon name="arrow" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div @click="getMeals(1)">
|
||||
<div>
|
||||
<img src="../../../assets/images/living/healthIndependentC_1.png" alt="" />
|
||||
</div>
|
||||
<div>膳食监测</div>
|
||||
</div>
|
||||
<div @click="getMeals(2)">
|
||||
<div>
|
||||
<img src="../../../assets/images/living/healthIndependentC_2.png" alt="" />
|
||||
</div>
|
||||
<div>运动监测</div>
|
||||
</div>
|
||||
<div @click="getMeals(3)">
|
||||
<div>
|
||||
<img src="../../../assets/images/living/healthIndependentC_3.png" alt="" />
|
||||
</div>
|
||||
<div>指标监测</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div :class="healthManage.dayType ? 'active' : ''" @click="openDailyPaper(healthManage.dayType)">健康日报 </div>
|
||||
<div :class="healthManage.weekType ? 'active' : ''" @click="openWeekly(healthManage.weekType)">健康周报 </div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>健康建议</div>
|
||||
<div>
|
||||
<div v-if="healthManage.status" @click="openAdjustmentSuggestion">
|
||||
<div>膳食结构调整建议</div>
|
||||
<div>查看</div>
|
||||
</div>
|
||||
<div v-if="healthManage.eatingBalanceStatus" @click="openSuggestionsOnEatingDynamicBalance">
|
||||
<div>吃动平衡建议</div>
|
||||
<div>查看</div>
|
||||
</div>
|
||||
<div @click="openDietarySciencePopularization">
|
||||
<div>膳食科普</div>
|
||||
<div>查看</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="healthManage.medicineNameList !== null && healthManage.medicineNameList.length > 0">
|
||||
<div>用药情况</div>
|
||||
<div>
|
||||
<div>{{ healthManage.medicineNameList ? healthManage.medicineNameList.join(',') : '' }} </div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { healthManageHome } from '/@/api/index';
|
||||
|
||||
import { defineComponent, onMounted, reactive, toRefs } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { showFailToast } from 'vant';
|
||||
import { newPageParams, openPage } from '/@/hooks/openPage';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const router = useRouter();
|
||||
const state = reactive({
|
||||
healthManage: {
|
||||
medicineNameList: [],
|
||||
},
|
||||
});
|
||||
|
||||
const openFileEntry = () => {
|
||||
// router.push({
|
||||
// path: '/fileEntryC',
|
||||
// query: {
|
||||
// startNewActivity: 1,
|
||||
// },
|
||||
// });
|
||||
openPage('/fileEntryC', newPageParams());
|
||||
};
|
||||
|
||||
const getHealthManageHome = () => {
|
||||
let params = {};
|
||||
healthManageHome(params)
|
||||
.then((res) => {
|
||||
state.healthManage = res.data;
|
||||
})
|
||||
.catch((err) => {
|
||||
showFailToast({
|
||||
message: err.msg,
|
||||
forbidClick: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const getMeals = (type) => {
|
||||
let url = '';
|
||||
if (type === 1) {
|
||||
// 膳食
|
||||
url = '/meals';
|
||||
} else if (type === 2) {
|
||||
// 运动
|
||||
url = '/sport';
|
||||
} else if (type === 3) {
|
||||
// 指标
|
||||
url = '/indicator';
|
||||
}
|
||||
// router.push({
|
||||
// path: url,
|
||||
// query: {
|
||||
// startNewActivity: 1,
|
||||
// },
|
||||
// });
|
||||
openPage(url, newPageParams());
|
||||
};
|
||||
const openPsychologicalEvaluationList = () => {
|
||||
// router.push({
|
||||
// path: '/psychologicalEvaluationListC',
|
||||
// query: {
|
||||
// startNewActivity: 1,
|
||||
// },
|
||||
// });
|
||||
openPage('/psychologicalEvaluationListC', newPageParams());
|
||||
};
|
||||
|
||||
const openDailyPaper = (bol) => {
|
||||
if (bol) {
|
||||
// router.push({
|
||||
// path: '/dailyPaperC',
|
||||
// query: {
|
||||
// times: state.healthManage.lastDate,
|
||||
// startNewActivity: 1,
|
||||
// },
|
||||
// });
|
||||
openPage(
|
||||
'/dailyPaperC',
|
||||
newPageParams({
|
||||
times: state.healthManage.lastDate,
|
||||
})
|
||||
);
|
||||
}
|
||||
};
|
||||
// 周报
|
||||
const openWeekly = (bol) => {
|
||||
if (bol) {
|
||||
// router.push({
|
||||
// path: '/weeklyC',
|
||||
// query: {
|
||||
// startNewActivity: 1,
|
||||
// },
|
||||
// });
|
||||
openPage('/weeklyC', newPageParams());
|
||||
}
|
||||
};
|
||||
// 膳食
|
||||
const openAdjustmentSuggestion = () => {
|
||||
// router.push({
|
||||
// path: '/adjustmentSuggestionC',
|
||||
// query: {
|
||||
// startNewActivity: 1,
|
||||
// },
|
||||
// });
|
||||
openPage('/adjustmentSuggestionC', newPageParams());
|
||||
};
|
||||
// 吃动平衡
|
||||
const openSuggestionsOnEatingDynamicBalance = () => {
|
||||
// router.push({
|
||||
// path: '/suggestionsOnEatingDynamicBalanceC',
|
||||
// query: {
|
||||
// startNewActivity: 1,
|
||||
// },
|
||||
// });
|
||||
openPage('/suggestionsOnEatingDynamicBalanceC', newPageParams());
|
||||
};
|
||||
// 膳食科普
|
||||
const openDietarySciencePopularization = () => {
|
||||
// router.push({
|
||||
// path: '/dietarySciencePopularizationC',
|
||||
// query: {
|
||||
// startNewActivity: 1,
|
||||
// },
|
||||
// });
|
||||
openPage('/dietarySciencePopularizationC', newPageParams());
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getHealthManageHome();
|
||||
});
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
openFileEntry,
|
||||
openPsychologicalEvaluationList,
|
||||
openDailyPaper,
|
||||
openWeekly,
|
||||
openAdjustmentSuggestion,
|
||||
openSuggestionsOnEatingDynamicBalance,
|
||||
openDietarySciencePopularization,
|
||||
getMeals,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#healthIndependent {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f5f7fb;
|
||||
|
||||
> div:nth-of-type(1) {
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
box-sizing: border-box;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
border-radius: 15px;
|
||||
box-sizing: border-box;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0 3px 8px 0 rgba(37, 37, 53, 0.1);
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
.icon {
|
||||
width: 46px;
|
||||
height: 46px;
|
||||
background: url('/@/assets/images/living/reportlogo.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.userInfor {
|
||||
width: 80%;
|
||||
padding-left: 3%;
|
||||
|
||||
> div:first-of-type {
|
||||
width: 100%;
|
||||
height: 17px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
|
||||
> div:first-of-type {
|
||||
color: #252535;
|
||||
font-size: 17px;
|
||||
height: 17px;
|
||||
font-weight: bold;
|
||||
line-height: 17px;
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
//width: 76px;
|
||||
padding-right: 5px;
|
||||
color: #BD130B;
|
||||
font-size: 16px;
|
||||
height: 16px;
|
||||
font-weight: bold;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
width: 100%;
|
||||
height: 18px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
> div:first-of-type {
|
||||
color: #77849e;
|
||||
font-size: 14px;
|
||||
height: 14px;
|
||||
line-height: 14px;
|
||||
|
||||
span {
|
||||
margin-right: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 18px;
|
||||
color: #252535;
|
||||
padding: 0 10px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
border-radius: 10px;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #e6e6ea;
|
||||
|
||||
img {
|
||||
width: 5px;
|
||||
height: 6px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.home-right {
|
||||
position: absolute;
|
||||
right: 2px;
|
||||
bottom: 0;
|
||||
width: 55px;
|
||||
height: 55px;
|
||||
background: url('/@/assets/images/living/homeRight.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-of-type(2) {
|
||||
width: 100%;
|
||||
border-radius: 15px;
|
||||
margin-bottom: 24px;
|
||||
box-sizing: border-box;
|
||||
padding: 20px 15px 24px;
|
||||
background-color: #ffffff;
|
||||
|
||||
> div:nth-of-type(1) {
|
||||
width: 100%;
|
||||
height: 16px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-left: 5px;
|
||||
margin-bottom: 15px;
|
||||
box-sizing: border-box;
|
||||
|
||||
> div:first-of-type {
|
||||
color: #252535;
|
||||
height: 16px;
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
height: 14px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
> div:first-of-type {
|
||||
color: #77849e;
|
||||
height: 14px;
|
||||
font-size: 13px;
|
||||
line-height: 14px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
background-color: #f5f7fb;
|
||||
border: 1px solid #e6e6ea;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-of-type(2) {
|
||||
width: 100%;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 24px;
|
||||
background-color: #f1f6ff;
|
||||
|
||||
> div:first-of-type {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
padding: 0 10px 0 15px;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid #eaecf1;
|
||||
|
||||
> div {
|
||||
color: #77849e;
|
||||
height: 40px;
|
||||
font-size: 12px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.entry {
|
||||
padding: 0 10px;
|
||||
height: 26px;
|
||||
line-height: 27px;
|
||||
//border: 1px solid #21BEBE ;
|
||||
//background-color: #ffffff;
|
||||
border-radius: 12px;
|
||||
|
||||
.van-icon {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
width: 100%;
|
||||
height: 110px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
padding: 10px 24px 12px;
|
||||
box-sizing: border-box;
|
||||
|
||||
> div {
|
||||
width: 65px;
|
||||
|
||||
> div:first-of-type {
|
||||
width: 65px;
|
||||
height: 65px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
width: 100%;
|
||||
height: 14px;
|
||||
text-align: center;
|
||||
line-height: 14px;
|
||||
font-size: 14px;
|
||||
color: #77849e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-of-type(3) {
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
|
||||
> div {
|
||||
color: #ffffff;
|
||||
width: 45%;
|
||||
font-size: 18px;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
border-radius: 8px;
|
||||
background-color: #b6b6b6;
|
||||
}
|
||||
|
||||
.active {
|
||||
background-color: #21bebe;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-of-type(3) {
|
||||
width: 100%;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 24px;
|
||||
|
||||
> div:first-of-type {
|
||||
color: #252535;
|
||||
width: 100%;
|
||||
height: 16px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
line-height: 16px;
|
||||
padding-left: 5px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
width: 100%;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0 2px 4px 0 rgba(51, 59, 66, 0.12);
|
||||
|
||||
> div:first-of-type {
|
||||
color: #333b42;
|
||||
height: 16px;
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
color: #77849e;
|
||||
height: 13px;
|
||||
font-size: 13px;
|
||||
line-height: 13px;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-of-type(4) {
|
||||
width: 100%;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
|
||||
> div:first-of-type {
|
||||
color: #252535;
|
||||
width: 100%;
|
||||
height: 16px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
line-height: 16px;
|
||||
padding-left: 5px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
width: 100%;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
color: #77849e;
|
||||
font-size: 14px;
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
padding: 0 15px;
|
||||
border-radius: 8px;
|
||||
box-sizing: border-box;
|
||||
background-color: #ffffff;
|
||||
margin-bottom: 15px;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<div id="healthMonitoringHelp">
|
||||
<img src="../../../assets/images/living/help.png" alt="">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {defineComponent} from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#healthMonitoringHelp {
|
||||
width: 100%;
|
||||
background-color: #F5F7FB;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,625 @@
|
||||
<template>
|
||||
<div id="healthMonitoring">
|
||||
<div>
|
||||
<div class="help" @click="openHealthMonitoringHelp">
|
||||
录入帮助
|
||||
<van-icon name="question-o" />
|
||||
</div>
|
||||
<template v-for="item in questionnaire">
|
||||
<div class="container">
|
||||
<div class="title">{{ item.title }}</div>
|
||||
<div class="content">
|
||||
<template v-for="(item_, index_) in item.children">
|
||||
<template v-if="item_.type === 'radio'">
|
||||
<div :class="id ? 'mask' : ''">
|
||||
<div class="tips">{{ index_ + 1 }}、{{ item_.title }}(单选)</div>
|
||||
<div class="radio">
|
||||
<template v-for="item__ in item_.options">
|
||||
<div
|
||||
:class="[healthMonitoring[item_.key].includes(item__.id) ? 'active' : '']"
|
||||
@click="radioChange(item_.key, item__.id)"
|
||||
>{{ item__.label }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="item_.type === 'checkbox'">
|
||||
<div :class="id ? 'mask' : ''">
|
||||
<div>{{ index_ + 1 }}、{{ item_.title }}(多选)</div>
|
||||
<div class="checkbox">
|
||||
<template v-for="item__ in item_.options">
|
||||
<div
|
||||
:class="[healthMonitoring[item_.key].includes(item__.id) ? 'active' : '']"
|
||||
@click="checkboxChange(item_.key, item__.id)"
|
||||
>{{ item__.label }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="item_.type === 'input'">
|
||||
<div :class="id ? 'mask' : ''">
|
||||
<div class="tips">{{ index_ + 1 }}、{{ item_.title }}</div>
|
||||
<div class="inputAfter">
|
||||
<div>
|
||||
<div>
|
||||
<van-field type="number" :label-width="0" v-model="healthMonitoring[item_.key]" clearable />
|
||||
</div>
|
||||
<div>{{ item_.unit }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div>
|
||||
<div v-if="id" @click="openBack">返回</div>
|
||||
<div v-else @click="submit">提交</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { addOrEdit, checkInfo, eatingInfo } from '/@/api/index';
|
||||
import moment from 'moment';
|
||||
import { defineComponent, onMounted, reactive, toRefs } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { showFailToast, showConfirmDialog, showSuccessToast } from 'vant';
|
||||
import { destroyPage } from '/@/hooks/openPage';
|
||||
import {useLoading} from '../../../utils/compUtils'
|
||||
const { loadingSpinner, loadingClose } = useLoading();
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const state = reactive({
|
||||
id: '',
|
||||
|
||||
healthMonitoring: {
|
||||
weight: '',
|
||||
waistline: '',
|
||||
bloodOxygenSbp: '',
|
||||
bloodOxygenDbp: '',
|
||||
sleepQuality: '',
|
||||
sleepTime: '',
|
||||
},
|
||||
questionnaire: [
|
||||
{
|
||||
title: '指标监测',
|
||||
children: [
|
||||
{
|
||||
title: '体重(手动记录/每日监测)?',
|
||||
type: 'input',
|
||||
key: 'weight',
|
||||
options: [],
|
||||
unit: 'kg',
|
||||
},
|
||||
{
|
||||
title: '指标监测-腰围(手动记录/每日监测)?',
|
||||
type: 'input',
|
||||
key: 'waistline',
|
||||
options: [],
|
||||
unit: 'cm',
|
||||
},
|
||||
{
|
||||
title: '当日血压平均收缩压?',
|
||||
type: 'input',
|
||||
key: 'bloodOxygenSbp',
|
||||
options: [],
|
||||
unit: 'mmHg',
|
||||
},
|
||||
{
|
||||
title: '当日血压平均舒张压?',
|
||||
type: 'input',
|
||||
key: 'bloodOxygenDbp',
|
||||
options: [],
|
||||
unit: 'mmHg',
|
||||
},
|
||||
{
|
||||
title: '您昨天的总体睡眠质量如何?',
|
||||
type: 'radio',
|
||||
key: 'sleepQuality',
|
||||
options: [
|
||||
{
|
||||
id: '1',
|
||||
label: '非常好',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
label: '尚好',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
label: '不好',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
label: '非常差',
|
||||
},
|
||||
],
|
||||
unit: '',
|
||||
},
|
||||
{
|
||||
title: '您昨天的实际睡眠时间有几个小时?',
|
||||
type: 'radio',
|
||||
key: 'sleepTime',
|
||||
options: [
|
||||
{
|
||||
id: '1',
|
||||
label: '4-6小时',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
label: '6-8小时',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
label: '8-10小时',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
label: '10小时以上',
|
||||
},
|
||||
],
|
||||
unit: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
const openBack = () => {
|
||||
// router.go(-1);
|
||||
destroyPage();
|
||||
};
|
||||
|
||||
const openHealthMonitoringHelp = () => {
|
||||
router.push({
|
||||
path: 'healthMonitoringHelpC',
|
||||
});
|
||||
};
|
||||
|
||||
const getInfo = (time) => {
|
||||
let params = {
|
||||
date: time,
|
||||
};
|
||||
eatingInfo(params).then((res) => {
|
||||
getRestult(res);
|
||||
});
|
||||
};
|
||||
|
||||
const getCheckInfo = (id) => {
|
||||
let params = {
|
||||
id: id,
|
||||
};
|
||||
checkInfo(params).then((res) => {
|
||||
getRestult(res);
|
||||
});
|
||||
};
|
||||
// 返回结果回填数据
|
||||
const getRestult = (res) => {
|
||||
state.healthMonitoring.weight = res.data.weight;
|
||||
state.healthMonitoring.waistline = res.data.waistline;
|
||||
state.healthMonitoring.bloodOxygenSbp = res.data.bloodOxygenSbp;
|
||||
state.healthMonitoring.bloodOxygenDbp = res.data.bloodOxygenDbp;
|
||||
state.healthMonitoring.sleepQuality = res.data.sleepQuality;
|
||||
state.healthMonitoring.sleepTime = res.data.sleepTime;
|
||||
};
|
||||
const submit = () => {
|
||||
let params = JSON.parse(JSON.stringify(state.healthMonitoring));
|
||||
let paramsList = [
|
||||
params.weight,
|
||||
params.waistline,
|
||||
params.bloodOxygenSbp,
|
||||
params.bloodOxygenDbp,
|
||||
params.sleepQuality,
|
||||
params.sleepTime,
|
||||
];
|
||||
//every 一个条件不满足返回false
|
||||
let otherParams = paramsList.every((item) => item !== '');
|
||||
if (!otherParams) {
|
||||
showFailToast({
|
||||
message: '必填项不能为空',
|
||||
forbidClick: true,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
loadingSpinner();
|
||||
showConfirmDialog({
|
||||
title: '提示',
|
||||
message: '信息是否填写无误?',
|
||||
}).then(() => {
|
||||
// 标识1指标已填写
|
||||
params.indexFlag = 1;
|
||||
addOrEdit(params)
|
||||
.then((res) => {
|
||||
loadingClose();
|
||||
showSuccessToast({
|
||||
message: res.msg,
|
||||
forbidClick: true,
|
||||
});
|
||||
setTimeout(() => {
|
||||
openBack();
|
||||
}, 1500);
|
||||
})
|
||||
.catch((err) => {
|
||||
loadingClose();
|
||||
showFailToast({
|
||||
message: err.msg,
|
||||
forbidClick: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const checkboxChange = (name, value) => {
|
||||
let nameValue = state.healthMonitoring[name] ? state.healthMonitoring[name].split(',') : [];
|
||||
let nameValueIndexOf = nameValue.indexOf(value);
|
||||
if (nameValueIndexOf === -1) {
|
||||
nameValue.push(value);
|
||||
} else {
|
||||
nameValue.splice(nameValueIndexOf, 1);
|
||||
}
|
||||
state.healthMonitoring[name] = nameValue.join(',');
|
||||
};
|
||||
|
||||
// 点击选择问题 单选
|
||||
const radioChange = (name, value) => {
|
||||
state.healthMonitoring[name] = value;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
state.id = route.query.id;
|
||||
if (route.query.id) {
|
||||
getCheckInfo(route.query.id);
|
||||
} else {
|
||||
let currentTime = moment(new Date()).format('YYYY-MM-DD');
|
||||
getInfo(currentTime);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
openBack,
|
||||
checkboxChange,
|
||||
openHealthMonitoringHelp,
|
||||
radioChange,
|
||||
submit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#healthMonitoring {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f5f7fb;
|
||||
|
||||
.add-icon {
|
||||
padding: 3px 10px;
|
||||
color: #21bebe;
|
||||
font-size: 12px;
|
||||
border: 1px solid #21bebe;
|
||||
border-radius: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.van-icon {
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
&:after {
|
||||
content: '*';
|
||||
position: absolute;
|
||||
left: -7px;
|
||||
top: -2px;
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
|
||||
.tips-info {
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
line-height: 28px;
|
||||
padding: 0 20px !important;
|
||||
background-color: #f5f7fb !important;
|
||||
|
||||
span {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.range {
|
||||
display: flex;
|
||||
line-height: 40px;
|
||||
color: #999999;
|
||||
|
||||
.input_van {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-of-type(1) {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
padding: 0 0 25px 0;
|
||||
overflow-y: scroll;
|
||||
box-sizing: border-box;
|
||||
height: calc(100% - 55px);
|
||||
|
||||
.help {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
height: 38px;
|
||||
color: #ff6028;
|
||||
box-sizing: border-box;
|
||||
line-height: 28px;
|
||||
margin: 0 auto 20px;
|
||||
border: 1px solid #e6e6ea;
|
||||
background-color: rgba(255, 96, 40, 0.2);
|
||||
|
||||
.van-icon {
|
||||
padding-left: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 0 15px 0 15px;
|
||||
|
||||
> .title {
|
||||
color: #252535;
|
||||
height: 16px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
> .content {
|
||||
width: 100%;
|
||||
margin-bottom: 30px;
|
||||
|
||||
> .mask {
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 15px;
|
||||
padding: 20px 15px 25px;
|
||||
box-sizing: border-box;
|
||||
background-color: #ffffff;
|
||||
|
||||
> div:first-of-type {
|
||||
color: #252535;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
line-height: 20px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
> .radio,
|
||||
> .checkbox {
|
||||
width: 100%;
|
||||
padding: 0 8px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.rang-options {
|
||||
margin: 0;
|
||||
height: 120px;
|
||||
padding: 0 10px 0 10px;
|
||||
border-top: none;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
border-bottom: 1px solid #e6e6ea;
|
||||
border-radius: 0;
|
||||
|
||||
.name {
|
||||
margin: 0 0 25px -10px;
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
> div {
|
||||
color: #77849e;
|
||||
font-size: 15px;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
padding: 0 20px;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 20px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #e6e6ea;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.active {
|
||||
color: #21bebe;
|
||||
background-color: rgba(33, 190, 190, 0.2);
|
||||
border: 1px solid #21bebe;
|
||||
}
|
||||
}
|
||||
|
||||
> .detailVoList {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.detailVoList-item {
|
||||
width: 100%;
|
||||
height: 190px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
border-bottom: 1px solid #e6e6ea;
|
||||
position: relative;
|
||||
|
||||
.sport-input {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
|
||||
.sport-icon {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 30%;
|
||||
color: #e6e6ea;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.van-cell {
|
||||
border: 1px solid #e6e6ea;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.sport-delete {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 25%;
|
||||
color: #77849e;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
.van-icon {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 11px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.sport-times {
|
||||
font-size: 12px;
|
||||
margin-top: 10px;
|
||||
padding: 0 18px;
|
||||
|
||||
span {
|
||||
margin-left: -12px;
|
||||
display: inline-block;
|
||||
margin-bottom: 36px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .inputAfter {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 8px;
|
||||
box-sizing: border-box;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
line-height: 50px;
|
||||
padding-right: 20px;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 20px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #e6e6ea;
|
||||
|
||||
> div:first-of-type {
|
||||
flex: 1;
|
||||
height: 50px;
|
||||
padding: 2px 0;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.sport-arrow {
|
||||
position: absolute;
|
||||
right: -5%;
|
||||
top: 30%;
|
||||
color: #e6e6ea;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
color: #77849e;
|
||||
font-size: 15px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.range-container {
|
||||
padding: 34px 10px 20px 10px;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-of-type(2) {
|
||||
width: 100%;
|
||||
height: 54px;
|
||||
padding: 7px 28px;
|
||||
box-sizing: border-box;
|
||||
background-color: #ffffff;
|
||||
|
||||
> div {
|
||||
color: #ffffff;
|
||||
font-size: 15px;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
border-radius: 8px;
|
||||
background-color: #21bebe;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
+179
@@ -0,0 +1,179 @@
|
||||
<template>
|
||||
<div id="psychologicalEvaluationList">
|
||||
<div>
|
||||
<template v-if="list && list.length">
|
||||
<template v-for="item in list">
|
||||
<div class="item" @click="openHealthMonitoring(item.id)">
|
||||
<div>{{ item.createTime }}</div>
|
||||
<div>查看</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="img">
|
||||
<img src="../../../assets/images/living/psychologicalEvaluationListNull.png" alt="" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div v-if="!btn">
|
||||
<div @click="openHealthMonitoring('')">{{ btn ? '重新评估' : '重新自测' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { list, listDiabetes } from '/@/api/index';
|
||||
|
||||
import { defineComponent, onMounted, reactive, toRefs } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
import { showFailToast } from 'vant';
|
||||
import { destroyPage } from '/@/hooks/openPage';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const state = reactive({
|
||||
list: [],
|
||||
btn: true,
|
||||
});
|
||||
|
||||
const getList = () => {
|
||||
let params = {};
|
||||
list(params)
|
||||
.then((res) => {
|
||||
state.list = res.data;
|
||||
})
|
||||
.catch((err) => {
|
||||
showFailToast({
|
||||
message: err.msg,
|
||||
forbidClick: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
const getDiabetes = () => {
|
||||
let params = {};
|
||||
listDiabetes(params)
|
||||
.then((res) => {
|
||||
state.list = res.data;
|
||||
})
|
||||
.catch((err) => {
|
||||
showFailToast({
|
||||
message: err.msg,
|
||||
forbidClick: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const openHealthMonitoring = (id) => {
|
||||
if (route.query.btn) {
|
||||
router.push({
|
||||
path: '/disbetHealthMonitoring',
|
||||
query: {
|
||||
id: id,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
router.push({
|
||||
path: '/healthMonitoringC',
|
||||
query: {
|
||||
id: id,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
if (route.query.btn) {
|
||||
state.btn = false;
|
||||
getDiabetes();
|
||||
} else {
|
||||
getList();
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
openHealthMonitoring,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#psychologicalEvaluationList {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f5f7fb;
|
||||
|
||||
> div:nth-of-type(1) {
|
||||
width: 100%;
|
||||
padding: 15px 15px 0;
|
||||
overflow-y: scroll;
|
||||
box-sizing: border-box;
|
||||
height: calc(100% - 55px);
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
height: 55px;
|
||||
padding: 0 15px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 15px;
|
||||
border-radius: 8px;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0 2px 4px 0 rgba(51, 59, 66, 0.12);
|
||||
|
||||
> div:first-of-type {
|
||||
height: 55px;
|
||||
font-size: 16px;
|
||||
color: #333b42;
|
||||
line-height: 55px;
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
height: 55px;
|
||||
font-size: 13px;
|
||||
color: #77849e;
|
||||
line-height: 55px;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 60%;
|
||||
padding-top: 100px;
|
||||
margin: 0 auto;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-of-type(2) {
|
||||
width: 100%;
|
||||
height: 54px;
|
||||
padding: 7px 28px;
|
||||
box-sizing: border-box;
|
||||
background-color: #ffffff;
|
||||
|
||||
> div {
|
||||
color: #ffffff;
|
||||
font-size: 15px;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
border-radius: 8px;
|
||||
background-color: #21bebe;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,787 @@
|
||||
<template>
|
||||
<div id="healthMonitoring">
|
||||
<div>
|
||||
<div class="help" @click="openHealthMonitoringHelp">
|
||||
录入帮助
|
||||
<van-icon name="question-o" />
|
||||
</div>
|
||||
<template v-for="item in questionnaire">
|
||||
<div class="container">
|
||||
<div class="title">{{ item.title }}</div>
|
||||
<div class="content">
|
||||
<template v-for="(item_, index_) in item.children">
|
||||
<template v-if="item_.type === 'radio'">
|
||||
<div :class="id ? 'mask' : ''">
|
||||
<div class="tips">{{ index_ + 1 }}、{{ item_.title }}(单选)</div>
|
||||
<div class="radio">
|
||||
<template v-for="item__ in item_.options">
|
||||
<div
|
||||
:class="[healthMonitoring[item_.key].includes(item__.id) ? 'active' : '']"
|
||||
@click="radioChange(item_.key, item__.id)"
|
||||
>{{ item__.label }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="item_.type === 'checkbox'">
|
||||
<div :class="id ? 'mask' : ''">
|
||||
<div>{{ index_ + 1 }}、{{ item_.title }}(多选)</div>
|
||||
<div class="checkbox">
|
||||
<template v-for="item__ in item_.options">
|
||||
<div
|
||||
:class="[healthMonitoring[item_.key].includes(item__.id) ? 'active' : '']"
|
||||
@click="checkboxChange(item_.key, item__.id)"
|
||||
>{{ item__.label }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="item_.type === 'input'">
|
||||
<div :class="id ? 'mask' : ''">
|
||||
<div class="tips">{{ index_ + 1 }}、{{ item_.title }}</div>
|
||||
<div class="inputAfter">
|
||||
<div>
|
||||
<div>
|
||||
<van-field type="number" :label-width="0" v-model="healthMonitoring[item_.key]" clearable />
|
||||
</div>
|
||||
<div>{{ item_.unit }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="item_.type === 'picker'">
|
||||
<div :class="id ? 'mask' : ''">
|
||||
<div class="tips">
|
||||
<div>{{ index_ + 1 }}、{{ item_.title }}</div>
|
||||
<div class="add-icon" v-if="item_.key === 'detailVoList'" @click="addSport">
|
||||
添加运动
|
||||
<van-icon name="add-o" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="inputAfter" v-if="item_.key === 'physicalActivityLevel'">
|
||||
<div>
|
||||
<div>
|
||||
<van-field
|
||||
:label-width="0"
|
||||
:placeholder="item_.placeholder"
|
||||
v-model="healthMonitoring[item_.key]"
|
||||
readonly
|
||||
@click="openPicker(item_.key, '')"
|
||||
/>
|
||||
<van-icon class="sport-arrow" name="arrow" />
|
||||
</div>
|
||||
<div>{{ item_.unit }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detailVoList" v-if="item_.key === 'detailVoList'">
|
||||
<div class="detailVoList-item" v-for="(sportItem, sportIndex) in healthMonitoring.detailVoList">
|
||||
<div
|
||||
class="sport-input"
|
||||
:style="{ width: sportIndex === 0 ? '100%' : '86%' }"
|
||||
@click="openPicker(item_.key, sportIndex)"
|
||||
>
|
||||
<van-field
|
||||
:label-width="0"
|
||||
:placeholder="item_.placeholder"
|
||||
v-model="sportItem.exerciseMode"
|
||||
readonly
|
||||
/>
|
||||
<van-icon class="sport-icon" name="arrow" />
|
||||
</div>
|
||||
<div class="sport-delete" v-if="sportIndex !== 0" @click="deletePicker(sportIndex)">
|
||||
<van-icon name="clear" />
|
||||
<span>删除</span>
|
||||
</div>
|
||||
<div class="sport-times">
|
||||
<span>时间(分)</span>
|
||||
<nut-range
|
||||
v-model="sportItem.exerciseTime"
|
||||
:min="0"
|
||||
:max="120"
|
||||
:marks="marksSport"
|
||||
:hiddenRange="true"
|
||||
@change="(data) => onChangeSport(data, sportIndex)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tips-info" v-if="item_.key === 'physicalActivityLevel'">
|
||||
<p
|
||||
><span>低</span
|
||||
>(75%的时间坐或站立,25%的时间站着活动。例如:办公室工作,修理电器钟表、售货员、酒店服务员、化学实验操作、讲课等)
|
||||
</p>
|
||||
<p
|
||||
><span>中</span
|
||||
>(40%的时间坐或站立,60%的时间特殊职业活动。例如:学生日常活动、机动车驾驶、电工安装、车床操作、金属切削等)
|
||||
</p>
|
||||
<p
|
||||
><span>高</span
|
||||
>(25%的时间站着活动,75%的时间特殊职业活动。例如:非机械化农业劳动,炼钢、舞蹈、体育运动、装卸、采矿等)
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div>
|
||||
<div v-if="id" @click="openBack">返回</div>
|
||||
<div v-else @click="submit">提交</div>
|
||||
</div>
|
||||
</div>
|
||||
<van-popup :show="picker.show" round position="bottom">
|
||||
<van-picker :columns="picker.columns" v-model="picker.value" @cancel="picker.show = false" @confirm="onConfirmPicker" />
|
||||
</van-popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { addOrEdit, checkInfo, eatingInfo } from '/@/api/index';
|
||||
import moment from 'moment';
|
||||
import { defineComponent, onMounted, reactive, toRefs } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { showFailToast, showConfirmDialog, showSuccessToast } from "vant";
|
||||
import { destroyPage } from '/@/hooks/openPage';
|
||||
import {useLoading} from '../../../utils/compUtils'
|
||||
const { loadingSpinner, loadingClose } = useLoading();
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const state = reactive({
|
||||
id: '',
|
||||
healthMonitoring: {
|
||||
physicalActivityLevel: '',
|
||||
weight: '',
|
||||
detailVoList: [
|
||||
{
|
||||
exerciseMode: '',
|
||||
exerciseTime: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
pickerVal: 0,
|
||||
sportIndex: 0,
|
||||
picker: {
|
||||
show: false,
|
||||
columns: [],
|
||||
key: '',
|
||||
},
|
||||
// 身体活动水平
|
||||
singleRow: [
|
||||
{ text: '低', value: '1' },
|
||||
{ text: '中', value: '2' },
|
||||
{ text: '高', value: '3' },
|
||||
],
|
||||
marksSport: {
|
||||
0: 0,
|
||||
30: 30,
|
||||
60: 60,
|
||||
90: 90,
|
||||
120: 120,
|
||||
},
|
||||
// 运动情况
|
||||
sportList: [
|
||||
{ text: '走路(慢)', value: '1' },
|
||||
{ text: '跑步(快)', value: '2' },
|
||||
{ text: '跑步(慢)', value: '3' },
|
||||
{ text: '跳绳', value: '4' },
|
||||
{ text: '游泳', value: '5' },
|
||||
{ text: '自行车', value: '6' },
|
||||
{ text: '踏板车', value: '7' },
|
||||
{ text: '瑜伽,普拉提', value: '8' },
|
||||
{ text: '篮球', value: '9' },
|
||||
{ text: '排球', value: '10' },
|
||||
{ text: '乒乓球', value: '11' },
|
||||
{ text: '台球', value: '12' },
|
||||
{ text: '网球', value: '13' },
|
||||
{ text: '羽毛球', value: '14' },
|
||||
{ text: '足球', value: '15' },
|
||||
{ text: '舞蹈', value: '16' },
|
||||
{ text: '太极拳', value: '17' },
|
||||
{ text: '单杠', value: '18' },
|
||||
{ text: '俯卧撑', value: '19' },
|
||||
{ text: '健身操', value: '20' },
|
||||
{ text: '上下楼(跑)', value: '21' },
|
||||
{ text: '上下楼(走)', value: '22' },
|
||||
],
|
||||
questionnaire: [
|
||||
{
|
||||
title: '运动监测数据',
|
||||
children: [
|
||||
{
|
||||
title: '您当日身体活动水平?',
|
||||
type: 'picker',
|
||||
key: 'physicalActivityLevel',
|
||||
options: [],
|
||||
placeholder: '请选择身体活动水平',
|
||||
unit: '',
|
||||
},
|
||||
{
|
||||
title: '体重(手动记录/每日监测)?',
|
||||
type: 'input',
|
||||
key: 'weight',
|
||||
options: [],
|
||||
unit: 'kg',
|
||||
},
|
||||
{
|
||||
title: '当日运动情况?',
|
||||
type: 'picker',
|
||||
key: 'detailVoList',
|
||||
placeholder: '请选择运动方式',
|
||||
options: [],
|
||||
unit: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
// 打开弹窗
|
||||
const openPicker = (key, index) => {
|
||||
state.picker.show = true;
|
||||
state.picker.key = key;
|
||||
state.sportIndex = index;
|
||||
state.picker.columns = key === 'physicalActivityLevel' ? state.singleRow : state.sportList;
|
||||
};
|
||||
// 运动方式
|
||||
const onConfirmPicker = (val) => {
|
||||
state.picker.show = false;
|
||||
let key = state.picker.key;
|
||||
if (key === 'physicalActivityLevel') {
|
||||
state.healthMonitoring[`${key}`] = returnValue(state.singleRow, val.selectedValues[0]).text;
|
||||
state.pickerVal = val.selectedValues[0];
|
||||
}
|
||||
if (key === 'detailVoList') {
|
||||
let repeatVal = state.healthMonitoring.detailVoList.find((item) => item.exerciseMode === val.selectedOptions[0].text);
|
||||
if (repeatVal) {
|
||||
showFailToast({
|
||||
message: '不能选择重复的运动方式',
|
||||
forbidClick: true,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
state.healthMonitoring.detailVoList[`${state.sportIndex}`].exerciseMode = returnValue(
|
||||
state.sportList,
|
||||
val.selectedValues[0]
|
||||
).text;
|
||||
}
|
||||
};
|
||||
// 运动时间
|
||||
const onChangeSport = (val, index) => {
|
||||
state.healthMonitoring.detailVoList[index].exerciseTime = val;
|
||||
};
|
||||
// 添加运动方式
|
||||
const addSport = () => {
|
||||
if (state.healthMonitoring.detailVoList.length >= 22) {
|
||||
showFailToast({
|
||||
message: '只能添加22种运动方式',
|
||||
forbidClick: true,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
state.healthMonitoring.detailVoList.push({
|
||||
exerciseMode: '',
|
||||
exerciseTime: 0,
|
||||
});
|
||||
};
|
||||
|
||||
// 删除运动方式
|
||||
const deletePicker = (index) => {
|
||||
state.healthMonitoring.detailVoList.splice(index, 1);
|
||||
};
|
||||
const returnValue = (list, val) => {
|
||||
let find = list.find((item) => item.value === val);
|
||||
if (find) return find;
|
||||
};
|
||||
const returnName = (list, val) => {
|
||||
let find = list.find((item) => item.text === val);
|
||||
if (find) return find;
|
||||
};
|
||||
const openBack = () => {
|
||||
// router.go(-1);
|
||||
destroyPage();
|
||||
};
|
||||
// 滑块
|
||||
const onChangeRange = (key, value) => {
|
||||
state.healthMonitoring[key] = value;
|
||||
};
|
||||
const openHealthMonitoringHelp = () => {
|
||||
router.push({
|
||||
path: 'healthMonitoringHelpC',
|
||||
});
|
||||
};
|
||||
|
||||
const getInfo = (time) => {
|
||||
let params = {
|
||||
date: time,
|
||||
};
|
||||
eatingInfo(params).then((res) => {
|
||||
getRestult(res);
|
||||
});
|
||||
};
|
||||
|
||||
const getCheckInfo = (id) => {
|
||||
let params = {
|
||||
id: id,
|
||||
};
|
||||
checkInfo(params).then((res) => {
|
||||
getRestult(res);
|
||||
});
|
||||
};
|
||||
// 返回结果回填数据
|
||||
const getRestult = (res) => {
|
||||
state.healthMonitoring.physicalActivityLevel = res.data.physicalActivityLevel;
|
||||
state.healthMonitoring.weight = res.data.weight;
|
||||
let physicalLevel = res.data.physicalActivityLevel;
|
||||
let sportList = res.data.detailVoList;
|
||||
// 身体活动水平
|
||||
if (physicalLevel) {
|
||||
let physicalVal = returnValue(state.singleRow, physicalLevel);
|
||||
if (physicalVal) {
|
||||
state.healthMonitoring.physicalActivityLevel = physicalVal.text;
|
||||
}
|
||||
}
|
||||
// 运动形式和时间回显
|
||||
if (sportList.length > 0) {
|
||||
sportList.map((item) => {
|
||||
let sortVal = returnValue(state.sportList, item.exerciseMode);
|
||||
if (sortVal) {
|
||||
item.exerciseMode = sortVal.text;
|
||||
}
|
||||
});
|
||||
state.healthMonitoring.detailVoList = sportList;
|
||||
} else {
|
||||
state.healthMonitoring.detailVoList = [
|
||||
{
|
||||
exerciseMode: '',
|
||||
exerciseTime: 0,
|
||||
},
|
||||
];
|
||||
}
|
||||
};
|
||||
const submit = () => {
|
||||
let params = JSON.parse(JSON.stringify(state.healthMonitoring));
|
||||
//every 一个条件不满足返回false
|
||||
let detailVis = params.detailVoList.every((item) => item.exerciseMode !== '' && item.exerciseTime !== 0);
|
||||
if (!detailVis || params.physicalActivityLevel === '' || params.weight === '') {
|
||||
showFailToast({
|
||||
message: '必填项不能为空',
|
||||
forbidClick: true,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
let physical = returnName(state.singleRow, params.physicalActivityLevel);
|
||||
if (physical) {
|
||||
params.physicalActivityLevel = state.id ? state.pickerVal : physical.value;
|
||||
}
|
||||
params.detailVoList.map((item) => {
|
||||
let sportVal = returnName(state.sportList, item.exerciseMode);
|
||||
if (sportVal) {
|
||||
item.exerciseMode = sportVal.value;
|
||||
}
|
||||
});
|
||||
loadingSpinner();
|
||||
showConfirmDialog({
|
||||
title: '提示',
|
||||
message: '信息是否填写无误?',
|
||||
}).then(() => {
|
||||
// 标识1运动已填写
|
||||
params.sportFlag = 1;
|
||||
addOrEdit(params)
|
||||
.then((res) => {
|
||||
loadingClose();
|
||||
showSuccessToast({
|
||||
message: res.msg,
|
||||
forbidClick: true,
|
||||
});
|
||||
setTimeout(() => {
|
||||
openBack();
|
||||
}, 1500);
|
||||
})
|
||||
.catch((err) => {
|
||||
loadingClose();
|
||||
showFailToast({
|
||||
message: err.msg,
|
||||
forbidClick: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const checkboxChange = (name, value) => {
|
||||
let nameValue = state.healthMonitoring[name] ? state.healthMonitoring[name].split(',') : [];
|
||||
let nameValueIndexOf = nameValue.indexOf(value);
|
||||
if (nameValueIndexOf === -1) {
|
||||
nameValue.push(value);
|
||||
} else {
|
||||
nameValue.splice(nameValueIndexOf, 1);
|
||||
}
|
||||
state.healthMonitoring[name] = nameValue.join(',');
|
||||
};
|
||||
|
||||
// 点击选择问题 单选
|
||||
const radioChange = (name, value) => {
|
||||
state.healthMonitoring[name] = value;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
state.id = route.query.id;
|
||||
if (route.query.id) {
|
||||
getCheckInfo(route.query.id);
|
||||
} else {
|
||||
let currentTime = moment(new Date()).format('YYYY-MM-DD');
|
||||
getInfo(currentTime);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
openBack,
|
||||
checkboxChange,
|
||||
openHealthMonitoringHelp,
|
||||
radioChange,
|
||||
submit,
|
||||
onChangeRange,
|
||||
openPicker,
|
||||
onConfirmPicker,
|
||||
addSport,
|
||||
onChangeSport,
|
||||
deletePicker,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#healthMonitoring {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f5f7fb;
|
||||
|
||||
.add-icon {
|
||||
padding: 3px 10px;
|
||||
color: #21bebe;
|
||||
font-size: 12px;
|
||||
border: 1px solid #21bebe;
|
||||
border-radius: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.van-icon {
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
&:after {
|
||||
content: '*';
|
||||
position: absolute;
|
||||
left: -7px;
|
||||
top: -2px;
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
|
||||
.tips-info {
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
line-height: 28px;
|
||||
padding: 0 20px !important;
|
||||
background-color: #f5f7fb !important;
|
||||
|
||||
span {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.range {
|
||||
display: flex;
|
||||
line-height: 40px;
|
||||
color: #999999;
|
||||
|
||||
.input_van {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-of-type(1) {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
padding: 0 0 25px 0;
|
||||
overflow-y: scroll;
|
||||
box-sizing: border-box;
|
||||
height: calc(100% - 55px);
|
||||
|
||||
.help {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
height: 38px;
|
||||
color: #ff6028;
|
||||
box-sizing: border-box;
|
||||
line-height: 28px;
|
||||
margin: 0 auto 20px;
|
||||
border: 1px solid #e6e6ea;
|
||||
background-color: rgba(255, 96, 40, 0.2);
|
||||
|
||||
.van-icon {
|
||||
padding-left: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 0 15px 0 15px;
|
||||
|
||||
> .title {
|
||||
color: #252535;
|
||||
height: 16px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
> .content {
|
||||
width: 100%;
|
||||
margin-bottom: 30px;
|
||||
|
||||
> .mask {
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 15px;
|
||||
padding: 20px 15px 25px;
|
||||
box-sizing: border-box;
|
||||
background-color: #ffffff;
|
||||
|
||||
> div:first-of-type {
|
||||
color: #252535;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
line-height: 20px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
> .radio,
|
||||
> .checkbox {
|
||||
width: 100%;
|
||||
padding: 0 8px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.rang-options {
|
||||
margin: 0;
|
||||
height: 120px;
|
||||
padding: 0 10px 0 10px;
|
||||
border-top: none;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
border-bottom: 1px solid #e6e6ea;
|
||||
border-radius: 0;
|
||||
|
||||
.name {
|
||||
margin: 0 0 25px -10px;
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
> div {
|
||||
color: #77849e;
|
||||
font-size: 15px;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
padding: 0 20px;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 20px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #e6e6ea;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.active {
|
||||
color: #21bebe;
|
||||
background-color: rgba(33, 190, 190, 0.2);
|
||||
border: 1px solid #21bebe;
|
||||
}
|
||||
}
|
||||
|
||||
> .detailVoList {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.detailVoList-item {
|
||||
width: 100%;
|
||||
height: 190px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
border-bottom: 1px solid #e6e6ea;
|
||||
position: relative;
|
||||
|
||||
.sport-input {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
|
||||
.sport-icon {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 30%;
|
||||
color: #e6e6ea;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.van-cell {
|
||||
border: 1px solid #e6e6ea;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.sport-delete {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 25%;
|
||||
color: #77849e;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
.van-icon {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 11px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.sport-times {
|
||||
font-size: 12px;
|
||||
margin-top: 10px;
|
||||
padding: 0 18px;
|
||||
|
||||
span {
|
||||
margin-left: -12px;
|
||||
display: inline-block;
|
||||
margin-bottom: 36px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .inputAfter {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 8px;
|
||||
box-sizing: border-box;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
line-height: 50px;
|
||||
padding-right: 20px;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 20px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #e6e6ea;
|
||||
|
||||
> div:first-of-type {
|
||||
flex: 1;
|
||||
height: 50px;
|
||||
padding: 2px 0;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.sport-arrow {
|
||||
position: absolute;
|
||||
right: -5%;
|
||||
top: 30%;
|
||||
color: #e6e6ea;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
color: #77849e;
|
||||
font-size: 15px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.range-container {
|
||||
padding: 34px 10px 20px 10px;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-of-type(2) {
|
||||
width: 100%;
|
||||
height: 54px;
|
||||
padding: 7px 28px;
|
||||
box-sizing: border-box;
|
||||
background-color: #ffffff;
|
||||
|
||||
> div {
|
||||
color: #ffffff;
|
||||
font-size: 15px;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
border-radius: 8px;
|
||||
background-color: #21bebe;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+255
@@ -0,0 +1,255 @@
|
||||
<template>
|
||||
<div id="suggestionsOnEatingDynamicBalance">
|
||||
<div>
|
||||
<div class="header-bg">
|
||||
<div :class="statusHeader" class="header-info">
|
||||
<div class="header">
|
||||
<span>姓名:{{ suggestionsOnEatingDynamicBalance.name }}</span>
|
||||
<span class="status-font">{{ suggestionsOnEatingDynamicBalance.desDesc }}</span>
|
||||
</div>
|
||||
<div class="header-status">
|
||||
<div class="circle-seat circle-border" :style="{ left: circleWidth }"></div>
|
||||
</div>
|
||||
<div class="status-name">
|
||||
<span>负平衡</span>
|
||||
<span>基本平衡</span>
|
||||
<span>正平衡</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="balance">您当日能量剩余量DES:{{ suggestionsOnEatingDynamicBalance.desValue }} kcal。</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div>行为指导建议</div>
|
||||
<div>
|
||||
<p v-for="item in suggestionsOnEatingDynamicBalance.getSomeAction">{{ item }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>膳食指导建议</div>
|
||||
<div>
|
||||
<p v-for="item in suggestionsOnEatingDynamicBalance.diet">{{ item }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>运动指导建议</div>
|
||||
<div>
|
||||
<p v-for="item in suggestionsOnEatingDynamicBalance.motion">{{ item }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getSuggestionsOnEating } from '/@/api/index';
|
||||
|
||||
import { defineComponent, onMounted, reactive, toRefs } from 'vue';
|
||||
|
||||
import { showFailToast } from 'vant';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const state = reactive({
|
||||
suggestionsOnEatingDynamicBalance: {},
|
||||
statusHeader: '',
|
||||
circleWidth: '',
|
||||
});
|
||||
|
||||
const getGetSuggestionsOnEating = () => {
|
||||
let params = {};
|
||||
getSuggestionsOnEating(params)
|
||||
.then((res) => {
|
||||
state.suggestionsOnEatingDynamicBalance = res.data;
|
||||
switch (res.data.desLevel) {
|
||||
case 1:
|
||||
//基本平衡
|
||||
state.statusHeader = 'status-bg2';
|
||||
state.circleWidth = '45%';
|
||||
break;
|
||||
case 2:
|
||||
// 正平衡-能量过量
|
||||
state.statusHeader = 'status-bg3';
|
||||
state.circleWidth = '80%';
|
||||
break;
|
||||
case 3:
|
||||
// 正平衡-能量严重过量
|
||||
state.statusHeader = 'status-bg3';
|
||||
state.circleWidth = '95%';
|
||||
break;
|
||||
case 4:
|
||||
// 负平衡-能量不足
|
||||
state.statusHeader = 'status-bg1';
|
||||
state.circleWidth = '13%';
|
||||
break;
|
||||
case 5:
|
||||
// 负平衡-能量严重不足
|
||||
state.statusHeader = 'status-bg1';
|
||||
state.circleWidth = '0';
|
||||
break;
|
||||
default:
|
||||
state.statusHeader = 'status-bg2';
|
||||
state.circleWidth = '45%';
|
||||
break;
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
showFailToast({
|
||||
message: err.msg,
|
||||
forbidClick: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getGetSuggestionsOnEating();
|
||||
});
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#suggestionsOnEatingDynamicBalance {
|
||||
width: 100%;
|
||||
background-color: #f5f7fb;
|
||||
|
||||
> div:nth-of-type(1) {
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
margin: 0 auto;
|
||||
box-sizing: border-box;
|
||||
.header-bg {
|
||||
background-color: #ffffff;
|
||||
border-radius: 15px;
|
||||
}
|
||||
.header-info {
|
||||
color: #252535;
|
||||
width: 100%;
|
||||
height: 115px;
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
font-weight: bold;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.14);
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.header-status {
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
height: 10px;
|
||||
border-radius: 10px;
|
||||
background-image: linear-gradient(to right, rgba(255, 79, 68, 1), rgba(255, 214, 51, 1), rgba(42, 199, 159, 1));
|
||||
position: relative;
|
||||
|
||||
.circle-seat {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.status-name {
|
||||
padding-top: 14px;
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
color: #333333;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.status-bg1 {
|
||||
background-color: rgba(255, 79, 68, 0.14);
|
||||
|
||||
.status-font {
|
||||
color: #ff4f44;
|
||||
}
|
||||
|
||||
.circle-border {
|
||||
border: 1px solid #ff4f44;
|
||||
}
|
||||
}
|
||||
|
||||
.status-bg2 {
|
||||
background-color: rgba(255, 214, 51, 0.14);
|
||||
|
||||
.status-font {
|
||||
color: #ffc833;
|
||||
}
|
||||
|
||||
.circle-border {
|
||||
border: 1px solid #ffc833;
|
||||
}
|
||||
}
|
||||
|
||||
.status-bg3 {
|
||||
background-color: rgba(48, 205, 155, 0.14);
|
||||
|
||||
.status-font {
|
||||
color: #2ac79f;
|
||||
}
|
||||
|
||||
.circle-border {
|
||||
border: 1px solid #2ac79f;
|
||||
}
|
||||
}
|
||||
.balance {
|
||||
padding: 20px;
|
||||
color: #77849e;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-of-type(2) {
|
||||
width: 100%;
|
||||
padding: 20px 15px 0;
|
||||
box-sizing: border-box;
|
||||
background-color: #ffffff;
|
||||
border-radius: 15px 15px 0 0;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
|
||||
> div:first-of-type {
|
||||
color: #252535;
|
||||
font-size: 16px;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding: 0 10px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 12px;
|
||||
background-color: #eef0f4;
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
width: 100%;
|
||||
padding: 0 12px;
|
||||
box-sizing: border-box;
|
||||
|
||||
p {
|
||||
color: #77849e;
|
||||
width: 100%;
|
||||
line-height: 20px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,413 @@
|
||||
<template>
|
||||
<div id="weekly">
|
||||
<div>
|
||||
<div>评估日期:{{ weekly.date }}</div>
|
||||
<div>
|
||||
<div class="header-info">
|
||||
<div class="header">
|
||||
<span>姓名:{{ weekly.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="margin-bottom: 10px">性别:{{ weekly.sex === '1' ? '女' : '男' }}</div>
|
||||
<div style="margin-bottom: 10px">年龄:{{ weekly.age }}岁</div>
|
||||
<div style="margin-bottom: 10px">身高:{{ weekly.height }}m</div>
|
||||
<div>体重:{{ weekly.weight }}kg</div>
|
||||
<div>腰围:{{ weekly.waistline }}cm</div>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div class="title">测验目的与意义</div>
|
||||
<div class="meaning">
|
||||
该问卷包括监测数据和随访数据,针对膳食数据监测和运动数据监测有效的对体重进行管理,体重管理不仅是减重,还包括调整饮食、运动和心理行为,重塑生活方式,以达到改善健康状况的目的。
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="title">测验结果</div>
|
||||
<div class="card">
|
||||
<div>指标信息</div>
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
>BMI:<span>{{ weekly.bmi }}kg/㎡</span></div
|
||||
>
|
||||
<div>{{ weekly.habitusType }}</div>
|
||||
</div>
|
||||
<template v-if="weekly.indexVo">
|
||||
<div>
|
||||
<div
|
||||
>血压:<span>收缩压:{{ weekly.indexVo.systolicPressure }}mmHg</span></div
|
||||
>
|
||||
<div>{{ weekly.indexVo.pressureStatus }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
>   <span>舒张压:{{ weekly.diastolicPressure }}mmHg</span></div
|
||||
>
|
||||
<div></div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" v-if="weekly.dietVo">
|
||||
<div>膳食数据</div>
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
>本周总能量摄入量:<span>{{ weekly.dietVo.foodTotalEnergy }}kcal</span></div
|
||||
>
|
||||
<div>{{ weekly.dietVo.totalEnergyStatus }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
>碳水化合物供能占比:<span>{{ weekly.dietVo.cho }}%</span></div
|
||||
>
|
||||
<div>{{ weekly.dietVo.choStatus }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
>蛋白质供能占比:<span>{{ weekly.dietVo.pro }}%</span></div
|
||||
>
|
||||
<div>{{ weekly.dietVo.proStatus }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
>脂肪供能占比:<span>{{ weekly.dietVo.fat }}%</span></div
|
||||
>
|
||||
<div>{{ weekly.dietVo.fatStatus }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" v-if="weekly.sportVo">
|
||||
<div>运动数据</div>
|
||||
<div>
|
||||
<div>
|
||||
<div>身体活动水平分级</div>
|
||||
<div v-if="weekly.sportVo.physicalActivityLevel === '1'">低</div>
|
||||
<div v-if="weekly.sportVo.physicalActivityLevel === '2'">中</div>
|
||||
<div v-if="weekly.sportVo.physicalActivityLevel === '3'">高</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
>本周运动消耗:<span>{{ weekly.sportVo.totalSportConsume }}kcal</span></div
|
||||
>
|
||||
<div v-if="weekly.sportVo.totalSportConsumeStatus">{{ weekly.sportVo.totalSportConsumeStatus }}</div>
|
||||
<div v-else>--</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="sport_name">运动情况:</div>
|
||||
<div v-if="weekly.sportVo.detailVoList && weekly.sportVo.detailVoList.length === 0">--</div>
|
||||
</div>
|
||||
<div class="sport_container" v-if="weekly.sportVo.detailVoList && weekly.sportVo.detailVoList.length > 0">
|
||||
<div class="item" v-for="item in weekly.sportVo.detailVoList">
|
||||
<span>{{ item.exerciseModeTrans }}</span>
|
||||
<span>{{ item.exerciseTime }}分钟</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" v-if="weekly.sportVo">
|
||||
<div>能量消耗</div>
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
>基础代谢率(BMR):<span>{{ weekly.sportVo.bmr }}kcal</span></div
|
||||
>
|
||||
<div>--</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
>本周工作消耗:<span>{{ weekly.sportVo.totalWorkConsume }}kcal</span></div
|
||||
>
|
||||
<div>--</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
>本周总消耗热量:<span>{{ weekly.sportVo.totalEnergyConsume }}kcal</span></div
|
||||
>
|
||||
<div>--</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" v-if="weekly.desValue">
|
||||
<div>吃动平衡评估结果</div>
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
>本周能量剩余量(DES):<span>{{ weekly.desValue }}kcal</span></div
|
||||
>
|
||||
<div class="result-warp">{{ weekly.desDesc }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { monitoringReportsOneWeek } from '/@/api/index';
|
||||
|
||||
import { defineComponent, onMounted, reactive, toRefs } from 'vue';
|
||||
|
||||
import { showFailToast } from 'vant';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const state = reactive({
|
||||
weekly: {},
|
||||
statusHeader: '',
|
||||
});
|
||||
|
||||
const getMonitoringReportsOneWeek = () => {
|
||||
let params = {};
|
||||
monitoringReportsOneWeek(params)
|
||||
.then((res) => {
|
||||
state.weekly = res.data;
|
||||
})
|
||||
.catch((err) => {
|
||||
showFailToast({
|
||||
message: err.msg,
|
||||
forbidClick: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getMonitoringReportsOneWeek();
|
||||
});
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#weekly {
|
||||
width: 100%;
|
||||
background-color: #f5f7fb;
|
||||
|
||||
> div:nth-of-type(1) {
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
box-sizing: border-box;
|
||||
|
||||
> div:first-of-type {
|
||||
height: 14px;
|
||||
font-size: 14px;
|
||||
color: #77849e;
|
||||
line-height: 14px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.status-bg1 {
|
||||
background-color: rgba(255, 79, 68, 0.14);
|
||||
.status-font {
|
||||
color: #ff4f44;
|
||||
}
|
||||
.circle-border {
|
||||
border: 1px solid #ff4f44;
|
||||
}
|
||||
}
|
||||
.status-bg2 {
|
||||
background-color: rgba(255, 214, 51, 0.14);
|
||||
.status-font {
|
||||
color: #ffc833;
|
||||
}
|
||||
.circle-border {
|
||||
border: 1px solid #ffc833;
|
||||
}
|
||||
}
|
||||
.status-bg3 {
|
||||
background-color: rgba(48, 205, 155, 0.14);
|
||||
.status-font {
|
||||
color: #2ac79f;
|
||||
}
|
||||
.circle-border {
|
||||
border: 1px solid #2ac79f;
|
||||
}
|
||||
}
|
||||
> div:last-of-type {
|
||||
width: 100%;
|
||||
border-radius: 15px;
|
||||
box-sizing: border-box;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0 3px 8px 0 rgba(37, 37, 53, 0.1);
|
||||
|
||||
> div:first-of-type {
|
||||
color: #252535;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.header-info {
|
||||
color: #252535;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
border-radius: 15px;
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-left: 20px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
.header-status {
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
height: 10px;
|
||||
border-radius: 10px;
|
||||
background-image: linear-gradient(to right, rgba(255, 79, 68, 1), rgba(255, 214, 51, 1), rgba(42, 199, 159, 1));
|
||||
position: relative;
|
||||
.circle-seat {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
}
|
||||
.status-name {
|
||||
padding-top: 14px;
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
color: #333333;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
> div:last-of-type {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
padding: 10px 20px 20px 20px;
|
||||
> div {
|
||||
flex: 0 0 33.333333%;
|
||||
color: #77849e;
|
||||
height: 14px;
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-of-type(2) {
|
||||
width: 100%;
|
||||
padding: 20px 15px 0;
|
||||
box-sizing: border-box;
|
||||
background-color: #ffffff;
|
||||
border-radius: 15px 15px 0 0;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
margin-bottom: 24px;
|
||||
|
||||
> .title {
|
||||
color: #252535;
|
||||
width: 100%;
|
||||
height: 16px;
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
> .meaning {
|
||||
width: 100%;
|
||||
color: #77849e;
|
||||
font-size: 13px;
|
||||
line-height: 22px;
|
||||
text-indent: 2em;
|
||||
}
|
||||
.sport_name {
|
||||
color: #252535 !important;
|
||||
}
|
||||
> .card {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
|
||||
> div:first-of-type {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
color: #252535;
|
||||
font-size: 16px;
|
||||
padding: 0 10px;
|
||||
line-height: 40px;
|
||||
box-sizing: border-box;
|
||||
background-color: #eef0f4;
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
width: 100%;
|
||||
padding: 15px 12px;
|
||||
box-sizing: border-box;
|
||||
background-color: #f5f7fb;
|
||||
border-radius: 0 0 8px 8px;
|
||||
.sport_container {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
height: auto;
|
||||
flex-direction: column;
|
||||
.item {
|
||||
padding: 8px 0;
|
||||
font-size: 13px;
|
||||
span {
|
||||
display: inline-block;
|
||||
color: #77849e;
|
||||
width: 50%;
|
||||
text-align: right;
|
||||
&:first-of-type {
|
||||
color: #252535;
|
||||
}
|
||||
&:last-of-type {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
> div {
|
||||
height: 14px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 15px;
|
||||
|
||||
> div:first-of-type {
|
||||
color: #252535;
|
||||
height: 14px;
|
||||
font-size: 13px;
|
||||
line-height: 14px;
|
||||
|
||||
> span {
|
||||
color: #77849e;
|
||||
}
|
||||
}
|
||||
|
||||
> div:last-of-type {
|
||||
color: #77849e;
|
||||
height: 14px;
|
||||
font-size: 13px;
|
||||
line-height: 14px;
|
||||
}
|
||||
.result-warp {
|
||||
width: 22%;
|
||||
}
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,197 @@
|
||||
<template>
|
||||
<div class="etiological">
|
||||
<HeaderCard :column="listColumn" :titleList="titleList" :checkTitle="checkTitle" @change="handleChange" />
|
||||
<div class="etioloical-subject" id="etioloicalView">
|
||||
<div class="subject-item" v-for="(subject, index) in subjectList" :key="index">
|
||||
<div class="subject-title">{{ subject.className }}</div>
|
||||
<div class="question-con" v-for="(qsItem, qsIndex) in subject.qsList" :key="qsIndex">
|
||||
<div class="subtitle">{{ qsIndex + 1 }}、{{ qsItem.qsDes }}</div>
|
||||
<div class="subject-options" v-if="qsItem.qsType === 1">
|
||||
<van-radio-group v-model="qsItem.answer" v-for="(option, optionIndex) in qsItem.answerList" :key="optionIndex" shape="dot">
|
||||
<van-radio class="subject-radio" :name="option.answerNo">{{ option.answerDesc }}</van-radio>
|
||||
</van-radio-group>
|
||||
</div>
|
||||
<template v-if="qsItem.qsType === 4">
|
||||
<div class="subject-input">
|
||||
<van-field v-model="qsItem.answer" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="etioloical-button">
|
||||
<div class="button-text" @click="submit">提交</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import HeaderCard from '../health/components/HeaderCard.vue';
|
||||
import { questionListApi, submitQuestionApi } from './etiologicalApi';
|
||||
import { ref } from 'vue';
|
||||
import { showSuccessToast, showFailToast } from 'vant';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { destroyPage } from '/@/hooks/openPage';
|
||||
import { useLoading } from '../../utils/compUtils';
|
||||
const { loadingSpinner, loadingClose } = useLoading();
|
||||
const router = useRouter();
|
||||
const checkTitle = ref('');
|
||||
const listColumn = {
|
||||
name: 'name',
|
||||
value: 'id',
|
||||
};
|
||||
const subjectList = ref([]);
|
||||
const titleList = ref([]);
|
||||
const subject = ref(null);
|
||||
getQuestion();
|
||||
function getQuestion() {
|
||||
questionListApi({
|
||||
templateNo: checkTitle.value,
|
||||
}).then((res: any) => {
|
||||
let { answer, dict, questions } = res.data;
|
||||
titleList.value = dict;
|
||||
checkTitle.value = checkTitle.value === '' ? dict[0].id : checkTitle.value;
|
||||
subjectList.value = questions.qsClassList;
|
||||
if (answer) getAnswer();
|
||||
});
|
||||
}
|
||||
/*
|
||||
* 回填将选中的答案改为数字类型
|
||||
* */
|
||||
function getAnswer() {
|
||||
let queList = subjectList.value;
|
||||
for (let i = 0; i < queList.length; i++) {
|
||||
for (let y = 0; y < queList[i].qsList.length; y++) {
|
||||
queList[i].qsList[y].answer = parseInt(queList[i].qsList[y].answer);
|
||||
}
|
||||
}
|
||||
}
|
||||
function handleChange(templateNo: number) {
|
||||
checkTitle.value = templateNo;
|
||||
scrollPosition();
|
||||
getQuestion();
|
||||
}
|
||||
// 设置滚动条的初始位置
|
||||
function scrollPosition() {
|
||||
let elementView = document.getElementById('etioloicalView');
|
||||
let { x, y } = elementView.getBoundingClientRect();
|
||||
elementView.scrollTo(x, y);
|
||||
}
|
||||
function submit() {
|
||||
let list: object[] = [];
|
||||
let status = true;
|
||||
let queList = subjectList.value;
|
||||
for (let i = 0; i < queList.length; i++) {
|
||||
for (let y = 0; y < queList[i].qsList.length; y++) {
|
||||
if (queList[i].qsList[y].answer == null) {
|
||||
status = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!status) {
|
||||
showFailToast({
|
||||
message: '请填写完再提交',
|
||||
forbidClick: true,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
loadingSpinner();
|
||||
let newsQueList = JSON.parse(JSON.stringify(queList));
|
||||
newsQueList.map((item: object) => {
|
||||
item.qsList.map((qsitem: object) => {
|
||||
delete qsitem.answerList;
|
||||
delete qsitem.factor;
|
||||
delete qsitem.qsDes;
|
||||
delete qsitem.qsType;
|
||||
delete qsitem.count;
|
||||
delete qsitem.applicableType;
|
||||
list.push(qsitem);
|
||||
});
|
||||
});
|
||||
submitQuestionApi({
|
||||
templateNo: checkTitle.value,
|
||||
qsList: list,
|
||||
}).then((res: any) => {
|
||||
if (res.code === 200) {
|
||||
loadingClose();
|
||||
// destroyPage();
|
||||
showSuccessToast({
|
||||
message: '提交成功',
|
||||
forbidClick: true,
|
||||
});
|
||||
} else {
|
||||
loadingClose();
|
||||
showFailToast({
|
||||
message: res.data.msg,
|
||||
forbidClick: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import '../../assets/less/index.less';
|
||||
.etiological {
|
||||
background-color: @card-gray;
|
||||
.etioloical-subject {
|
||||
background-color: @card-fff;
|
||||
height: calc(100vh - 120px);
|
||||
padding: 0 20px;
|
||||
overflow-y: auto;
|
||||
margin-top: 10px;
|
||||
:deep(.van-cell) {
|
||||
padding: 0;
|
||||
}
|
||||
:deep(.van-radio__icon--checked) {
|
||||
border-color: #21bebe;
|
||||
}
|
||||
:deep(.van-radio__icon--checked.van-radio__icon--dot .van-radio__icon--dot__icon) {
|
||||
background-color: #21bebe;
|
||||
}
|
||||
.subject-input {
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
padding: 0 0 5px 5px;
|
||||
}
|
||||
.subject-item {
|
||||
margin: 10px 0;
|
||||
.subject-title {
|
||||
color: #333333;
|
||||
font-weight: bold;
|
||||
padding: 10px 0;
|
||||
}
|
||||
.question-con {
|
||||
padding: 0 5px;
|
||||
.subtitle {
|
||||
font-size: 15px;
|
||||
padding: 10px 0 10px 5px;
|
||||
position: relative;
|
||||
&:after {
|
||||
content: '*';
|
||||
position: absolute;
|
||||
left: -2px;
|
||||
top: 8px;
|
||||
color: #fd1805;
|
||||
}
|
||||
}
|
||||
}
|
||||
.subject-radio {
|
||||
margin: 14px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.etioloical-button {
|
||||
background-color: @card-fff;
|
||||
height: 50px;
|
||||
padding-top: 20px;
|
||||
.button-text {
|
||||
height: 40px;
|
||||
flex: 1;
|
||||
.flex-center();
|
||||
margin: 0 10%;
|
||||
.footerButton();
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,7 @@
|
||||
import { get, post } from '/@/views/mobile/api/api';
|
||||
|
||||
const prefix: string = import.meta.env.VITE_GLOB_APP_PREFIX || '';
|
||||
|
||||
export const questionListApi = (params) => get(`${prefix}/rest/health-survey/trace/questionnaire`, params);
|
||||
|
||||
export const submitQuestionApi = (params) => post(`${prefix}/rest/health-survey/trace/submit`, params);
|
||||
@@ -0,0 +1,258 @@
|
||||
<template>
|
||||
<div class="answer-page">
|
||||
<div class="answer-progress">
|
||||
<div class="progress-text">
|
||||
<div class="progress-left"
|
||||
>答题进度 {{ schedule }}/{{ questionList.length }}
|
||||
<span>({{ toInt(progressScore) }}%)</span>
|
||||
</div>
|
||||
<div class="progress-right"
|
||||
>作答时间: <span>{{ formatTime }}</span></div
|
||||
>
|
||||
</div>
|
||||
<div class="progress-outer">
|
||||
<a-progress :percent="(100 / questionList.length) * schedule" :show-info="false" strokeLinecap="square" strokeColor="#21BEBE" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="answer-content">
|
||||
<!--答题区域-->
|
||||
<van-skeleton title :row="8" :loading="loading">
|
||||
<QuestionList
|
||||
class="page"
|
||||
:class="pageActive ? '' : 'active'"
|
||||
:key="Date.now()"
|
||||
:isEdit="isEdit"
|
||||
:list="questionList"
|
||||
:current="questionCurrent"
|
||||
@change-option="changeOption"
|
||||
/>
|
||||
</van-skeleton>
|
||||
<AnswerFooter class="bottom-module" @popup-toggle="popupToggle" @next-question="nextQuestion" :next-questionText="nextQuestionText" />
|
||||
</div>
|
||||
<van-popup v-model:show="showPopup" position="bottom" :style="{ height: '100%' }">
|
||||
<AnswerPanel :isEdit="isEdit" :list="questionList" v-if="showPopup" @back="back" @go-to-question="goToQuestion" />
|
||||
</van-popup>
|
||||
<QuitAnswering :questionnaireIndex="questionCurrent" ref="quitDialog" @exit="exit" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref, unref, watch } from 'vue';
|
||||
import QuestionList from '/@/components/questionList/questionList.vue';
|
||||
import AnswerPanel from '/@/views/health-questions/answerPanel.vue';
|
||||
import AnswerFooter from '/@/views/health-questions/components/answerFooter.vue';
|
||||
import QuitAnswering from '/@/components/quitAnswering.vue';
|
||||
import { useRouter, useRoute, onBeforeRouteLeave } from 'vue-router';
|
||||
import { list, useNextQuestionText, useTime } from '/@/views/health-questions/useQuestion';
|
||||
import { showConfirmDialog, showToast } from 'vant';
|
||||
import { getAnswerList, submitAnswer } from '/@/views/health-questions/api';
|
||||
import { timeFormat, toInt } from '/@/hooks/utils';
|
||||
import { newPageParams } from '/@/hooks/openPage';
|
||||
import { useInterceptBack } from '/@/hooks/useInterceptAndroid';
|
||||
import { useLoading } from '/@/utils/compUtils';
|
||||
const progressScore = computed(() => {
|
||||
if (!questionList.value?.length) return 0;
|
||||
return (100 / questionList.value.length) * schedule.value;
|
||||
});
|
||||
const loading = ref(true); //加载骨架屏
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const questionList = ref([]); // 题目数据
|
||||
const questionCurrent = ref(0); // 当前题号
|
||||
const time = ref({
|
||||
startDate: timeFormat(new Date()),
|
||||
endDate: '',
|
||||
});
|
||||
const schedule = computed(() => {
|
||||
let arr = questionList.value.map((item) => item.qsOptionCode) || [];
|
||||
return arr.filter((item) => item != null && item != '').length || 0;
|
||||
});
|
||||
// 底部下一题按钮文本
|
||||
const nextQuestionText = computed(() => useNextQuestionText(questionList.value.length, questionCurrent, true));
|
||||
const isEdit = true;
|
||||
const { formatTime, startTimer, pauseTimer } = useTime(); //定时器
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
const pageActive = ref(true);
|
||||
watch(questionCurrent, () => {
|
||||
if (questionCurrent.value !== 0) {
|
||||
pageActive.value = false;
|
||||
}
|
||||
});
|
||||
async function getList() {
|
||||
let { code, data } = await getAnswerList({ quTotal: '10', module: route.query.module });
|
||||
loading.value = false;
|
||||
if (code !== 200) {
|
||||
return showToast('题库加载失败,请稍后再试');
|
||||
}
|
||||
|
||||
if (!data.length) {
|
||||
showToast('暂无答题内容');
|
||||
let timerId = setTimeout(() => {
|
||||
clearTimeout(timerId);
|
||||
return router.go(-1);
|
||||
}, 2000);
|
||||
} else {
|
||||
startTimer();
|
||||
questionList.value = data || [];
|
||||
}
|
||||
}
|
||||
|
||||
//选择答题选项
|
||||
function changeOption(answer: any) {
|
||||
let current: string = questionCurrent.value + '';
|
||||
questionList.value[current] = unref(answer);
|
||||
}
|
||||
|
||||
// 退出弹窗
|
||||
const quitDialog: any = ref(null);
|
||||
const { loadingSpinner, loadingClose } = useLoading();
|
||||
function nextQuestion() {
|
||||
// 1.如果没有选择禁止进入下一题
|
||||
let len = questionList.value.length;
|
||||
let current = questionCurrent.value;
|
||||
let { qsOptionCode } = questionList.value[current] || '';
|
||||
if (!qsOptionCode) {
|
||||
return showToast('请先填写此问题');
|
||||
}
|
||||
if (len - 1 > current) {
|
||||
questionCurrent.value += 1;
|
||||
quitDialog.value.editBackStatus(current !== len);
|
||||
//判断是否有没做的题
|
||||
const list = unref(questionList.value);
|
||||
let index = list.findIndex((item) => !item?.qsOptionCode);
|
||||
if (index == -1) {
|
||||
questionCurrent.value = questionList.value.length - 1;
|
||||
}
|
||||
} else {
|
||||
//判断是否有没做的题
|
||||
const list = unref(questionList.value);
|
||||
let index = list.findIndex((item) => !item?.qsOptionCode);
|
||||
if (index !== -1) {
|
||||
return showToast(`第${index + 1}题没做,请答完再提交`);
|
||||
}
|
||||
quitDialog.value.editBackStatus(false);
|
||||
showConfirmDialog({
|
||||
title: '',
|
||||
message: '是否确认提交',
|
||||
closeOnPopstate: false,
|
||||
})
|
||||
.then(() => {
|
||||
useInterceptBack(0);
|
||||
time.value.endDate = timeFormat(new Date());
|
||||
const params = {
|
||||
...time.value,
|
||||
list: questionList.value,
|
||||
module: route.query.module,
|
||||
};
|
||||
loadingSpinner();
|
||||
submitAnswer(params)
|
||||
.then(({ code, data, message }) => {
|
||||
loadingClose();
|
||||
if (code !== 200 || !data) {
|
||||
return showToast(message);
|
||||
}
|
||||
router.replace({
|
||||
path: '/complete-answer',
|
||||
query: newPageParams({
|
||||
id: data + '',
|
||||
module: route.query.module,
|
||||
}),
|
||||
});
|
||||
})
|
||||
.catch((msg) => {
|
||||
console.log('msg', msg);
|
||||
loadingClose();
|
||||
showToast('请稍后再试!');
|
||||
});
|
||||
pauseTimer();
|
||||
})
|
||||
.catch(() => {
|
||||
// on cancel
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
const showPopup = ref(false);
|
||||
|
||||
function popupToggle() {
|
||||
showPopup.value = !showPopup.value;
|
||||
}
|
||||
|
||||
function back() {
|
||||
popupToggle();
|
||||
}
|
||||
|
||||
// 答题卡切题
|
||||
function goToQuestion(index: number) {
|
||||
questionCurrent.value = index;
|
||||
}
|
||||
|
||||
function exit() {
|
||||
goToQuestion(1);
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
@import '/@/assets/less/index';
|
||||
.page {
|
||||
position: relative;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* 设置页面的目标位置 */
|
||||
.page.active {
|
||||
animation: move 0.4s forwards;
|
||||
position: relative;
|
||||
}
|
||||
@keyframes move {
|
||||
0% {
|
||||
left: 0;
|
||||
}
|
||||
49% {
|
||||
left: -100%;
|
||||
}
|
||||
50% {
|
||||
left: 100%;
|
||||
}
|
||||
100% {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
.answer-page {
|
||||
height: 100vh;
|
||||
font-size: 16px;
|
||||
.flex-column();
|
||||
justify-content: space-between;
|
||||
|
||||
.answer-progress {
|
||||
height: 60px;
|
||||
|
||||
.progress-text {
|
||||
margin-top: 10px;
|
||||
padding: 0 16px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.progress-left {
|
||||
}
|
||||
|
||||
.progress-right {
|
||||
}
|
||||
}
|
||||
|
||||
.answer-content {
|
||||
min-height: 400px;
|
||||
flex: 1;
|
||||
.flex-column();
|
||||
justify-content: space-between;
|
||||
overflow: hidden;
|
||||
|
||||
.bottom-module {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,117 @@
|
||||
<!--答题卡页-->
|
||||
<template>
|
||||
<div class="question-panel">
|
||||
<div class="question-container">
|
||||
<AnswerStatusDesc :isEdit="isEdit" />
|
||||
<div class="question">
|
||||
<div class="question-list">
|
||||
<div v-for="(question, index) in list" :key="index" @click="goToQuestion(index)" class="question-item" :class="status(index)">
|
||||
{{ index + 1 }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="back" @click="backPage">返回</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import AnswerStatusDesc from '/@/views/health-questions/components/answerStatusDesc.vue';
|
||||
|
||||
const emit = defineEmits(['back', 'goToQuestion']);
|
||||
const props = defineProps({
|
||||
isEdit: {
|
||||
type: Boolean,
|
||||
default: () => true,
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
},
|
||||
// 答题卡选择状态
|
||||
answerStatus: {
|
||||
type: Array,
|
||||
},
|
||||
});
|
||||
const status = (i) => {
|
||||
if (props.isEdit) {
|
||||
return props.list[i].qsOptionCode ? 'already' : '';
|
||||
} else {
|
||||
return props.answerStatus[i] ? 'already' : 'wrong';
|
||||
}
|
||||
};
|
||||
|
||||
function goToQuestion(index: number) {
|
||||
emit('goToQuestion', index);
|
||||
emit('back');
|
||||
}
|
||||
|
||||
function backPage() {
|
||||
emit('back');
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
@import '../../assets/less/index';
|
||||
|
||||
.question-panel {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.question-container {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.question {
|
||||
margin: 10px 10px;
|
||||
|
||||
.question-topic {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.question-subText {
|
||||
font-size: 14px;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.question-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 10px 0;
|
||||
|
||||
.question-item {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: 10px;
|
||||
margin-bottom: 0;
|
||||
border-radius: 50%;
|
||||
.flex-center();
|
||||
border: 1px solid #999999;
|
||||
|
||||
&.already {
|
||||
background: rgba(33, 190, 190, 0.2);
|
||||
//border: 1px solid #21bebe;
|
||||
border: none;
|
||||
color: #21bebe;
|
||||
}
|
||||
|
||||
&.wrong {
|
||||
background: rgba(237, 42, 38, 0.2);
|
||||
//border: 1px solid #ed2a26;
|
||||
border: none;
|
||||
color: #ed2a26;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.back {
|
||||
margin: 20px 30%;
|
||||
height: 35px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #999999;
|
||||
border-radius: 35px;
|
||||
.flex-center();
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div class="answer-records-list" :class="[empty ? 'em-bg' : '']">
|
||||
<template v-for="(item, k) in recordList" :key="k">
|
||||
<AnswerRecordsCard :cardInfo="item" cardType="card1" @view-record="viewRecord" />
|
||||
</template>
|
||||
<van-empty class="em-position" v-if="empty" image-size="200" description="暂无数据" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import AnswerRecordsCard from '/@/views/health-questions/components/answerRecordsCard.vue';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { answerRecordList } from '/@/views/health-questions/api';
|
||||
import { newPageParams, openPage } from '/@/hooks/openPage';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
const route = useRoute();
|
||||
const recordList = ref([]);
|
||||
const empty = ref(false);
|
||||
onMounted(() => {
|
||||
empty.value = false;
|
||||
getRecordList();
|
||||
});
|
||||
|
||||
function getRecordList() {
|
||||
answerRecordList({ module: route.query.module })
|
||||
.then(({ code, data }) => {
|
||||
if (code == 200) {
|
||||
if (!data.length) return (empty.value = true);
|
||||
recordList.value = data;
|
||||
empty.value = false;
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
empty.value = true;
|
||||
});
|
||||
}
|
||||
|
||||
// 查看记录
|
||||
function viewRecord(id: number) {
|
||||
openPage('/complete-answer', newPageParams({ id: id + '', module: route.query.module }));
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
@import '../../assets/less/index.less';
|
||||
|
||||
.answer-records-list {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
.flex-column();
|
||||
padding: 10px 20px;
|
||||
background-color: #efefef;
|
||||
|
||||
&.em-bg {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.em-position {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,34 @@
|
||||
import { get, post } from '/@/views/mobile/api/api';
|
||||
import { apiPrefix } from '/@/api/apiPrefix';
|
||||
|
||||
export enum QsType {
|
||||
testType = '1', //1推荐试卷 0 固定试卷
|
||||
}
|
||||
|
||||
const prefix: string = import.meta.env.VITE_GLOB_APP_PREFIX;
|
||||
const { healthAnswer } = apiPrefix;
|
||||
export const Api = {
|
||||
answerList: prefix + `/rest/${healthAnswer}/answer/answerList`,
|
||||
submitAnswer: prefix + `/rest/${healthAnswer}/answer/submitAnswer`,
|
||||
answerInfoByRecordId: prefix + `/rest/${healthAnswer}/answer/answerInfoByRecordId`,
|
||||
answerRecordList: prefix + `/rest/${healthAnswer}/answer/answerUserRecordList`,
|
||||
questionHome: prefix + `/rest/${healthAnswer}/answer/home`,
|
||||
};
|
||||
|
||||
// 获取题目
|
||||
export const getAnswerList = (params: any) =>
|
||||
post(Api.answerList, {
|
||||
qsAnsType: QsType.testType,
|
||||
...params,
|
||||
});
|
||||
|
||||
// 提交试卷
|
||||
export const submitAnswer = (params: any) => post(Api.submitAnswer, params);
|
||||
|
||||
// 查询考卷记录
|
||||
export const answerInfoByRecordId = (params: any) => post(Api.answerInfoByRecordId, params);
|
||||
|
||||
// 查询答题记录列表
|
||||
export const answerRecordList = (params: any) => get(Api.answerRecordList, params);
|
||||
//题目列表接口
|
||||
export const questionHome = (params: any) => get(Api.questionHome, params);
|
||||
@@ -0,0 +1,286 @@
|
||||
<!--完成答题页-->
|
||||
<template>
|
||||
<div class="complete-answer-page">
|
||||
<div class="bg-top">
|
||||
<div class="top-content">
|
||||
<div>
|
||||
<p class="complete-title">完成答题</p>
|
||||
<p class="complete-sub-title">快来看看你的得分情况吧</p>
|
||||
</div>
|
||||
<div class="item-group">
|
||||
<div class="item-row">
|
||||
<div class="item-col">
|
||||
<p>{{ recordInfo.questionNum }}</p>
|
||||
<p>总计(题)</p>
|
||||
</div>
|
||||
<div class="item-col">
|
||||
<p>{{ recordInfo.trueAnswer }}</p>
|
||||
<p>答对(题)</p>
|
||||
</div>
|
||||
<div class="item-col">
|
||||
<p>{{ timeFormat(recordInfo.startTime, 'HH:mm') }}</p>
|
||||
<p>{{ timeFormat(recordInfo.startTime, 'yyyy-MM-DD') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-row">
|
||||
<div class="item-col">
|
||||
<p>{{ recordInfo.totalScore }}</p>
|
||||
<p>总分(分)</p>
|
||||
</div>
|
||||
<div class="item-col">
|
||||
<p>{{ recordInfo.sumScore }}</p>
|
||||
<p>得分(分)</p>
|
||||
</div>
|
||||
<div class="item-col">
|
||||
<p>{{ recordInfo.answerUseTime }}</p>
|
||||
<p>作答用时(分)</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="answer-content">
|
||||
<div class="answer-con-top">
|
||||
<van-skeleton title :row="8" :loading="loading">
|
||||
<ResultQuestion :isEdit="false" :list="questionList" :current="questionCurrent" />
|
||||
</van-skeleton>
|
||||
</div>
|
||||
<div>
|
||||
<AnswerFooter @popup-toggle="popupToggle" @next-question="nextQuestion" :nextQuestionText="nextQuestionText" />
|
||||
</div>
|
||||
</div>
|
||||
<van-popup v-model:show="showPopup" :style="{ height: '100%' }" position="bottom">
|
||||
<AnswerPanel
|
||||
v-if="showPopup"
|
||||
:isEdit="false"
|
||||
:list="questionList"
|
||||
:answer-status="answerStatus"
|
||||
@back="back"
|
||||
@go-to-question="goToQuestion"
|
||||
/>
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import ResultQuestion from '/@/components/result-question/resultQuestion.vue';
|
||||
import AnswerFooter from '/@/views/health-questions/components/answerFooter.vue';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { useNextQuestionText } from '/@/views/health-questions/useQuestion';
|
||||
import AnswerPanel from '/@/views/health-questions/answerPanel.vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { answerInfoByRecordId } from '/@/views/health-questions/api';
|
||||
import { showToast } from 'vant';
|
||||
import { timeFormat } from '/@/hooks/utils';
|
||||
import { newPageParams } from '/@/hooks/openPage.ts';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const questionList = ref([]);
|
||||
// 答题卡状态-颜色
|
||||
const answerStatus = computed(() => {
|
||||
let arr: any[] = [];
|
||||
questionList.value.map((item: any) => {
|
||||
// 单选
|
||||
if (item.qsAnsType == 0) {
|
||||
let status = item.optionVoList.find((val: any) => val.qsScore !== 0).qsOptionCode == item?.chooseOption;
|
||||
arr.push(status);
|
||||
// 多选
|
||||
} else if (item.qsAnsType == 1) {
|
||||
let correct = item.optionVoList.filter((val: any) => val.qsScore !== 0);
|
||||
let status = correct.every((val: any) => item.chooseOption.includes(val.qsOptionCode));
|
||||
arr.push(status);
|
||||
}
|
||||
});
|
||||
return arr;
|
||||
});
|
||||
const questionCurrent = ref(0);
|
||||
|
||||
onMounted(() => {
|
||||
getAnswerInfo();
|
||||
});
|
||||
const loading = ref(true); //加载骨架屏
|
||||
// 答题信息
|
||||
const recordInfo = ref({
|
||||
questionNum: '',
|
||||
startTime: '',
|
||||
sumScore: '',
|
||||
totalScore: '',
|
||||
trueAnswer: '',
|
||||
answerUseTime: '',
|
||||
});
|
||||
|
||||
function getAnswerInfo() {
|
||||
if (!route.query.id) return showToast('请求参数信息有误');
|
||||
const params = {
|
||||
recordId: route.query.id + '',
|
||||
};
|
||||
answerInfoByRecordId(params)
|
||||
.then(({ code, data }) => {
|
||||
loading.value = false;
|
||||
if (code == 200) {
|
||||
const { answerQsOptionVoList, questionNum, startTime, sumScore, totalScore, trueAnswer, answerUseTime } = data;
|
||||
recordInfo.value = {
|
||||
questionNum,
|
||||
startTime,
|
||||
sumScore,
|
||||
totalScore,
|
||||
trueAnswer,
|
||||
answerUseTime,
|
||||
};
|
||||
if (!answerQsOptionVoList?.length) {
|
||||
loading.value = false;
|
||||
}
|
||||
questionList.value = answerQsOptionVoList?.map((item: any) => ({
|
||||
...item,
|
||||
correctOption: item.optionVoList.find((val: any) => val.qsScore !== 0).qsOptionCode,
|
||||
}));
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
// 下一题
|
||||
function nextQuestion() {
|
||||
let len = questionList.value.length;
|
||||
let current = questionCurrent.value;
|
||||
if (current < len - 1) {
|
||||
questionCurrent.value += 1;
|
||||
} else {
|
||||
router.replace({ path: '/answer-recordsList', query: newPageParams({ module: route.query.module }) });
|
||||
// openPage('/answer-recordsList', newPageParams());
|
||||
}
|
||||
}
|
||||
|
||||
const showPopup = ref(false);
|
||||
|
||||
function popupToggle() {
|
||||
showPopup.value = !showPopup.value;
|
||||
}
|
||||
|
||||
function back() {
|
||||
popupToggle();
|
||||
}
|
||||
|
||||
// 答题卡切题
|
||||
function goToQuestion(index: number) {
|
||||
questionCurrent.value = index;
|
||||
}
|
||||
|
||||
const nextQuestionText = computed(() => useNextQuestionText(questionList.value.length, questionCurrent, false));
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.complete-answer-page {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.bg-top {
|
||||
height: 300px;
|
||||
min-height: 300px;
|
||||
background: url('/@/assets/images/health-interventions/complete-bg.png') no-repeat;
|
||||
background-size: 100%;
|
||||
|
||||
.top-content {
|
||||
padding: 20px;
|
||||
|
||||
.complete-title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.complete-sub-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
margin: 6px 0 10px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.item-group {
|
||||
height: 140px;
|
||||
min-height: 140px;
|
||||
background: rgba(16, 158, 158, 0.3);
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0 12px;
|
||||
|
||||
.item-row {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
||||
.item-col {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.item-col:nth-child(2):before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: 30%;
|
||||
left: 0;
|
||||
width: 1px;
|
||||
height: 30%;
|
||||
background-color: rgba(222, 222, 222, 0.7);
|
||||
}
|
||||
|
||||
.item-col:nth-child(2):after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: 30%;
|
||||
right: 0;
|
||||
width: 1px;
|
||||
height: 30%;
|
||||
background-color: rgba(222, 222, 222, 0.7);
|
||||
}
|
||||
|
||||
.item-col > p {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.item-col > p:first-child {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.item-row:first-child {
|
||||
border-bottom: 1px solid rgba(222, 222, 222, 0.4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.answer-content {
|
||||
flex: 1;
|
||||
min-height: 450px;
|
||||
margin: -58px 20px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
height: 281px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 8px 18px 2px rgba(51, 51, 51, 0.1);
|
||||
border-radius: 10px 10px 0 0;
|
||||
|
||||
.answer-con-top {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<div class="answer-footer">
|
||||
<div class="answer-sheet" @click="popupToggle">
|
||||
<van-icon class="vant-icon" name="records" />
|
||||
<div class="sheet-text">答题卡</div>
|
||||
</div>
|
||||
<div class="next-question" @click="nextQuestion">
|
||||
{{ nextQuestionText }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
|
||||
const emit = defineEmits(['popupToggle', 'nextQuestion']);
|
||||
const props = defineProps({
|
||||
nextQuestionText: propTypes.string.def(''),
|
||||
});
|
||||
|
||||
function popupToggle() {
|
||||
emit('popupToggle');
|
||||
}
|
||||
|
||||
function nextQuestion() {
|
||||
emit('nextQuestion');
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
@import '/@/assets/less/index';
|
||||
|
||||
.answer-footer {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.answer-sheet {
|
||||
width: 120px;
|
||||
.flex-center();
|
||||
flex-direction: column;
|
||||
|
||||
.vant-icon {
|
||||
font-size: 20px;
|
||||
height: 23px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sheet-text {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.next-question {
|
||||
.flex-center();
|
||||
flex: 1;
|
||||
color: #fff;
|
||||
height: 36px;
|
||||
margin-right: 20px;
|
||||
border-radius: 35px;
|
||||
.qs-btn();
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,154 @@
|
||||
<template>
|
||||
<div class="answer-records-card" :style="card.style.bgc">
|
||||
<div class="tag-title" :style="card.style.fontColor">{{ questionTit(cardInfo?.testType) }}</div>
|
||||
<div class="tag-score">{{ cardInfo?.sumScore }}分</div>
|
||||
<div class="tab-content">
|
||||
<div class="tab-content-text">
|
||||
<h3 class="tab-title">{{ cardInfo?.title }}</h3>
|
||||
<p class="tab-p">{{ cardInfo?.desc }}</p>
|
||||
<div class="tab-button-box">
|
||||
<div class="tab-button" :style="card.style.fontColor" @click="viewRecord">查看</div>
|
||||
<p class="answer-time"> 答题用时:{{ cardInfo?.useTime <= 1 ? 1 : cardInfo?.useTime }}分钟</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-content-img" v-if="false">
|
||||
<img :src="card.imgUrl" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { questionTit } from '/@/views/health-questions/useQuestion.ts';
|
||||
|
||||
const props = defineProps({
|
||||
cardType: String,
|
||||
cardInfo: Object,
|
||||
});
|
||||
const emit = defineEmits(['viewRecord']);
|
||||
const cardList = {
|
||||
card1: {
|
||||
imgUrl: new URL('/@/assets/images/health-interventions/ques-icon1.png', import.meta.url).href,
|
||||
style: {
|
||||
fontColor: 'color: #1F91F2',
|
||||
bgc: 'background: linear-gradient(147deg, #40A1F4 0%, #4D89DC 100%);',
|
||||
},
|
||||
},
|
||||
card2: {
|
||||
imgUrl: new URL('/@/assets/images/health-interventions/ques-icon2.png', import.meta.url).href,
|
||||
style: {
|
||||
fontColor: 'color: #52C41A',
|
||||
bgc: 'background: linear-gradient(147deg, #75C34D 0%, #5AA238 100%);',
|
||||
},
|
||||
},
|
||||
card3: {
|
||||
imgUrl: new URL('/@/assets/images/health-interventions/ques-icon3.png', import.meta.url).href,
|
||||
style: {
|
||||
fontColor: 'color: #13C2C2',
|
||||
bgc: 'background: linear-gradient(147deg, #3EBDBD 0%, #369898 100%);',
|
||||
},
|
||||
},
|
||||
};
|
||||
const card = computed(() => cardList[props.cardType]);
|
||||
|
||||
//查看记录
|
||||
function viewRecord() {
|
||||
emit('viewRecord', props.cardInfo.recordId + '');
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
@import '../../../assets/less/index.less';
|
||||
|
||||
.answer-records-card {
|
||||
width: 100%;
|
||||
//height: 160px;
|
||||
padding-bottom: 10px;
|
||||
position: relative;
|
||||
background: linear-gradient(147deg, #40a1f4 0%, #4d89dc 100%);
|
||||
border-radius: 20px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.tag-title {
|
||||
.flex-center();
|
||||
margin-left: 20px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #1f91f2;
|
||||
width: 80px;
|
||||
height: 25px;
|
||||
background: #ffffff;
|
||||
border-radius: 0 0 6px 6px;
|
||||
}
|
||||
|
||||
.tag-score {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 10px;
|
||||
font-size: 17px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
margin-left: 20px;
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
.tab-content-text {
|
||||
width: 85%;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.tab-title {
|
||||
font-size: 17px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.tab-p {
|
||||
font-size: 14px;
|
||||
font-weight: 300;
|
||||
margin: 0;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.tab-button-box {
|
||||
display: flex;
|
||||
|
||||
.tab-button {
|
||||
.flex-center();
|
||||
width: 100px;
|
||||
height: 30px;
|
||||
color: #5596f0;
|
||||
background: #ffffff;
|
||||
margin-top: 10px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
box-shadow: 0 4px 8px 0 rgba(46, 85, 138, 0.2);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.answer-time {
|
||||
margin: 14px 0 0 6px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-content-img {
|
||||
position: absolute;
|
||||
top: 28px;
|
||||
right: 19px;
|
||||
width: 80px;
|
||||
height: 66px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<div v-if="isEdit" class="status-desc">
|
||||
<span class="desc-text">状态说明:</span>
|
||||
<span class="status-text already">已作答</span>
|
||||
<span class="status-text">未作答</span>
|
||||
</div>
|
||||
<div v-else class="status-desc">
|
||||
<span class="desc-text">状态说明:</span>
|
||||
<span class="status-text already">正确</span>
|
||||
<span class="status-text wrong">错误</span>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
isEdit: {
|
||||
type: Boolean,
|
||||
default: () => true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.status-desc {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
font-size: 16px;
|
||||
background-color: #eeeeee;
|
||||
|
||||
.desc-text {
|
||||
margin: 0 20px;
|
||||
}
|
||||
|
||||
.status-text:before {
|
||||
display: inline-block;
|
||||
content: '';
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin: 0 4px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #999999;
|
||||
}
|
||||
|
||||
.already {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.already:before {
|
||||
background: rgba(33, 190, 190, 0.2);
|
||||
border: 1px solid #21bebe;
|
||||
}
|
||||
|
||||
.wrong:before {
|
||||
background: rgba(237, 42, 38, 0.2);
|
||||
border: 1px solid #ed2a26;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,138 @@
|
||||
<template>
|
||||
<div class="tab-card" :style="cardInfo?.style.bgc">
|
||||
<div class="tag-title" :style="cardInfo?.style.fontColor">{{ card?.module_dictText }}</div>
|
||||
<div class="tag-time">{{ cardInfo?.timeText }}</div>
|
||||
<div class="tab-content">
|
||||
<div class="tab-content-text">
|
||||
<h3 class="tab-title">{{ card?.title }}</h3>
|
||||
<p class="tab-p">{{ card?.desc }}</p>
|
||||
</div>
|
||||
<div class="tab-content-img" v-if="false">
|
||||
<img :src="cardInfo?.imgUrl" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-list">
|
||||
<div class="tab-button record-btn" @click="recordClick">
|
||||
{{ cardInfo?.recordText }}
|
||||
</div>
|
||||
<div class="tab-button" :style="cardInfo?.style.fontColor" @click="btnClick">
|
||||
{{ cardInfo?.tabBtnText }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { cardList } from '/@/views/health-questions/data';
|
||||
const props = defineProps({
|
||||
cardType: String,
|
||||
card: Object,
|
||||
});
|
||||
const emits = defineEmits(['btnClick', 'recordClick']);
|
||||
|
||||
const cardInfo = computed(() => cardList[props.cardType]);
|
||||
|
||||
function btnClick() {
|
||||
emits('btnClick');
|
||||
}
|
||||
|
||||
function recordClick() {
|
||||
emits('recordClick');
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
@import '/@/assets/less/index.less';
|
||||
|
||||
.tab-card {
|
||||
width: 100%;
|
||||
padding-bottom: 10px;
|
||||
position: relative;
|
||||
background: linear-gradient(147deg, #40a1f4 0%, #4d89dc 100%);
|
||||
border-radius: 20px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.tag-title {
|
||||
.flex-center();
|
||||
margin-left: 20px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #1f91f2;
|
||||
width: 80px;
|
||||
height: 25px;
|
||||
background: #ffffff;
|
||||
border-radius: 0 0 6px 6px;
|
||||
}
|
||||
|
||||
.tag-time {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 10px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
margin-left: 20px;
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
.tab-content-text {
|
||||
width: 85%;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.tab-title {
|
||||
font-size: 17px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.tab-p {
|
||||
font-size: 14px;
|
||||
font-weight: 300;
|
||||
margin: 0;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.tab-content-img {
|
||||
position: absolute;
|
||||
top: 28px;
|
||||
right: 19px;
|
||||
width: 80px;
|
||||
height: 66px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-list {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.tab-button {
|
||||
.flex-center();
|
||||
width: 100px;
|
||||
height: 30px;
|
||||
color: #5596f0;
|
||||
background: #ffffff;
|
||||
margin-top: 10px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
box-shadow: 0 4px 8px 0 rgba(46, 85, 138, 0.2);
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.record-btn {
|
||||
background: transparent;
|
||||
border: 1px solid #ffffff;
|
||||
color: #fff;
|
||||
margin-left: 10px;
|
||||
box-shadow: 0 4px 8px 0 rgba(46, 85, 138, 0.2);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user