From 13660d1a8c90fe0ecf757f95f9a94ec31240303a Mon Sep 17 00:00:00 2001
From: huliyong <2783385703@qq.com>
Date: Wed, 4 Jun 2025 13:47:57 +0800
Subject: [PATCH] =?UTF-8?q?fix(=E8=AE=A2=E5=8D=95=E7=AE=A1=E7=90=86):=20?=
=?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AE=A0=E7=89=A9=E6=A1=A3=E6=A1=88=E8=B7=B3?=
=?UTF-8?q?=E8=BD=AC=E7=BC=BA=E5=B0=91=E8=AE=A2=E5=8D=95ID=E7=9A=84?=
=?UTF-8?q?=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
修复订单详情页跳转宠物档案页面时未传递orderId参数的问题
```
```msg
refactor(认证考试): 重构考试答案提交逻辑
将单个题目提交改为批量提交,优化考试流程:
1. 基础考试和培训考试都改为最后统一提交答案
2. 添加加载状态提示
3. 使用Promise.all处理并发请求
```
```msg
fix(认证考试): 修复考试完成状态判断逻辑
修改answeBaseIsFinish和answeTrainIsFinish接口的返回判断逻辑,从检查code改为检查data字段
```
```msg
feat(认证考试): 新增重新考试和成为伴宠师接口
1. 添加retakeExam和appletUsersTeacher接口
2. 在错误详情页添加重新考试功能
3. 在考试完成页添加成为伴宠师功能
```
```msg
style(时间轴组件): 优化操作按钮布局
1. 添加按钮间距(gap)
2. 使用flex:1使按钮等宽
3. 根据状态显示不同按钮文本
4. 添加serviceBtn属性控制档案按钮显示
```
```msg
refactor(订单弹窗): 重构服务档案弹窗组件
1. 使用timelineService组件替代原有实现
2. 简化数据结构处理
3. 添加状态判断逻辑
4. 优化弹窗标题和样式
```
```msg
fix(表单验证): 添加认证考试结束页表单验证
1. 添加姓名、电话、地址的必填验证
2. 添加格式验证(电话格式、姓名格式)
3. 添加长度验证
4. 添加错误状态样式
5. 优化错误提示体验
```
```msg
refactor(工作台): 重构伴宠师申请流程
1. 优化申请条件判断逻辑
2. 添加用户状态检查
3. 完善考试状态跳转逻辑
4. 统一使用store获取用户信息
---
api/examination/index.js | 35 ++-
.../authentication/components/questionCard.vue | 24 +-
otherPages/authentication/examination/base.vue | 58 ++++-
otherPages/authentication/examination/end.vue | 154 +++++++++++-
.../authentication/examination/errorDetail.vue | 24 +-
otherPages/authentication/examination/train.vue | 27 +-
otherPages/orderTakingManage/detail/index.vue | 2 +-
.../components/petServicePopup - 副本.vue | 277 +++++++++++++++++++++
.../myOrdersManage/components/petServicePopup.vue | 225 ++---------------
pages/myOrdersManage/components/systemOrder.vue | 37 ++-
.../myOrdersManage/components/timelineService.vue | 22 +-
pages/workbenchManage/index.vue | 98 +++++---
12 files changed, 695 insertions(+), 288 deletions(-)
create mode 100644 pages/myOrdersManage/components/petServicePopup - 副本.vue
diff --git a/api/examination/index.js b/api/examination/index.js
index 82876d5..ef3a46f 100644
--- a/api/examination/index.js
+++ b/api/examination/index.js
@@ -133,14 +133,14 @@ export const answeTrainByQuestionId = (params) => {
// 伴宠师工作台-查询用户基本考核是否完成
export const answeBaseIsFinish = (params) => {
return request({
- url: '/applet/examination/answeBaseIsFinish',
+ url: '/applet/examination/answeBaseIsFinishV2',
headers: {
isToken: true
},
method: "get",
params
}).then(res => {
- return res.code == 200
+ return res.data == 1
})
}
@@ -148,13 +148,40 @@ export const answeBaseIsFinish = (params) => {
// 伴宠师工作台-查询用户培训考核是否完成
export const answeTrainIsFinish = (params) => {
return request({
- url: '/applet/examination/answeTrainIsFinish',
+ url: '/applet/examination/answeTrainIsFinishV2',
headers: {
isToken: true
},
method: "get",
params
}).then(res => {
- return res.code == 200
+ return res.data == 1
})
}
+
+
+// 伴宠师工作台-成为伴宠师
+export const appletUsersTeacher = (params) => {
+ return request({
+ url: '/applet/examination/appletUsersTeacher',
+ headers: {
+ isToken: true
+ },
+ method: "get",
+ params
+ })
+}
+
+
+// 伴宠师工作台-重新考试
+export const retakeExam = (params) => {
+ return request({
+ url: '/applet/examination/retakeExam',
+ headers: {
+ isToken: true
+ },
+ method: "get",
+ params
+ })
+}
+
diff --git a/otherPages/authentication/components/questionCard.vue b/otherPages/authentication/components/questionCard.vue
index 542df0b..0a42e10 100644
--- a/otherPages/authentication/components/questionCard.vue
+++ b/otherPages/authentication/components/questionCard.vue
@@ -103,18 +103,18 @@
const onChange = (val) => {
value.value = val
- const data = {
- userId: userId.value,
- questionId: props.data.id,
- }
-
- if (props.type === '基本') {
- data.answerId = val
- addBaseAnswer(data)
- } else if (props.type === '培训') {
- data.answer = val
- addTrainAnswer(data)
- }
+ // const data = {
+ // userId: userId.value,
+ // questionId: props.data.id,
+ // }
+
+ // if (props.type === '基本') {
+ // data.answerId = val
+ // addBaseAnswer(data)
+ // } else if (props.type === '培训') {
+ // data.answer = val
+ // addTrainAnswer(data)
+ // }
}
diff --git a/otherPages/authentication/examination/base.vue b/otherPages/authentication/examination/base.vue
index 89a87dc..b67c281 100644
--- a/otherPages/authentication/examination/base.vue
+++ b/otherPages/authentication/examination/base.vue
@@ -40,6 +40,17 @@
import { ref, computed } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { getQuestionList, getQuestionOptions } from '@/api/examination'
+ import {
+ addBaseAnswer,
+ addTrainAnswer
+ } from '@/api/examination'
+ import {
+ store
+ } from '@/store'
+
+ const userId = computed(() => {
+ return store.state.user.userInfo.userId
+ })
import questionCard from '../components/questionCard.vue';
@@ -50,13 +61,21 @@ const total = ref(0)
const initQuestion = async () => {
try {
- let questions = (await getQuestionList({ type: TYPE })).map(item => ({ id: item.id, title: item.title, value: null }))
+ let questions = (await getQuestionList({ type: TYPE })).map(item => ({
+ id: item.id,
+ title: item.title,
+ value: null,
+ answerList : item.answerList,
+ }))
// todo: 替换成批量查询接口
for (let i = 0; i < questions.length; i++) {
- const options = (await getQuestionOptions({ questionId: questions[i].id })).map(item => ({ id: item.id, title: item.title}))
+ // const options = (await getQuestionOptions({ questionId: questions[i].id })).map(item => ({ id: item.id, title: item.title}))
- questions[i].options = options
+ // questions[i].options = options
+
+ questions[i].options = questions[i].answerList
+
}
list.value = questions
@@ -87,7 +106,38 @@ const progress = computed(() => {
return Math.floor(answered.value / total.value * 100)
})
-const toNext = () => {
+const toNext = async () => {
+
+ const data = []
+
+ uni.showLoading({
+ 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({
+ // userId: userId.value,
+ // questionId: n.id,
+ // answerId : n.value,
+ // })
+ // })
+
+ // await addBaseAnswer({
+ // list : JSON.stringify(data)
+ // })
+
uni.navigateTo({
url: "/otherPages/authentication/examination/baseCompleted"
})
diff --git a/otherPages/authentication/examination/end.vue b/otherPages/authentication/examination/end.vue
index bc88d67..834cd02 100644
--- a/otherPages/authentication/examination/end.vue
+++ b/otherPages/authentication/examination/end.vue
@@ -114,19 +114,31 @@
姓名:
-
+
电话:
-
+
地址:
-
+
@@ -170,6 +182,7 @@
udpateUser,
getUserOne
} from '@/api/userTeacher'
+import { appletUsersTeacher } from '@/api/examination'
import stepProgress from '../components/stepProgress.vue';
@@ -192,8 +205,20 @@
latitude: null,
longitude: null,
address: null,
+ phone: null,
})
+ // 添加错误状态管理
+ const formErrors = reactive({
+ name: false,
+ phone: false,
+ address: false
+ })
+
+ // 清除单个字段错误状态
+ const clearFieldError = (field) => {
+ formErrors[field] = false
+ }
const initData = async () => {
console.log('--initData')
@@ -257,8 +282,101 @@
})
}
+ const validateForm = () => {
+ const { name, phone, address } = form
+ let hasError = false
+
+ // 重置错误状态
+ Object.keys(formErrors).forEach(key => {
+ formErrors[key] = false
+ })
+
+ // 必填字段验证
+ if (!name || name.trim() === '') {
+ formErrors.name = true
+ hasError = true
+ uni.showToast({
+ title: '请输入姓名',
+ icon: 'none'
+ })
+ return false
+ }
+
+ if (!phone || phone.trim() === '') {
+ formErrors.phone = true
+ hasError = true
+ uni.showToast({
+ title: '请输入电话号码',
+ icon: 'none'
+ })
+ return false
+ }
+
+ if (!address || address.trim() === '') {
+ formErrors.address = true
+ hasError = true
+ uni.showToast({
+ title: '请输入收货地址',
+ icon: 'none'
+ })
+ return false
+ }
+
+ // 姓名长度验证
+ if (name.trim().length < 2 || name.trim().length > 10) {
+ formErrors.name = true
+ hasError = true
+ uni.showToast({
+ title: '姓名长度应在2-10个字符之间',
+ icon: 'none'
+ })
+ return false
+ }
+
+ // 电话号码格式验证
+ const phoneRegex = /^1[3-9]\d{9}$/
+ if (!phoneRegex.test(phone.trim())) {
+ formErrors.phone = true
+ hasError = true
+ uni.showToast({
+ title: '请输入正确的手机号码',
+ icon: 'none'
+ })
+ return false
+ }
+
+ // 地址长度验证
+ if (address.trim().length < 5 || address.trim().length > 100) {
+ formErrors.address = true
+ hasError = true
+ uni.showToast({
+ title: '地址长度应在5-100个字符之间',
+ icon: 'none'
+ })
+ return false
+ }
+
+ // 姓名格式验证(只允许中文、英文字母)
+ const nameRegex = /^[\u4e00-\u9fa5a-zA-Z\s]+$/
+ if (!nameRegex.test(name.trim())) {
+ formErrors.name = true
+ hasError = true
+ uni.showToast({
+ title: '姓名只能包含中文和英文字母',
+ icon: 'none'
+ })
+ return false
+ }
+
+ return true
+ }
+
const onSave = async () => {
try {
+ // 先进行表单验证
+ if (!validateForm()) {
+ return
+ }
const {
area,
@@ -274,13 +392,20 @@
area,
latitude,
longitude,
- address,
- name,
- phone,
+ address: address.trim(),
+ name: name.trim(),
+ phone: phone.trim(),
}
await udpateUser(data)
+ //成为伴宠师
+ await appletUsersTeacher({
+ userId : userId.value
+ })
+
+ store.dispatch('getUserInfo')
+
uni.showToast({
title: '提交成功!',
icon: "none"
@@ -293,7 +418,11 @@
}, 1000)
} catch (err) {
-
+ uni.showToast({
+ title: '提交失败,请重试',
+ icon: 'none'
+ })
+ console.error('提交失败:', err)
}
}
@@ -478,4 +607,15 @@
.highlight {
color: #FFBF60;
}
+
+ // 添加输入框错误状态样式
+ .input-error {
+ border: 1px solid #ff4757 !important;
+ background-color: #fff5f5 !important;
+ color: #ff4757 !important;
+ }
+
+ .input-error::placeholder {
+ color: #ff9999 !important;
+ }
\ No newline at end of file
diff --git a/otherPages/authentication/examination/errorDetail.vue b/otherPages/authentication/examination/errorDetail.vue
index 1681ca1..4a50de4 100644
--- a/otherPages/authentication/examination/errorDetail.vue
+++ b/otherPages/authentication/examination/errorDetail.vue
@@ -34,9 +34,9 @@
\ No newline at end of file
diff --git a/pages/myOrdersManage/components/petServicePopup.vue b/pages/myOrdersManage/components/petServicePopup.vue
index d777f10..753c881 100644
--- a/pages/myOrdersManage/components/petServicePopup.vue
+++ b/pages/myOrdersManage/components/petServicePopup.vue
@@ -1,44 +1,16 @@
@@ -46,6 +18,7 @@