volunteer-secondary/src/chart-sub/evaluate/doPage/assessmentPage.vue

366 lines
9.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view class="flex flex-col h-screen relative">
<Navbar
safeAreaInsetTop
:bordered="false"
leftArrow
@clickLeft="handleBack"
bg-color="transparent"
>
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium text-[#fff]">{{ pageName }}</text>
</template>
</Navbar>
<view class="h-full w-full custom-bg absolute top-0 left-0 -z-1"></view>
<view class="question-container flex-1 overflow-hidden mt-[30rpx] flex">
<view class="flex-1 h-0 relative">
<view
v-for="(question, index) in questions"
:key="index"
:class="`h-full overflow-y-auto card-container ${currentIndex === index ? 'current-card' : ''}`"
>
<view class="px-[30rpx] py-[40rpx] flex flex-col card-content">
<text class="mb-[30rpx] text-[34rpx] font-semibold">
{{ index + 1 }}、{{ question.title }}
</text>
<CheckboxGroup
v-model="checkedList"
checked-color="#1580FF"
@change="handleCheckChange"
:max="questionType === 0 ? 1 : 0"
checkgroupStyle="grid-template-columns: repeat(1, 1fr);"
>
<Checkbox
v-for="item in question.answer"
:key="item.key"
:name="item.key"
cell
shape="button"
root-class="custom-checkbox"
default-style="width: 100%;height: 80rpx;background-color: #f6f7f8;border-radius: 8rpx;display: flex;align-items: center;justify-content: center;font-size: 28rpx;font-weight: 400;color: #303030;border: 2rpx solid #f6f7f8;"
>
{{ item.name }}
</Checkbox>
</CheckboxGroup>
</view>
</view>
</view>
<view class="mt-[86rpx] px-[30rpx]">
<button class="next-question" :disabled="disableBtn" @click="handleNextQuestion">
{{ currentIndex === questions.length - 1 ? '提交' : '下一题' }}
({{ currentIndex + 1 }}/{{ questions.length }})
</button>
</view>
</view>
</view>
<MessageBox v-model:show="show" title="" :defaultPadding="false" defaultWidth="80%">
<template>
<view class="custom-background">
<view class="px-[32rpx] pt-[48rpx]">
<text class="text-[#000] text-[48rpx] font-semibold">{{ questionName }}</text>
<view
class="bg-[rgba(21,128,255,0.1)] flex items-center gap-[10rpx] text-[24rpx] text-[#444] px-[24rpx] py-[6rpx] w-max rounded-[10rpx] mt-[10rpx]"
>
<view class="i-carbon-time-filled text-[#1580FF] w-[24rpx] h-[24rpx]"></view>
<view>{{ useTime }}</view>
</view>
<view class="text-[30rpx] my-[40rpx] text-[#333] text-[28rpx]">
{{ quesApplication }}
</view>
</view>
<view
class="text-center py-[26rpx] text-[#1580FF] text-[36rpx] font-medium start-border"
@click="show = false"
>
开始答题
</view>
</view>
</template>
</MessageBox>
</template>
<script setup lang="ts">
import Navbar from '@/chart-sub/components/navbar/Navbar.vue'
import MessageBox from '@/chart-sub/components/messageBox/MessageBox.vue'
import {
getAssessmentQuestions,
getBusScaleDescription,
saveBusScaleAnswer,
} from '@/service'
import Checkbox from '@/chart-sub/components/check-group/Checkbox.vue'
import CheckboxGroup from '@/chart-sub/components/check-group/CheckboxGroup.vue'
import { useUserStore } from '@/store/user'
import { useRouterDetail } from '@/hooks/useRouterDetail'
// #ifdef MP-WEIXIN
definePage({
style: {
navigationStyle: 'custom',
},
})
// #endif
// #ifndef MP-WEIXIN
definePage({
style: {
navigationStyle: 'custom',
transparentTitle: 'always',
navigationBarTitleText: '',
},
})
// #endif
const userStore = useUserStore()
const pageName = ref('')
const pageId = ref(-1)
const show = ref(true)
const handleBack = () => {
uni.navigateBack()
}
const checkedList = ref([])
const answerMap = new Map()
const disableBtn = ref(true)
const handleCheckChange = (value: any[]) => {
if (value.length === 0) {
disableBtn.value = true
return
} else {
disableBtn.value = false
}
if (questionType.value === 0 && value.length > 0) {
// 单选题就点完跳下一题
const timer = setTimeout(() => {
handleNextQuestion()
clearTimeout(timer)
}, 250)
}
}
const calcScore = () => {
// 取当前题目的评分维度 type同一维度的题目会累计到 answerMap 的同一个 key 下
let _type = questions.value[currentIndex.value].type
// 维度名称取当前题目第一个答案项上的 tag用于提交时展示该维度名称
// 从当前题目的全部选项中筛出用户已勾选的选项,单选/多选都按 checkedList 统一处理
let _options = questions.value[currentIndex.value].answer.filter((answer:any) => {
return checkedList.value.includes(answer.key)
})
let _name = _options[0]?.tag || questions.value[currentIndex.value].answer[0].tag
if (answerMap.has(_type)) {
// 如果该维度之前已经答过题,就在已有总分上叠加本题已选选项的分值
let val = answerMap.get(_type)
val.value += _options.reduce((count, cur) => (count = count + Number(cur.value)), 0)
answerMap.set(_type, val)
} else {
// 如果是第一次遇到该维度,则初始化该维度的名称和分值
answerMap.set(_type, {
name: _name,
value: _options.reduce((count, cur) => (count = count + Number(cur.value)), 0),
})
}
}
// 当前显示的卡片索引
const currentIndex = ref(0)
const questions = ref<any[]>([])
const questionType = ref(-1)
const questionName = ref('')
const useTime = ref('')
const quesApplication = ref('')
const isLoading = ref(false)
onLoad((options:any) => {
pageName.value = options.name
pageId.value = options.id
getAssessmentQuestions({query:{ ScaleId: pageId.value }}).then((res) => {
if (res.code === 200) {
let result = res.result as {
name: string
description: string
go: number
questionsType: number
scaleQuestions: any[]
}
questions.value = result.scaleQuestions
questionType.value = result.questionsType
}
})
getBusScaleDescription({query:{ ScaleId: pageId.value }}).then((res) => {
if (res.code === 200) {
let result = (
res.result as {
busScaleDescriptions: any[]
}
).busScaleDescriptions[0]
questionName.value = result.title
quesApplication.value = result.application
useTime.value = result.usesTime
}
})
})
const handleNextQuestion = () => {
if (disableBtn.value) return
disableBtn.value = true
calcScore()
checkedList.value = []
if (currentIndex.value === questions.value.length - 1) {
handleSubmit()
} else {
currentIndex.value++
}
}
const handleSubmit = () => {
if (isLoading.value) {
return
}
isLoading.value = true
let params:any = {
customId: userStore.userInfo.wxId,
scaleId: pageId.value,
inputs: [],
}
let _inputs:any[] = []
answerMap.forEach((value, key) => {
_inputs.push({ type: key, name: value.name, value: value.value })
})
params.inputs = _inputs
saveBusScaleAnswer({data:params}).then((res) => {
isLoading.value = false
let _result = res.result as {
reportId: string
type: number
}
if (res.code === 200) {
// uni.navigateBack()
useRouterDetail({ reportsId: _result.reportId, type: _result.type })
} else {
uni.showToast({
title: res.message,
icon: 'none',
})
}
})
}
</script>
<style scoped lang="scss">
.custom-bg {
background: linear-gradient(184deg, #0d79fc 0%, #2186fc 56%, #b3ebfc 100%);
}
.custom-background {
background: linear-gradient(180deg, #d8e7fc 0%, rgba(255, 255, 255, 0) 20%);
border-radius: 24rpx;
}
:deep(.icon-class) {
color: #fff !important;
}
.start-border {
border-top: 1rpx solid #dedede;
}
.next-question {
background: #1580ff;
border-radius: 16rpx;
height: 88rpx;
line-height: 1;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
}
:deep(.custom-checkbox) {
//
.checkbox {
width: 100%;
height: 80rpx;
background-color: #f6f7f8;
border-radius: 8rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
font-weight: 400;
color: #303030;
border: 2rpx solid #f6f7f8;
}
.checkbox__icon {
display: none;
}
}
:deep(.checkbox-group) {
display: grid !important;
gap: 16rpx;
// padding: 32rpx 16rpx 16rpx;
}
:deep(.checkbox-active) {
background: rgba(21, 128, 255, 0.05) !important;
border: 2rpx solid #1580ff !important;
border: 2rpx solid #1580ff;
.checkbox__label {
color: #2a82e4 !important;
}
}
.question-container {
position: relative;
display: flex;
flex-direction: column;
padding-bottom: calc(20rpx + constant(safe-area-inset-bottom));
padding-bottom: calc(env(safe-area-inset-bottom) + 20rpx);
// safe-area-inset-bottom 0 padding-bottom 20rpx
@if env(safe-area-inset-bottom) == 0 {
padding-bottom: 20rpx;
}
}
.card-container {
background: rgb(140, 199, 245);
width: calc(100% - 60rpx);
border-radius: 20rpx;
position: absolute;
transform: translate3d(100vw, 0, 0);
margin: 0 30rpx;
overflow-y: auto;
}
.current-card {
background: #fff;
z-index: 1;
transform: translate3d(0, 0, 0);
transition: all 0.3s ease;
}
wx-button[disabled]:not([type]) {
background-color: rgba(255, 255, 255, 0.4);
color: #fff;
}
</style>