猫妈狗爸伴宠师小程序前端代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

317 lines
6.7 KiB

2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
fix(订单管理): 修复宠物档案跳转缺少订单ID的问题 修复订单详情页跳转宠物档案页面时未传递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获取用户信息
1 month ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
fix(订单管理): 修复宠物档案跳转缺少订单ID的问题 修复订单详情页跳转宠物档案页面时未传递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获取用户信息
1 month ago
fix(订单管理): 修复宠物档案跳转缺少订单ID的问题 修复订单详情页跳转宠物档案页面时未传递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获取用户信息
1 month ago
fix(订单管理): 修复宠物档案跳转缺少订单ID的问题 修复订单详情页跳转宠物档案页面时未传递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获取用户信息
1 month ago
fix(订单管理): 修复宠物档案跳转缺少订单ID的问题 修复订单详情页跳转宠物档案页面时未传递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获取用户信息
1 month ago
  1. <template>
  2. <!-- <view>伴宠师认证</view> -->
  3. <view class="page">
  4. <view class="box">
  5. <view class="content bg-fff">
  6. <!-- 基本题部分 - 基本考核不通过时显示 -->
  7. <view class="question-section" v-if="basicQuestions.length > 0 && !baseSuccess">
  8. <view class="section-title">基本题</view>
  9. <questionCard
  10. v-for="(question, index) in basicQuestions"
  11. :key="`question-${index}`"
  12. :index="index"
  13. :data="prepareQuestionData(question)"
  14. mode="display"
  15. type="基本"
  16. />
  17. </view>
  18. <!-- 培训题部分 - 后台审核不通过时显示 -->
  19. <view class="question-section" v-if="trainQuestions.length > 0 && baseSuccess">
  20. <view class="section-title">培训题</view>
  21. <questionCard
  22. v-for="(question, index) in trainQuestions"
  23. :key="`train-question-${index}`"
  24. :index="index"
  25. :data="prepareTrainQuestionData(question)"
  26. mode="display"
  27. type="培训"
  28. />
  29. </view>
  30. <view class="question-section" v-if="detail.reason">
  31. <view class="section-title">驳回原因</view>
  32. <view class="question__view display" style="color: #f60;font-size: 28rpx;">
  33. {{ detail.reason }}
  34. </view>
  35. </view>
  36. </view>
  37. </view>
  38. <view class="footer-btn flex-colc">
  39. <view class="size-22 color-777 tips-rest" v-if="!baseSuccess">
  40. <!-- todo -->
  41. 剩余考试机会<text class="highlight">{{ restTimes - examNumber }}</text>
  42. </view>
  43. <view class="btn" @click="onClick">
  44. 重新考试
  45. </view>
  46. </view>
  47. <!-- 客服组件 -->
  48. <CustomerService />
  49. </view>
  50. </template>
  51. <script setup>
  52. import { ref, computed, onMounted } from 'vue'
  53. import { onShow } from '@dcloudio/uni-app'
  54. import { getAnswerBuildData, retakeExam } from '@/api/examination'
  55. import { useStore } from 'vuex'
  56. import { isOptionSelected, isAnswerCorrect, isQuestionAnswered, isSuccessPrecision } from '@/utils/exam.js'
  57. import questionCard from '../components/questionCard.vue'
  58. const store = useStore()
  59. const questionList = ref([])
  60. const detail = ref({})
  61. const baseSuccess = ref(false)
  62. const configList = computed(() => {
  63. return store.getters.configList
  64. })
  65. const userInfo = computed(() => {
  66. return store.state.user.userInfo
  67. })
  68. const restTimes = ref(0)
  69. const examNumber = ref(0)
  70. // 选择题列表 (根据type字段判断)
  71. const basicQuestions = computed(() => {
  72. return questionList.value.filter(item => item.type === '基本')
  73. })
  74. // 填空题列表 (根据type字段判断)
  75. const trainQuestions = computed(() => {
  76. return questionList.value.filter(item => item.type === '培训')
  77. })
  78. onMounted(() => {
  79. getExamData()
  80. })
  81. const getExamData = () => {
  82. getAnswerBuildData(userInfo.value.userId).then(res => {
  83. detail.value = res
  84. questionList.value = res.answerList
  85. examNumber.value = res.examNumber || 0
  86. // 使用新的工具函数判断成功率,只考虑基本题目
  87. const basicQuestionsList = res.answerList.filter(item => item.type === '基本')
  88. baseSuccess.value = isSuccessPrecision(basicQuestionsList)
  89. })
  90. }
  91. // 准备基本题数据格式
  92. const prepareQuestionData = (question) => {
  93. return {
  94. id: question.id,
  95. title: question.title,
  96. typeAnswer: question.typeAnswer,
  97. options: question.answerList || [],
  98. userAnswerBaseList: question.userAnswerBaseList || [],
  99. // 添加调试信息
  100. rawQuestion: question
  101. }
  102. }
  103. // 准备培训题数据格式
  104. const prepareTrainQuestionData = (question) => {
  105. return {
  106. id: question.id,
  107. title: question.title,
  108. typeAnswer: question.typeAnswer,
  109. options: question.answerList || [], // 培训题可能也有选择题
  110. value: question.userAppletAnswerTrain?.answer || '',
  111. answer: question.answer || '',
  112. numberWords: question.numberWords || 0,
  113. userAnswerBaseList: question.userAnswerBaseList || [], // 培训选择题的答案
  114. // 添加调试信息
  115. rawQuestion: question
  116. }
  117. }
  118. onShow(() => {
  119. restTimes.value = parseInt(configList.value.pet_work_num.paramValueText || 0)
  120. })
  121. const onClick = () => {
  122. retakeExam({
  123. userId: userInfo.value.userId,
  124. type : baseSuccess.value ? 1 : 0,//1清除培训考核的答案,0清除全部
  125. }).then(res => {
  126. if(baseSuccess.value){
  127. uni.reLaunch({
  128. url: "/otherPages/authentication/examination/baseCompleted"
  129. })
  130. }else{
  131. uni.reLaunch({
  132. url: "/otherPages/authentication/examination/start"
  133. })
  134. }
  135. })
  136. }
  137. </script>
  138. <style lang="scss" scoped>
  139. $bar-height: 163rpx;
  140. .page {
  141. padding-bottom: $bar-height;
  142. }
  143. .box {
  144. // background-image: linear-gradient(to bottom, #ffbf60, #f2f2f2);
  145. padding: 16rpx;
  146. .step {
  147. width: 720rpx;
  148. height: 32rpx;
  149. border-radius: 32rpx;
  150. background-color: #D9D9D9;
  151. .in {
  152. width: 50%;
  153. height: 32rpx;
  154. background-color: #ffbf60;
  155. border-radius: 32rpx;
  156. }
  157. }
  158. }
  159. .content {
  160. border-radius: 20rpx;
  161. padding: 15rpx 20rpx;
  162. .label {
  163. width: 86rpx;
  164. padding: 5rpx 15rpx;
  165. color: #fff;
  166. background-color: #FFBF60;
  167. justify-content: center;
  168. }
  169. }
  170. .group + .group {
  171. margin-top: 68rpx;
  172. }
  173. .level {
  174. display: flex;
  175. }
  176. .footer-btn {
  177. height: $bar-height;
  178. }
  179. .tips {
  180. &-rest {
  181. color: #707070;
  182. font-size: 22rpx;
  183. margin: 9rpx 0 13rpx 0;
  184. .highlight {
  185. color: #FF8DC6;
  186. }
  187. }
  188. }
  189. .question-section {
  190. margin-bottom: 40rpx;
  191. }
  192. .section-title {
  193. font-size: 32rpx;
  194. font-weight: bold;
  195. color: #333;
  196. margin: 30rpx 0;
  197. padding-left: 20rpx;
  198. border-left: 8rpx solid #FFBF60;
  199. }
  200. .question {
  201. color: #000000;
  202. }
  203. .option {
  204. background-color: #F3F3F3;
  205. color: #707070;
  206. line-height: 37rpx;
  207. padding: 23rpx;
  208. border-radius: 28rpx;
  209. position: relative;
  210. &+& {
  211. margin-top: 20rpx;
  212. }
  213. .icon {
  214. position: absolute;
  215. right: 45rpx;
  216. bottom: 23rpx;
  217. display: none;
  218. }
  219. &.is-correct {
  220. background-color: rgba($color: #05C160, $alpha: 0.08);
  221. color: #05C160;
  222. .icon-correct {
  223. display: block;
  224. }
  225. }
  226. &.is-error {
  227. background-color: rgba($color: #FFEBCE, $alpha: 0.36);
  228. color: #FF2A2A;
  229. .icon-error {
  230. display: block;
  231. }
  232. }
  233. }
  234. .textarea {
  235. background-color: #F3F3F3;
  236. padding: 23rpx;
  237. border-radius: 16rpx;
  238. margin-top: 20rpx;
  239. .answer-content {
  240. font-size: 28rpx;
  241. color: #333;
  242. line-height: 1.6;
  243. margin-bottom: 20rpx;
  244. }
  245. .highlight {
  246. color: #FF2A2A;
  247. font-size: 28rpx;
  248. line-height: 1.6;
  249. padding-top: 20rpx;
  250. border-top: 1px solid rgba(0, 0, 0, 0.1);
  251. }
  252. }
  253. .footer-btn {
  254. position: fixed;
  255. left: 0;
  256. right: 0;
  257. bottom: 0;
  258. height: $bar-height;
  259. background: #fff;
  260. box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
  261. }
  262. .btn {
  263. width: 600rpx;
  264. height: 80rpx;
  265. line-height: 80rpx;
  266. text-align: center;
  267. background: #FFBF60;
  268. color: #fff;
  269. border-radius: 40rpx;
  270. font-size: 32rpx;
  271. }
  272. </style>