【订单】 新增# 师傅上传服务照片

dev1.0
kaeery 2025-01-22 00:48:00 +08:00
parent 549435671a
commit 2f9cc36776
9 changed files with 301 additions and 77 deletions

View File

@ -54,3 +54,7 @@ export const apiByteQueryRefund = (params: any) =>
// 取消订单扣分规则
export const apiCancelOrderRule = (params: any) =>
request.get({ url: '/order/getCancelOrderConfigByOrder', data: params })
// 师傅上传服务照片
export const apiServiceImages = (params: any) =>
request.post({ url: '/order/staff/uploadServiceImg', data: params })

View File

@ -26,16 +26,29 @@
<text class="statusDec ml-[15rpx]">{{ orderData.orderStatusName }}</text>
</view>
<!-- 地址卡片 -->
<view class="card">
<view class="card--header" @click="openLocation">
<view class="title">{{ orderData.contact }} {{ orderData.mobile }}</view>
<view class="card flex flex-col gap-[40rpx]">
<!-- 地址卡片 -->
<view @click="openLocation">
<view class="card--header">
<view class="title text-black font-bold">
{{ orderData.province }}
{{ orderData.city }}
{{ orderData.district }}
{{ orderData.address }}
</view>
</view>
<view class="text-[28rpx] text-[#666]">
<text class="mr-[28rpx]">{{ orderData.contact }}</text>
<text>{{ orderData.mobile }}</text>
</view>
</view>
<view class="text-sm text-muted">
{{ orderData.province }}
{{ orderData.city }}
{{ orderData.district }}
{{ orderData.address }}
<!-- 上门时间 -->
<view class="normal text-base flex justify-between">
<view class="text-[#333]">上门时间</view>
<view class="text-[#1869FF]">
{{ orderData.appointTime }} {{ orderData.weekDay }}
{{ orderData.appointTimeStartStr }}-{{ orderData.appointTimeEndStr }}
</view>
</view>
</view>
@ -65,15 +78,6 @@
</view>
</view>
<!-- 上门时间 -->
<view class="card normal text-base flex justify-between">
<view>上门时间</view>
<view>
{{ orderData.appointTime }} {{ orderData.weekDay }}
{{ orderData.appointTimeStartStr }}-{{ orderData.appointTimeEndStr }}
</view>
</view>
<!-- 服务金额 -->
<view class="card normal text-base">
<view class="flex justify-between">
@ -119,6 +123,22 @@
<view>{{ orderData.cancelTime }}</view>
</view>
</view>
<view
class="card bg-white card normal text-base flex flex-col gap-[12rpx] rounded-[12rpx]"
>
<text>服务照片</text>
<view class="flex gap-[12rpx] flex-wrap">
<u-image
v-for="(image, index) in orderData.serviceImages"
:key="index"
:src="image"
width="200"
height="200"
@click="handlePreviewImage(index)"
></u-image>
</view>
</view>
<!-- Main End -->
</view>
</uni-transition>
@ -140,11 +160,11 @@
</template>
<script lang="ts" setup>
import { ref, computed, unref } from 'vue'
import { onLoad, onShow, onUnload } from '@dcloudio/uni-app'
import { apiStaffOrderDetail } from '@/api/order'
import Price from '@/components/price/index.vue'
import OrderFooter from '@/components/order-footer/index.vue'
import Price from '@/components/price/index.vue'
import { onLoad } from '@dcloudio/uni-app'
import { computed, ref, unref } from 'vue'
/** Data Start **/
const orderData = ref<any>({
@ -192,6 +212,12 @@ const openLocation = () => {
}
})
}
const handlePreviewImage = (index: number) => {
uni.previewImage({
urls: [...orderData.value.serviceImages],
current: index
})
}
</script>
<style lang="scss">
@ -199,7 +225,10 @@ const openLocation = () => {
height: 100%;
padding: 30rpx 24rpx;
padding-bottom: 140rpx;
background: linear-gradient(to bottom, #1296db 200rpx, transparent 0);
// background: linear-gradient(to bottom, #1296db 200rpx, transparent 0);
background-image: url('~@/static/images/order-detail-bg.png');
background-size: 100% 400rpx;
background-repeat: no-repeat;
.statusDec {
color: rgba(255, 255, 255, 1) !important;

View File

@ -0,0 +1,128 @@
<template>
<view class="uploader-container flex wrap">
<u-upload
@on-change="handleCallback"
:action="action"
:header="{ token: token, version: versions }"
:deletable="deletable"
:max-count="maxUpload"
:showProgress="showProgress"
@on-remove="remove"
:multiple="mutiple"
:width="previewSize"
:height="previewSize"
ref="upload"
maxSize="10485760"
:file-list="setFileList(modelValue)"
/>
</view>
</template>
<script lang="ts" setup>
import { version } from '@/config/app'
import { useUserStore } from '@/stores/user'
import { toast } from '@/utils/util'
import { computed, onMounted, ref, watch } from 'vue'
const userStore = useUserStore()
/** Emit Start **/
const emit = defineEmits(['update:modelValue', 'setValue', 'remove'])
/** Emit End **/
/** Props Start **/
const props = withDefaults(
defineProps<{
mutiple?: boolean //
maxUpload?: number //
previewSize?: number // upload
deletable?: boolean //
tips?: string //
showProgress?: false //
modelValue?: []
}>(),
{
mutiple: false,
maxUpload: 1,
previewSize: 160,
deletable: true,
tips: '上传图片',
showProgress: false,
modelValue: []
}
)
/** Props End **/
/** Data Start **/
const action = ref<string | null>('')
const token = ref<string | null>('')
const fileList = ref<Array<any>>([])
const versions = ref<string | null>(version)
const upload = ref()
/** Data End **/
/** Methods Start **/
/**
* @param { params } 上传返回值
* @return { void }
* @description 上传不管成不成功都返回数据提示
*/
const handleCallback = (params: any) => {
toast(JSON.parse(params.data).msg)
if (JSON.parse(params.data).code == 200) {
emit('setValue', JSON.parse(params.data).data.path)
} else {
uni.$emit('popOneLists')
}
}
/**
* @param { event } 索引值
* @return { void }
* @description 删除一个图片
*/
const remove = (event: number | string) => {
fileList.value.splice(event, 1)
emit('update:modelValue', fileList.value)
emit('remove', event)
}
/** Methods End **/
/** Life Cycle Start **/
onMounted(() => {
action.value = `${import.meta.env.VITE_APP_BASE_URL}/api/upload/image`
token.value = userStore.token
})
/** Life Cycle End **/
const setFileList = computed(() => list => {
return list.map((item: string) => {
return {
url: item
}
})
})
watch(
() => props.modelValue,
val => {
fileList.value = val
}
)
</script>
<style lang="scss" scoped>
.uploader-container {
.uplader-upload {
position: relative;
width: 160rpx;
height: 160rpx;
padding-top: 30rpx;
text-align: center;
margin: 11rpx;
border: 2px dashed #e5e5e5;
background-color: #ffffff;
> view {
color: #bbb;
}
}
}
</style>

View File

@ -0,0 +1,77 @@
<template>
<view class="p-[20rpx] service">
<!-- 师傅完成服务拍照上传 -->
<view
class="flex-1 p-[20rpx] bg-white card normal text-base flex flex-col gap-[12rpx] rounded-[12rpx]"
>
<text>上传服务照片</text>
<TUploader
mutiple
:maxUpload="6"
image-fit="aspectFill"
v-model="formData.serviceImages"
@set-value="setServiceImages"
@remove="removeServiceImages"
/>
</view>
<view class="footer mt-[30rpx]">
<button
class="bg-primary text-lg text-white leading-[80rpx] h-[80rpx] rounded-full"
@click="handleSubmit"
>
提交
</button>
</view>
</view>
</template>
<script setup lang="ts">
import { apiStaffOrderDetail } from '@/api/order'
import { toast } from '@/utils/util'
import { onLoad } from '@dcloudio/uni-app'
import { ref } from 'vue'
import TUploader from './components/TUpload.vue'
const formData = ref({
id: '',
orderStatus: '',
serviceImages: []
})
onLoad(option => {
if (option.id) {
formData.value.id = option.id
initOrderDetail()
}
})
const initOrderDetail = async () => {
const result = await apiStaffOrderDetail({ id: formData.value.id })
formData.value.orderStatus = result.orderStatus
formData.value.serviceImages = result.serviceImages
}
const handleSubmit = async () => {
const serviceImages = [...formData.value.serviceImages, ...tempFiles.value]
if (!serviceImages.length) return toast('请上传服务图片')
try {
const data = {
...formData.value
}
await apiServiceImages(data)
toast('提交成功', 'success')
uni.navigateBack()
} catch (error) {}
}
const tempFiles = ref([])
const setServiceImages = (path: string) => {
tempFiles.value.push(path)
}
const removeServiceImages = (index: number) => {
tempFiles.value.splice(index, 1)
}
</script>
<style scoped lang="scss">
.service {
display: flex;
flex-direction: column;
}
</style>

View File

@ -42,7 +42,7 @@
</template>
<!-- 联系师傅 -->
<!-- <template
<template
v-if="
staffMobile?.length > 0 &&
!(confirmService || verification) &&
@ -55,7 +55,7 @@
>
联系师傅
</button>
</template> -->
</template>
<!-- 联系客户 -->
<template v-if="mobile && (confirmService || verification)">
@ -97,7 +97,6 @@
</template>
<!-- 核销订单 -->
<template v-if="verification">
<view class="flex justify-around">
<button
@ -107,11 +106,17 @@
手动核销码
</button>
<button
class="flex-1 bg-primary text-sm text-white leading-[70rpx] h-[70rpx] rounded-full"
class="flex-1 mr-2 bg-primary text-sm text-white leading-[70rpx] h-[70rpx] rounded-full"
@click.stop="handleScanQRCode"
>
扫码核销
</button>
<button
class="bg-primary text-sm text-white leading-[70rpx] h-[70rpx] rounded-full"
@click.stop="handleNavigate"
>
</button>
</view>
<!-- 手动输入核销码MODAL -->
@ -136,16 +141,6 @@
</view>
</u-modal>
</template>
<!-- 已预约用户确认服务 -->
<template v-if="orderStatus == 2">
<button
class="bg-primary text-lg text-white leading-[70rpx] h-[70rpx] rounded-full"
@click.stop="handleUserConfirm"
>
确认服务
</button>
</template>
</view>
<u-popup
v-model="showConfirmPop"
@ -213,23 +208,20 @@
</template>
<script lang="ts" setup>
import { ref, onUnmounted, onMounted, unref, reactive } from 'vue'
import {
apiOrderCancel,
apiStaffOrderConfirmService,
apiStaffOrderVerification,
apiOrderDel,
apiByteQueryRefund,
apiCancelOrderRule,
apiUserOrderVerification
apiOrderCancel,
apiOrderDel,
apiStaffOrderConfirmService,
apiStaffOrderVerification
} from '@/api/order'
import { OrderStatusEnum, PayFromType } from '@/enums/appEnums'
import { useUserStore } from '@/stores/user'
import { storeToRefs } from 'pinia'
import { getClient } from '@/utils/client'
import { isWeixinClient } from '@/utils/client'
import { useToggle } from '@/hooks/useLockFn'
import { getClient, isWeixinClient } from '@/utils/client'
import { toast } from '@/utils/util'
import { storeToRefs } from 'pinia'
import { onMounted, onUnmounted, reactive, ref, unref } from 'vue'
const emit = defineEmits(['refresh', 'backRefresh', 'contact'])
const userStore = useUserStore()
@ -476,16 +468,10 @@ const handleCancel = () => {
code.value = ''
emit('refresh')
}
//
const handleUserConfirm = async () => {
const modelRes = await uni.showModal({
title: '温馨提示',
content: '确认核销该订单吗?'
const handleNavigate = () => {
uni.navigateTo({
url: `/bundle/pages/service_order_image/index?id=${props.orderId}`
})
if (modelRes.cancel) return
await apiUserOrderVerification({ id: props.orderId })
uni.$u.toast('订单核销成功')
emit('refresh')
}
// 2
const isCanConfirmService = ref(false) // 2

View File

@ -18,11 +18,10 @@
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import { useUserStore } from '@/stores/user'
import { version } from '@/config/app'
import { useUserStore } from '@/stores/user'
import { toast } from '@/utils/util'
import UUpload from '../../uni_modules/vk-uview-ui/components/u-upload/u-upload.vue'
import { onMounted, ref } from 'vue'
const userStore = useUserStore()
/** Emit Start **/
@ -55,6 +54,7 @@ const action = ref<string | null>('')
const token = ref<string | null>('')
const fileList = ref<Array<any>>([])
const versions = ref<string | null>(version)
const upload = ref()
/** Data End **/
/** Methods Start **/
@ -89,7 +89,6 @@ onMounted(() => {
action.value = `${import.meta.env.VITE_APP_BASE_URL}/api/upload/image`
token.value = userStore.token
})
/** Life Cycle End **/
</script>
<style lang="scss" scoped>

View File

@ -399,6 +399,12 @@
"style": {
"navigationBarTitleText": "选择优惠券"
}
},
{
"path": "pages/service_order_image/index",
"style": {
"navigationBarTitleText": "上传服务照片"
}
}
]
}

View File

@ -78,18 +78,13 @@ const tabList = ref<any>([
orderStatus: 0,
refresh: false
},
// {
// name: '',
// orderStatus: 1,
// refresh: false
// },
// {
// name: '',
// orderStatus: 2,
// refresh: false
// },
{
name: '已预约',
name: '预约中',
orderStatus: 1,
refresh: false
},
{
name: '服务中',
orderStatus: 2,
refresh: false
},

View File

@ -79,15 +79,15 @@
</view>
<!-- 服务师傅 -->
<!-- <template v-if="orderData?.staff?.id">
<template v-if="orderData?.staff?.id">
<view class="card normal text-base flex justify-between">
<view>服务师傅</view>
<view>{{ orderData?.staff?.name }} {{ orderData?.staff?.mobile }}</view>
</view>
</template> -->
</template>
<!-- 我的核销码 -->
<!-- <template v-if="orderData.orderStatus === 2">
<template v-if="orderData.orderStatus === 2">
<view class="card normal text-base">
<view class="">
<view>我的核销码</view>
@ -107,7 +107,7 @@
核销码{{ orderData.verificationCode }}
</view>
</view>
</template> -->
</template>
<!-- 服务金额 -->
<view class="card normal text-base">
@ -237,13 +237,13 @@
</template>
<script lang="ts" setup>
import { ref, reactive, computed, unref } from 'vue'
import { onLoad, onUnload, onShow, onHide } from '@dcloudio/uni-app'
import { apiOrderDetail } from '@/api/order'
import Price from '@/components/price/index.vue'
import OrderFooter from '@/components/order-footer/index.vue'
import Price from '@/components/price/index.vue'
import qrcode from '@/components/qrcode/index.vue'
import ContactModal from '@/components/widgets/my-service/components/customer-service.vue'
import { onHide, onLoad, onShow, onUnload } from '@dcloudio/uni-app'
import { computed, reactive, ref, unref } from 'vue'
const contact = ref()
const orderData = ref<any>({