|
|
@ -3,27 +3,56 @@ |
|
|
|
<view class="page"> |
|
|
|
<view class="box"> |
|
|
|
<view class="content bg-fff"> |
|
|
|
<view class="group" v-for="(group, gIdx) in list" :key="`group-${gIdx}`"> |
|
|
|
<view class="label size-22 level" :style="{borderRadius:'10rpx'}"> |
|
|
|
{{ group.title }} |
|
|
|
<!-- 选择题部分 --> |
|
|
|
<view class="question-section" v-if="basicQuestions.length > 0 && !baseSuccess"> |
|
|
|
<view class="section-title">选择题</view> |
|
|
|
<view class="question__view display" v-for="(question, index) in basicQuestions" :key="index"> |
|
|
|
<view class="size-28 mb20 question"> |
|
|
|
{{ `${question.title}` }} |
|
|
|
</view> |
|
|
|
<view class="size-28 option" v-for="(option, oIdx) in question.answerList" |
|
|
|
:key="`${index}-option-${oIdx}`" |
|
|
|
:class="[ |
|
|
|
option.isTrue ? 'is-correct' : '', |
|
|
|
isOptionSelected(question, option.id) && !option.isTrue ? 'is-error' : '' |
|
|
|
]"> |
|
|
|
{{ option.title }} |
|
|
|
<view class="icon icon-correct" v-if="option.isTrue"> |
|
|
|
<up-icon name="checkmark" color="#05C160" size="35rpx"></up-icon> |
|
|
|
</view> |
|
|
|
<view class="icon icon-error" v-if="isOptionSelected(question, option.id) && !option.isTrue"> |
|
|
|
<up-icon name="close" color="#FF2A2A" size="35rpx"></up-icon> |
|
|
|
</view> |
|
|
|
</view> |
|
|
|
</view> |
|
|
|
<view > |
|
|
|
<questionCard |
|
|
|
v-for="(item, qIdx) in group.children" |
|
|
|
:key="`${gIdx}-question-${qIdx}`" |
|
|
|
:index="qIdx" |
|
|
|
:data="item" |
|
|
|
:type="item.type" |
|
|
|
mode="display" |
|
|
|
></questionCard> |
|
|
|
</view> |
|
|
|
|
|
|
|
<!-- 培训题部分 --> |
|
|
|
<view class="question-section" v-if="trainQuestions.length > 0"> |
|
|
|
<view class="section-title">培训题</view> |
|
|
|
<view class="question__view display" v-for="(question, index) in trainQuestions" :key="index"> |
|
|
|
<view class="size-28 mb20 question"> |
|
|
|
{{ `${question.title}` }} |
|
|
|
</view> |
|
|
|
<view class="textarea"> |
|
|
|
<view class="answer-content">{{ question.userAppletAnswerTrain?.answer || '未作答' }}</view> |
|
|
|
<view class="highlight" v-if="question.answer">{{ question.answer }}</view> |
|
|
|
</view> |
|
|
|
</view> |
|
|
|
</view> |
|
|
|
|
|
|
|
<view class="question-section" v-if="detail.reason"> |
|
|
|
<view class="section-title">驳回原因</view> |
|
|
|
<view class="question__view display" style="color: #f60;font-size: 28rpx;"> |
|
|
|
{{ detail.reason }} |
|
|
|
</view> |
|
|
|
</view> |
|
|
|
</view> |
|
|
|
</view> |
|
|
|
<view class="footer-btn flex-colc"> |
|
|
|
<view class="size-22 color-777 tips-rest"> |
|
|
|
<view class="size-22 color-777 tips-rest" v-if="!baseSuccess"> |
|
|
|
<!-- todo --> |
|
|
|
剩余考试机会:<text class="highlight">{{ restTimes }}</text>次 |
|
|
|
剩余考试机会:<text class="highlight">{{ restTimes - examNumber }}</text>次 |
|
|
|
</view> |
|
|
|
<view class="btn" @click="onClick"> |
|
|
|
重新考试 |
|
|
@ -34,14 +63,16 @@ |
|
|
|
</template> |
|
|
|
|
|
|
|
<script setup> |
|
|
|
import { ref, computed } from 'vue' |
|
|
|
import { ref, computed, onMounted } from 'vue' |
|
|
|
import { onShow } from '@dcloudio/uni-app' |
|
|
|
import { getQuestionList, getQuestionOptions, answeBaseByQuestionId, answeTrainByQuestionId, retakeExam } from '@/api/examination' |
|
|
|
import { getAnswerBuildData, retakeExam } from '@/api/examination' |
|
|
|
import { useStore } from 'vuex' |
|
|
|
|
|
|
|
import questionCard from '../components/questionCard.vue'; |
|
|
|
import { isOptionSelected, isAnswerCorrect, isQuestionAnswered, isSuccessPrecision } from '@/utils/exam.js' |
|
|
|
|
|
|
|
const store = useStore() |
|
|
|
const questionList = ref([]) |
|
|
|
const detail = ref({}) |
|
|
|
const baseSuccess = ref(false) |
|
|
|
|
|
|
|
const configList = computed(() => { |
|
|
|
return store.getters.configList |
|
|
@ -50,94 +81,54 @@ |
|
|
|
return store.state.user.userInfo |
|
|
|
}) |
|
|
|
|
|
|
|
const list = ref([ |
|
|
|
{ |
|
|
|
title: '选择题', |
|
|
|
children: [], |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '主观题', |
|
|
|
children: [], |
|
|
|
}, |
|
|
|
]) |
|
|
|
|
|
|
|
const initList = async () => { |
|
|
|
try { |
|
|
|
|
|
|
|
let groups = [ |
|
|
|
{ title: '选择题', children: [], }, |
|
|
|
{ title: '主观题', children: [], }, |
|
|
|
] |
|
|
|
|
|
|
|
let questions = await getQuestionList() |
|
|
|
|
|
|
|
for (let i = 0; i < questions.length; i++) { |
|
|
|
const { id, title, type } = questions[i] |
|
|
|
|
|
|
|
let data = { id, title, type } |
|
|
|
|
|
|
|
if (type === '基本') { |
|
|
|
const options = (await getQuestionOptions({ questionId: id })).map(item => ({ id: item.id, title: item.title})) |
|
|
|
data.options = options |
|
|
|
|
|
|
|
// todo: 替换成批量查询接口 |
|
|
|
const { answer, answerId } = await answeBaseByQuestionId({ questionId: id }) |
|
|
|
|
|
|
|
if (answer.isTrue) { |
|
|
|
continue |
|
|
|
} |
|
|
|
|
|
|
|
data.answer = answer.id |
|
|
|
data.value = answerId |
|
|
|
data.isTrue = answer.isTrue |
|
|
|
|
|
|
|
groups[0].children.push(data) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// todo: 替换成批量查询接口 |
|
|
|
const { answer, remark } = await answeTrainByQuestionId({ questionId: id }) |
|
|
|
const restTimes = ref(0) |
|
|
|
const examNumber = ref(0) |
|
|
|
|
|
|
|
if (!remark) { |
|
|
|
continue |
|
|
|
} |
|
|
|
// 选择题列表 |
|
|
|
const basicQuestions = computed(() => { |
|
|
|
return questionList.value.filter(item => item.type === '基本') |
|
|
|
}) |
|
|
|
|
|
|
|
data.answer = remark |
|
|
|
data.value = answer |
|
|
|
// 培训题列表 |
|
|
|
const trainQuestions = computed(() => { |
|
|
|
return questionList.value.filter(item => item.type === '培训' && isQuestionAnswered(item)) |
|
|
|
}) |
|
|
|
|
|
|
|
groups[1].children.push(data) |
|
|
|
} |
|
|
|
} |
|
|
|
onMounted(() => { |
|
|
|
getExamData() |
|
|
|
}) |
|
|
|
|
|
|
|
list.value = groups.filter(group => group.children.length > 0) |
|
|
|
const getExamData = () => { |
|
|
|
getAnswerBuildData(userInfo.value.userId).then(res => { |
|
|
|
detail.value = res |
|
|
|
questionList.value = res.answerList |
|
|
|
examNumber.value = res.examNumber || 0 |
|
|
|
|
|
|
|
console.log('--list', list.value) |
|
|
|
} catch (err) { |
|
|
|
console.log('--initList--err', err) |
|
|
|
} |
|
|
|
baseSuccess.value = isSuccessPrecision(res.answerList) |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
const restTimes = ref() |
|
|
|
|
|
|
|
onShow(() => { |
|
|
|
// todo: fetch |
|
|
|
restTimes.value = parseInt(configList.value.pet_work_num.paramValueText || 0) |
|
|
|
|
|
|
|
initList() |
|
|
|
}) |
|
|
|
|
|
|
|
const onClick = () => { |
|
|
|
|
|
|
|
retakeExam({ |
|
|
|
userId : userInfo.value.userId |
|
|
|
userId: userInfo.value.userId, |
|
|
|
type : baseSuccess.value ? 1 : 0,//1清除培训考核的答案,0清除全部 |
|
|
|
}).then(res => { |
|
|
|
uni.reLaunch({ |
|
|
|
url: "/otherPages/authentication/examination/start" |
|
|
|
// todo: check |
|
|
|
// url: "/otherPages/authentication/list/index" |
|
|
|
}) |
|
|
|
|
|
|
|
if(baseSuccess.value){ |
|
|
|
uni.reLaunch({ |
|
|
|
url: "/otherPages/authentication/examination/baseCompleted" |
|
|
|
}) |
|
|
|
}else{ |
|
|
|
uni.reLaunch({ |
|
|
|
url: "/otherPages/authentication/examination/start" |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
</script> |
|
|
@ -203,4 +194,102 @@ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.question-section { |
|
|
|
margin-bottom: 40rpx; |
|
|
|
} |
|
|
|
|
|
|
|
.section-title { |
|
|
|
font-size: 32rpx; |
|
|
|
font-weight: bold; |
|
|
|
color: #333; |
|
|
|
margin: 30rpx 0; |
|
|
|
padding-left: 20rpx; |
|
|
|
border-left: 8rpx solid #FFBF60; |
|
|
|
} |
|
|
|
|
|
|
|
.question { |
|
|
|
color: #000000; |
|
|
|
} |
|
|
|
|
|
|
|
.option { |
|
|
|
background-color: #F3F3F3; |
|
|
|
color: #707070; |
|
|
|
line-height: 37rpx; |
|
|
|
padding: 23rpx; |
|
|
|
border-radius: 28rpx; |
|
|
|
position: relative; |
|
|
|
|
|
|
|
&+& { |
|
|
|
margin-top: 20rpx; |
|
|
|
} |
|
|
|
|
|
|
|
.icon { |
|
|
|
position: absolute; |
|
|
|
right: 45rpx; |
|
|
|
bottom: 23rpx; |
|
|
|
display: none; |
|
|
|
} |
|
|
|
|
|
|
|
&.is-correct { |
|
|
|
background-color: rgba($color: #05C160, $alpha: 0.08); |
|
|
|
color: #05C160; |
|
|
|
|
|
|
|
.icon-correct { |
|
|
|
display: block; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
&.is-error { |
|
|
|
background-color: rgba($color: #FFEBCE, $alpha: 0.36); |
|
|
|
color: #FF2A2A; |
|
|
|
|
|
|
|
.icon-error { |
|
|
|
display: block; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.textarea { |
|
|
|
background-color: #F3F3F3; |
|
|
|
padding: 23rpx; |
|
|
|
border-radius: 16rpx; |
|
|
|
margin-top: 20rpx; |
|
|
|
|
|
|
|
.answer-content { |
|
|
|
font-size: 28rpx; |
|
|
|
color: #333; |
|
|
|
line-height: 1.6; |
|
|
|
margin-bottom: 20rpx; |
|
|
|
} |
|
|
|
|
|
|
|
.highlight { |
|
|
|
color: #FF2A2A; |
|
|
|
font-size: 28rpx; |
|
|
|
line-height: 1.6; |
|
|
|
padding-top: 20rpx; |
|
|
|
border-top: 1px solid rgba(0, 0, 0, 0.1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.footer-btn { |
|
|
|
position: fixed; |
|
|
|
left: 0; |
|
|
|
right: 0; |
|
|
|
bottom: 0; |
|
|
|
height: $bar-height; |
|
|
|
background: #fff; |
|
|
|
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05); |
|
|
|
} |
|
|
|
|
|
|
|
.btn { |
|
|
|
width: 600rpx; |
|
|
|
height: 80rpx; |
|
|
|
line-height: 80rpx; |
|
|
|
text-align: center; |
|
|
|
background: #FFBF60; |
|
|
|
color: #fff; |
|
|
|
border-radius: 40rpx; |
|
|
|
font-size: 32rpx; |
|
|
|
} |
|
|
|
</style> |