Browse Source

feat: 更新考试系统功能并修复多个问题

- 新增考试结果查询接口getAnswerBuildData
- 修改考试提交接口为addBaseAnswerV2
- 修复订单服务项显示顺序问题
- 增加补充信息字数限制和校验
- 优化考试流程和错误处理逻辑
- 更新图片资源路径
- 添加考试工具函数和错误详情页面
master
前端-胡立永 1 day ago
parent
commit
862b488dcf
16 changed files with 633 additions and 137 deletions
  1. +16
    -1
      api/examination/index.js
  2. +1
    -1
      components/order/ServiceItems.vue
  3. +34
    -16
      otherPages/authentication/examination/base.vue
  4. +206
    -0
      otherPages/authentication/examination/errorDetail - 副本.vue
  5. +180
    -91
      otherPages/authentication/examination/errorDetail.vue
  6. +83
    -10
      otherPages/authentication/examination/start.vue
  7. +6
    -1
      otherPages/myOrdersManage/clock/index.vue
  8. +7
    -0
      pages/myOrdersManage/index.vue
  9. +9
    -9
      pages/orderTakingManage/components/list.vue
  10. +2
    -2
      pages/userManage/index.vue
  11. +16
    -4
      pages/workbenchManage/index.vue
  12. BIN
      static/images/user/a1.png
  13. BIN
      static/images/user/a2.png
  14. +69
    -0
      utils/exam.js
  15. +2
    -2
      utils/getUrl.js
  16. +2
    -0
      utils/serviceTime.js

+ 16
- 1
api/examination/index.js View File

@ -80,7 +80,7 @@ export const getQuestionOptions = (params) => {
// 伴宠师工作台-添加用户基本考核答案
export const addBaseAnswer = (data) => {
return request({
url: '/applet/examination/addBaseAnswer',
url: '/applet/examination/addBaseAnswerV2',
headers: {
isToken: true
},
@ -185,3 +185,18 @@ export const retakeExam = (params) => {
})
}
// 伴宠师工作台-查询考试结果对象
export const getAnswerBuildData = (userId) => {
return request({
url: '/applet/examination/getAnswerBuildData',
headers: {
isToken: true
},
method: 'get',
params : {
userId
}
}).then(res => res.data)
}

+ 1
- 1
components/order/ServiceItems.vue View File

@ -11,10 +11,10 @@
<view class="item-id">{{item.day}}</view>
<text style="margin: 0 10rpx;">|</text>
<view class="item-name">
<text>{{ item.itemsText[0] }}</text>
<text v-if="item.itemsText.length >= 2">
{{ item.itemsText[0] }}+{{ item.itemsText[item.itemsText.length - 1] }}{{ item.itemsText.length }}
</text>
<text v-else>{{ item.itemsText[0] }}</text>
</view>
<view class="item-price-action">
<view class="item-price">¥{{item.price.toFixed(2)}}</view>


+ 34
- 16
otherPages/authentication/examination/base.vue View File

@ -39,7 +39,8 @@
<script setup>
import { ref, computed } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { getQuestionList, getQuestionOptions } from '@/api/examination'
import { getQuestionList, getQuestionOptions, getAnswerBuildData } from '@/api/examination'
import { isSuccessPrecision } from '@/utils/exam.js'
import {
addBaseAnswer,
addTrainAnswer
@ -114,30 +115,47 @@ const toNext = async () => {
title: '提交中...'
})
// list.value.forEach(n => {
// data.push(addBaseAnswer({
// userId: userId.value,
// questionId: n.id,
// answerId : n.value,
// }))
// })
// await Promise.all(data)
// uni.hideLoading()
list.value.forEach(n => {
data.push(addBaseAnswer({
data.push({
userId: userId.value,
questionId: n.id,
answerId : n.value,
}))
})
})
await Promise.all(data)
await addBaseAnswer({
answerBase : data
})
const res = await getAnswerBuildData(userId.value)
if(!isSuccessPrecision(res.answerList.filter(item => item.type === '基本'))){
uni.showToast({
title: '考试未通过',
icon: 'none'
})
uni.navigateTo({
url: "/otherPages/authentication/examination/errorDetail"
})
return
}
uni.hideLoading()
// list.value.forEach(n => {
// data.push({
// userId: userId.value,
// questionId: n.id,
// answerId : n.value,
// })
// })
// await addBaseAnswer({
// list : JSON.stringify(data)
// })
uni.navigateTo({
url: "/otherPages/authentication/examination/baseCompleted"
})


+ 206
- 0
otherPages/authentication/examination/errorDetail - 副本.vue View File

@ -0,0 +1,206 @@
<template>
<!-- <view>伴宠师认证</view> -->
<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>
<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>
</view>
</view>
<view class="footer-btn flex-colc">
<view class="size-22 color-777 tips-rest">
<!-- todo -->
剩余考试机会<text class="highlight">{{ restTimes }}</text>
</view>
<view class="btn" @click="onClick">
重新考试
</view>
</view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { getQuestionList, getQuestionOptions, answeBaseByQuestionId, answeTrainByQuestionId, retakeExam } from '@/api/examination'
import { useStore } from 'vuex'
import questionCard from '../components/questionCard.vue';
const store = useStore()
const configList = computed(() => {
return store.getters.configList
})
const userInfo = computed(() => {
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 })
if (!remark) {
continue
}
data.answer = remark
data.value = answer
groups[1].children.push(data)
}
}
list.value = groups.filter(group => group.children.length > 0)
console.log('--list', list.value)
} catch (err) {
console.log('--initList--err', err)
}
}
const restTimes = ref()
onShow(() => {
// todo: fetch
restTimes.value = parseInt(configList.value.pet_work_num.paramValueText || 0)
initList()
})
const onClick = () => {
retakeExam({
userId : userInfo.value.userId
}).then(res => {
uni.reLaunch({
url: "/otherPages/authentication/examination/start"
// todo: check
// url: "/otherPages/authentication/list/index"
})
})
}
</script>
<style lang="scss" scoped>
$bar-height: 163rpx;
.page {
padding-bottom: $bar-height;
}
.box {
// background-image: linear-gradient(to bottom, #ffbf60, #f2f2f2);
padding: 16rpx;
.step {
width: 720rpx;
height: 32rpx;
border-radius: 32rpx;
background-color: #D9D9D9;
.in {
width: 50%;
height: 32rpx;
background-color: #ffbf60;
border-radius: 32rpx;
}
}
}
.content {
border-radius: 20rpx;
padding: 15rpx 20rpx;
.label {
width: 86rpx;
padding: 5rpx 15rpx;
color: #fff;
background-color: #FFBF60;
justify-content: center;
}
}
.group + .group {
margin-top: 68rpx;
}
.level {
display: flex;
}
.footer-btn {
height: $bar-height;
}
.tips {
&-rest {
color: #707070;
font-size: 22rpx;
margin: 9rpx 0 13rpx 0;
.highlight {
color: #FF8DC6;
}
}
}
</style>

+ 180
- 91
otherPages/authentication/examination/errorDetail.vue View File

@ -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,//10
}).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>

+ 83
- 10
otherPages/authentication/examination/start.vue View File

@ -30,15 +30,18 @@
</view>
</view>
</view>
<view class="footer-btn flex-colc">
<view class="size-22 color-777 tips-rest">
<!-- todo -->
剩余考试机会<text class="highlight">{{ restTimes }}</text>
<template v-if="canTakeExam">
剩余考试机会<text class="highlight">{{ restTimes - examNumber }}</text>
</template>
<template v-else>
<text class="next-exam-time">下次考试时间{{ nextExamTime }}</text>
</template>
</view>
<view class="btn" @click="toNext">
开始考试
<view class="btn" :class="{ 'btn-disabled': !canTakeExam }" @click="toNext">
{{ canTakeExam ? '开始考试' : '暂无考试机会' }}
</view>
</view>
</view>
@ -48,15 +51,61 @@
import { ref, computed } from 'vue'
import { useStore } from 'vuex'
import { onLoad } from '@dcloudio/uni-app'
import { insertUser, udpateUser, getUserOne } from '@/api/userTeacher'
import dayjs from 'dayjs'
const store = useStore()
const petType = ref([])
const restTimes = ref()
const lastExamTime = ref('')
//
const examNumber = ref(0)
const configList = computed(() => {
return store.getters.configList
})
const userId = computed(() => {
return store.state.user.userInfo.userId
})
//
const nextExamTime = computed(() => {
if (!lastExamTime.value) return ''
const nextTime = dayjs(lastExamTime.value).add(1, 'year')
return nextTime.format('YYYY年MM月DD日')
})
//
const canTakeExam = computed(() => {
if((restTimes.value - examNumber.value) > 0){
return true
}
if (!lastExamTime.value) return true
const nextTime = dayjs(lastExamTime.value).add(1, 'year')
return dayjs().isAfter(nextTime)
})
const getInfo = async () => {
try {
if(!userId.value) {
return
}
const data = await getUserOne(userId.value)
examNumber.value = data.examNumber || 0
lastExamTime.value = data.examTime
petType.value = data.petType.split(',').map(n => parseInt(n))
} catch (err) {
console.log('--err', err)
}
}
const petTypeImg = computed(() => {
return store.getters.petTypeOptions.
@ -64,15 +113,19 @@
})
onLoad((option) => {
store.dispatch('fetchPetTypeOptions')
petType.value = option.petType.split(',').map(n => parseInt(n))
// todo: fetch
store.dispatch('fetchPetTypeOptions')
getInfo()
restTimes.value = parseInt(configList.value.pet_work_num.paramValueText || 0)
})
const toNext = () => {
if (!canTakeExam.value) {
uni.showToast({
title: `请于${nextExamTime.value}后再来考试`,
icon: 'none'
})
return
}
uni.navigateTo({
url: "/otherPages/authentication/examination/base"
})
@ -138,9 +191,29 @@
}
}
.next-exam-time {
color: #FF2A2A;
}
.footer-btn {
height: 163rpx;
box-sizing: border-box;
padding-bottom: 18rpx;
}
.btn {
width: 600rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
background: #FFBF60;
color: #fff;
border-radius: 40rpx;
font-size: 32rpx;
&-disabled {
background: #CCCCCC;
color: #FFFFFF;
}
}
</style>

+ 6
- 1
otherPages/myOrdersManage/clock/index.vue View File

@ -197,7 +197,7 @@
其他补充信息(必填)
</view>
<view class="mt32 ml10" :style="{color:'#999999',fontSize:'30rpx'}">
可记录一下今日趣事宠物状况提醒事项等
可记录一下今日趣事宠物状况提醒事项等最少30个字
</view>
<view class="mt24">
<textarea cols="30" rows="10"
@ -303,6 +303,7 @@
event.file.forEach(n => {
ossUpload(n.url)
.then(url => {
console.log(url);
fileList[event.name].push({
url
})
@ -349,6 +350,10 @@
if(!form.value.notes){
return msg('请填写补充信息')
}
if(form.value.notes.length < 30){
return msg('补充信息不少于30字')
}
saveDraft(true)
}


+ 7
- 0
pages/myOrdersManage/index.vue View File

@ -214,6 +214,13 @@
let totalOrders = 0;
dateOrderList.value.forEach(item => {
totalOrders += item.list.length || 0;
item.list.forEach(n => {
n.pets.forEach(pet => {
pet.orderItemList.reverse()
})
})
});
tabList2[index].badge.value = totalOrders;
}


+ 9
- 9
pages/orderTakingManage/components/list.vue View File

@ -8,16 +8,16 @@
<!-- 订单列表 -->
<up-list v-else @scrolltolower="scrolltolower">
<up-list-item v-for="item in orderList">
<view class="mb28 container-list-item">
<view class="flex-between flex" style="background: #FFF4E5;padding: 22rpx 42rpx">
<view>
<text v-if="current != 2">待接单</text>
</view>
<view>本单酬劳
<text style="color: #FF530A">{{ item.orderGive }}</text>
</view>
<up-list-item v-for="item in orderList">
<view class="mb28 container-list-item">
<view class="flex-between flex" style="background: #FFF4E5;padding: 22rpx 42rpx">
<view>
<text v-if="current != 2">待接单</text>
</view>
<view>本单酬劳
<text style="color: #FF530A">{{ item.orderGive }}</text>
</view>
</view>
<view class="container-list">
<view class="flex mb28"
@click="toDetail(pet.id)"


+ 2
- 2
pages/userManage/index.vue View File

@ -33,7 +33,7 @@
<view class="mb20 flex">
<!-- <up-image :show-loading="true" src="https://cdn.catmdogd.com/Work/image/work/icon4.png"
width="68rpx" height="68rpx"></up-image> -->
<up-image :show-loading="true" src="/static/images/user/q1.png"
<up-image :show-loading="true" src="/static/images/user/a2.png"
style="margin-right: 14rpx;"
width="50rpx" height="50rpx"></up-image>
服务酬劳
@ -50,7 +50,7 @@
<!-- <up-image :show-loading="true" src="https://cdn.catmdogd.com/Work/image/work/icon4.png"
width="68rpx" height="68rpx"></up-image> -->
<up-image :show-loading="true" src="/static/images/user/q2.png"
<up-image :show-loading="true" src="/static/images/user/a1.png"
style="margin-right: 14rpx;"
width="50rpx" height="50rpx"></up-image>


+ 16
- 4
pages/workbenchManage/index.vue View File

@ -100,9 +100,11 @@
import configPopup from '@/components/configPopup.vue'
import {
answeBaseIsFinish,
answeTrainIsFinish
answeTrainIsFinish,
getAnswerBuildData,
} from '@/api/examination'
import { insertUser, udpateUser, getUserOne } from '@/api/userTeacher'
import utilsExam from '@/utils/exam.js'
import {
code
} from "../../uni_modules/uview-plus/libs/function/test";
@ -244,7 +246,8 @@
try {
const data = await getUserOne(userInfo.value.userId)
const data = await getAnswerBuildData(userInfo.value.userId)
// const data = await getUserOne(userInfo.value.userId)
if(!data || !data.id){
@ -276,12 +279,21 @@
url: `/otherPages/authentication/examination/trainCompleted/index?status=0`
})
} else if(code1){
//
if(!utilsExam.isSuccessPrecision(data.answerList.filter(item => item.type === '基本'))){
uni.navigateTo({
url: "/otherPages/authentication/examination/errorDetail"//
})
return
}
uni.navigateTo({
url: "/otherPages/authentication/examination/train"
url: "/otherPages/authentication/examination/baseCompleted"//train
})
}else{
uni.navigateTo({
url: "/otherPages/authentication/examination/base"
url: "/otherPages/authentication/examination/start"//base
})
}


BIN
static/images/user/a1.png View File

Before After
Width: 102  |  Height: 102  |  Size: 9.9 KiB

BIN
static/images/user/a2.png View File

Before After
Width: 102  |  Height: 102  |  Size: 10 KiB

+ 69
- 0
utils/exam.js View File

@ -0,0 +1,69 @@
import dayjs from "dayjs";
// 判断选项是否被选中
export function isOptionSelected(question, optionId) {
if (!question.userAnswerBaseList || !question.userAnswerBaseList.length) return false;
return question.userAnswerBaseList.some(answer => answer.answerId === optionId);
}
// 判断答案是否正确
export function isAnswerCorrect(question) {
if (!question.userAnswerBaseList || !question.userAnswerBaseList.length) return false;
// 获取所有正确答案的ID
const correctOptionIds = question.answerList
.filter(option => option.isTrue)
.map(option => option.id);
// 获取用户选择的答案ID
const userAnswerIds = [...new Set(question.userAnswerBaseList.map(answer => answer.answerId))];
// 判断用户选择的答案数量是否与正确答案数量相同
if (userAnswerIds.length !== correctOptionIds.length) {
return false;
}
// 判断用户选择的答案是否都是正确的
return userAnswerIds.every(answerId => correctOptionIds.includes(answerId));
}
export function isQuestionAnswered(question) {
if (question.type == '培训') {
// 填空题:检查是否有答案且答案不为空
return question.userAppletAnswerTrain &&
question.userAppletAnswerTrain.answer &&
question.userAppletAnswerTrain.answer.trim() !== '';
} else {
// 选择题:检查是否有选择的答案
return question.userAnswerBaseList && question.userAnswerBaseList.length > 0;
}
}
// 判断全部题目答案是否达到指定的准确率
export function isSuccessPrecision(list, number = 100){
let errNumber = 0
for (var index = 0; index < list.length; index++) {
var question = list[index];
if (question.type == '基本' && !isAnswerCorrect(question)) {
errNumber++
}
}
console.log(errNumber, (list.length - errNumber) / list.length * 100);
if(((list.length - errNumber) / list.length * 100) < number){
return false
}
return true
}
export default {
isOptionSelected,
isAnswerCorrect,
isQuestionAnswered,
isSuccessPrecision,
}

+ 2
- 2
utils/getUrl.js View File

@ -1,6 +1,6 @@
let current = "develop";
let current = "trial";
const accountInfo = wx.getAccountInfoSync();
// current = accountInfo.miniProgram.envVersion;
current = accountInfo.miniProgram.envVersion;
const api = {
develop:"http://127.0.0.1:8002",


+ 2
- 0
utils/serviceTime.js View File

@ -35,6 +35,8 @@ export function getProductNameText(petId, productList, orderServiceList) {
let list = (productList
.filter(product => orderService.filter(service => service.id == product.orderServiceId).length > 0)
.map(product => product.productName))
list = list.reverse();
return [...new Set(list)]
}


Loading…
Cancel
Save