diff --git a/api/amount/index.js b/api/amount/index.js index a52a692..2554889 100644 --- a/api/amount/index.js +++ b/api/amount/index.js @@ -47,4 +47,16 @@ export const teacherPayPrice = (data) => { method: "post", data }) +} + +// 提现成功 +export const withdrawalSuccessful = (params) => { + return request({ + url: '/applet/amount/withdrawalSuccessful', + headers: { + isToken: true + }, + method: "post", + params + }) } \ No newline at end of file diff --git a/components/CustomerService/index.vue b/components/CustomerService/index.vue new file mode 100644 index 0000000..ed9b55e --- /dev/null +++ b/components/CustomerService/index.vue @@ -0,0 +1,45 @@ + + + + + \ No newline at end of file diff --git a/main.js b/main.js index ca6e470..08ad24b 100644 --- a/main.js +++ b/main.js @@ -4,11 +4,15 @@ import store from './store' // #ifndef VUE3 import Vue from 'vue' import App from './App' +import shareMixin from '@/utils/shareMixin.js' Vue.config.productionTip = false App.mpType = 'app' +// 全局混入分享功能 +Vue.mixin(shareMixin) + const app = new Vue({ ...App }) @@ -21,11 +25,17 @@ import { createSSRApp } from 'vue' import App from './App.vue' +import CustomerService from '@/components/CustomerService/index.vue' +import shareMixin from '@/utils/shareMixin.js' export function createApp() { const app = createSSRApp(App) app.use(uviewPlus) app.use(store) + // 全局注册客服按钮组件 + app.component('CustomerService', CustomerService) + // 全局混入分享功能 + app.mixin(shareMixin) return { app } diff --git a/otherPages/authentication/components/questionCard.vue b/otherPages/authentication/components/questionCard.vue index 0a42e10..a35da54 100644 --- a/otherPages/authentication/components/questionCard.vue +++ b/otherPages/authentication/components/questionCard.vue @@ -2,12 +2,19 @@ {{ props.data.title }} + + {{ isMultipleChoice ? '(多选题)' : '(单选题)' }} + + + (填空题) + @@ -68,6 +59,7 @@ import { getAnswerBuildData, retakeExam } from '@/api/examination' import { useStore } from 'vuex' import { isOptionSelected, isAnswerCorrect, isQuestionAnswered, isSuccessPrecision } from '@/utils/exam.js' + import questionCard from '../components/questionCard.vue' const store = useStore() const questionList = ref([]) @@ -84,14 +76,14 @@ const restTimes = ref(0) const examNumber = ref(0) - // 选择题列表 + // 选择题列表 (根据type字段判断) const basicQuestions = computed(() => { return questionList.value.filter(item => item.type === '基本') }) - // 培训题列表 + // 填空题列表 (根据type字段判断) const trainQuestions = computed(() => { - return questionList.value.filter(item => item.type === '培训' && isQuestionAnswered(item)) + return questionList.value.filter(item => item.type === '培训') }) onMounted(() => { @@ -104,10 +96,41 @@ questionList.value = res.answerList examNumber.value = res.examNumber || 0 - baseSuccess.value = isSuccessPrecision(res.answerList) + // 使用新的工具函数判断成功率,只考虑基本题目 + const basicQuestionsList = res.answerList.filter(item => item.type === '基本') + baseSuccess.value = isSuccessPrecision(basicQuestionsList) }) } + // 准备基本题数据格式 + const prepareQuestionData = (question) => { + return { + id: question.id, + title: question.title, + typeAnswer: question.typeAnswer, + options: question.answerList || [], + userAnswerBaseList: question.userAnswerBaseList || [], + // 添加调试信息 + rawQuestion: question + } + } + + // 准备培训题数据格式 + const prepareTrainQuestionData = (question) => { + return { + id: question.id, + title: question.title, + typeAnswer: question.typeAnswer, + options: question.answerList || [], // 培训题可能也有选择题 + value: question.userAppletAnswerTrain?.answer || '', + answer: question.answer || '', + numberWords: question.numberWords || 0, + userAnswerBaseList: question.userAnswerBaseList || [], // 培训选择题的答案 + // 添加调试信息 + rawQuestion: question + } + } + onShow(() => { restTimes.value = parseInt(configList.value.pet_work_num.paramValueText || 0) }) diff --git a/otherPages/authentication/examination/start.vue b/otherPages/authentication/examination/start.vue index 3727815..f99cbc2 100644 --- a/otherPages/authentication/examination/start.vue +++ b/otherPages/authentication/examination/start.vue @@ -44,6 +44,9 @@ {{ canTakeExam ? '开始考试' : '暂无考试机会' }} + + + diff --git a/otherPages/authentication/examination/train.vue b/otherPages/authentication/examination/train.vue index 59c8b2b..855e91a 100644 --- a/otherPages/authentication/examination/train.vue +++ b/otherPages/authentication/examination/train.vue @@ -14,7 +14,7 @@ - 主观题 + 混合题型 @@ -28,6 +28,9 @@ 提交 + + + @@ -70,9 +73,28 @@ id: item.id, title: item.title, value: null, - numberWords: item.numberWords + numberWords: item.numberWords, + ...item, })) + // 根据题目类型初始化value + for (let i = 0; i < questions.length; i++) { + if (questions[i].typeAnswer == 0) { + // 选择题 + questions[i].options = questions[i].answerList + + // 判断是否是多选题,初始化对应的 value 类型 + const correctAnswers = questions[i].answerList.filter(option => option.isTrue === 1 || option.isTrue === true) + const isMultipleChoice = correctAnswers.length > 1 + + // 多选题初始化为空数组,单选题初始化为 null + questions[i].value = isMultipleChoice ? [] : null + } else if (questions[i].typeAnswer == 1) { + // 填空题 + questions[i].value = null + } + } + list.value = questions total.value = questions.length @@ -89,11 +111,25 @@ return false } - if (typeof item.value == 'string') { - return item.value.length >= (item.numberWords || 0) + if (item.typeAnswer == 0) { + // 选择题逻辑 + // 检查多选题是否至少选择了一个选项 + if(Array.isArray(item.value)){ + return item.value.length > 0 + } + + // 单选题检查是否有值 + return item.value !== null && item.value !== undefined + } else if (item.typeAnswer == 1) { + // 填空题逻辑 + if (typeof item.value == 'string') { + return item.value.length >= (item.numberWords || 0) + } + + return false } - return true + return false }).length @@ -106,17 +142,51 @@ const toNext = async () => { - const data = [] + const answerBase = [] + const answerTrains = [] list.value.forEach(n => { - data.push(addTrainAnswer({ - userId: userId.value, - questionId: n.id, - answer : n.value, - })) + if (n.typeAnswer == 0) { + // 选择题 - 基本考核 + if (Array.isArray(n.value)) { + // 多选题:为每个选中的选项创建一个答案记录 + n.value.forEach(answerId => { + answerBase.push({ + userId: userId.value, + questionId: n.id, + answerId: answerId, + }) + }) + } else { + // 单选题:直接使用原有格式 + answerBase.push({ + userId: userId.value, + questionId: n.id, + answerId: n.value, + }) + } + } else if (n.typeAnswer == 1) { + // 填空题 - 培训考核 + answerTrains.push({ + userId: userId.value, + questionId: n.id, + answer: n.value, + }) + } }) - await Promise.all(data) + // 根据题目类型判断提交数据的type字段 + const hasBaseQuestions = list.value.some(item => item.typeAnswer == 0) + const hasTrainQuestions = list.value.some(item => item.typeAnswer == 1) + + // 提交数据 + const submitData = { + answerBase: answerBase, + answerTrains: answerTrains, + type: hasTrainQuestions ? 1 : 0 // 如果有培训考核题则type为1,否则为0 + } + + await addBaseAnswer(submitData) uni.navigateTo({ url: "/otherPages/authentication/examination/trainCompleted/index" diff --git a/otherPages/authentication/examination/trainCompleted/index.vue b/otherPages/authentication/examination/trainCompleted/index.vue index 904b221..8f32814 100644 --- a/otherPages/authentication/examination/trainCompleted/index.vue +++ b/otherPages/authentication/examination/trainCompleted/index.vue @@ -11,6 +11,8 @@ + + - - \ No newline at end of file diff --git a/otherPages/authentication/list/index.vue b/otherPages/authentication/list/index.vue index 1e62d23..ab02e97 100644 --- a/otherPages/authentication/list/index.vue +++ b/otherPages/authentication/list/index.vue @@ -73,6 +73,8 @@ + + @@ -386,16 +388,17 @@ data.id = id.value await udpateUser(data) } else { - await insertUser(data) + let r = await insertUser(data) + if(r.code != 200){ + return + } } uni.navigateTo({ url: `/otherPages/authentication/examination/start?petType=${petType.value.join(',')}` }) } catch (err) { - uni.navigateTo({ - url: `/otherPages/authentication/examination/start?petType=${petType.value.join(',')}` - }) + } } diff --git a/otherPages/authentication/serve/index.vue b/otherPages/authentication/serve/index.vue index dadebb5..fceec0e 100644 --- a/otherPages/authentication/serve/index.vue +++ b/otherPages/authentication/serve/index.vue @@ -111,7 +111,10 @@ - + @@ -121,6 +124,9 @@ + + + @@ -182,6 +188,7 @@ } const baseFormRef = ref(null) + const tData = ref({}) const formData = reactive({ introduction: '', @@ -222,8 +229,10 @@ const fetchUserInfo = async () => { try { const data = await getUserOne(userInfo.value.userId) - if (data) { + + tData.value = data + // 设置基本资料 baseFormData.userName = userInfo.value.userName || '' baseFormData.userTelephone = data.phone || userInfo.value.userTelephone || '' @@ -242,8 +251,8 @@ } // 设置增值服务 - if (data.license) { - serveFormData.serve = data.license.split(';').map(item => parseInt(item)) + if (data.addServices) { + serveFormData.serve = data.addServices.split(';').map(item => parseInt(item)) } } } catch (err) { @@ -343,7 +352,7 @@ userBrief: formData.userBrief, experience: formData.experience, petType: form.type.length > 0 ? form.type.join(',') : null, - license: serveFormData.serve.join(';'), + addServices: serveFormData.serve.join(';'), } if (form.headImage) { diff --git a/otherPages/authentication/serve/popupServeSelect.vue b/otherPages/authentication/serve/popupServeSelect.vue index 808be97..e01f2c3 100644 --- a/otherPages/authentication/serve/popupServeSelect.vue +++ b/otherPages/authentication/serve/popupServeSelect.vue @@ -7,14 +7,16 @@ - + {{ option.title }} {{ option.detail }} { - return store.getters.increaseServiceOptions + return store.getters.increaseServiceOptions || [] }) const onSelectServe = (serve) => { @@ -62,6 +68,26 @@ serves.value = newServes } + function isNeedCertificate(needCertificate) { + if (!needCertificate || typeof needCertificate !== 'string') { + return true + } + + let a = false + + const needCertificateArr = needCertificate.split(';') + const certificateArr = props.certificate ? props.certificate.split(';') : [] + + + needCertificateArr.forEach(item => { + if (certificateArr.includes(item)) { + a = true + } + }) + + return a + } + const popupRef = ref() const open = () => { diff --git a/otherPages/binding/share/index.vue b/otherPages/binding/share/index.vue index 0a6e0af..ab4928e 100644 --- a/otherPages/binding/share/index.vue +++ b/otherPages/binding/share/index.vue @@ -10,6 +10,8 @@ + + - - \ No newline at end of file diff --git a/otherPages/myOrdersManage/clock/index.vue b/otherPages/myOrdersManage/clock/index.vue index 7a53e2e..09e68cc 100644 --- a/otherPages/myOrdersManage/clock/index.vue +++ b/otherPages/myOrdersManage/clock/index.vue @@ -226,6 +226,8 @@ + + diff --git a/otherPages/myOrdersManage/list/index.vue b/otherPages/myOrdersManage/list/index.vue deleted file mode 100644 index d797a0d..0000000 --- a/otherPages/myOrdersManage/list/index.vue +++ /dev/null @@ -1,66 +0,0 @@ - - - - - diff --git a/otherPages/myOrdersManage/service/detail - 副本.vue b/otherPages/myOrdersManage/service/detail - 副本.vue deleted file mode 100644 index 1caebca..0000000 --- a/otherPages/myOrdersManage/service/detail - 副本.vue +++ /dev/null @@ -1,754 +0,0 @@ - - - - - \ No newline at end of file diff --git a/otherPages/myOrdersManage/service/detail.vue b/otherPages/myOrdersManage/service/detail.vue index fd2f21e..3df456f 100644 --- a/otherPages/myOrdersManage/service/detail.vue +++ b/otherPages/myOrdersManage/service/detail.vue @@ -701,6 +701,8 @@ 下一页 + + diff --git a/otherPages/myOrdersManage/service/index - 副本.vue b/otherPages/myOrdersManage/service/index - 副本.vue deleted file mode 100644 index e65d635..0000000 --- a/otherPages/myOrdersManage/service/index - 副本.vue +++ /dev/null @@ -1,80 +0,0 @@ - - - - - \ No newline at end of file diff --git a/otherPages/myOrdersManage/transaction/index.vue b/otherPages/myOrdersManage/transaction/index.vue index e14fe2b..44c6783 100644 --- a/otherPages/myOrdersManage/transaction/index.vue +++ b/otherPages/myOrdersManage/transaction/index.vue @@ -12,21 +12,41 @@ - + {{ item.title }} + + + {{ getMoneyTypeText(item.moneyType) }} + {{ item.createTime }} + + + 待审核 + 审核通过 + 审核不通过 + + + + 备注:{{ item.remark }} + - - ¥{{ item.amount }} + + + ¥{{ item.amount }} + + + + 领取 + @@ -36,18 +56,31 @@ import { ref } from "vue" + import { useStore } from 'vuex' import { amountLogList } from "@/api/amount/index.js" + import { + withdrawalSuccessful + } from "@/api/amount/index.js" import { - onShow + onShow, + onLoad } from "@dcloudio/uni-app" + onLoad((options) => { + // 如果有type参数,设置默认选中的tab + if (options.type) { + type.value = parseInt(options.type) + } + }) + onShow(() => { getRunningWater() }) + const store = useStore() const list = ref([]); const type = ref(0); @@ -55,7 +88,8 @@ const getRunningWater = async () => { let response = await amountLogList({ type: type.value, - moneyType:1 + moneyType:1, + userId: store.state.user.userInfo.userId }); if (response.code == 200) { list.value = response.data @@ -66,14 +100,156 @@ type.value = index; getRunningWater(); } + + // 获取金额类型文本 + const getMoneyTypeText = (moneyType) => { + switch (moneyType) { + case 0: + return '合伙人余额' + case 1: + return '伴宠师余额' + case 2: + return '保证金余额' + default: + return '' + } + } + + // 获取金额类型样式类名 + const getMoneyTypeClass = (moneyType) => { + switch (moneyType) { + case 0: + return 'money-type-partner' + case 1: + return 'money-type-sitter' + case 2: + return 'money-type-deposit' + default: + return '' + } + } + + // 领取提现 + const receiveWithdrawal = async (item) => { + try { + console.log('开始领取提现,item:', item) + + // 先确认是否要领取 + const confirmResult = await new Promise((resolve) => { + uni.showModal({ + title: '确认领取', + content: `确定要领取¥${item.amount}吗?`, + success: (res) => { + resolve(res.confirm) + } + }) + }) + + if (!confirmResult) { + return + } + + uni.showLoading({ + title: '处理中...' + }) + + // 检查是否支持微信转账 + if (typeof wx === 'undefined' || !wx.canIUse('requestMerchantTransfer')) { + console.log('微信API不可用,尝试直接调用后端接口') + // 如果微信API不可用,直接调用后端接口标记为已领取 + const result = await withdrawalSuccessful({ + id: item.id, + userId: store.state.user.userInfo.userId + }) + console.log('withdrawalSuccessful result:', result) + + uni.hideLoading() + + if (result.code === 200) { + uni.showToast({ + title: '领取成功', + icon: 'success', + duration: 1500, + success() { + // 刷新列表 + getRunningWater() + } + }) + } else { + uni.showToast({ + title: result.msg || '领取失败', + icon: 'error', + duration: 2000 + }) + } + return + } + + // 调用微信商户转账API + wx.requestMerchantTransfer({ + mchId: '1665639691', // 商户ID + appId: wx.getAccountInfoSync().miniProgram.appId, + package: item.packageInfo || '', // 从后端获取的转账包信息 + success: async (res) => { + console.log('微信转账成功:', res) + // 转账成功后调用成功接口 + try { + const result = await withdrawalSuccessful({ + id: item.id, + userId: store.state.user.userInfo.userId + }) + console.log('withdrawalSuccessful result:', result) + + uni.hideLoading() + + if (result.code === 200) { + uni.showToast({ + title: '领取成功', + icon: 'success', + duration: 1500, + success() { + // 刷新列表 + getRunningWater() + } + }) + } else { + uni.showToast({ + title: result.msg || '领取失败', + icon: 'error', + duration: 2000 + }) + } + } catch (error) { + console.error('调用withdrawalSuccessful失败:', error) + uni.hideLoading() + uni.showToast({ + title: '网络异常,请重试', + icon: 'error', + duration: 2000 + }) + } + }, + fail: (res) => { + } + }) + } catch (error) { + uni.hideLoading() + console.error('领取提现异常:', error) + uni.showToast({ + title: '网络异常,请重试', + icon: 'error', + duration: 2000 + }) + } + } \ No newline at end of file diff --git a/otherPages/orderTakingManage/detail/index.vue b/otherPages/orderTakingManage/detail/index.vue index 1e76c57..5ca8230 100644 --- a/otherPages/orderTakingManage/detail/index.vue +++ b/otherPages/orderTakingManage/detail/index.vue @@ -252,6 +252,9 @@ + + + - - diff --git a/otherPages/otherPages/myOrdersManage/bond/detail.vue b/otherPages/otherPages/myOrdersManage/bond/detail.vue deleted file mode 100644 index f65c2fd..0000000 --- a/otherPages/otherPages/myOrdersManage/bond/detail.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - - - \ No newline at end of file diff --git a/otherPages/otherPages/myOrdersManage/bond/index.vue b/otherPages/otherPages/myOrdersManage/bond/index.vue deleted file mode 100644 index 35d0a59..0000000 --- a/otherPages/otherPages/myOrdersManage/bond/index.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - - - \ No newline at end of file diff --git a/otherPages/otherPages/myOrdersManage/detail/index.vue b/otherPages/otherPages/myOrdersManage/detail/index.vue deleted file mode 100644 index e4d6aef..0000000 --- a/otherPages/otherPages/myOrdersManage/detail/index.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - - - \ No newline at end of file diff --git a/otherPages/otherPages/myOrdersManage/withdrawal/index.vue b/otherPages/otherPages/myOrdersManage/withdrawal/index.vue deleted file mode 100644 index a2d06a3..0000000 --- a/otherPages/otherPages/myOrdersManage/withdrawal/index.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - - - \ No newline at end of file diff --git a/otherPages/userManage/list/index.vue b/otherPages/userManage/list/index.vue deleted file mode 100644 index 2cf1a01..0000000 --- a/otherPages/userManage/list/index.vue +++ /dev/null @@ -1,66 +0,0 @@ - - - - - diff --git a/otherPages/userManage/pet/components/petBaseInfo.vue b/otherPages/userManage/pet/components/petBaseInfo.vue deleted file mode 100644 index 74e22d7..0000000 --- a/otherPages/userManage/pet/components/petBaseInfo.vue +++ /dev/null @@ -1,316 +0,0 @@ - - - - - \ No newline at end of file diff --git a/otherPages/userManage/pet/components/petHealthInfo.vue b/otherPages/userManage/pet/components/petHealthInfo.vue deleted file mode 100644 index a0a4b4c..0000000 --- a/otherPages/userManage/pet/components/petHealthInfo.vue +++ /dev/null @@ -1,253 +0,0 @@ - - - - - \ No newline at end of file diff --git a/otherPages/userManage/pet/index.vue b/otherPages/userManage/pet/index.vue index 945fa33..18df1e3 100644 --- a/otherPages/userManage/pet/index.vue +++ b/otherPages/userManage/pet/index.vue @@ -72,6 +72,8 @@ + + diff --git a/otherPages/userManage/pet/petInfo.vue b/otherPages/userManage/pet/petInfo.vue index 078ce0f..932ecd1 100644 --- a/otherPages/userManage/pet/petInfo.vue +++ b/otherPages/userManage/pet/petInfo.vue @@ -13,9 +13,171 @@ - - + + + + 宠物基本信息 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 取消 + + + + + + + 确定 + + + + + + + + + + + 宠物健康情况 + + + + + + + + + + + + + + + + + + + + + + 未办理养犬许可证且需要外出遛狗, 犬只存在被相关单位收缴 + 甚至捕杀的可能,请您遵守当地养犬规范,合法文明养犬。具体 + 请您查看当地养犬条例 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 取消 + + + + + + + 确定 + + + + + + + + + + + + + + @@ -44,7 +206,8 @@ - - \ No newline at end of file diff --git a/otherPages/userManage/userInfo.vue b/otherPages/userManage/userInfo.vue index 6d89380..afa854a 100644 --- a/otherPages/userManage/userInfo.vue +++ b/otherPages/userManage/userInfo.vue @@ -52,6 +52,8 @@ + + - - \ No newline at end of file diff --git a/otherPages/workbenchManage/feedingStaff/index.vue b/otherPages/workbenchManage/feedingStaff/index.vue index 49eb306..19760fb 100644 --- a/otherPages/workbenchManage/feedingStaff/index.vue +++ b/otherPages/workbenchManage/feedingStaff/index.vue @@ -40,6 +40,9 @@ + + + - - diff --git a/pages.json b/pages.json index f981a3d..d6f1025 100644 --- a/pages.json +++ b/pages.json @@ -8,7 +8,8 @@ "^u-([^-].*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue" } }, - "pages": [{ + "pages": [ + { "path": "pages/workbenchManage/index", "style": { "navigationBarTitleText": "工作台" @@ -33,9 +34,15 @@ } }, { - "path": "pages/test/index", + "path": "pages/userManage/mine/platformManual", + "style": { + "navigationBarTitleText": "平台手册" + } + }, + { + "path": "pages/userManage/mine/home_agreement", "style": { - "navigationBarTitleText": "测试" + "navigationBarTitleText": "平台协议" } }, { @@ -171,9 +178,6 @@ "root": "otherPages/orderTakingManage", // 接单大厅 "pages": [{ - "path": "list/index" - }, - { "path": "detail/index", "style": { "navigationBarTitleText": "订单详情" @@ -205,9 +209,6 @@ "root": "otherPages/myOrdersManage", // 我的订单 "pages": [{ - "path": "list/index" - }, - { "path": "bond/index", "style": { "navigationBarTitleText": "保证金" @@ -356,9 +357,6 @@ "root": "otherPages/userManage", // 我的 "pages": [{ - "path": "list/index" - }, - { "path": "record/index", "style": { "navigationBarTitleText": "服务记录" diff --git a/pages/login/index.vue b/pages/login/index.vue index 31e9b02..ad0d663 100644 --- a/pages/login/index.vue +++ b/pages/login/index.vue @@ -37,6 +37,8 @@ + + - - \ No newline at end of file diff --git a/pages/myOrdersManage/components/timelineService - 副本.vue b/pages/myOrdersManage/components/timelineService - 副本.vue deleted file mode 100644 index ac7aa2b..0000000 --- a/pages/myOrdersManage/components/timelineService - 副本.vue +++ /dev/null @@ -1,636 +0,0 @@ - - - - - \ No newline at end of file diff --git a/pages/myOrdersManage/index.vue b/pages/myOrdersManage/index.vue index 72730e1..7c62851 100644 --- a/pages/myOrdersManage/index.vue +++ b/pages/myOrdersManage/index.vue @@ -76,6 +76,9 @@ + + + diff --git a/pages/myOrdersManage/index1.vue b/pages/myOrdersManage/index1.vue index 2cf1a01..5c2172e 100644 --- a/pages/myOrdersManage/index1.vue +++ b/pages/myOrdersManage/index1.vue @@ -20,7 +20,9 @@ - + + + - - \ No newline at end of file diff --git a/pages/userManage/index.scss b/pages/userManage/index.scss index 7cb451b..f78b987 100644 --- a/pages/userManage/index.scss +++ b/pages/userManage/index.scss @@ -54,6 +54,10 @@ display: flex; flex-direction: column; align-items: center; + background-color: #fff; + .image{ + background-color: #fff; + } } .cw-box { diff --git a/pages/userManage/index.vue b/pages/userManage/index.vue index 9a4d360..2994b12 100644 --- a/pages/userManage/index.vue +++ b/pages/userManage/index.vue @@ -107,8 +107,10 @@ - + 我的评价 @@ -116,8 +118,10 @@ src="https://cdn.catmdogd.com/Work/image/work/icon2.png" width="68rpx" height="68rpx"> --> - + 平台协议 @@ -137,8 +143,10 @@ src="https://t9.baidu.com/it/u=2834693008,3232051400&fm=193" width="68rpx" height="68rpx"> --> - + 分享好友 @@ -166,6 +174,9 @@ + + + + + diff --git a/pages/userManage/mine/platformManual.vue b/pages/userManage/mine/platformManual.vue new file mode 100644 index 0000000..978dcf2 --- /dev/null +++ b/pages/userManage/mine/platformManual.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/pages/workbenchManage/index.vue b/pages/workbenchManage/index.vue index 7a18c60..43a4f4d 100644 --- a/pages/workbenchManage/index.vue +++ b/pages/workbenchManage/index.vue @@ -67,6 +67,9 @@ + + + @@ -201,7 +204,12 @@ if (item.name == '平台手册') { // pet_platform_introduction - return configPopupRef.value.open('pet_platform_introduction') + // return configPopupRef.value.open('pet_platform_introduction') + + uni.navigateTo({ + url: '/pages/userManage/mine/platformManual' + }) + return } if (item.url) { diff --git a/store/modules/system.js b/store/modules/system.js index 4a77e51..6c5b2d0 100644 --- a/store/modules/system.js +++ b/store/modules/system.js @@ -36,6 +36,7 @@ const system = { const data = await getConfigList() commit('setConfigList', data) + } catch (err) { } diff --git a/uni_modules/uview-plus/components/u-swipe-action-item/index - backup.wxs b/uni_modules/uview-plus/components/u-swipe-action-item/index - backup.wxs deleted file mode 100644 index 04cab92..0000000 --- a/uni_modules/uview-plus/components/u-swipe-action-item/index - backup.wxs +++ /dev/null @@ -1,256 +0,0 @@ -/** - * 此为wxs模块,只支持APP-VUE,微信和QQ小程序以及H5平台 - * wxs内部不支持es6语法,变量只能使用var定义,无法使用解构,箭头函数等特性 - */ - -// 开始触摸 -function touchstart(event, ownerInstance) { - // 触发事件的组件的ComponentDescriptor实例 - var instance = event.instance - // wxs内的局部变量快照,此快照是属于整个组件的,在touchstart和touchmove事件中都能获取到相同的结果 - var state = instance.getState() - if (state.disable) return - var touches = event.touches - // 如果进行的是多指触控,不允许进行操作 - if (touches && touches.length > 1) return - // 标识当前为滑动中状态 - state.moving = true - // 记录触摸开始点的坐标值 - state.startX = touches[0].pageX - state.startY = touches[0].pageY -} - -// 触摸滑动 -function touchmove(event, ownerInstance) { - // 触发事件的组件的ComponentDescriptor实例 - var instance = event.instance - // wxs内的局部变量快照 - var state = instance.getState() - if (state.disabled || !state.moving) return - - var touches = event.touches - var pageX = touches[0].pageX - var pageY = touches[0].pageY - var moveX = pageX - state.startX - var moveY = pageY - state.startY - var buttonsWidth = state.buttonsWidth - - // 移动的X轴距离大于Y轴距离,也即终点与起点位置连线,与X轴夹角小于45度时,禁止页面滚动 - if (Math.abs(moveX) > Math.abs(moveY) || Math.abs(moveX) > state.threshold) { - event.preventDefault() - event.stopPropagation() - } - // 如果移动的X轴距离小于Y轴距离,也即终点位置与起点位置连线,与Y轴夹角小于45度时,认为是页面上下滑动,而不是左右滑动单元格 - if (Math.abs(moveX) < Math.abs(moveY)) return - - // 限制右滑的距离,不允许内容部分往右偏移,右滑会导致X轴偏移值大于0,以此做判断 - // 此处不能直接return,因为滑动过程中会缺失某些关键点坐标,会导致错乱,最好的办法就是 - // 在超出后,设置为0 - if (state.status === 'open') { - // 在开启状态下,向左滑动,需忽略 - if (moveX < 0) moveX = 0 - // 想要收起菜单,最大能移动的距离为按钮的总宽度 - if (moveX > buttonsWidth) moveX = buttonsWidth - // 如果是已经打开了的状态,向左滑动时,移动收起菜单 - moveSwipeAction(-buttonsWidth + moveX, instance, ownerInstance) - } else { - // 关闭状态下,右滑动需忽略 - if (moveX > 0) moveX = 0 - // 滑动的距离不允许超过所有按钮的总宽度,此时只能是左滑,最终设置按钮的总宽度,同时为负数 - if (Math.abs(moveX) > buttonsWidth) moveX = -buttonsWidth - // 只要是在滑过程中,就不断移动菜单的内容部分,从而使隐藏的菜单显示出来 - moveSwipeAction(moveX, instance, ownerInstance) - } -} - -// 触摸结束 -function touchend(event, ownerInstance) { - // 触发事件的组件的ComponentDescriptor实例 - var instance = event.instance - // wxs内的局部变量快照 - var state = instance.getState() - if (!state.moving || state.disabled) return - var touches = event.changedTouches ? event.changedTouches[0] : {} - var pageX = touches.pageX - var pageY = touches.pageY - var moveX = pageX - state.startX - if (state.status === 'open') { - // 在展开的状态下,继续左滑,无需操作 - if (moveX < 0) return - // 在开启状态下,点击一下内容区域,moveX为0,也即没有进行移动,这时执行收起菜单逻辑 - if (moveX === 0) { - return closeSwipeAction(instance, ownerInstance) - } - // 在开启状态下,滑动距离小于阈值,则默认为不关闭,同时恢复原来的打开状态 - if (Math.abs(moveX) < state.threshold) { - openSwipeAction(instance, ownerInstance) - } else { - // 如果滑动距离大于阈值,则执行收起逻辑 - closeSwipeAction(instance, ownerInstance) - } - } else { - // 在关闭的状态下,右滑,无需操作 - if (moveX > 0) return - // 理由同上 - if (Math.abs(moveX) < state.threshold) { - closeSwipeAction(instance, ownerInstance) - } else { - openSwipeAction(instance, ownerInstance) - } - } -} - -// 获取过渡时间 -function getDuration(value) { - if (value.toString().indexOf('s') >= 0) return value - return value > 30 ? value + 'ms' : value + 's' -} - -// 滑动结束时判断滑动的方向 -function getMoveDirection(instance, ownerInstance) { - var state = instance.getState() -} - -// 移动滑动选择器内容区域,同时显示出其隐藏的菜单 -function moveSwipeAction(moveX, instance, ownerInstance) { - var state = instance.getState() - // 获取所有按钮的实例,需要通过它去设置按钮的位移 - var buttons = ownerInstance.selectAllComponents('.u-swipe-action-item__right__button') - var len = buttons.length - var previewButtonsMoveX = 0 - - // 设置菜单内容部分的偏移 - instance.requestAnimationFrame(function() { - instance.setStyle({ - // 设置translateX的值 - 'transition': 'none', - transform: 'translateX(' + moveX + 'px)', - '-webkit-transform': 'translateX(' + moveX + 'px)' - }) - // 折叠按钮动画 - for (var i = len - 1; i >= 0; i--) { - // 通过比例,得出元素自身该移动的距离 - var translateX = state.buttons[i].width / state.buttonsWidth * moveX - // 最终移动的距离,是通过自身比例算出的距离,再加上在它之前所有按钮移动的距离之和 - var realTranslateX = translateX + previewButtonsMoveX - buttons[i].setStyle({ - // 在移动期间,不能使用过渡效果,否则会造成卡顿,本质原因是每次移动一点,就要花一定时间去过渡这个过程 - 'transition': 'none', - 'transform': 'translateX(' + realTranslateX + 'px)', - '-webkit-transform': 'translateX(' + realTranslateX + 'px)' - }) - // 记录本按钮之前的所有按钮的移动距离之和 - previewButtonsMoveX += translateX - } - }) -} - -// 一次性展开滑动菜单 -function openSwipeAction(instance, ownerInstance) { - var state = instance.getState() - // 获取所有按钮的实例,需要通过它去设置按钮的位移 - var buttons = ownerInstance.selectAllComponents('.u-swipe-action-item__right__button') - var len = buttons.length - // 处理duration单位问题 - const duration = getDuration(state.duration) - // 展开过程中,是向左移动,所以X的偏移应该为负值 - var buttonsWidth = -state.buttonsWidth - var previewButtonsMoveX = 0 - instance.requestAnimationFrame(function() { - // 设置菜单主体内容 - instance.setStyle({ - 'transition': 'transform ' + duration, - 'transform': 'translateX(' + buttonsWidth + 'px)', - '-webkit-transform': 'translateX(' + buttonsWidth + 'px)', - }) - // 设置各个隐藏的按钮为展开的状态 - for (var i = len - 1; i >= 0; i--) { - // 通过比例,得出元素自身该移动的距离 - var translateX = state.buttons[i].width / state.buttonsWidth * buttonsWidth - // 最终移动的距离,是通过自身比例算出的距离,再加上在它之前所有按钮移动的距离之和 - var realTranslateX = translateX + previewButtonsMoveX - buttons[i].setStyle({ - // 在移动期间,需要加上动画效果 - 'transition': 'transform ' + duration, - 'transform': 'translateX(' + realTranslateX + 'px)', - '-webkit-transform': 'translateX(' + realTranslateX + 'px)' - }) - // 记录本按钮之前的所有按钮的移动距离之和 - previewButtonsMoveX += translateX - } - }) - setStatus('open', instance) -} - -// 标记菜单的当前状态,open-已经打开,close-已经关闭 -function setStatus(status, instance) { - var state = instance.getState() - state.status = status -} - -// 一次性收起滑动菜单 -function closeSwipeAction(instance, ownerInstance) { - var state = instance.getState() - // 获取所有按钮的实例,需要通过它去设置按钮的位移 - var buttons = ownerInstance.selectAllComponents('.u-swipe-action-item__right__button') - var len = buttons.length - // 处理duration单位问题 - const duration = getDuration(state.duration) - instance.requestAnimationFrame(function() { - // 设置菜单主体内容 - instance.setStyle({ - 'transition': 'transform ' + duration, - 'transform': 'translateX(0px)', - '-webkit-transform': 'translateX(0px)' - }) - // 设置各个隐藏的按钮为收起的状态 - for (var i = len - 1; i >= 0; i--) { - buttons[i].setStyle({ - 'transition': 'transform ' + duration, - 'transform': 'translateX(0px)', - '-webkit-transform': 'translateX(0px)' - }) - } - }) - setStatus('close', instance) -} - -// show的状态发生变化 -function showChange(newValue, oldValue, ownerInstance, instance) { - var state = instance.getState() - if (state.disabled) return - // 打开或关闭单元格 - if (newValue) { - openSwipeAction(instance, ownerInstance) - } else { - closeSwipeAction(instance, ownerInstance) - } -} - -// 菜单尺寸发生变化 -function sizeChange(newValue, oldValue, ownerInstance, instance) { - // wxs内的局部变量快照 - var state = instance.getState() - state.disabled = newValue.disabled - state.duration = newValue.duration - state.show = newValue.show - state.threshold = newValue.threshold - state.buttons = newValue.buttons - - var len = state.buttons.length - if (len) { - var buttonsWidth = 0 - var buttons = newValue.buttons - for (var i = 0; i < len; i++) { - buttonsWidth += buttons[i].width - } - } - state.buttonsWidth = buttonsWidth -} - -module.exports = { - touchstart: touchstart, - touchmove: touchmove, - touchend: touchend, - sizeChange: sizeChange -} diff --git a/uni_modules/uview-plus/components/u-swipe-action-item/nvue - backup.js b/uni_modules/uview-plus/components/u-swipe-action-item/nvue - backup.js deleted file mode 100644 index f114ca6..0000000 --- a/uni_modules/uview-plus/components/u-swipe-action-item/nvue - backup.js +++ /dev/null @@ -1,270 +0,0 @@ -// nvue操作dom的库,用于获取dom的尺寸信息 -const dom = uni.requireNativePlugin('dom') -// nvue中用于操作元素动画的库,类似于uni.animation,只不过uni.animation不能用于nvue -const animation = uni.requireNativePlugin('animation') -import { sleep } from '../../libs/function/index'; -export default { - data() { - return { - // 是否滑动中 - moving: false, - // 状态,open-打开状态,close-关闭状态 - status: 'close', - // 开始触摸点的X和Y轴坐标 - startX: 0, - startY: 0, - // 所有隐藏按钮的尺寸信息数组 - buttons: [], - // 所有按钮的总宽度 - buttonsWidth: 0, - // 记录上一次移动的位置值 - moveX: 0, - // 记录上一次滑动的位置,用于前后两次做对比,如果移动的距离小于某一阈值,则认为前后之间没有移动,为了解决可能存在的通信阻塞问题 - lastX: 0 - } - }, - computed: { - // 获取过渡时间 - getDuratin() { - let duration = String(this.duration) - // 如果ms为单位,返回ms的数值部分 - if (duration.indexOf('ms') >= 0) return parseInt(duration) - // 如果s为单位,为了得到ms的数值,需要乘以1000 - if (duration.indexOf('s') >= 0) return parseInt(duration) * 1000 - // 如果值传了数值,且小于30,认为是s单位 - duration = Number(duration) - return duration < 30 ? duration * 1000 : duration - } - }, - watch: { - show: { - immediate: true, - handler(n) { - // if(n === true) { - // sleep(50).then(() => { - // this.openSwipeAction() - // }) - // } else { - // this.closeSwipeAction() - // } - } - } - }, - mounted() { - sleep(20).then(() => { - this.queryRect() - }) - }, - methods: { - close() { - this.closeSwipeAction() - }, - // 触摸单元格 - touchstart(event) { - if (this.disabled) return - this.closeOther() - const { touches } = event - // 记录触摸开始点的坐标值 - this.startX = touches[0].pageX - this.startY = touches[0].pageY - }, - // // 触摸滑动 - touchmove(event) { - if (this.disabled) return - const { touches } = event - const { pageX } = touches[0] - const { pageY } = touches[0] - let moveX = pageX - this.startX - const moveY = pageY - this.startY - const { buttonsWidth } = this - const len = this.buttons.length - - // 判断前后两次的移动距离,如果小于一定值,则不进行移动处理 - if (Math.abs(pageX - this.lastX) < 0.3) return - this.lastX = pageX - - // 移动的X轴距离大于Y轴距离,也即终点与起点位置连线,与X轴夹角小于45度时,禁止页面滚动 - if (Math.abs(moveX) > Math.abs(moveY) || Math.abs(moveX) > this.threshold) { - event.stopPropagation() - } - // 如果移动的X轴距离小于Y轴距离,也即终点位置与起点位置连线,与Y轴夹角小于45度时,认为是页面上下滑动,而不是左右滑动单元格 - if (Math.abs(moveX) < Math.abs(moveY)) return - - // 限制右滑的距离,不允许内容部分往右偏移,右滑会导致X轴偏移值大于0,以此做判断 - // 此处不能直接return,因为滑动过程中会缺失某些关键点坐标,会导致错乱,最好的办法就是 - // 在超出后,设置为0 - if (this.status === 'open') { - // 在开启状态下,向左滑动,需忽略 - if (moveX < 0) moveX = 0 - // 想要收起菜单,最大能移动的距离为按钮的总宽度 - if (moveX > buttonsWidth) moveX = buttonsWidth - // 如果是已经打开了的状态,向左滑动时,移动收起菜单 - this.moveSwipeAction(-buttonsWidth + moveX) - } else { - // 关闭状态下,右滑动需忽略 - if (moveX > 0) moveX = 0 - // 滑动的距离不允许超过所有按钮的总宽度,此时只能是左滑,最终设置按钮的总宽度,同时为负数 - if (Math.abs(moveX) > buttonsWidth) moveX = -buttonsWidth - // 只要是在滑过程中,就不断移动菜单的内容部分,从而使隐藏的菜单显示出来 - this.moveSwipeAction(moveX) - } - }, - // 单元格结束触摸 - touchend(event) { - if (this.disabled) return - const touches = event.changedTouches ? event.changedTouches[0] : {} - const { pageX } = touches - const { pageY } = touches - const { buttonsWidth } = this - this.moveX = pageX - this.startX - if (this.status === 'open') { - // 在展开的状态下,继续左滑,无需操作 - if (this.moveX < 0) this.moveX = 0 - if (this.moveX > buttonsWidth) this.moveX = buttonsWidth - // 在开启状态下,点击一下内容区域,moveX为0,也即没有进行移动,这时执行收起菜单逻辑 - if (this.moveX === 0) { - return this.closeSwipeAction() - } - // 在开启状态下,滑动距离小于阈值,则默认为不关闭,同时恢复原来的打开状态 - if (Math.abs(this.moveX) < this.threshold) { - this.openSwipeAction() - } else { - // 如果滑动距离大于阈值,则执行收起逻辑 - this.closeSwipeAction() - } - } else { - // 在关闭的状态下,右滑,无需操作 - if (this.moveX >= 0) this.moveX = 0 - if (this.moveX <= -buttonsWidth) this.moveX = -buttonsWidth - // 理由同上 - if (Math.abs(this.moveX) < this.threshold) { - this.closeSwipeAction() - } else { - this.openSwipeAction() - } - } - }, - // 移动滑动选择器内容区域,同时显示出其隐藏的菜单 - moveSwipeAction(moveX) { - if (this.moving) return - this.moving = true - - let previewButtonsMoveX = 0 - const len = this.buttons.length - animation.transition(this.$refs['u-swipe-action-item__content'].ref, { - styles: { - transform: `translateX(${moveX}px)` - }, - timingFunction: 'linear' - }, () => { - this.moving = false - }) - // 按钮的组的长度 - for (let i = len - 1; i >= 0; i--) { - const buttonRef = this.$refs[`u-swipe-action-item__right__button-${i}`][0].ref - // 通过比例,得出元素自身该移动的距离 - const translateX = this.buttons[i].width / this.buttonsWidth * moveX - // 最终移动的距离,是通过自身比例算出的距离,再加上在它之前所有按钮移动的距离之和 - const realTranslateX = translateX + previewButtonsMoveX - animation.transition(buttonRef, { - styles: { - transform: `translateX(${realTranslateX}px)` - }, - duration: 0, - delay: 0, - timingFunction: 'linear' - }, () => {}) - // 记录本按钮之前的所有按钮的移动距离之和 - previewButtonsMoveX += translateX - } - }, - // 关闭菜单 - closeSwipeAction() { - if (this.status === 'close') return - this.moving = true - const { buttonsWidth } = this - animation.transition(this.$refs['u-swipe-action-item__content'].ref, { - styles: { - transform: 'translateX(0px)' - }, - duration: this.getDuratin, - timingFunction: 'ease-in-out' - }, () => { - this.status = 'close' - this.moving = false - this.closeHandler() - }) - // 按钮的组的长度 - const len = this.buttons.length - for (let i = len - 1; i >= 0; i--) { - const buttonRef = this.$refs[`u-swipe-action-item__right__button-${i}`][0].ref - // 如果不满足边界条件,返回 - if (this.buttons.length === 0 || !this.buttons[i] || !this.buttons[i].width) return - - animation.transition(buttonRef, { - styles: { - transform: 'translateX(0px)' - }, - duration: this.getDuratin, - timingFunction: 'ease-in-out' - }, () => {}) - } - }, - // 打开菜单 - openSwipeAction() { - if (this.status === 'open') return - this.moving = true - const buttonsWidth = -this.buttonsWidth - let previewButtonsMoveX = 0 - animation.transition(this.$refs['u-swipe-action-item__content'].ref, { - styles: { - transform: `translateX(${buttonsWidth}px)` - }, - duration: this.getDuratin, - timingFunction: 'ease-in-out' - }, () => { - this.status = 'open' - this.moving = false - this.openHandler() - }) - // 按钮的组的长度 - const len = this.buttons.length - for (let i = len - 1; i >= 0; i--) { - const buttonRef = this.$refs[`u-swipe-action-item__right__button-${i}`][0].ref - // 如果不满足边界条件,返回 - if (this.buttons.length === 0 || !this.buttons[i] || !this.buttons[i].width) return - // 通过比例,得出元素自身该移动的距离 - const translateX = this.buttons[i].width / this.buttonsWidth * buttonsWidth - // 最终移动的距离,是通过自身比例算出的距离,再加上在它之前所有按钮移动的距离之和 - const realTranslateX = translateX + previewButtonsMoveX - animation.transition(buttonRef, { - styles: { - transform: `translateX(${realTranslateX}px)` - }, - duration: this.getDuratin, - timingFunction: 'ease-in-out' - }, () => {}) - previewButtonsMoveX += translateX - } - }, - // 查询按钮节点信息 - queryRect() { - // 历遍所有按钮数组,通过getRectByDom返回一个promise - const promiseAll = this.rightOptions.map((item, index) => this.getRectByDom(this.$refs[`u-swipe-action-item__right__button-${index}`][0])) - // 通过promise.all方法,让所有按钮的查询结果返回一个数组的形式 - Promise.all(promiseAll).then((sizes) => { - this.buttons = sizes - // 计算所有按钮总宽度 - this.buttonsWidth = sizes.reduce((sum, cur) => sum + cur.width, 0) - }) - }, - // 通过nvue的dom模块,查询节点信息 - getRectByDom(ref) { - return new Promise((resolve) => { - dom.getComponentRect(ref, (res) => { - resolve(res.size) - }) - }) - } - } -} diff --git a/utils/exam.js b/utils/exam.js index 12a97bb..bd56923 100644 --- a/utils/exam.js +++ b/utils/exam.js @@ -1,60 +1,137 @@ import dayjs from "dayjs"; +// 判断题目是否为多选题 +export function isMultipleChoice(question) { + // 只有选择题才有多选/单选的概念 + if (question.typeAnswer !== 0) return false; + if (!question.answerList || !question.answerList.length) return false; + const correctAnswers = question.answerList.filter(option => option.isTrue === 1 || option.isTrue === true); + return correctAnswers.length > 1; +} // 判断选项是否被选中 export function isOptionSelected(question, optionId) { + // 只有选择题才有选项的概念 + if (question.typeAnswer !== 0) return false; 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; + if (question.typeAnswer === 0) { + // 选择题逻辑 + if (!question.userAnswerBaseList || !question.userAnswerBaseList.length) return false; - // 获取所有正确答案的ID - const correctOptionIds = question.answerList - .filter(option => option.isTrue) - .map(option => option.id); + // 获取所有正确答案的ID + const correctOptionIds = question.answerList + .filter(option => option.isTrue === 1 || option.isTrue === true) + .map(option => option.id); - // 获取用户选择的答案ID - const userAnswerIds = [...new Set(question.userAnswerBaseList.map(answer => answer.answerId))]; + // 获取用户选择的答案ID + const userAnswerIds = [...new Set(question.userAnswerBaseList.map(answer => answer.answerId))]; - // 判断用户选择的答案数量是否与正确答案数量相同 - if (userAnswerIds.length !== correctOptionIds.length) { - return false; - } + // 判断用户选择的答案数量是否与正确答案数量相同 + if (userAnswerIds.length !== correctOptionIds.length) { + return false; + } - // 判断用户选择的答案是否都是正确的 - return userAnswerIds.every(answerId => correctOptionIds.includes(answerId)); + // 判断用户选择的答案是否都是正确的 + return userAnswerIds.every(answerId => correctOptionIds.includes(answerId)); + } else if (question.typeAnswer === 1) { + // 填空题逻辑 + if (!question.userAppletAnswerTrain || !question.userAppletAnswerTrain.answer) return false; + + // 如果有标准答案,进行比较 + if (question.answer) { + // 简单的字符串比较,可以根据实际需求调整比较逻辑 + return question.userAppletAnswerTrain.answer.trim().toLowerCase() === question.answer.trim().toLowerCase(); + } + + // 如果没有标准答案,只要有内容就认为是正确的 + return question.userAppletAnswerTrain.answer.trim() !== ''; + } + + return false; } export function isQuestionAnswered(question) { - if (question.type == '培训') { + if (question.typeAnswer === 1) { // 填空题:检查是否有答案且答案不为空 return question.userAppletAnswerTrain && question.userAppletAnswerTrain.answer && question.userAppletAnswerTrain.answer.trim() !== ''; - } else { + } else if (question.typeAnswer === 0) { // 选择题:检查是否有选择的答案 - return question.userAnswerBaseList && question.userAnswerBaseList.length > 0; + if (!question.userAnswerBaseList || !question.userAnswerBaseList.length) return false; + + // 对于多选题和单选题,都要求至少有一个答案 + return question.userAnswerBaseList.length > 0; } + + return false; +} + +// 获取题目的用户答案数组(支持单选和多选) +export function getUserAnswerIds(question) { + // 只有选择题才有answerId的概念 + if (question.typeAnswer !== 0) return []; + if (!question.userAnswerBaseList || !question.userAnswerBaseList.length) return []; + return [...new Set(question.userAnswerBaseList.map(answer => answer.answerId))]; } -// 判断全部题目答案是否达到指定的准确率 +// 获取题目的正确答案数组 +export function getCorrectAnswerIds(question) { + // 只有选择题才有answerId的概念 + if (question.typeAnswer !== 0) return []; + if (!question.answerList || !question.answerList.length) return []; + return question.answerList + .filter(option => option.isTrue === 1 || option.isTrue === true) + .map(option => option.id); +} + +// 获取填空题的用户答案 +export function getUserTextAnswer(question) { + if (question.typeAnswer !== 1) return ''; + if (!question.userAppletAnswerTrain || !question.userAppletAnswerTrain.answer) return ''; + return question.userAppletAnswerTrain.answer.trim(); +} + +// 获取填空题的正确答案 +export function getCorrectTextAnswer(question) { + if (question.typeAnswer !== 1) return ''; + return question.answer || ''; +} + +// 判断全部题目答案是否达到指定的准确率(只判断选择题) export function isSuccessPrecision(list, number = 100){ let errNumber = 0 + let totalChoiceQuestions = 0 for (var index = 0; index < list.length; index++) { var question = list[index]; - if (question.type == '基本' && !isAnswerCorrect(question)) { - errNumber++ + + // 只判断选择题(typeAnswer === 0),无论是基本题还是培训题 + if (question.typeAnswer === 0) { + totalChoiceQuestions++ + if (!isAnswerCorrect(question)) { + errNumber++ + } } } - console.log(errNumber, (list.length - errNumber) / list.length * 100); + // 如果没有选择题,返回true + if (totalChoiceQuestions === 0) { + console.log('没有选择题需要判断'); + return true + } + + const accuracy = (totalChoiceQuestions - errNumber) / totalChoiceQuestions * 100 + + console.log('选择题总数:', totalChoiceQuestions, '答错题目数:', errNumber, '正确率:', accuracy); - if(((list.length - errNumber) / list.length * 100) < number){ + if(accuracy < number){ return false } @@ -62,8 +139,13 @@ export function isSuccessPrecision(list, number = 100){ } export default { + isMultipleChoice, isOptionSelected, isAnswerCorrect, isQuestionAnswered, + getUserAnswerIds, + getCorrectAnswerIds, + getUserTextAnswer, + getCorrectTextAnswer, isSuccessPrecision, } \ No newline at end of file diff --git a/utils/getUrl.js b/utils/getUrl.js index 6803389..0d226f3 100644 --- a/utils/getUrl.js +++ b/utils/getUrl.js @@ -3,7 +3,7 @@ const accountInfo = wx.getAccountInfoSync(); // current = accountInfo.miniProgram.envVersion; const api = { - develop:"http://127.0.0.1:8002", + develop:"http://127.0.0.1:8080", // develop:"http://h5.xzaiyp.top", // develop:"https://api.catmdogd.com/prod-api", trial:"https://pet-admin.hhlm1688.com/api", diff --git a/utils/shareMixin.js b/utils/shareMixin.js new file mode 100644 index 0000000..55adac5 --- /dev/null +++ b/utils/shareMixin.js @@ -0,0 +1,101 @@ +import { useStore } from 'vuex' +import { computed } from 'vue' + +export default { + data() { + return { + shareConfig: { + // 默认分享配置 + title: '', + desc: '', + imageUrl: '', + path: '', + query: '' + } + } + }, + + async onLoad(options) { + // 构建当前页面路径,包含参数 + const pages = getCurrentPages() + const currentPage = pages[pages.length - 1] + let path = currentPage.route + + // 构建查询参数 + if (options && Object.keys(options).length > 0) { + const queryString = Object.keys(options) + .map(key => `${key}=${options[key]}`) + .join('&') + path = `${path}?${queryString}` + } + + this.shareConfig.path = path + this.shareConfig.query = options || {} + + // 设置默认分享内容 + this.setDefaultShareConfig() + }, + + methods: { + // 设置默认分享配置 + setDefaultShareConfig() { + try { + const store = useStore() + const configList = computed(() => store.getters.configList) + + // 从全局配置中获取默认分享信息 + this.shareConfig.title = configList.value?.applet_info?.paramValueText || '猫妈狗爸伴宠师' + this.shareConfig.imageUrl = configList.value?.applet_info?.paramValueImage || '' + } catch (error) { + console.log('获取分享配置失败:', error) + // 设置默认值 + this.shareConfig.title = '猫妈狗爸伴宠师' + this.shareConfig.imageUrl = '' + } + }, + + // 自定义分享配置 + setShareConfig(config = {}) { + this.shareConfig = { + ...this.shareConfig, + ...config + } + }, + + // 获取分享配置 + getShareConfig() { + return { + title: this.shareConfig.title, + desc: this.shareConfig.desc, + imageUrl: this.shareConfig.imageUrl, + path: this.shareConfig.path, + query: this.shareConfig.query + } + }, + + // 显示分享菜单 + showShareMenu() { + // #ifdef MP-WEIXIN + uni.showShareMenu({ + withShareTicket: true, + success: () => { + console.log('显示分享菜单成功') + }, + fail: (error) => { + console.error('显示分享菜单失败:', error) + } + }) + // #endif + }, + }, + + // 微信小程序分享给朋友 + onShareAppMessage(res) { + return this.getShareConfig() + }, + + // 微信小程序分享到朋友圈 + onShareTimeline(res) { + return this.getShareConfig() + }, +} \ No newline at end of file