Browse Source

Merge pull request 'feat: 接口对接;' (#8) from fox into master

Reviewed-on: http://175.178.51.79:3000/Augcl/pet-front/pulls/8
pull/9/head
Fox 3 weeks ago
parent
commit
1f6f53c8d3
14 changed files with 670 additions and 240 deletions
  1. +20
    -0
      api/config/config.js
  2. +2
    -12
      api/examination/index.js
  3. +10
    -2
      api/serviceLog/index.js
  4. +92
    -12
      otherPages/authentication/examination/end.vue
  5. +4
    -4
      otherPages/authentication/examination/errorDetail.vue
  6. +18
    -8
      otherPages/authentication/examination/start.vue
  7. +13
    -17
      otherPages/authentication/list/index.vue
  8. +37
    -93
      otherPages/authentication/serve/index.vue
  9. +15
    -12
      otherPages/authentication/serve/popupServeSelect.vue
  10. +19
    -26
      otherPages/authentication/serve/popupTypeSelect.vue
  11. +250
    -17
      otherPages/authentication/serve/record.vue
  12. +153
    -34
      otherPages/authentication/serve/upload.vue
  13. +3
    -1
      store/getters.js
  14. +34
    -2
      store/modules/system.js

+ 20
- 0
api/config/config.js View File

@ -39,4 +39,24 @@ export function trainList() {
}).then(res => {
return res.data
})
}
// 伴宠师工作台-查询宠物类型列表
export const getPetTypeList = () => {
return request({
url: '/applet/examination/petTypeList',
method: "get"
}).then(res => {
return res.data
})
}
// 伴宠师工作台-增值服务列表数据查询
export const getIncreaseServiceList = () => {
return request({
url: '/applet/config/increaseServiceList',
method: "get"
}).then(res => {
return res.data
})
}

+ 2
- 12
api/examination/index.js View File

@ -11,16 +11,6 @@ export const getLicenseList = () => {
})
}
// 伴宠师工作台-查询宠物类型列表
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',
@ -93,7 +83,7 @@ export const answeBaseByQuestionId = (params) => {
method: "get",
params
}).then(res => {
return res.data?.[0] || {}
return res.data?.pop() || {}
})
}
@ -119,6 +109,6 @@ export const answeTrainByQuestionId = (params) => {
method: "get",
params
}).then(res => {
return res.data?.[0] || {}
return res.data?.pop() || {}
})
}

+ 10
- 2
api/serviceLog/index.js View File

@ -1,5 +1,5 @@
// 伴宠师工作台-服务记录
import request from '@/utils/request'u
import request from '@/utils/request'
// 伴宠师工作台-服务记录删除
export const deleteServiceLog = (data) => {
@ -25,7 +25,7 @@ export const insertServiceLog = (data) => {
})
}
// 伴宠师工作台-服务记录添加
// 伴宠师工作台-服务记录列表数据查询
export const serviceLogList = (params) => {
return request({
url: '/applet/serviceLog/serviceLogList',
@ -34,6 +34,14 @@ export const serviceLogList = (params) => {
},
method: "get",
params
}).then(res => {
return res.data?.map?.(item => {
return {
...item,
typeIds: item.serviceType?.split?.(','),
images: item.image?.split?.(',') || []
}
}) || []
})
}


+ 92
- 12
otherPages/authentication/examination/end.vue View File

@ -94,8 +94,7 @@
<image class="img" src="@/static/images/ydd/end13.png" mode="widthFix"></image>
<text class="size-30 color-000 fw700">服务工具准备</text>
</view>
<!-- todo -->
<view class="size-22 flex-rowr">
<view class="size-22 flex-rowr" @click="openToolsInfoModal">
<text>查看工具包</text>
<up-icon name="arrow-down" color="#7F7F7F" size="17rpx" style="margin-left: 5rpx;"></up-icon>
</view>
@ -121,13 +120,23 @@
</view>
</view>
<view class="footer-btn" @click="onClick">
<view class="footer-btn" @click="onSave">
<view class="btn">
提交审核
</view>
</view>
</view>
<up-modal
:show="showToolsInfoModal"
:showConfirmButton="false"
:showCancelButton="false"
:closeOnClickOverlay="true"
@close="closeToolsInfoModal"
>
<up-parse class="size-28" :content="configList.pet_tools.paramValueArea"></up-parse>
</up-modal>
</view>
<button plain class="chat" open-type="contact">
<image src="@/static/images/ydd/chat.png" mode="widthFix"></image>
@ -136,13 +145,24 @@
</template>
<script setup>
import { reactive } from "vue";
import { ref, reactive, computed } from "vue";
import { onShow } from '@dcloudio/uni-app'
import { store } from '@/store'
import { useStore } from 'vuex'
import { udpateUser, getUserOne } from '@/api/userTeacher'
import stepProgress from '../components/stepProgress.vue';
const configList = store.state.system.configList
const store = useStore()
const configList = computed(() => {
return store.getters.configList
})
const userId = computed(() => {
return store.state.user.userInfo.userId
})
const id = ref()
const form = reactive({
name: null,
@ -153,12 +173,31 @@
address: null,
})
onShow(() => {
// todo: delete test data
const initData = async () => {
console.log('--initData')
try {
const data = await getUserOne(userId.value)
const {
id: _id,
name,
idCard,
} = data
id.value = _id
form.name = '李*乐'
form.idCard = '4211********5624'
form.name = name
form.idCard = idCard
} catch (err) {
console.log('--err', err)
}
}
onShow(() => {
initData()
})
const jumpToBond = () => {
@ -167,6 +206,14 @@
})
}
const showToolsInfoModal = ref(false)
const openToolsInfoModal = () => {
showToolsInfoModal.value = true
}
const closeToolsInfoModal = () => {
showToolsInfoModal.value = false
}
const setAddress = (res) => {
//
form.latitude = res.latitude
@ -189,8 +236,41 @@
})
}
const onClick = () => {
// todo
const onSave = async () => {
try {
const {
area,
latitude,
longitude,
address,
} = form
const data = {
id: id.value,
area,
latitude,
longitude,
address,
}
await udpateUser(data)
uni.showToast({
title: '提交成功!',
icon: "none"
})
setTimeout(() => {
uni.reLaunch({
url: "/pages/workbenchManage/index"
})
}, 1000)
} catch (err) {
}
}
</script>


+ 4
- 4
otherPages/authentication/examination/errorDetail.vue View File

@ -71,15 +71,15 @@
data.options = options
// todo:
const { answer, answerId, isTrue } = await answeBaseByQuestionId({ questionId: id })
const { answer, answerId } = await answeBaseByQuestionId({ questionId: id })
if (isTrue) {
if (answer.isTrue) {
continue
}
data.answer = answer.id
data.value = answerId
data.isTrue = isTrue
data.isTrue = answer.isTrue
groups[0].children.push(data)
@ -99,7 +99,7 @@
}
}
list.value = groups
list.value = groups.filter(group => group.children.length > 0)
console.log('--list', list.value)
} catch (err) {


+ 18
- 8
otherPages/authentication/examination/start.vue View File

@ -6,7 +6,7 @@
<view class="com-title size-32 fw700 flex-rowl">
您选择的宠物类型
</view>
<image class="mt32" :src="petTypeData.image" mode="widthFix"></image>
<image class="mt32" :src="petTypeImg" mode="widthFix"></image>
</view>
<view class="text po-r bg-fff">
@ -40,17 +40,27 @@
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { store } from '@/store'
import { ref, computed } from 'vue'
import { useStore } from 'vuex'
import { onLoad } from '@dcloudio/uni-app'
const store = useStore()
const petTypeData = ref({})
const petType = ref()
const restTimes = ref()
const configList = store.state.system.configList
const configList = computed(() => {
return store.getters.configList
})
onShow(() => {
petTypeData.value = uni.getStorageSync('petTypeData')
const petTypeImg = computed(() => {
return store.getters.petTypeOptions.find(item => item.id == petType.value)?.image
})
onLoad((option) => {
store.dispatch('fetchPetTypeOptions')
petType.value = option.petType
// todo: fetch
restTimes.value = 3


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

@ -76,16 +76,20 @@
<script setup>
import { ref, reactive, computed } from "vue";
import { useStore } from 'vuex'
import { onLoad } from '@dcloudio/uni-app'
import { ossUpload } from '@/utils/oss-upload/oss/index.js'
import { getLicenseList, getPetTypeList } from '@/api/examination'
import { getLicenseList } from '@/api/examination'
import { insertUser, udpateUser, getUserOne } 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 store = useStore()
const configList = computed(() => {
return store.getters.configList
})
const userId = computed(() => {
return store.state.user.userInfo.userId
@ -213,7 +217,7 @@
}
fetchPetTypeOptions()
store.dispatch('fetchPetTypeOptions')
fetchLicenseOptions()
} catch (err) {
@ -248,17 +252,12 @@
};
const petType = ref()
const petTypeOptions = ref([])
const petTypeOptions = computed(() => {
return store.getters.petTypeOptions
})
const onSelectPetType = (type) => {
petType.value = type
}
const fetchPetTypeOptions = async () => {
try {
petTypeOptions.value = await getPetTypeList()
} catch (err) {
}
}
const toNext = async () => {
try {
@ -298,20 +297,17 @@
await insertUser(data)
}
uni.setStorageSync('petTypeData', petTypeOptions.value.find(item => item.id === petType.value))
uni.navigateTo({
url: "/otherPages/authentication/examination/start"
url: `/otherPages/authentication/examination/start?petType=${petType.value}`
})
} catch (err) {
}
}
onLoad(() => {
fetchUserInfo()
store.dispatch('fetchPetTypeOptions')
})
</script>


+ 37
- 93
otherPages/authentication/serve/index.vue View File

@ -17,7 +17,7 @@
</button>
</view>
<view class="form">
<DForm ref="baseInfoRef" :list="state.baseInfoList" @input="handleSubmit"></DForm>
<DForm ref="baseInfoRef" :list="state.baseInfoList" @input="fetchUpdate"></DForm>
</view>
</view>
@ -27,7 +27,7 @@
<text class="size-22 color-ffb fw700">(重要)</text>
</view>
<view class="form">
<DForm ref="displayInfoRef" :list="state.displayInfoList" @input="handleSubmit">
<DForm ref="displayInfoRef" :list="state.displayInfoList" @input="fetchUpdate">
<!-- 服务记录 -->
<template v-slot:jilu>
<view class="flex-rowr" @click="jumpToServeRecord">
@ -44,7 +44,7 @@
服务资料
</view>
<view class="form">
<DForm ref="serveInfoRef" :list="state.serveInfoList" @input="handleSubmit">
<DForm ref="serveInfoRef" :list="state.serveInfoList" @input="fetchUpdate">
<!-- 服务宠物类型 -->
<template v-slot:type>
<view class="flex-rowr" @click="openTypeSelectPopup">
@ -67,15 +67,16 @@
伴宠师查看服务酬劳服务时长等规则
</view>
<popupTypeSelect ref="popupTypeSelectRef" v-model="form.type" ></popupTypeSelect>
<popupTypeSelect ref="popupTypeSelectRef" v-model="form.type" @confirm="fetchUpdate" ></popupTypeSelect>
<popupServeSelect ref="popupServeSelectRef" v-model="form.serve" :options="serveOptions" ></popupServeSelect>
<popupServeSelect ref="popupServeSelectRef" v-model="form.serve" @confirm="fetchUpdate" ></popupServeSelect>
</view>
</template>
<script setup>
import { ref, reactive, computed } from "vue";
import { useStore } from 'vuex'
import { onShow } from '@dcloudio/uni-app'
import { ossUpload } from '@/utils/oss-upload/oss/index.js'
@ -83,6 +84,12 @@
import popupTypeSelect from "./popupTypeSelect.vue";
import popupServeSelect from "./popupServeSelect.vue";
const store = useStore()
const fetchUpdate = () => {
// todo
}
const form = reactive({
headImage: null,
type: [],
@ -93,6 +100,8 @@
ossUpload(res.target.avatarUrl)
.then(url => {
form.headImage = url
fetchUpdate()
})
}
@ -163,7 +172,6 @@
{
type: "input",
label: "基础服务",
unit: "年",
key: "base",
placeholder: "宠物喂养上门遛狗",
},
@ -176,14 +184,6 @@
],
})
onShow(() => {
// todo: fetch data and init data
})
const handleSubmit = () => {
// todo
}
const jumpToServeRecord = () => {
uni.navigateTo({
url: "/otherPages/authentication/serve/record"
@ -194,104 +194,48 @@
const openTypeSelectPopup = () => {
popupTypeSelectRef.value.open()
}
const petTypeOptions = computed(() => {
return store.getters.petTypeOptions
})
const typeDesc = computed(() => {
const typeCodes = form.type
if (!typeCodes.length) {
const typeIds = form.type
if (!typeIds.length) {
return '请选择'
}
let descArr = typeCodes.reduce((arr, item) => {
switch(item) {
case 'cat':
arr.push('猫咪')
break
case 'dog':
arr.push('狗狗')
break
case 'special-pet':
arr.push('异宠')
break
default:
break
}
return arr
}, [])
let descArr = typeIds.map(typeId => {
return petTypeOptions.value.find(item => item.id === typeId).title
})
return descArr.join('、')
})
const popupServeSelectRef = ref()
const serveOptions = reactive([
{
title: '陪玩/遛狗',
desc: '外出遛狗或者陪玩,10mins/次',
value: 0,
},
{
title: '一天多次',
desc: '每额外上门一次,收取基础服务费用的80%',
value: 1,
},
{
title: '护理',
desc: '清洁宠物耳道、眼部、鼻部以及梳毛,10mins/次',
value: 2,
},
{
title: '提前熟悉',
desc: '提前上门熟悉,购买此服务支持免费更换伴宠师1次',
value: 3,
},
{
title: '清洁',
desc: '清洗砂盆或其他区域卫生,15mins/次',
value: 4,
},
{
title: '喂药',
desc: '将药品喂入宠物口中',
value: 5,
},
{
title: '上药',
desc: '将药品放入宠物水粮、或者涂抹在皮肤外表',
value: 6,
},
{
title: '打针',
desc: '兽医上门打针,自备药品',
value: 7,
},
{
title: '在线问诊',
desc: '在线问诊在职兽医健康问题',
value: 8,
},
{
title: '线下体察',
desc: '上门外表体查,给予宠物健康咨询',
value: 9,
},
])
const increaseServiceOptions = computed(() => {
return store.getters.increaseServiceOptions
})
const openServeSelectPopup = () => {
popupServeSelectRef.value.open()
}
const serveDesc = computed(() => {
const serveCodes = form.serve
if (!serveCodes.length) {
const serveIds = form.serve
if (!serveIds.length) {
return '请选择'
}
let descArr = serveCodes.reduce((arr, item) => {
const desc = serveOptions.find(option => option.value === item)?.title
let descArr = serveIds.map(serveId => {
return increaseServiceOptions.value.find(option => option.id === serveId)?.title
})
arr.push(desc)
return descArr.join('、')
})
onShow(() => {
store.dispatch('fetchPetTypeOptions')
store.dispatch('fetchIncreaseServiceOptions')
return arr
}, [])
// todo: fetch data and init data
return descArr.join('、')
})
</script>


+ 15
- 12
otherPages/authentication/serve/popupServeSelect.vue View File

@ -6,17 +6,17 @@
>
<view class="content">
<view class="flex-between option"
v-for="(option, index) in props.options"
v-for="(option, index) in increaseServiceOptions"
:key="`option-${index}`"
@click="onSelectServe(option.value)"
@click="onSelectServe(option.id)"
>
<view class="option-info">
<view class="option-title">{{ option.title }}</view>
<view class="option-desc">{{ option.desc }}</view>
<view class="option-desc">{{ option.detail }}</view>
</view>
<up-icon
name="checkmark-circle-fill"
:color="serves.includes(option.value) ? '#FFBF60' : '#BDBDBD'"
:color="serves.includes(option.id) ? '#FFBF60' : '#BDBDBD'"
size="46rpx"
></up-icon>
</view>
@ -25,10 +25,13 @@
</template>
<script setup>
import { ref } from 'vue'
import { ref, computed } from 'vue'
import { useStore } from 'vuex'
import popupSelect from '../components/popupSelect.vue';
const store = useStore()
const props = defineProps({
modelValue: {
type: Array,
@ -36,17 +39,15 @@
return []
}
},
options: {
type: Array,
default() {
return []
}
},
})
const emit = defineEmits(['update:modelValue'])
const emit = defineEmits(['update:modelValue', 'confirm'])
const serves = ref([])
const increaseServiceOptions = computed(() => {
return store.getters.increaseServiceOptions
})
const onSelectServe = (serve) => {
const oldServes = serves.value
@ -64,6 +65,7 @@
const popupRef = ref()
const open = () => {
store.dispatch('fetchIncreaseServiceOptions')
serves.value = props.modelValue
popupRef.value.open()
}
@ -74,6 +76,7 @@
const onConfirm = () => {
emit('update:modelValue', serves.value)
emit('confirm')
}
defineExpose({ open, close })


+ 19
- 26
otherPages/authentication/serve/popupTypeSelect.vue View File

@ -7,30 +7,14 @@
>
<view class="flex-between content">
<view class="type" @click="onSelectPetType('cat')">
<image src="@/static/images/ydd/cat.png" mode="widthFix"></image>
<template v-if="petTypes.includes('cat')">
<image class="active" src="@/static/images/ydd/cat-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" @click="onSelectPetType('dog')">
<image src="@/static/images/ydd/dog.png" mode="widthFix"></image>
<template v-if="petTypes.includes('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" @click="onSelectPetType('special-pet')">
<image src="@/static/images/ydd/special-pet.png" mode="widthFix"></image>
<template v-if="petTypes.includes('special-pet')">
<image class="active" src="@/static/images/ydd/special-pet-active.png" mode="widthFix"></image>
<view class="type"
v-for="item in petTypeOptions"
:key="`petType-${item.id}`"
@click="onSelectPetType(item.id)"
>
<image :src="item.imageNo" mode="widthFix"></image>
<template v-if="petTypes.includes(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>
@ -42,10 +26,13 @@
</template>
<script setup>
import { ref } from 'vue'
import { ref, computed } from 'vue'
import { useStore } from 'vuex'
import popupSelect from '../components/popupSelect.vue';
const store = useStore()
const props = defineProps({
modelValue: {
type: Array,
@ -55,10 +42,14 @@
}
})
const emit = defineEmits(['update:modelValue'])
const emit = defineEmits(['update:modelValue', 'confirm'])
const petTypes = ref([])
const petTypeOptions = computed(() => {
return store.getters.petTypeOptions
})
const onSelectPetType = (type) => {
const oldTypes = petTypes.value
let newTypes = []
@ -75,6 +66,7 @@
const popupRef = ref()
const open = () => {
store.dispatch('fetchPetTypeOptions')
petTypes.value = props.modelValue
popupRef.value.open()
}
@ -85,6 +77,7 @@
const onConfirm = () => {
emit('update:modelValue', petTypes.value)
emit('confirm')
}
defineExpose({ open, close })


+ 250
- 17
otherPages/authentication/serve/record.vue View File

@ -1,17 +1,74 @@
<template>
<view class="page">
<view class="flex-rowl">
<view class="size-28 color-ffb fw700 tab">
<view class="flex-rowl tab">
<view class="size-28 color-ffb fw700 tab-item">
全部记录
</view>
</view>
<view v-if="list.length">
<view class="box" v-for="item in list" :key="item.id">
<view class="flex-rowl box-top">
<up-avatar :src="userInfo.userImage" size="126rpx"></up-avatar>
<view class="box-info">
<view class="row highlight">{{ userInfo.userName }}</view>
<view class="row">{{ `服务时间:${dayjs(item.createTime).format('YYYY-MM-DD')}` }}</view>
<view class="row">{{ `宠物:${getTypeDesc(item.typeIds)}` }}</view>
</view>
<view class="box-address">
<text>{{ item.serviceSpot }}</text>
</view>
</view>
<view class="box-text">
{{ item.text }}
</view>
<view class="box-img">
<view
class="box-img-item"
v-for="(url, imgIdx) in item.images"
:key="`${item.id}-img-${imgIdx}`"
>
<up-image
:src="url"
:show-loading="true"
width="154rpx"
height="164rpx"
></up-image>
</view>
</view>
<view class="flex-rowr box-tools">
<button plain class="box-btn" @click="onEdit(item.id)">
<view class="flex-rowc">
<up-icon name="edit-pen" color="#707070" size="22rpx"></up-icon>
<text>编辑</text>
</view>
</button>
<button plain class="box-btn" @click="onDelete(item.id)">
<view class="flex-rowc">
<up-icon name="trash" color="#707070" size="22rpx"></up-icon>
<text>删除</text>
</view>
</button>
</view>
</view>
</view>
<view v-else class="flex-rowc">
<image src="@/static/images/ydd/empy.png" mode="widthFix"></image>
<image class="img-empty" src="@/static/images/ydd/empy.png" mode="widthFix"></image>
</view>
<up-modal
:show="deleteModal.show"
:showConfirmButton="false"
:showCancelButton="false"
>
<view class="modal">
<view class="modal-content">确定要删除该条服务信息吗</view>
<view>
<button plain class="modal-btn modal-btn-cancel" @click="onCancelDelete">取消</button>
<button plain class="modal-btn modal-btn-confirm" @click="onConfirmDelete">确定</button>
</view>
</view>
</up-modal>
<view class="footer-btn">
<view class="btn" @click="toUp">
立即上传
@ -21,38 +78,214 @@
</template>
<script setup>
import { onShow } from '@dcloudio/uni-app'
import { usePageList } from "@/utils/pageList";
// todo
const { list, total, getData } = usePageList()
onShow(() => {
// todo: delte test data
import { ref, reactive, computed } from 'vue'
import { useStore } from 'vuex'
import { onShow, onLoad } from '@dcloudio/uni-app'
import { serviceLogList, deleteServiceLog } from '@/api/serviceLog'
import dayjs from 'dayjs'
const store = useStore()
const userInfo = computed(() => {
return store.getters.userInfo
})
const petTypeOptions = computed(() => {
return store.getters.petTypeOptions
})
const getTypeDesc = (typeIds) => {
if (!typeIds.length) {
return ''
}
let descArr = typeIds.map(typeId => {
return petTypeOptions.value.find(item => item.id == typeId)?.title || typeId
})
return descArr.join('、')
}
const list = ref([])
const fetchLogList = async () => {
try {
list.value = await serviceLogList({ userId: store.getters.userInfo.userId })
} catch (err) {
}
}
const onEdit = (id) => {
uni.setStorageSync('serviceLogData', list.value.find(item => item.id === id))
uni.navigateTo({
url: `/otherPages/authentication/serve/upload?id=${id}`
})
}
const deleteModal = reactive({
show: false,
id: null,
})
const onDelete = (id) => {
deleteModal.id = id
deleteModal.show = true
}
const onCancelDelete = () => {
deleteModal.show = false
}
const onConfirmDelete = async () => {
try {
await deleteServiceLog({ id: deleteModal.id })
fetchLogList()
deleteModal.show = false
} catch (err) {
}
}
const toUp = () => {
uni.navigateTo({
url: "/otherPages/authentication/serve/upload"
})
}
onShow(async () => {
await store.dispatch('fetchPetTypeOptions')
fetchLogList()
})
</script>
<style lang="scss" scoped>
.page {
min-height: 100vh;
padding: 24rpx 24rpx 144rpx 24rpx;
background-color: #F5F5F5;
}
.tab {
padding: 9rpx 28rpx 16rpx 28rpx;
background-color: #fff;
.tab {
&-item {
padding-bottom: 9rpx;
border-bottom: 4rpx solid #FFBF60;
}
}
image {
width: 250rpx;
.box {
margin-top: 6rpx;
padding: 34rpx 43rpx 16rpx 28rpx;
background-color: #fff;
.img__view {
flex-wrap: wrap;
}
&-top {
align-items: start;
}
&-info {
flex: 1;
padding: 0 20rpx;
color: rgba($color: #000000, $alpha: 0.5);
font-size: 28rpx;
line-height: 37rpx;
.highlight {
color: #000000;
font-size: 30rpx;
font-weight: 700;
line-height: 40rpx;
}
.row + .row {
margin-top: 6rpx;
}
}
&-address {
max-width: 200rpx;
text-align: right;
color: #FFBF60;
font-size: 28rpx;
line-height: 37rpx;
}
&-text {
padding: 21rpx 32rpx 18rpx 16rpx;
color: #000000;
font-size: 30rpx;
line-height: 40rpx;
}
&-img {
&-item {
display: inline-block;
border-radius: 20rpx;
overflow: hidden;
margin-bottom: 16rpx;
margin-left: 16rpx;
}
}
&-btn {
display: inline-block;
border: none;
padding: 0;
margin: 0;
color: #707070;
font-size: 22rpx;
line-height: 29rpx;
& + & {
margin-left: 44rpx;
}
}
}
.img-empty {
width: 250rpx;
margin-top: 20vh;
}
.modal {
&-content {
text-align: center;
color: #000000;
font-size: 30rpx;
line-height: 40rpx;
margin-bottom: 35rpx;
}
&-btn {
display: inline-block;
padding: 20rpx 89rpx;
border: none;
margin: 0;
width: auto;
height: auto;
font-size: 30rpx;
line-height: 40rpx;
border-radius: 40rpx;
& + & {
margin-left: 25rpx;
}
&-cancel {
background-color: #FFF4E6;
color: #FFBF60;
}
&-confirm {
background-color: #FFBF60;
color: #FFFFFF;
}
}
}
</style>

+ 153
- 34
otherPages/authentication/serve/upload.vue View File

@ -8,10 +8,10 @@
服务类型
<text class="size-22 color-999 ml10">可多选</text>
</view>
<up-checkbox-group v-model="state.petType" @change="checkboxChange">
<up-checkbox-group v-model="form.serviceType">
<view class="flex-between mt40" style="width: 100%;">
<up-checkbox shape="circle" class="mr10" :customStyle="{marginBottom: '8px'}"
v-for="(item, index) in petTypeOptions" :key="index" :label="item.name" :name="item.name">
v-for="item in petTypeOptions" :key="`serviceType-${item.id}`" :label="item.title" :name="item.id" activeColor="#FFBF60">
</up-checkbox>
</view>
</up-checkbox-group>
@ -24,12 +24,12 @@
<view class="flex-between mt16">
<text class="size-28 color-999">选择服务时间</text>
<view class="flex-rowr" @click="openTimePicker">
<view class="t-r size-28 mr10" :class="[state.serveTime ? 'highlight' : '']">{{ serveTimeDesc }}</view>
<view class="t-r size-28 mr10" :class="[form.serviceTime ? 'highlight' : '']">{{ serveTimeDesc }}</view>
<up-icon name="arrow-right" color="#999999" size="27rpx"></up-icon>
</view>
</view>
<up-datetime-picker
v-model="state.serveTime"
v-model="form.serviceTime"
:show="showTimePicker"
mode="date"
:closeOnClickOverlay="true"
@ -45,8 +45,8 @@
</view>
<view class="flex-between mt16">
<text class="size-28 color-999">选择服务地点</text>
<view class="flex-rowr" @click="jumpToSeletAddress">
<view class="t-r size-28 mr10" :class="[selectedAddress.address ? 'highlight' : '']">{{ selectedAddress.address || '请选择' }}</view>
<view class="flex-rowr" @click="selectAddr">
<view class="t-r size-28 mr10" :class="[form.serviceSpot ? 'highlight' : '']">{{ form.serviceSpot || '请选择' }}</view>
<up-icon name="arrow-right" color="#999999" size="27rpx"></up-icon>
</view>
</view>
@ -56,7 +56,10 @@
<view class="title">
文字记录
</view>
<textarea class="text" placeholder="请输入文字记录,可简单描述服务过程中发生的趣事,或夸奖一下服务宠物吧,10-100字"></textarea>
<textarea class="text"
v-model="form.text"
placeholder="请输入文字记录,可简单描述服务过程中发生的趣事,或夸奖一下服务宠物吧,10-100字"
></textarea>
</view>
<view class="li bg-fff">
@ -66,10 +69,20 @@
<view class="size-28 color-999 mt16">
请选择具有代表性的2-3张服务宠物图片服务过程图片或视频截图让铲屎官感受到您对毛孩子的爱吧
</view>
<view style="margin-top: 34rpx;">
<up-upload
:fileList="form.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="footer-btn">
<view class="btn">
<view class="btn" @click="onSave">
立即上传
</view>
</view>
@ -78,25 +91,54 @@
<script setup>
import { ref, reactive, computed } from 'vue';
import { onShow } from '@dcloudio/uni-app'
import { onLoad } from '@dcloudio/uni-app'
import { useStore } from 'vuex'
import dayjs from 'dayjs'
import { ossUpload } from '@/utils/oss-upload/oss/index.js'
import { insertServiceLog, udpateServiceLog } from '@/api/serviceLog'
const store = useStore()
const id = ref()
const form = reactive({
serviceType: [],
serviceTime: null,
serviceSpot: null,
latitude: null,
longitude: null,
text: null,
fileList: [],
})
const fetchServiceLogDetail = async () => {
try {
const data = (await serviceLogList({ id: id.value }))?.[0]
// const data = uni.getStorageSync('serviceLogData')
const {
serviceType,
serviceTime,
serviceSpot,
text,
image,
} = data
const state = reactive({
petType: [],
serveTime: null,
form.serviceType = serviceType?.split?.(',').map(item => parseInt(item)) || []
form.serviceTime = serviceTime
form.serviceSpot = serviceSpot
form.text = text
form.fileList = image?.split?.(',').map(url => ({ url })) || []
} catch (err) {
}
}
const petTypeOptions = computed(() => {
return store.getters.petTypeOptions
})
const petTypeOptions = [{
name: '猫咪喂养',
},
{
name: '狗狗喂养',
},
{
name: '异宠喂养',
},
]
const checkboxChange = () => {}
const showTimePicker = ref(false)
const openTimePicker = () => {
@ -106,24 +148,97 @@
showTimePicker.value = false
}
const serveTimeDesc = computed(() => {
if (!state.serveTime) {
if (!form.serviceTime) {
return '请选择'
}
return dayjs(state.serveTime).format('YYYY/MM/DD')
return dayjs(form.serviceTime).format('YYYY/MM/DD')
})
const selectedAddress = ref({})
const jumpToSeletAddress = () => {
// todo: check select from map or address book ?
uni.navigateTo({
url: "/otherPages/authentication/connectAddress/index"
const setAddress = (res) => {
//
form.latitude = res.latitude
form.longitude = res.longitude
if (!res.address && res.name) { //
return form.serviceSpot = res.name
}
if (res.address || res.name) {
return form.serviceSpot = res.address + res.name
}
form.serviceSpot = '' //
}
const selectAddr = () => {
uni.chooseLocation({
success: function(res) {
setAddress(res)
}
})
}
const afterRead = (event) => {
event.file.forEach(n => {
ossUpload(n.url)
.then(url => {
form.fileList.push({
url
})
})
})
};
const deletePic = (event) => {
form.fileList.splice(event.index, 1);
};
const onSave = async () => {
try {
const {
serviceType,
serviceTime,
serviceSpot,
text,
fileList,
} = form
onShow(() => {
selectedAddress.value = uni.getStorageSync('serveAddress')
const data = {
userId: store.getters.userInfo.userId,
serviceType: serviceType.join(','),
serviceTime: dayjs(serviceTime).format('YYYY-MM-DD HH:mm:ss'),
serviceSpot,
text,
image: fileList.map(item => item.url).join(',')
}
if (id.value) {
data.id = id.value
await udpateServiceLog(data)
} else {
await insertServiceLog(data)
}
uni.showToast({
title: '上传成功!',
icon: "none"
})
setTimeout(() => {
uni.navigateBack()
}, 1000)
} catch (err) {
}
}
onLoad((option) => {
store.dispatch('fetchPetTypeOptions')
id.value = option.id
if (id.value) {
fetchServiceLogDetail()
}
})
</script>
@ -172,4 +287,8 @@
.highlight {
color: #FFBF60;
}
.footer-btn {
z-index: 4;
}
</style>

+ 3
- 1
store/getters.js View File

@ -6,6 +6,8 @@ const getters = {
roles: state => state.user.roles,
permissions: state => state.user.permissions,
isLogin: state=>state.user.isLogin,
configList: state => state.system.configList
configList: state => state.system.configList,
petTypeOptions: state => state.system.petTypeOptions,
increaseServiceOptions: state => state.system.increaseServiceOptions,
}
export default getters

+ 34
- 2
store/modules/system.js View File

@ -1,8 +1,10 @@
import { getConfigList } from '@/api/config/config.js'
import { getConfigList, getPetTypeList, getIncreaseServiceList } from '@/api/config/config.js'
const system = {
state: {
configList: {},
petTypeOptions: [],
increaseServiceOptions: [],
},
mutations: {
setConfigList(state, list) {
@ -14,6 +16,12 @@ const system = {
state.configList = obj;
},
setPetTypeOptions(state, list) {
state.petTypeOptions = list
},
setIncreaseServiceOptions(state, list) {
state.increaseServiceOptions = list
},
},
actions: {
async fetchConfigList({commit, state}) {
@ -24,7 +32,31 @@ const system = {
} catch (err) {
}
}
},
async fetchPetTypeOptions({commit, state}) {
if (state.petTypeOptions.length) {
return
}
try {
const data = await getPetTypeList()
commit('setPetTypeOptions', data)
} catch (err) {
}
},
async fetchIncreaseServiceOptions({commit, state}) {
if (state.increaseServiceOptions.length) {
return
}
try {
const data = await getIncreaseServiceList()
commit('setIncreaseServiceOptions', data)
} catch (err) {
}
},
}
}

Loading…
Cancel
Save