#4 feat: 伴宠师认证流程-接口对接;

Merged
Fox merged 1 commits from fox into master 3 weeks ago
  1. +3
    -0
      App.vue
  2. +109
    -0
      api/examination.js
  3. +11
    -0
      api/system/index.js
  4. +12
    -0
      api/userTeacher.js
  5. +33
    -12
      otherPages/authentication/components/questionCard.vue
  6. +5
    -2
      otherPages/authentication/components/stepProgress.vue
  7. +30
    -106
      otherPages/authentication/examination/base.vue
  8. +81
    -22
      otherPages/authentication/examination/baseCompleted.vue
  9. +4
    -1
      otherPages/authentication/examination/end.vue
  10. +69
    -78
      otherPages/authentication/examination/errorDetail.vue
  11. +9
    -12
      otherPages/authentication/examination/start.vue
  12. +22
    -41
      otherPages/authentication/examination/train.vue
  13. +4
    -1
      otherPages/authentication/examination/trainCompleted/fail.vue
  14. +1
    -1
      otherPages/authentication/examination/trainCompleted/index.vue
  15. +5
    -2
      otherPages/authentication/examination/trainCompleted/pass.vue
  16. +5
    -2
      otherPages/authentication/examination/trainCompleted/waiting.vue
  17. +72
    -67
      otherPages/authentication/list/index.vue
  18. +6
    -3
      store/index.js
  19. +31
    -0
      store/modules/system.js
  20. +1
    -0
      style/index.scss
  21. +0
    -4
      utils/pageList.js

+ 3
- 0
App.vue View File

@ -1,8 +1,11 @@
<script>
import { store } from '@/store'
export default {
onLaunch: function() {
console.warn('当前组件仅支持 uni_modules 目录结构 ,请升级 HBuilderX 到 3.1.0 版本以上!')
console.log('App Launch')
store.dispatch('fetchConfigList')
},
onShow: function() {
console.log('App Show')


+ 109
- 0
api/examination.js View File

@ -0,0 +1,109 @@
import request from '@/utils/request'
export const getLicenseList = () => {
return request({
url: '/applet/examination/licenseList',
method: "get"
}).then(res => {
return res.data
})
}
export const getPetTypeList = () => {
return request({
url: '/applet/examination/petTypeList',
method: "get"
}).then(res => {
return res.data
})
}
export const getServiceList = (params) => {
return request({
url: '/applet/config/serviceList',
method: "get",
params
}).then(res => {
return res.data?.map?.(item => {
const { id, title, video } = item
return { id, title, video }
}) || []
})
}
export const getTrainList = (params) => {
return request({
url: '/applet/config/trainList',
method: "get",
params
}).then(res => {
return res.data?.map?.(item => {
const { id, title, content } = item
return { id, title, content }
}) || []
})
}
export const getQuestionList = (params) => {
return request({
url: '/applet/examination/questionList',
method: "get",
params
}).then(res => {
return res.data
})
}
export const getQuestionOptions = (params) => {
return request({
url: '/applet/examination/insertUser',
method: "get",
params
}).then(res => {
return res.data
})
}
export const addBaseAnswer = (data) => {
return request({
url: '/applet/examination/addBaseAnswer',
headers: {
isToken: true
},
method: 'post',
data
})
}
export const answeBaseByQuestionId = (params) => {
return request({
url: '/applet/examination/answeBaseByQuestionId',
method: "get",
params
}).then(res => {
return res.data?.[0] || {}
})
}
export const addTrainAnswer = (data) => {
return request({
url: '/applet/examination/addTrainAnswer',
headers: {
isToken: true
},
method: 'post',
data
})
}
export const answeTrainByQuestionId = (params) => {
return request({
url: '/applet/examination/answeTrainByQuestionId',
method: "get",
params
}).then(res => {
return res.data?.[0] || {}
})
}

+ 11
- 0
api/system/index.js View File

@ -0,0 +1,11 @@
import request from '@/utils/request'
// 获取配置信息
export function getConfigList() {
return request({
'url': '/applet/config/configList',
'method': 'get'
}).then(res => {
return res.data
})
}

+ 12
- 0
api/userTeacher.js View File

@ -0,0 +1,12 @@
import request from '@/utils/request'
export const insertUser = (data) => {
return request({
url: '/applet/UserTeacher/insertUser',
headers: {
isToken: true
},
method: 'post',
data
})
}

+ 33
- 12
otherPages/authentication/components/questionCard.vue View File

@ -1,17 +1,19 @@
<template>
<view class="mt32 question__view" :class="[props.mode]">
<view class="size-28 mb20 question">
{{ `${props.index + 1}${props.data.question}` }}
{{ props.data.title }}
<!-- {{ `${props.index + 1}${props.data.title}` }} -->
</view>
<template v-if="props.mode === 'edit'">
<template v-if="props.data.options?.length">
<view class="size-28 option"
v-for="(option, oIdx) in props.data.options"
:key="`${props.index}-option-${oIdx}`"
:class="[value === option.value ? 'is-selected' : '']"
@click="onClick(option.value)"
:class="[value === option.id ? 'is-selected' : '']"
@click="onChange(option.id)"
>
{{ `${String.fromCharCode(65 + oIdx)}${option.label}` }}
{{ option.title }}
<!-- {{ `${String.fromCharCode(65 + oIdx)}${option.label}` }} -->
</view>
</template>
<template v-else>
@ -20,6 +22,7 @@
v-model="value"
placeholder="请输入您的答案,不得低于700个字"
:rows="10"
@blur="onChange($event.detail.value)"
></textarea>
</view>
</template>
@ -30,13 +33,12 @@
v-for="(option, oIdx) in props.data.options"
:key="`${props.index}-option-${oIdx}`"
:class="[
props.data.answer === option.value ? 'is-correct' : '',
props.data.value === option.value ? 'is-error' : '',
props.data.answer === option.id ? 'is-correct' : '',
props.data.value === option.id && props.data.answer !== option.id ? 'is-error' : '',
]"
@click="onClick(option.value)"
>
{{ `${String.fromCharCode(65 + oIdx)}${option.label}` }}
{{ option.title }}
<!-- {{ `${String.fromCharCode(65 + oIdx)}${option.label}` }} -->
<view class="icon icon-correct">
<up-icon name="checkmark" color="#05C160" size="35rpx"></up-icon>
</view>
@ -48,7 +50,7 @@
<template v-else>
<view class="textarea">
<view>{{ props.data.value }}</view>
<view class="highlight">{{ props.data.reason }}</view>
<view class="highlight">{{ props.data.answer }}</view>
</view>
</template>
</template>
@ -56,7 +58,8 @@
</template>
<script setup>
import { computed } from 'vue'
import { computed, watch } from 'vue'
import { addBaseAnswer, addTrainAnswer } from '@/api/examination'
const props = defineProps({
index: {
@ -76,6 +79,10 @@ const props = defineProps({
mode: {
type: String,
default: 'edit', // edit | display
},
type: {
type: String,
default: null, // '' | ''
}
})
@ -90,8 +97,22 @@ const value = computed({
}
})
const onClick = (val) => {
const onChange = (val) => {
value.value = val
console.log('--onChange', val)
const data = {
questionId: props.data.id,
}
if (props.type === '基本') {
data.answerId = val
addBaseAnswer(data)
} else if (props.type === '培训') {
data.answer = val
addTrainAnswer(data)
}
}
</script>


+ 5
- 2
otherPages/authentication/components/stepProgress.vue View File

@ -1,7 +1,7 @@
<template>
<view>
<view class="flex-rowl">
<image src="@/static/images/ydd/logo.png" mode="" class="logo"></image>
<image :src="configList.applet_logo.paramValueImage" mode="" class="logo"></image>
<view class="size-36 fw700 color-fff">
伴宠师认证
</view>
@ -23,7 +23,7 @@
</template>
</view>
<view class="color-ffb size-22 mt32">
为保证喂养员认证顺利进行请认真填写并确保信息的真实性
{{ configList.pet_describe.paramValueText }}
</view>
</view>
</view>
@ -31,6 +31,9 @@
<script setup>
import { reactive } from 'vue'
import { store } from '@/store'
const configList = store.state.system.configList
const props = defineProps({
step: {


+ 30
- 106
otherPages/authentication/examination/base.vue View File

@ -19,17 +19,18 @@
<questionCard
v-for="(item, qIdx) in list"
:key="`question-${qIdx}`"
v-model="item.value"
:index="qIdx"
:data="item"
v-model="item.value"
:type="TYPE"
></questionCard>
</view>
</view>
</view>
<view class="footer-btn">
<view class="btn" @click="toNext">
<button plain class="btn" @click="toNext" :disabled="answered < total">
提交
</view>
</button>
</view>
</view>
@ -38,114 +39,33 @@
<script setup>
import { ref, computed } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { usePageList } from "@/utils/pageList";
import { getQuestionList, getQuestionOptions } from '@/api/examination'
import questionCard from '../components/questionCard.vue';
// todo
const { list, total, getData } = usePageList()
const TYPE = '基本'
onShow(() => {
// todo: delete test data
total.value = 100
list.value = [
{
question: '猫咪每天在地上走路,时不时还会打滚,身上是很不干净的,最好每个星期洗次澡',
options: [
{
label: '对',
value: 0,
},
{
label: '错',
value: 1,
},
],
value: null,
},
{
question: '当狗狗出现乱拉乱尿或者捣乱拆家等反映时,您会如何处理?',
options: [
{
label: '暴力制止,根据情况是否严重来判断下手轻重,让狗狗知道这样做会受到惩罚',
value: 0,
},
{
label: '奖罚分明,制止后耐心引导,直到狗狗做出正确的行为,并立马给出奖励',
value: 1,
},
{
label: '狗狗也不是故意的,也不会造成什么很大的影响,默默打扫好就算了吧',
value: 2,
},
],
value: null,
},
{
question: '狗狗和猫咪一样是肉食性动物,最好可以纯肉喂养,对狗狗的身心健康有很大好处',
options: [
{
label: '对',
value: 0,
},
{
label: '错',
value: 1,
},
],
value: null,
},
{
question: '猫咪每天在地上走路,时不时还会打滚,身上是很不干净的,最好每个星期洗次澡',
options: [
{
label: '对',
value: 0,
},
{
label: '错',
value: 1,
},
],
value: null,
},
{
question: '当狗狗出现乱拉乱尿或者捣乱拆家等反映时,您会如何处理?',
options: [
{
label: '暴力制止,根据情况是否严重来判断下手轻重,让狗狗知道这样做会受到惩罚',
value: 0,
},
{
label: '奖罚分明,制止后耐心引导,直到狗狗做出正确的行为,并立马给出奖励',
value: 1,
},
{
label: '狗狗也不是故意的,也不会造成什么很大的影响,默默打扫好就算了吧',
value: 2,
},
],
value: null,
},
{
question: '狗狗和猫咪一样是肉食性动物,最好可以纯肉喂养,对狗狗的身心健康有很大好处',
options: [
{
label: '对',
value: 0,
},
{
label: '错',
value: 1,
},
],
value: null,
},
]
const list = ref([])
const total = ref(0)
})
const initQuestion = async () => {
try {
let questions = (await getQuestionList({ type: TYPE })).map(item => ({ id: item.id, title: item.title, value: null }))
// 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}))
questions[i].options = options
}
list.value = questions
total.value = questions.length
} catch (err) {
}
}
const answered = computed(() => {
return list.value.filter(item => item.value !== null).length
@ -161,6 +81,10 @@ const toNext = () => {
})
}
onShow(() => {
initQuestion()
})
</script>
<style lang="scss" scoped>


+ 81
- 22
otherPages/authentication/examination/baseCompleted.vue View File

@ -22,17 +22,13 @@
</view>
<view class="info-box-content">
<view class="flex-colc info-item"
v-for="(item, index) in introList"
:key="`intro-${index}`"
v-for="item in serviceList"
:key="`service-${item.id}`"
>
<view class="video">
<video
:src="item.url"
:src="item.video"
play-btn-position="center"
:show-fullscreen-btn="false"
:show-center-play-btn="true"
:show-progress="false"
:show-play-btn="false"
:picture-in-picture-mode="[]"
></video>
</view>
@ -45,10 +41,30 @@
服务培训
</view>
<view class="info-box-content">
<view class="flex-colc info-item">
<image src="../static/examination/bg-train-manual.png" mode="widthFix"></image>
<view class="flex-colc info-item"
v-for="item in trainList"
:key="`train-${item.id}`"
@click="openPopup(item.title, item.content)"
>
<image :src="configList.pet_service_training.paramValueImage" mode="widthFix"></image>
<text class="desc">{{ item.title }}</text>
</view>
</view>
<up-popup
:show="popupData.show"
round="16rpx"
@close="closePopup"
>
<view class="popup">
<view class="popup-header">
<text class="popup-title">{{ popupData.title }}</text>
</view>
<view class="popup-content">
<up-parse class="size-28" :content="popupData.content"></up-parse>
</view>
</view>
</up-popup>
</view>
<view class="flex-rowc tools">
<view class="flex-rowc btn" @click="toNext">
@ -61,30 +77,57 @@
</template>
<script setup>
import { ref } from 'vue'
import { ref, reactive } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { store } from '@/store'
import { getServiceList, getTrainList } from '@/api/examination'
import stepProgress from '../components/stepProgress.vue';
const configList = store.state.system.configList
const toNext = () => {
uni.navigateTo({
url: "/otherPages/authentication/examination/train"
})
}
const introList = ref([])
const serviceList = ref([])
const fetchServiceList = async () => {
try {
serviceList.value = await getServiceList()
} catch (err) {
}
}
const trainList = ref([])
const fetchTrainList = async () => {
try {
trainList.value = await getTrainList()
} catch (err) {
}
}
const popupData = reactive({
show: false,
title: null,
content: null,
})
const openPopup = (title, content) => {
popupData.show = true
popupData.title = title
popupData.content = content
}
const closePopup = () => {
popupData.show = false
}
onShow(() => {
// todo: delete test data
introList.value = [
{
url: '',
title: '猫妈狗爸平台介绍',
},
{
url: '',
title: '喂养学习视频',
},
]
fetchServiceList()
fetchTrainList()
})
</script>
@ -211,4 +254,20 @@
border-radius: 41rpx;
background-color: #FFBF60;
}
.popup {
padding: 28rpx;
&-header {
margin-bottom: 28rpx;
}
&-title {
color: #000000;
font-weight: 700;
font-size: 30rpx;
line-height: 40rpx;
}
}
</style>

+ 4
- 1
otherPages/authentication/examination/end.vue View File

@ -68,7 +68,7 @@
<view class="item">
<view class="flex-between mb10">
<view class="flex-rowl">
<image class="img" src="@/static/images/ydd/end1(4).png" mode="widthFix"></image>
<image class="img" :src="configList.wx_image.paramValueImage" mode="widthFix"></image>
<text class="size-30 color-000 fw700">添加客服微信</text>
</view>
<view class="size-22 highlight">
@ -138,9 +138,12 @@
<script setup>
import { reactive } from "vue";
import { onShow } from '@dcloudio/uni-app'
import { store } from '@/store'
import stepProgress from '../components/stepProgress.vue';
const configList = store.state.system.configList
const form = reactive({
name: null,
idCard: null,


+ 69
- 78
otherPages/authentication/examination/errorDetail.vue View File

@ -13,6 +13,7 @@
:key="`${gIdx}-question-${qIdx}`"
:index="qIdx"
:data="item"
:type="item.type"
mode="display"
></questionCard>
</view>
@ -35,11 +36,76 @@
<script setup>
import { ref } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { usePageList } from "@/utils/pageList";
import { getQuestionList, getQuestionOptions, answeBaseByQuestionId, answeTrainByQuestionId } from '@/api/examination'
import questionCard from '../components/questionCard.vue';
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, isTrue } = await answeBaseByQuestionId({ questionId: id })
if (isTrue) {
continue
}
data.answer = answer.id
data.value = answerId
data.isTrue = 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)
}
}
const { list, getData } = usePageList()
list.value = groups
console.log('--list', list.value)
} catch (err) {
console.log('--initList--err', err)
}
}
const restTimes = ref()
@ -47,82 +113,7 @@
// todo: fetch
restTimes.value = 3
list.value = [
{
title: '选择题',
children: [
{
question: '猫咪每天在地上走路,时不时还会打滚,身上是很不干净的,最好每个星期洗次澡',
options: [
{
label: '对',
value: 0,
},
{
label: '错',
value: 1,
},
],
answer: 0,
value: 1,
},
{
question: '当狗狗出现乱拉乱尿或者捣乱拆家等反映时,您会如何处理?',
options: [
{
label: '暴力制止,根据情况是否严重来判断下手轻重,让狗狗知道这样做会受到惩罚',
value: 0,
},
{
label: '奖罚分明,制止后耐心引导,直到狗狗做出正确的行为,并立马给出奖励',
value: 1,
},
{
label: '狗狗也不是故意的,也不会造成什么很大的影响,默默打扫好就算了吧',
value: 2,
},
],
answer: 1,
value: 2,
},
{
question: '狗狗和猫咪一样是肉食性动物,最好可以纯肉喂养,对狗狗的身心健康有很大好处',
options: [
{
label: '对',
value: 0,
},
{
label: '错',
value: 1,
},
],
answer: 1,
value: 0,
},
]
},
{
title: '主观题',
children: [
{
question: '喂养服务流程:如果您收到一笔喂养猫咪的订单,备注猫咪性格活泼,请问您会如何进行服务?请详细描述和上一题服务过程的不同之处(若服务宠物不包含猫咪可回答“略”)',
reason: '字数低于700字,不予合格',
value: '猫咪性格怕生,我耐心的与猫咪接触,和它玩耍 先建立良好的关系,再进行喂养。',
},
{
question: '喂养服务流程:如果您收到一笔喂养猫咪的订单,备注猫咪性格活泼,请问您会如何进行服务?请详细描述和上一题服务过程的不同之处(若服务宠物不包含猫咪可回答“略”)',
reason: '字数低于700字,不予合格',
value: '猫咪性格怕生,我耐心的与猫咪接触,和它玩耍 先建立良好的关系,再进行喂养。',
},
{
question: '喂养服务流程:如果您收到一笔喂养猫咪的订单,备注猫咪性格活泼,请问您会如何进行服务?请详细描述和上一题服务过程的不同之处(若服务宠物不包含猫咪可回答“略”)',
reason: '字数低于700字,不予合格',
value: '猫咪性格怕生,我耐心的与猫咪接触,和它玩耍 先建立良好的关系,再进行喂养。',
},
]
}
]
initList()
})
const onClick = () => {


+ 9
- 12
otherPages/authentication/examination/start.vue View File

@ -6,14 +6,11 @@
<view class="com-title size-32 fw700 flex-rowl">
您选择的宠物类型
</view>
<image class="mt32" v-if="petType === 'cat'" src="@/static/images/ydd/cat-active.png" mode="widthFix"></image>
<image class="mt32" v-else-if="petType === 'dog'" src="@/static/images/ydd/dog-active.png" mode="widthFix"></image>
<image class="mt32" v-else-if="petType === 'special-pet'" src="@/static/images/ydd/special-pet-active.png" mode="widthFix"></image>
<image class="mt32" :src="petTypeData.image" mode="widthFix"></image>
</view>
<view class="text po-r bg-fff">
<text
class="size-28">即将开始基础养宠经验考核该环节是对喂养员科学养宠经验及理念的基础考核考核题目均为选择判断题题目较为简单;大多为科学养宠所涉及的常识题以客观事实判定标准答案;小部分题目为平台对喂养员的要求以平台自行判定标准答案!</text>
<up-parse class="size-28" :content="configList.pet_raising_details.paramValueArea"></up-parse>
<view class="po-a flex-rowl tips">
<image class="ml16" src="@/static/images/ydd/icon1.png" mode="widthFix"></image>
<text class="size-28 ml16">养宠考试说明</text>
@ -21,8 +18,7 @@
</view>
<view class="text po-r bg-fff mb150">
<text
class="size-28">即将开始基础养宠经验考核该环节是对喂养员科学养宠经验及理念的基础考核考核题目均为选择判断题题目较为简单;大多为科学养宠所涉及的常识题以客观事实判定标准答案;小部分题目为平台对喂养员的要求以平台自行判定标准答案!</text>
<up-parse class="size-28" :content="configList.pet_attention_details.paramValueArea"></up-parse>
<view class="po-a flex-rowl tips">
<image class="ml16" src="@/static/images/ydd/icon2.png" mode="widthFix"></image>
<text class="size-28 ml16">考试注意事项</text>
@ -46,19 +42,20 @@
<script setup>
import { ref, onMounted } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { store } from '@/store'
const petType = ref()
const petTypeData = ref({})
const restTimes = ref()
const configList = store.state.system.configList
onShow(() => {
petTypeData.value = uni.getStorageSync('petTypeData')
// todo: fetch
petType.value = 'cat'
restTimes.value = 3
})
const content =
`即将开始基础养宠经验考核,该环节是对喂养员科学养宠经验及理念的基础考核,考核题目均为选择判断题,题目较为简单;大多为科学养宠所涉及的常识题,以客观事实判定标准答案;小部分题目为平台对喂养员的要求,以平台自行判定标准答案!`
const toNext = () => {
uni.navigateTo({
url: "/otherPages/authentication/examination/base"


+ 22
- 41
otherPages/authentication/examination/train.vue View File

@ -23,14 +23,15 @@
:index="qIdx"
:data="item"
v-model="item.value"
:type="TYPE"
></questionCard>
</view>
</view>
</view>
<view class="footer-btn buttom ">
<view class="btn" @click="toNext">
<button plain class="btn" @click="toNext" :disabled="answered < total">
提交
</view>
</button>
</view>
</view>
</template>
@ -38,50 +39,26 @@
<script setup>
import { ref, computed } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { usePageList } from "@/utils/pageList";
import { getQuestionList } from '@/api/examination'
import questionCard from '../components/questionCard.vue';
// todo
const { list, total, getData } = usePageList()
const TYPE = '培训'
onShow(() => {
// todo: delete test data
total.value = 100
list.value = [
{
question: '喂养服务流程:如果您收到一笔喂养猫咪的订单,备注猫咪性格活泼,请问您会如何进行服务?请详细描述和上一题服务过程的不同之处(若服务宠物不包含猫咪可回答“略”)',
value: null,
},
{
question: '喂养服务流程:如果您收到一笔喂养猫咪的订单,备注猫咪性格活泼,请问您会如何进行服务?请详细描述和上一题服务过程的不同之处(若服务宠物不包含猫咪可回答“略”)',
value: null,
},
{
question: '喂养服务流程:如果您收到一笔喂养猫咪的订单,备注猫咪性格活泼,请问您会如何进行服务?请详细描述和上一题服务过程的不同之处(若服务宠物不包含猫咪可回答“略”)',
value: null,
},
{
question: '喂养服务流程:如果您收到一笔喂养猫咪的订单,备注猫咪性格活泼,请问您会如何进行服务?请详细描述和上一题服务过程的不同之处(若服务宠物不包含猫咪可回答“略”)',
value: null,
},
{
question: '喂养服务流程:如果您收到一笔喂养猫咪的订单,备注猫咪性格活泼,请问您会如何进行服务?请详细描述和上一题服务过程的不同之处(若服务宠物不包含猫咪可回答“略”)',
value: null,
},
{
question: '喂养服务流程:如果您收到一笔喂养猫咪的订单,备注猫咪性格活泼,请问您会如何进行服务?请详细描述和上一题服务过程的不同之处(若服务宠物不包含猫咪可回答“略”)',
value: null,
},
{
question: '喂养服务流程:如果您收到一笔喂养猫咪的订单,备注猫咪性格活泼,请问您会如何进行服务?请详细描述和上一题服务过程的不同之处(若服务宠物不包含猫咪可回答“略”)',
value: null,
},
]
const list = ref([])
const total = ref(0)
})
const initQuestion = async () => {
try {
let questions = (await getQuestionList({ type: TYPE })).map(item => ({ id: item.id, title: item.title, value: null }))
list.value = questions
total.value = questions.length
} catch (err) {
}
}
const answered = computed(() => {
return list.value.filter(item => item.value?.length).length
@ -97,6 +74,10 @@ const toNext = () => {
})
}
onShow(() => {
initQuestion()
})
</script>


+ 4
- 1
otherPages/authentication/examination/trainCompleted/fail.vue View File

@ -1,7 +1,7 @@
<template>
<view class="content_">
<view class="img_">
<image src="../../static/examination/unqualified.png" mode="" style="width: 310rpx;height: 311rpx;"></image>
<image :src="configList.pet_low.paramValueImage" mode="" style="width: 310rpx;height: 311rpx;"></image>
</view>
<view class="flex-rowc tools">
<view class="flex-rowc btn" :style="{borderRadius:'41rpx'}" @click="onClick">
@ -13,6 +13,9 @@
</template>
<script setup>
import { store } from '@/store'
const configList = store.state.system.configList
const onClick = () => {
uni.navigateTo({


+ 1
- 1
otherPages/authentication/examination/trainCompleted/index.vue View File

@ -25,7 +25,7 @@
const status = ref('waiting')
onShow(() => {
// todo: fetch
// todo: fetch audit status
status.value = 'pass'
})


+ 5
- 2
otherPages/authentication/examination/trainCompleted/pass.vue View File

@ -1,10 +1,10 @@
<template>
<view class="content_ box-size">
<view class="img_">
<image src="../../static/examination/approved.png" mode="" style="width: 310rpx;height: 311rpx;"></image>
<image :src="configList.pet_success.paramValueImage" mode="" style="width: 310rpx;height: 311rpx;"></image>
</view>
<view class="text_ level">
审核留言:-您好呀感谢您的认真作答~从您的回答中我们感受到了您对宠物的用心相信您可以胜任宠物喂养员这份小小的工作!希望您能在猫妈狗爸给更多毛孩子带去您的关爱!
{{ configList.pet_success.paramValueText }}
</view>
<view class="buttom" :style="{borderRadius:'41rpx'}" @click="onClick">
下一步
@ -13,6 +13,9 @@
</template>
<script setup>
import { store } from '@/store'
const configList = store.state.system.configList
const onClick = () => {
uni.navigateTo({


+ 5
- 2
otherPages/authentication/examination/trainCompleted/waiting.vue View File

@ -1,10 +1,10 @@
<template>
<view class="content_">
<view class="img_">
<image src="../../static/examination/examine.png" mode="" style="width: 310rpx;height: 311rpx;"></image>
<image :src="configList.pet_in.paramValueImage" mode="" style="width: 310rpx;height: 311rpx;"></image>
</view>
<view class="text level">
平台会在三个工作日内完成审核请及时查看审核结果
{{ configList.pet_in.paramValueText }}
</view>
<view class="buttom" :style="{borderRadius:'41rpx'}" @click="onClick">
我知道了
@ -13,6 +13,9 @@
</template>
<script setup>
import { store } from '@/store'
const configList = store.state.system.configList
const onClick = () => {
// todo


+ 72
- 67
otherPages/authentication/list/index.vue View File

@ -24,16 +24,16 @@
>
<view class="license-options">
<up-checkbox
v-for="item in LICENSE_OPTIONS"
:key="`license-${item.value}`"
:label="item.label"
:name="item.value"
v-for="item in licenseOptions"
:key="`license-${item.id}`"
:label="item.title"
:name="item.id"
>
</up-checkbox>
</view>
</up-checkbox-group>
<view class="tips">
温馨提示上传专业执照将大大增加通过概率且会快速晋升为高级伴宠师获取更高报酬
{{ configList.pet_news.paramValueText }}
</view>
<up-upload
:fileList="licenseData.fileList"
@ -52,38 +52,15 @@
</view>
<view class="flex-between wrap mt32">
<view class="type">
<image src="@/static/images/ydd/cat.png" mode="widthFix" @click="onSelectPetType('cat')"></image>
<template v-if="petType === 'cat'">
<image class="active" src="@/static/images/ydd/cat-active.png" mode="widthFix"></image>
<view class="type" v-for="item in petTypeOptions" :key="`petType-${item.id}`">
<image :src="item.imageNo" mode="widthFix" @click="onSelectPetType(item.id)"></image>
<template v-if="petType === item.id">
<image class="active" :src="item.image" mode="widthFix"></image>
<view class="active-icon">
<up-icon name="checkmark-circle" color="#FFBF60" size="32rpx"></up-icon>
</view>
</template>
</view>
<view class="type">
<image src="@/static/images/ydd/dog.png" mode="widthFix" @click="onSelectPetType('dog')"></image>
<template v-if="petType === 'dog'">
<image class="active" src="@/static/images/ydd/dog-active.png" mode="widthFix"></image>
<view class="active-icon">
<up-icon name="checkmark-circle" color="#FFBF60" size="32rpx"></up-icon>
</view>
</template>
</view>
<view class="type">
<image src="@/static/images/ydd/special-pet.png" mode="widthFix" @click="onSelectPetType('special-pet')"></image>
<template v-if="petType === 'special-pet'">
<image class="active" src="@/static/images/ydd/special-pet-active.png" mode="widthFix"></image>
<view class="active-icon">
<up-icon name="checkmark-circle" color="#FFBF60" size="32rpx"></up-icon>
</view>
</template>
</view>
</view>
</view>
@ -99,11 +76,17 @@
<script setup>
import { ref, reactive } from "vue";
import { onShow } from '@dcloudio/uni-app'
import { ossUpload } from '@/utils/oss-upload/oss/index.js'
import { getLicenseList, getPetTypeList } from '@/api/examination'
import { insertUser } from '@/api/userTeacher'
import { store } from '@/store'
import dForm from "@/components/dForm/index.vue"
import stepProgress from '../components/stepProgress.vue';
const configList = store.state.system.configList
const state = reactive({
list: [{
type: "input",
@ -134,13 +117,13 @@
{
type: "input",
label: "年龄",
key: "gender",
key: "age",
placeholder: "请输入您的年龄",
},
{
type: "input",
label: "养宠经验",
key: "shij",
key: "experience",
placeholder: "请输入您的养宠年限",
unit: "年"
},
@ -170,28 +153,14 @@
selected: [],
fileList: []
})
const LICENSE_OPTIONS = [
{
label: '兽医职称专业执照',
value: 0,
},
{
label: '宠物美容洗护专业执照',
value: 1,
},
{
label: '宠物康复护理专业执照',
value: 2,
},
{
label: '宠物膳食管理专业执照',
value: 3,
},
{
label: '其他专业执照',
value: 4,
},
]
const licenseOptions = ref([])
const fetchLicenseOptions = async () => {
try {
licenseOptions.value = await getLicenseList()
} catch (err) {
}
}
const afterRead = (event) => {
event.file.forEach(n => {
ossUpload(n.url)
@ -207,25 +176,61 @@
};
const petType = ref()
const petTypeOptions = ref([])
const onSelectPetType = (type) => {
petType.value = type
}
const fetchPetTypeOptions = async () => {
try {
petTypeOptions.value = await getPetTypeList()
} catch (err) {
const toNext = () => {
// todo: save data
const data = {
...form.value,
...licenseData,
petType: petType.value,
}
}
console.log('--data', data)
const toNext = async () => {
try {
const {
name,
idCard,
sex,
age,
experience,
license,
} = form.value
const data = {
name,
idCard,
sex,
age,
experience,
petType: petType.value,
}
uni.navigateTo({
url: "/otherPages/authentication/examination/start"
})
if (license) {
const { selected, fileList } = licenseData
data.license = selected.join(';')
data.images = fileList.join(';')
}
await insertUser(data)
uni.setStorageSync('petTypeData', petTypeOptions.value.find(item => item.id === petType.value))
uni.navigateTo({
url: "/otherPages/authentication/examination/start"
})
} catch (err) {
}
}
onShow(() => {
fetchPetTypeOptions()
fetchLicenseOptions()
})
</script>
<style lang="scss" scoped>


+ 6
- 3
store/index.js View File

@ -1,12 +1,15 @@
import { createStore } from 'vuex';
import system from './modules/system';
import user from './modules/user';
import getters from './getters'
export const store = createStore({
modules: {
user
system,
user,
},
//类似计算属性
getters
});
});
export default store

+ 31
- 0
store/modules/system.js View File

@ -0,0 +1,31 @@
import { getConfigList } from '@/api/system'
const system = {
state: {
configList: {},
},
mutations: {
setConfigList(state, list) {
const obj = {}
list.forEach(n => {
obj[n.paramCode] = n;
})
state.configList = obj
}
},
actions: {
async fetchConfigList({commit, state}) {
try {
const data = await getConfigList()
commit('setConfigList', data)
} catch (err) {
}
}
}
}
export default system

+ 1
- 0
style/index.scss View File

@ -64,6 +64,7 @@ $mainColor:#FFBF60;
height: 94rpx;
border-radius: 94rpx;
background-color: #FFBF60;
border: none;
}
}


+ 0
- 4
utils/pageList.js View File

@ -46,17 +46,13 @@ export const usePageList = (apiFun, defaultQueryParams) => {
}
onShow(() => {
// todo fetch
console.log('--onShow')
return
getData()
})
onReachBottom(() => {
// todo fetch
console.log('--onReachBottom')
return
getMore()
})


Loading…
Cancel
Save