Browse Source

Merge pull request 'feat: 伴宠师认证流程(暂存);' (#2) from fox into master

Reviewed-on: http://175.178.51.79:3000/Augcl/pet-front/pulls/2
pull/6/head
Fox 3 weeks ago
parent
commit
e4f634d3d7
14 changed files with 454 additions and 187 deletions
  1. +104
    -11
      otherPages/authentication/components/questionCard.vue
  2. +4
    -0
      otherPages/authentication/components/stepProgress.vue
  3. +4
    -7
      otherPages/authentication/examination/base.vue
  4. +116
    -41
      otherPages/authentication/examination/baseCompleted.vue
  5. +102
    -46
      otherPages/authentication/examination/errorDetail.vue
  6. +104
    -71
      otherPages/authentication/examination/train.vue
  7. +17
    -9
      otherPages/authentication/examination/trainCompleted/fail.vue
  8. +1
    -1
      otherPages/authentication/examination/trainCompleted/index.vue
  9. +2
    -0
      otherPages/authentication/examination/trainCompleted/pass.vue
  10. +0
    -1
      otherPages/authentication/examination/trainCompleted/waiting.vue
  11. BIN
      otherPages/authentication/static/examination/bg-train-manual.png
  12. BIN
      static/images/ydd/approved.png
  13. BIN
      static/images/ydd/examine.png
  14. BIN
      static/images/ydd/unqualified.png

+ 104
- 11
otherPages/authentication/components/questionCard.vue View File

@ -3,18 +3,60 @@
<view class="size-28 mb20 question">
{{ `${props.index + 1}${props.data.question}` }}
</view>
<view class="size-28 option"
v-for="(option, oIdx) in props.data.options"
:key="`${props.index}-option-${oIdx}`"
:class="[props.modelValue === option.value ? 'is-selected' : '']"
@click="onClick(option.value)"
>
{{ `${String.fromCharCode(65 + oIdx)}${option.label}` }}
</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)"
>
{{ `${String.fromCharCode(65 + oIdx)}${option.label}` }}
</view>
</template>
<template v-else>
<view class="textarea">
<textarea
v-model="value"
placeholder="请输入您的答案,不得低于700个字"
:rows="10"
></textarea>
</view>
</template>
</template>
<template v-else>
<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="[
props.data.answer === option.value ? 'is-correct' : '',
props.data.value === option.value ? 'is-error' : '',
]"
@click="onClick(option.value)"
>
{{ `${String.fromCharCode(65 + oIdx)}${option.label}` }}
<view class="icon icon-correct">
<up-icon name="checkmark" color="#05C160" size="35rpx"></up-icon>
</view>
<view class="icon icon-error">
<up-icon name="close" color="#FF2A2A" size="35rpx"></up-icon>
</view>
</view>
</template>
<template v-else>
<view class="textarea">
<view>{{ props.data.value }}</view>
<view class="highlight">{{ props.data.reason }}</view>
</view>
</template>
</template>
</view>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({
index: {
@ -33,14 +75,23 @@ const props = defineProps({
},
mode: {
type: String,
default: 'select', // select | display
default: 'edit', // edit | display
}
})
const emit = defineEmits(['update:modelValue'])
const value = computed({
set(val) {
emit('update:modelValue', val)
},
get() {
return props.modelValue
}
})
const onClick = (val) => {
emit('update:modelValue', val)
value.value = val
}
</script>
@ -57,15 +108,57 @@ const onClick = (val) => {
padding: 23rpx;
border-radius: 28rpx;
position: relative;
& + & {
margin-top: 20rpx;
}
.icon {
position: absolute;
right: 45rpx;
bottom: 23rpx;
display: none;
}
}
.question__view.select {
.textarea {
background-color: #F3F3F3;
padding: 23rpx;
border-radius: 16rpx;
.highlight {
color: #FF2A2A;
font-size: 28rpx;
}
}
.question__view.edit {
.option.is-selected {
background-color: rgba($color: #FFBF60, $alpha: 0.22);
color: #FFBF60;
}
}
.question__view.display {
.option {
&.is-correct {
background-color: rgba($color: #05C160, $alpha: 0.08);
color: #05C160;
.icon-correct {
display: block;
}
}
&.is-error {
background-color: rgba($color: #FFEBCE, $alpha: 0.36);
color: #FF2A2A;
.icon-error {
display: block;
}
}
}
}
</style>

+ 4
- 0
otherPages/authentication/components/stepProgress.vue View File

@ -83,12 +83,16 @@ const steps = reactive(['基本考核', '培训考核', '最终准备'])
.desc {
white-space: nowrap;
color: #BDBDBD;
}
.line.is-active,
.step.is-active .num {
background-color: #FFBF60;
}
.step.is-active .desc {
color: #000000;
}
}
}
</style>

+ 4
- 7
otherPages/authentication/examination/base.vue View File

@ -2,7 +2,7 @@
<view class="page">
<view class="header">
<view class="flex-rowc color-fff size-28 title">
<view class="flex-rowl color-fff size-28 title">
{{ `答题进度 ${answered}/${total}` }}
</view>
<up-line-progress class="progress" :percentage="progress" activeColor="#FFBF60" inactiveColor="#D9D9D9" height="16rpx" :showText="false"></up-line-progress>
@ -42,11 +42,8 @@ import { usePageList } from "@/utils/pageList";
import questionCard from '../components/questionCard.vue';
const total = ref(0)
// todo
const { list, getData } = usePageList()
const { list, total, getData } = usePageList()
onShow(() => {
// todo: delete test data
@ -87,7 +84,7 @@ onShow(() => {
value: null,
},
{
question: '3、狗狗和猫咪一样是肉食性动物,最好可以纯肉喂养,对狗狗的身心健康有很大好处',
question: '狗狗和猫咪一样是肉食性动物,最好可以纯肉喂养,对狗狗的身心健康有很大好处',
options: [
{
label: '对',
@ -133,7 +130,7 @@ onShow(() => {
value: null,
},
{
question: '3、狗狗和猫咪一样是肉食性动物,最好可以纯肉喂养,对狗狗的身心健康有很大好处',
question: '狗狗和猫咪一样是肉食性动物,最好可以纯肉喂养,对狗狗的身心健康有很大好处',
options: [
{
label: '对',


+ 116
- 41
otherPages/authentication/examination/baseCompleted.vue View File

@ -7,37 +7,51 @@
<view class="info">
<view class="top">
<view class="top-title">
<view class="flex-rowl top-title">
<up-icon class="icon" name="checkmark-circle-fill" color="#FFBF60" size="34rpx"></up-icon>
<text>基本考核答题已完成</text>
</view>
<view class="top-desc">
<view class="flex-rowl top-desc">
<up-icon class="icon" name="error-circle" color="#707070" size="27rpx"></up-icon>
<text>进行培训考核的答题前请认真观看下面的视频和资料</text>
</view>
</view>
<view class="info-item">
<view class="info-item-title">
<view class="info-box">
<view class="info-box-title">
平台&服务介绍
</view>
<view class="flex-between">
<view class="veo_">
<video src=""></video>
猫妈狗爸平台介绍
</view>
<view class="">
<video src=""></video>
喂养学习视频
<view class="info-box-content">
<view class="flex-colc info-item"
v-for="(item, index) in introList"
:key="`intro-${index}`"
>
<view class="video">
<video
:src="item.url"
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>
<text class="desc">{{ item.title }}</text>
</view>
</view>
</view>
<view class="info-item">
<view class="info-item-title">
<view class="info-box">
<view class="info-box-title">
服务培训
</view>
<view class="info-box-content">
<view class="flex-colc info-item">
<image src="../static/examination/bg-train-manual.png" mode="widthFix"></image>
</view>
</view>
</view>
<view class="footer-btn">
<view class="btn" @click="toNext">
<view class="flex-rowc tools">
<view class="flex-rowc btn" @click="toNext">
进入培训考核
</view>
</view>
@ -47,6 +61,8 @@
</template>
<script setup>
import { ref } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import stepProgress from '../components/stepProgress.vue';
const toNext = () => {
@ -54,11 +70,28 @@
url: "/otherPages/authentication/examination/train"
})
}
const introList = ref([])
onShow(() => {
// todo: delete test data
introList.value = [
{
url: '',
title: '猫妈狗爸平台介绍',
},
{
url: '',
title: '喂养学习视频',
},
]
})
</script>
<style scoped lang="scss">
.page {
position: relative;
width: 100vw;
.mainBg {
width: 100vw;
@ -70,10 +103,13 @@
top: 0;
left: 0;
padding: 16rpx;
width: 100%;
box-sizing: border-box;
}
}
.info{
margin-top: 22rpx;
box-sizing: border-box;
width: 100%;
height: auto;
@ -84,56 +120,95 @@
.top{
width: 100%;
background-color: #FFFCF1;
box-sizing: border-box;
padding: 19rpx 26rpx;
border-radius: 16rpx;
color: #707070;
&-title {
font-size: 28rpx;
.icon {
margin-right: 5rpx;
}
}
&-desc {
margin-top: 22rpx;
font-size: 22rpx;
.icon {
margin-right: 12rpx;
}
}
}
&-item {
&-box {
margin-top: 30rpx;
&-title {
display: inline-block;
font-size: 30rpx;
&::before {
content: "";
display: block;
display: inline-block;
width: 9rpx;
height: 33rpx;
background-color: #FFBF60;
margin-right: 7rpx;
border-radius: 5rpx;
}
}
&-content {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-column-gap: 27rpx;
}
}
}
.footer-btn {
width: 100vw;
height: 144rpx;
background-color: #fff;
display: flex;
justify-content: center;
position: fixed;
bottom: 0;
left: 0;
align-items: center;
.btn {
font-size: 30rpx;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
width: 574rpx;
height: 94rpx;
border-radius: 94rpx;
background-color: #FFBF60;
&-item {
width: 100%;
margin-top: 30rpx;
.video {
width: 100%;
height: 197rpx;
border-radius: 16rpx;
overflow: hidden;
}
video {
width: 100%;
height: 100%;
}
image {
width: 100%;
}
.desc {
color: #707070;
font-size: 22rpx;
line-height: 40rpx;
}
}
}
.tools {
margin-top: 79rpx;
}
.btn {
font-size: 30rpx;
line-height: 40rpx;
color: #fff;
width: 574rpx;
padding: 27rpx 0;
box-sizing: border-box;
border-radius: 41rpx;
background-color: #FFBF60;
}
</style>

+ 102
- 46
otherPages/authentication/examination/errorDetail.vue View File

@ -1,41 +1,25 @@
<template>
<!-- <view>伴宠师认证</view> -->
<view>
<view class="page">
<view class="box">
<view class="content bg-fff">
<view class="">
<view class="group" v-for="(group, gIdx) in list" :key="`group-${gIdx}`">
<view class="label size-22 level" :style="{borderRadius:'10rpx'}">
选择题
{{ group.title }}
</view>
<view class="">
<view class="size-28 mt32 mb20">
1猫咪每天在地上走路时不时还会打滚 身上是很不干净的最好每个星期洗次澡
</view>
<view class="size-28 color-777 p20 daan mb24">
A
</view>
<view class="size-28 color-777 p20 daan active mb24">
B
</view>
</view>
</view>
<view class="mt60">
<view class="label size-22 level" :style="{borderRadius:'10rpx'}">
主观题
</view>
<view class="">
<view class="size-28 mt32 mb20">
1喂养服务流程:如果您收到一笔喂养猫咪的订单备注猫咪性格怕生请问您会如何进行服务?请详细描述您的全部服务流程(若服务宠物不包含猫咪可回答)
</view>
<view class="size-28 color-777 p20 daan">
<textarea value="" placeholder="" />
<text :style="{color:'#FF2A2A'}">字数低于700字不予合格</text>
</view>
<questionCard
v-for="(item, qIdx) in group.children"
:key="`${gIdx}-question-${qIdx}`"
:index="qIdx"
:data="item"
mode="display"
></questionCard>
</view>
</view>
</view>
</view>
<view class="footer-btn buttom ">
<view class="footer-btn flex-colc">
<view class="size-22 color-777 tips-rest">
<!-- todo -->
剩余考试机会<text class="highlight">{{ restTimes }}</text>
@ -51,12 +35,94 @@
<script setup>
import { ref } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { usePageList } from "@/utils/pageList";
import questionCard from '../components/questionCard.vue';
const { list, getData } = usePageList()
const restTimes = ref()
onShow(() => {
// 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: '猫咪性格怕生,我耐心的与猫咪接触,和它玩耍 先建立良好的关系,再进行喂养。',
},
]
}
]
})
const onClick = () => {
@ -69,18 +135,10 @@
</script>
<style lang="scss" scoped>
.active {
color: #FFBF60;
background-color: rgb(255, 241, 240);
}
.daan {
background-color: #F3F3F3;
border-radius: 50rpx;
}
$bar-height: 163rpx;
.p20 {
padding: 20px;
.page {
padding-bottom: $bar-height;
}
.box {
@ -115,19 +173,17 @@
}
}
.level {
display: flex;
.group + .group {
margin-top: 68rpx;
}
.subjectivity {
height: auto;
.level {
display: flex;
}
.buttom {
display: grid;
place-items: center;
.footer-btn {
height: $bar-height;
}
.tips {
&-rest {


+ 104
- 71
otherPages/authentication/examination/train.vue View File

@ -1,28 +1,29 @@
<template>
<!-- <view>培训考核</view> -->
<view>
<view class="box">
<view class="">
<view class="color-fff size-28">
答题进度 2/5
</view>
<view class="step mt20 mb32">
<view class="in">
<view class="page">
<view class="header">
<view class="flex-rowl color-fff size-28 title">
{{ `答题进度 ${answered}/${total}` }}
</view>
<up-line-progress class="progress" :percentage="progress" activeColor="#FFBF60" inactiveColor="#D9D9D9" height="16rpx" :showText="false"></up-line-progress>
</view>
</view>
</view>
<view class="content bg-fff">
<view class="label size-22 level" :style="{borderRadius:'10rpx'}">
<view class="box">
<view class="content bg-fff">
<view>
<view class="label size-22">
主观题
</view>
<view class="">
<view class="size-28 mt32 mb20">
1喂养服务流程:如果您收到一笔喂养猫咪的订单备注猫咪性格怕生请问您会如何进行服务?请详细描述您的全部服务流程(若服务宠物不包含猫咪可回答
</view>
<view class="size-28 color-777 p20 daan">
<textarea value="" placeholder="请输入您的答案,不得低于700个字" />
</view>
</view>
</view>
<view class="">
<questionCard
v-for="(item, qIdx) in list"
:key="`question-${qIdx}`"
:index="qIdx"
:data="item"
v-model="item.value"
></questionCard>
</view>
</view>
</view>
@ -35,68 +36,100 @@
</template>
<script setup>
import { ref, computed } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { usePageList } from "@/utils/pageList";
import questionCard from '../components/questionCard.vue';
// todo
const { list, total, getData } = usePageList()
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 answered = computed(() => {
return list.value.filter(item => item.value?.length).length
})
const progress = computed(() => {
return Math.floor(answered.value / total.value * 100)
})
const toNext = () => {
uni.navigateTo({
url: "/otherPages/authentication/examination/trainCompleted/index"
})
}
const toNext = () => {
uni.navigateTo({
url: "/otherPages/authentication/examination/trainCompleted/index"
})
}
</script>
<style scoped lang="scss">
.active {
color: #FFBF60;
background-color: rgb(255, 241, 240);
}
.daan {
background-color: #F3F3F3;
border-radius: 50rpx;
<style lang="scss" scoped>
.page {
padding-bottom: 144rpx;
}
.p20 {
padding: 20px;
.header {
padding: 0 36rpx;
position: sticky;
top: 0;
background-image: linear-gradient(180deg, #FFBF60 0, #ffbf60 2%, #ffbf60 8%, #f2f2f2 90%);
.progress {
margin-top: 19rpx;
}
}
.box {
height: 180rpx;
background-image: linear-gradient(to bottom, #ffbf60, #f2f2f2);
margin-top: 31rpx;
padding: 16rpx;
position: absolute;
.step {
width: 720rpx;
height: 15rpx;
border-radius: 32rpx;
background-color: #D9D9D9;
.in {
width: 50%;
height: 15rpx;
background-color: #ffbf60;
border-radius: 32rpx;
}
}
}
.content {
border-radius: 20rpx;
padding: 15rpx 20rpx;
position: relative;
bottom: 0;
left: 0;
.label {
width: 80rpx;
justify-content: center;
padding: 5rpx 15rpx;
color: #fff;
background-color: #FFBF60;
.content {
border-radius: 20rpx;
padding: 15rpx 20rpx;
.label {
display: inline-block;
padding: 5rpx 15rpx;
color: #fff;
background-color: #FFBF60;
}
}
}
.level{
display: flex;
}
</style>

+ 17
- 9
otherPages/authentication/examination/trainCompleted/fail.vue View File

@ -3,9 +3,11 @@
<view class="img_">
<image src="../../static/examination/unqualified.png" mode="" style="width: 310rpx;height: 311rpx;"></image>
</view>
<view class="buttom" :style="{borderRadius:'41rpx'}" @click="onClick">
查看错题原因
<!-- todo: icon-arrow -->
<view class="flex-rowc tools">
<view class="flex-rowc btn" :style="{borderRadius:'41rpx'}" @click="onClick">
<text>查看错题原因</text>
<up-icon class="icon" name="arrow-right-double" color="#FFFFFF" size="23rpx"></up-icon>
</view>
</view>
</view>
</template>
@ -36,16 +38,22 @@
justify-content: center;
margin: 30rpx 0 0 140rpx;
}
.tools {
margin-top: 327rpx;
}
.buttom{
.btn{
width: 594rpx;
height: 94rpx;
display: grid;
place-items: center;
background-color: #FFBF60;
margin: 250rpx 0 0 40rpx;
font-size: 30rpx;
color: #FFFFFF;
padding: 27rpx 0;
font-size: 30rpx;
line-height: 40rpx;
.icon {
margin-left: 10rpx;
}
}
}


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

@ -27,7 +27,7 @@
onShow(() => {
// todo: fetch
status.value = 'waiting'
status.value = 'pass'
})
</script>


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

@ -40,6 +40,8 @@
justify-content: center;
margin: 30rpx 0 0 10rpx;
font-size: 22rpx !important;
line-height: 40rpx;
color: #707070;
}
.buttom{


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

@ -2,7 +2,6 @@
<view class="content_">
<view class="img_">
<image src="../../static/examination/examine.png" mode="" style="width: 310rpx;height: 311rpx;"></image>
<image src="/static/images/ydd/examine.png" mode="" style="width: 310rpx;height: 311rpx;"></image>
</view>
<view class="text level">
平台会在三个工作日内完成审核请及时查看审核结果


BIN
otherPages/authentication/static/examination/bg-train-manual.png View File

Before After
Width: 304  |  Height: 197  |  Size: 15 KiB

BIN
static/images/ydd/approved.png View File

Before After
Width: 310  |  Height: 323  |  Size: 25 KiB

BIN
static/images/ydd/examine.png View File

Before After
Width: 310  |  Height: 311  |  Size: 25 KiB

BIN
static/images/ydd/unqualified.png View File

Before After
Width: 311  |  Height: 333  |  Size: 25 KiB

Loading…
Cancel
Save