Browse Source

feat: 伴宠师认证流程(暂存);

pull/1/head
Fox-33 3 weeks ago
parent
commit
9739f49cab
15 changed files with 423 additions and 88 deletions
  1. +32
    -11
      components/dForm/index.vue
  2. +132
    -50
      otherPages/authentication/examination/base.vue
  3. +35
    -3
      otherPages/authentication/examination/start.vue
  4. +157
    -17
      otherPages/authentication/list/index.vue
  5. +0
    -0
      otherPages/authentication/static/list/cat-active.png
  6. +0
    -0
      otherPages/authentication/static/list/cat.png
  7. +0
    -0
      otherPages/authentication/static/list/dog-active.png
  8. +0
    -0
      otherPages/authentication/static/list/dog.png
  9. BIN
      otherPages/authentication/static/list/icon-upload.png
  10. +0
    -0
      otherPages/authentication/static/list/special-pet-active.png
  11. +0
    -0
      otherPages/authentication/static/list/special-pet.png
  12. +11
    -6
      pages.json
  13. +1
    -1
      project.config.json
  14. BIN
      static/images/ydd/img3.png
  15. +55
    -0
      utils/pageList.js

+ 32
- 11
components/dForm/index.vue View File

@ -10,34 +10,36 @@
class="ml10">{{item.unit?item.unit:""}}</text>
</div>
</template>
<template v-if="item.type==='select'">
<up-input inputAlign="right" v-model="formData[item.key]" disabled disabledColor="#ffffff"
<template v-else-if="item.type==='select'">
<up-input inputAlign="right" :value="getDesc(formData[item.key], item.options)" disabled disabledColor="#ffffff"
:placeholder="item.placeholder" border="none"></up-input>
<template #right>
<up-icon name="arrow-right"></up-icon>
</template>
</template>
<template v-if="item.type==='radio'">
<template v-else-if="item.type==='radio'">
<up-radio-group v-model="formData[item.key]" placement="column">
<div class="flex-rowr">
<up-radio class="mr16" activeColor="#FFBF60" :customStyle="{marginBottom: '8px'}"
v-for="key in item.options" :key="key.name" :label="key.name" :name="key.name">
v-for="option in item.options" :key="option.value" :label="option.name" :name="option.value">
</up-radio>
</div>
</up-radio-group>
</template>
<template v-if="item.type==='textarea'">
<template v-else-if="item.type==='textarea'">
<up-textarea v-model="formData[item.key]" :placeholder="item.placeholder" count autoHeight
:maxlength="item.maxlength"></up-textarea>
</template>
<template v-if="item.type==='upload'">
<template v-else-if="item.type==='upload'">
<up-upload :fileList="item.fileList" @afterRead="afterRead" @delete="deletePic" name="1"
:multiple="item.multiple" :maxCount="item.maxCount" :accept='item.accept'
:previewFullImage="item.previewFullImage"></up-upload>
</template>
</up-form-item>
<slot :name="item.key"></slot>
</div>
<up-button @click="handleSubmit" class="mt20" type="warning" v-if="isFooter">提交</up-button>
</up-form>
@ -50,7 +52,8 @@
import {
reactive,
ref,
computed
computed,
watch,
} from "vue"
const {
list,
@ -66,12 +69,18 @@
},
isFooter: true
})
const emit = defineEmits(['submit'])
const emit = defineEmits(['submit', 'input'])
const formData = reactive({
name: ""
})
watch(formData, (val) => {
emit('input', val)
})
const sheet = reactive({
show: false,
key: null,
actions: [],
title: "",
description: ""
@ -89,6 +98,7 @@
//
const open = (item) => {
sheet.show = true
sheet.key = item.key
sheet.actions = item.options
sheet.title = item.placeholder
sheet.description = item.description || ""
@ -100,8 +110,13 @@
//
const handleSelect = (val) => {
console.log(val)
formData[sheet.key] = val?.value
}
const getDesc = (val, options) => {
return options.find(item => item.value === val)?.name
}
//
const afterRead = () => {}
//
@ -115,11 +130,17 @@
}
})
}
const validate = () => {
return dFormRef.value.validate()
}
defineExpose({ validate })
</script>
<style>
.form-item {
height: 90rpx;
min-height: 90rpx;
padding-top: 10rpx;
width: 100%;
border-bottom: 1rpx solid #f5f5f5;


+ 132
- 50
otherPages/authentication/examination/base.vue View File

@ -1,44 +1,141 @@
<template>
<view class="box">
<view class="">
<view class="color-fff size-28">
答题进度 10/23
</view>
<view class="step mt20 mb32">
<view class="in">
<view class="page">
<view class="bg"></view>
</view>
</view>
</view>
<view class="content">
<view class="content bg-fff">
<view class="label size-22">
选择题
</view>
<view class="">
<view class="size-28 mt32 mb20">
1猫咪每天在地上走路时不时还会打滚 身上是很不干净的最好每个星期洗次澡
<view class="box">
<view class="">
<view class="flex-rowc color-fff size-28">
{{ `答题进度 ${answerCount}/${total}` }}
</view>
<up-line-progress :percentage="progress" activeColor="FFBF60" inactiveColor="#D9D9D9" height="16rpx" :showText="false"></up-line-progress>
</view>
<view class="size-28 color-777 p20 daan">
A
<view class="content bg-fff">
<view class="label size-22">
选择题
</view>
<view class="">
<view v-for="(item, qIdx) in list" :key="`question-${qIdx}`">
<view class="size-28 mt32 mb20">
{{ item.question }}
</view>
<view class="size-28 color-777 p20 daan"
v-for="(option, oIdx) in item.options"
:key="`${qIdx}-option-${oIdx}`"
>
{{ `${String.fromCharCode(65 + oIdx)}${option.label}` }}
</view>
</view>
</view>
</view>
<view class="size-28 color-777 p20 daan active mt24">
B
</view>
<view class="footer-btn">
<view class="btn">
提交
</view>
</view>
</view>
</view>
<view class="footer-btn">
<view class="btn">
提交
</view>
</view>
</template>
<script>
<script setup>
import { ref, computed } from 'vue'
import { onShow, onReachBottom } from '@dcloudio/uni-app'
import { usePageList } from "@/utils/pageList";
const answerCount = ref(0)
const total = ref(0)
// todo
const { list, getData, getMore } = usePageList()
onShow(() => {
// todo fetch
answerCount.value = 30
total.value = 100
list.value = [
{
question: '猫咪每天在地上走路,时不时还会打滚,身上是很不干净的,最好每个星期洗次澡',
options: [
{
label: '对',
value: 0,
},
{
label: '错',
value: 1,
},
]
},
{
question: '当狗狗出现乱拉乱尿或者捣乱拆家等反映时,您会如何处理?',
options: [
{
label: '暴力制止,根据情况是否严重来判断下手轻重,让狗狗知道这样做会受到惩罚',
value: 0,
},
{
label: '奖罚分明,制止后耐心引导,直到狗狗做出正确的行为,并立马给出奖励',
value: 1,
},
{
label: '狗狗也不是故意的,也不会造成什么很大的影响,默默打扫好就算了吧',
value: 2,
},
]
},
{
question: '3、狗狗和猫咪一样是肉食性动物,最好可以纯肉喂养,对狗狗的身心健康有很大好处',
options: [
{
label: '对',
value: 0,
},
{
label: '错',
value: 1,
},
]
},
]
return
getData()
})
onReachBottom(() => {
// todo: fetch more
return
getMore()
})
const progress = computed(() => {
return Math.floor(answerCount.value / total.value)
})
</script>
<style lang="scss" scoped>
.page {
width: 100vw;
& > .bg {
width: 100%;
height: 298rpx;
background: linear-gradient(178deg,#ffbf60 2%, #ffbf60 5%, #f2f2f2 63%);
}
& > .content {
position: absolute;
top: 0;
width: 100%;
}
}
.active {
color: #FFBF60;
background-color: rgb(255, 241, 240);
@ -54,32 +151,17 @@
}
.box {
background-image: linear-gradient(to bottom, #ffbf60, #f2f2f2);
padding: 16rpx;
.step {
width: 720rpx;
height: 32rpx;
border-radius: 32rpx;
background-color: #D9D9D9;
.in {
width: 50%;
height: 32rpx;
background-color: #ffbf60;
border-radius: 32rpx;
}
}
}
.content {
border-radius: 20rpx;
padding: 15rpx 20rpx;
.content {
border-radius: 20rpx;
padding: 15rpx 20rpx;
.label {
padding: 5rpx 15rpx;
color: #fff;
background-color: #FFBF60;
.label {
padding: 5rpx 15rpx;
color: #fff;
background-color: #FFBF60;
}
}
}
</style>

+ 35
- 3
otherPages/authentication/examination/start.vue View File

@ -6,7 +6,9 @@
<view class="com-title size-32 fw700 flex-rowl">
您选择的宠物类型
</view>
<image class="mt32" src="../../../static/images/ydd/img1.png" mode="widthFix"></image>
<image class="mt32" v-if="petType === 'cat'" src="../static/list/cat-active.png" mode="widthFix"></image>
<image class="mt32" v-else-if="petType === 'dog'" src="../static/list/dog-active.png" mode="widthFix"></image>
<image class="mt32" v-else-if="petType === 'special-pet'" src="../static/list/special-pet-active.png" mode="widthFix"></image>
</view>
<view class="text po-r bg-fff">
@ -30,8 +32,9 @@
</view>
<view class="footer-btn flex-colc">
<view class="size-22 color-777">
剩余考试次数:3
<view class="size-22 color-777 tips-rest">
<!-- todo -->
剩余考试机会<text class="highlight">{{ restTimes }}</text>
</view>
<view class="btn" @click="toNext">
开始考试
@ -41,6 +44,18 @@
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { onShow } from '@dcloudio/uni-app'
const petType = ref()
const restTimes = ref()
onShow(() => {
// todo: fetch
petType.value = 'cat'
restTimes.value = 3
})
const content =
`即将开始基础养宠经验考核,该环节是对喂养员科学养宠经验及理念的基础考核,考核题目均为选择判断题,题目较为简单;大多为科学养宠所涉及的常识题,以客观事实判定标准答案;小部分题目为平台对喂养员的要求,以平台自行判定标准答案!`
@ -97,4 +112,21 @@
width: 198rpx;
}
}
.tips {
&-rest {
color: #707070;
font-size: 22rpx;
margin: 9rpx 0 13rpx 0;
.highlight {
color: #FF8DC6;
}
}
}
.footer-btn {
height: 163rpx;
box-sizing: border-box;
padding-bottom: 18rpx;
}
</style>

+ 157
- 17
otherPages/authentication/list/index.vue View File

@ -1,6 +1,7 @@
<template>
<view class="containers po-r">
<image src="" mode="" class="mainBg"></image>
<view class="w-100 po-a content">
<view class="flex-rowl">
<image src="@/static/images/ydd/logo.png" mode="" class="logo"></image>
@ -44,7 +45,40 @@
<view class="title fw700 size-30 flex-rowl">
基本信息
</view>
<dFrom :list="state.list" :isFooter="false" />
<dForm ref="formRef" :list="state.list" labelWidth="220rpx" :isFooter="false" @input="onFormInput"></dForm>
</view>
<view class="license__view" v-if="form.license">
<view class="license">
<up-checkbox-group
v-model="licenseData.selected"
shape="circle"
activeColor="#FFBF60"
labelColor="#000000"
labelSize="26rpx"
>
<view class="license-options">
<up-checkbox
v-for="item in LICENSE_OPTIONS"
:key="`license-${item.value}`"
:label="item.label"
:name="item.value"
>
</up-checkbox>
</view>
</up-checkbox-group>
<view class="tips">
温馨提示上传专业执照将大大增加通过概率且会快速晋升为高级伴宠师获取更高报酬
</view>
<up-upload
:fileList="licenseData.fileList"
@afterRead="afterRead"
@delete="deletePic"
multiple
>
<image src="../static/list/icon-upload.png" style="width: 144rpx;height: 144rpx;"></image>
</up-upload>
</view>
</view>
<view class="bg-fff mt22 form bt120">
@ -52,12 +86,24 @@
个人宠物类型
</view>
<view class="flex-between wrap mt32">
<image class="type" src="@/static/images/ydd/img1.png" mode="widthFix"></image>
<image class="type" src="@/static/images/ydd/img2.png" mode="widthFix"></image>
<image class="type" src="@/static/images/ydd/img3.png" mode="widthFix"></image>
<image class="type" src="@/static/images/ydd/img4.png" mode="widthFix"></image>
<image class="type" src="@/static/images/ydd/img5.png" mode="widthFix"></image>
<image class="type" src="@/static/images/ydd/img6.png" mode="widthFix"></image>
<view class="type">
<image src="../static/list/cat.png" mode="widthFix" @click="onSelectPet('cat')"></image>
<image class="active" v-if="petType === 'cat'" src="../static/list/cat-active.png" mode="widthFix"></image>
</view>
<view class="type">
<image src="../static/list/dog.png" mode="widthFix" @click="onSelectPet('dog')"></image>
<image class="active" v-if="petType === 'dog'" src="../static/list/dog-active.png" mode="widthFix"></image>
</view>
<view class="type">
<image src="../static/list/special-pet.png" mode="widthFix" @click="onSelectPet('special-pet')"></image>
<image class="active" v-if="petType === 'special-pet'" src="../static/list/special-pet-active.png" mode="widthFix"></image>
</view>
</view>
</view>
@ -72,10 +118,8 @@
</template>
<script setup>
import {
reactive
} from "vue";
import dFrom from "@/components/dForm/index.vue"
import { ref, reactive } from "vue";
import dForm from "@/components/dForm/index.vue"
const state = reactive({
list: [{
@ -95,10 +139,12 @@
label: "性别",
key: "sex",
options: [{
name: "男"
name: "男",
value: 0,
},
{
name: "女"
name: "女",
value: 1,
}
]
},
@ -116,20 +162,76 @@
unit: "年"
},
{
type: "select",
type: "radio",
label: "是否有专业执照",
key: "shij",
key: "license",
placeholder: "请选择",
options: [{
name: "是"
name: "是",
value: 1,
}, {
name: "没有"
name: "没有",
value: 0,
}]
},
]
})
const formRef = ref()
const form = ref({})
const onFormInput = (e) => {
form.value = e
}
const licenseData = reactive({
selected: [],
fileList: []
})
const LICENSE_OPTIONS = [
{
label: '兽医职称专业执照',
value: 0,
},
{
label: '宠物美容洗护专业执照',
value: 1,
},
{
label: '宠物康复护理专业执照',
value: 2,
},
{
label: '宠物膳食管理专业执照',
value: 3,
},
{
label: '其他专业执照',
value: 4,
},
]
const afterRead = () => {
// todo
}
const deletePic = (event) => {
licenseData.fileList.splice(event.index, 1);
};
const petType = ref()
const onSelectPet = (type) => {
petType.value = type
}
const toNext = () => {
// todo: save data
const data = {
...form.value,
...licenseData,
petType: petType.value,
}
console.log('--data', data)
uni.navigateTo({
url: "/otherPages/authentication/examination/start"
})
@ -170,6 +272,17 @@
.type {
width: 190rpx;
margin-bottom: 74rpx;
position: relative;
image {
width: 100%;
}
.active {
position: absolute;
top: 0;
left: 0;
}
}
.form {
@ -244,4 +357,31 @@
}
}
}
.license__view {
width: 716rpx;
padding-bottom: 40rpx;
box-sizing: border-box;
background-color: #FFFFFF;
.license {
width: 100%;
padding: 13rpx 16rpx;
box-sizing: border-box;
background-color: #FFFCF1;
&-options {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
}
.tips {
margin: 22rpx 0 24rpx 0;
color: #FFBF60;
font-size: 22rpx;
width: 100%;
word-break: break-all;
}
}
</style>

static/images/ydd/img1.png → otherPages/authentication/static/list/cat-active.png View File


static/images/ydd/img5.png → otherPages/authentication/static/list/cat.png View File


static/images/ydd/img7.png → otherPages/authentication/static/list/dog-active.png View File


static/images/ydd/img2.png → otherPages/authentication/static/list/dog.png View File


BIN
otherPages/authentication/static/list/icon-upload.png View File

Before After
Width: 144  |  Height: 144  |  Size: 6.7 KiB

static/images/ydd/img6.png → otherPages/authentication/static/list/special-pet-active.png View File


static/images/ydd/img4.png → otherPages/authentication/static/list/special-pet.png View File


+ 11
- 6
pages.json View File

@ -65,7 +65,17 @@
"style": {
"navigationBarTitleText": "基础考核"
}
}, {
},
{
"path": "training/index",
"style": {
"navigationBarTitleText": "培训考核"
}
},
{
"path": "examination/end",
"style": {
"navigationBarTitleText": "伴宠师认证"
@ -100,11 +110,6 @@
"style": {
"navigationBarTitleText": "伴宠师认证"
}
}, {
"path": "training/index",
"style": {
"navigationBarTitleText": "培训考核"
}
}, {
"path": "training/detail",
"style": {


+ 1
- 1
project.config.json View File

@ -1,5 +1,5 @@
{
"appid": "wx90d494bba15f99c3",
"appid": "wx01f0f43759922fda",
"compileType": "miniprogram",
"libVersion": "3.7.8",
"packOptions": {


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

Before After
Width: 189  |  Height: 221  |  Size: 6.2 KiB

+ 55
- 0
utils/pageList.js View File

@ -0,0 +1,55 @@
import { ref, reactive } from 'vue'
export const usePageList = (apiFun, defaultQueryParams) => {
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
...defaultQueryParams
})
const list = ref([])
const total = ref(0)
const fetchData = async () => {
try {
const res = await apiFun(queryParams)
if (res.code === 200) {
return res.data
}
return { list: [], total: 0 }
} catch (err) {
return { list: [], total: 0 }
}
}
const getData = async () => {
queryParams.pageNo = 1
const { list: _list, total: _total } = await fetchData()
list.value = _list
total.value = _total
}
const getMore = async () => {
if (list.value.length >= total.value) {
return
}
queryParams.pageNo++
const { list: _list } = await fetchData()
list.value = list.value.concat(_list)
}
return {
queryParams,
list,
total,
getData,
getMore,
}
}

Loading…
Cancel
Save