删除不需要的文件
This commit is contained in:
@ -2,7 +2,6 @@
|
||||
import { onHide, onLaunch, onShow } from '@dcloudio/uni-app'
|
||||
import { navigateToInterceptor } from '@/router/interceptor'
|
||||
import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'
|
||||
import { LOCATION_DEFAULT_CITY, LOCATION_DEFAULT_LAT, LOCATION_DEFAULT_LNG, LOCATION_LAT_KEY, LOCATION_LNG_KEY, LOCATION_CITY_KEY } from '@/hooks/useLocation'
|
||||
|
||||
onLaunch((options) => {
|
||||
// 处理直接进入页面路由的情况:如h5直接输入路由、微信小程序分享后进入等
|
||||
|
||||
@ -41,26 +41,6 @@ export function getLocationToCity(data: ILocationToCityParams) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取门店列表
|
||||
*/
|
||||
export interface IHomeTeaStoreListParams {
|
||||
page: number
|
||||
size: number
|
||||
search: string
|
||||
latitude: number
|
||||
longitude: number
|
||||
}
|
||||
|
||||
export function getHomeTeaStoreList(data: IHomeTeaStoreListParams) {
|
||||
return http.Post<IHomeTeaRoomListResult>('/api/teaStore/teaStoreLists',
|
||||
data,
|
||||
{
|
||||
meta: { ignoreAuth: true }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取茶室开通城市列表
|
||||
*/
|
||||
@ -72,20 +52,6 @@ export function getOpenCityList() {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 茶室搜索历史
|
||||
*/
|
||||
export function getTeaRoomSearchHistory() {
|
||||
return http.Post<{ list: Array<string> }>('/api/teaStore/teaStoreSearchHistory')
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除茶室搜索历史
|
||||
*/
|
||||
export function clearTeaRoomSearchHistory() {
|
||||
return http.Post('/api/teaStore/delTeaStoreSearchHistory', null)
|
||||
}
|
||||
|
||||
/**
|
||||
* 茶室详情
|
||||
*/
|
||||
|
||||
@ -164,4 +164,11 @@ export function getExclusiveCirclesLabel() {
|
||||
meta: { ignoreAuth: true }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户(茶艺师)等级
|
||||
*/
|
||||
export function getUserLevel() {
|
||||
return http.Post<any>('/teamapi/user/userLevel')
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -218,7 +218,7 @@
|
||||
class="service-icon-wrapper h-96rpx w-96rpx flex items-center justify-center rounded-16rpx bg-[#FFFFFF]">
|
||||
<wd-img width="48rpx" height="48rpx" :src="`${OSS}images/chayishi/data.png`" />
|
||||
</view>
|
||||
<text class="text-24rpx text-[#303133] leading-34rpx">上传资料</text>
|
||||
<text class="text-24rpx text-[#303133] leading-34rpx">资质证书</text>
|
||||
</view>
|
||||
<!-- 行程记录 -->
|
||||
<!-- <view class="service-item flex flex-col items-center" @click="My.handleServiceClick('record')">
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
</view>
|
||||
|
||||
<!-- 营业执照 -->
|
||||
<view class="rounded-24rpx bg-white mx-30rpx relative">
|
||||
<view class="rounded-24rpx bg-white mx-30rpx relative mt-20rpx">
|
||||
<!-- 审核状态标签 -->
|
||||
<view class="absolute top-20rpx right-34rpx">
|
||||
<view v-if="auditStatus == 0"
|
||||
@ -54,7 +54,7 @@
|
||||
</view>
|
||||
|
||||
<!-- 营业执照 -->
|
||||
<view class="info-card mt-30rpx px-30rpx pt-20rpx">
|
||||
<!-- <view class="info-card mt-30rpx px-30rpx pt-20rpx">
|
||||
<text class="mb-24rpx block text-32rpx text-[#303133] font-bold leading-44rpx">营业执照</text>
|
||||
<view v-if="documents.businessLicense" class="relative w-[200rpx]">
|
||||
<wd-img width="200rpx" height="200rpx" :src="documents.businessLicense" mode="aspectFill"
|
||||
@ -64,10 +64,10 @@
|
||||
<wd-img width="120rpx" height="120rpx" :src="`${OSS}images/chayishi/text.png`" />
|
||||
<text class="mt-24rpx text-28rpx text-[#909399] leading-40rpx">暂未提交信息</text>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 资质证书 -->
|
||||
<view class="info-card px-30rpx">
|
||||
<view class="info-card px-30rpx pt-20rpx">
|
||||
<text class="mb-24rpx block text-32rpx text-[#303133] font-bold leading-44rpx">资质证书</text>
|
||||
<view v-if="documents.qualification" class="relative w-[200rpx]">
|
||||
<wd-img width="200rpx" height="200rpx" :src="documents.qualification" mode="aspectFill"
|
||||
@ -105,7 +105,7 @@
|
||||
<!-- 新增/编辑状态 -->
|
||||
<template v-else>
|
||||
<!-- 营业执照 -->
|
||||
<view class="info-card mx-30rpx mt-30rpx rounded-24rpx bg-white p-30rpx">
|
||||
<!-- <view class="info-card mx-30rpx mt-30rpx rounded-24rpx bg-white p-30rpx">
|
||||
<text class="mb-24rpx block text-32rpx text-[#303133] font-bold leading-44rpx">营业执照</text>
|
||||
<view class="relative mb-24rpx w-[200rpx]">
|
||||
<wd-upload
|
||||
@ -125,7 +125,7 @@
|
||||
</view>
|
||||
</wd-upload>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 资质证书 -->
|
||||
<view class="info-card mx-30rpx mt-30rpx rounded-24rpx bg-white p-30rpx">
|
||||
@ -137,6 +137,8 @@
|
||||
:limit="1"
|
||||
image-mode="scaleToFill"
|
||||
:action="action"
|
||||
@progress="isUploading = true"
|
||||
@fail="isUploading = false"
|
||||
@success="UploadData.handleUploadQualification">
|
||||
<view
|
||||
class="border-2rpx border-dashed border-[#E5E5E5] w-184rpx h-184rpx flex flex-col items-center justify-center rounded-16rpx">
|
||||
@ -160,6 +162,8 @@
|
||||
:limit="1"
|
||||
image-mode="scaleToFill"
|
||||
:action="action"
|
||||
@progress="isUploading = true"
|
||||
@fail="isUploading = false"
|
||||
@success="UploadData.handleUploadHealthCert">
|
||||
<view
|
||||
class="border-2rpx border-dashed border-[#E5E5E5] w-184rpx h-184rpx flex flex-col items-center justify-center rounded-16rpx">
|
||||
@ -189,7 +193,8 @@
|
||||
<view v-if="pageStatus === 'add' || pageStatus === 'edit'"
|
||||
class="fixed bottom-0 left-0 right-0 px-30rpx pb-40rpx pt-24rpx z-100">
|
||||
<view class="save-btn h-88rpx rounded-8rpx bg-[#4C9F44] text-center leading-88rpx"
|
||||
@click="UploadData.handleSubmit">
|
||||
:class="{'opacity-50': !canSubmit}"
|
||||
@click="handleSubmitClick">
|
||||
<text class="text-32rpx text-[#fff] font-bold">提交</text>
|
||||
</view>
|
||||
</view>
|
||||
@ -197,6 +202,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, inject } from 'vue'
|
||||
import { router } from '@/utils/tools'
|
||||
import { useToast } from 'wot-design-uni'
|
||||
import { addTeaSpecialistQualification, getTeaSpecialistQualification, editTeaSpecialistQualification } from '@/api/tes-specialist'
|
||||
@ -206,6 +212,7 @@
|
||||
const rightPadding = inject('capsuleOffset')
|
||||
const token = ref<string>('') // 用户token
|
||||
const toast = useToast()
|
||||
const isUploading = ref<boolean>(false)
|
||||
|
||||
// 页面状态:'add' | 'edit' | 'pending' | 'view'
|
||||
// 可以通过路由参数或API获取状态,这里使用静态数据模拟
|
||||
@ -213,11 +220,22 @@
|
||||
|
||||
// 资料数据
|
||||
const documents = ref({
|
||||
businessLicense: '', // 营业执照
|
||||
// businessLicense: '', // 营业执照
|
||||
qualification: '', // 资质证书
|
||||
healthCert: '', // 健康证
|
||||
})
|
||||
|
||||
// 提交按钮是否可用(所有图片都已上传)
|
||||
const canSubmit = computed(() => {
|
||||
return !!documents.value.qualification && !!documents.value.healthCert && !isUploading.value
|
||||
})
|
||||
|
||||
const handleSubmitClick = () => {
|
||||
if (canSubmit.value) {
|
||||
UploadData.handleSubmit()
|
||||
}
|
||||
}
|
||||
|
||||
// 审核状态
|
||||
const auditStatus = ref<number>(0) // 0 待审核 1 通过 2 未通过
|
||||
|
||||
@ -259,13 +277,13 @@
|
||||
const res = await getTeaSpecialistQualification(certId.value)
|
||||
|
||||
// 回显图片-编辑状态
|
||||
fileList1.value = res.license_img ? [{ url: res.license_img }] : [] // 营业执照
|
||||
// fileList1.value = res.license_img ? [{ url: res.license_img }] : [] // 营业执照
|
||||
fileList2.value = res.cert_img ? [{ url: res.cert_img }] : [] // 资质证书
|
||||
fileList3.value = res.fitness_img ? [{ url: res.fitness_img }] : [] // 健康证
|
||||
|
||||
// 回显图片-预览状态
|
||||
documents.value = {
|
||||
businessLicense: res.license_img || '',
|
||||
// businessLicense: res.license_img || '',
|
||||
qualification: res.cert_img || '',
|
||||
healthCert: res.fitness_img || '',
|
||||
}
|
||||
@ -282,24 +300,25 @@
|
||||
/**
|
||||
* 上传营业执照
|
||||
*/
|
||||
handleUploadBusinessLicense: async (e: any) => {
|
||||
try {
|
||||
const response = JSON.parse(e.file.response)
|
||||
if (response.code) {
|
||||
const avatarUrl = response.data.url
|
||||
documents.value.businessLicense = avatarUrl
|
||||
} else {
|
||||
throw new Error('上传失败')
|
||||
}
|
||||
} catch (error) {
|
||||
toast.show('上传失败')
|
||||
}
|
||||
},
|
||||
// handleUploadBusinessLicense: async (e: any) => {
|
||||
// try {
|
||||
// const response = JSON.parse(e.file.response)
|
||||
// if (response.code) {
|
||||
// const avatarUrl = response.data.url
|
||||
// documents.value.businessLicense = avatarUrl
|
||||
// } else {
|
||||
// throw new Error('上传失败')
|
||||
// }
|
||||
// } catch (error) {
|
||||
// toast.show('上传失败')
|
||||
// }
|
||||
// },
|
||||
|
||||
/**
|
||||
* 上传资质证书
|
||||
*/
|
||||
handleUploadQualification: async (e: any) => {
|
||||
isUploading.value = false
|
||||
try {
|
||||
const response = JSON.parse(e.file.response)
|
||||
if (response.code) {
|
||||
@ -317,6 +336,7 @@
|
||||
* 上传健康证
|
||||
*/
|
||||
handleUploadHealthCert: async (e: any) => {
|
||||
isUploading.value = false
|
||||
try {
|
||||
const response = JSON.parse(e.file.response)
|
||||
if (response.code) {
|
||||
@ -334,15 +354,15 @@
|
||||
* 提交数据
|
||||
*/
|
||||
handleSubmit: async () => {
|
||||
const licenseImg = documents.value.businessLicense ? documents.value.businessLicense.replace(import.meta.env.VITE_OSS_BASEURL, '') : ''
|
||||
const certImg = documents.value.qualification ? documents.value.qualification.replace(import.meta.env.VITE_OSS_BASEURL, '') : ''
|
||||
const fitnessImg = documents.value.healthCert ? documents.value.healthCert.replace(import.meta.env.VITE_OSS_BASEURL, '') : ''
|
||||
|
||||
// const licenseImg = documents.value.businessLicense ? documents.value.businessLicense.replace(import.meta.env.VITE_OSS_BASEURL, '') : ''
|
||||
const certImg = documents.value.qualification ? documents.value.qualification.replace(import.meta.env.VITE_UPLOAD_IMAGE_URL, '') : ''
|
||||
const fitnessImg = documents.value.healthCert ? documents.value.healthCert.replace(import.meta.env.VITE_UPLOAD_IMAGE_URL, '') : ''
|
||||
|
||||
if (certId.value > 0) {
|
||||
// 编辑资料
|
||||
await editTeaSpecialistQualification({
|
||||
id: certId.value,
|
||||
license_img: licenseImg,
|
||||
// license_img: licenseImg,
|
||||
cert_img: certImg,
|
||||
fitness_img: fitnessImg,
|
||||
})
|
||||
@ -350,7 +370,7 @@
|
||||
} else {
|
||||
// 添加资料
|
||||
await addTeaSpecialistQualification({
|
||||
license_img: licenseImg,
|
||||
// license_img: licenseImg,
|
||||
cert_img: certImg,
|
||||
fitness_img: fitnessImg,
|
||||
})
|
||||
@ -361,6 +381,7 @@
|
||||
pageStatus.value = 'pending'
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@ -399,7 +420,7 @@
|
||||
height: 200rpx;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:active {
|
||||
&:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,698 +0,0 @@
|
||||
<route lang="jsonc" type="page">
|
||||
{
|
||||
"needLogin": false,
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useMessage } from 'wot-design-uni'
|
||||
import PriceFormat from '@/components/PriceFormat.vue'
|
||||
import { copy, router } from '@/utils/tools'
|
||||
|
||||
const OSS = inject('OSS')
|
||||
|
||||
// 消息提示框
|
||||
const message = useMessage('wd-message-box-slot')
|
||||
|
||||
// 订单记录弹窗
|
||||
const showOrderRecordPopup = ref(false)
|
||||
|
||||
// 订单数据
|
||||
const orderData = ref({
|
||||
id: 7,
|
||||
serviceName: '苓苑共享茶室空间',
|
||||
serviceType: '到店服务',
|
||||
price: 212.20,
|
||||
appointmentTimeFull: '2025-03-18 09:00-12:00',
|
||||
duration: '3小时',
|
||||
servicePeople: 1,
|
||||
teaName: '福鼎白茶 (3泡)',
|
||||
teawareUsage: '客户自备',
|
||||
address: '青浦区仓桥路478号',
|
||||
latitude: 31.2304,
|
||||
longitude: 121.4737,
|
||||
orderSn: '7327328627526903',
|
||||
paymentMethod: '微信支付',
|
||||
createTime: '2019-05-16 12:20:26',
|
||||
payTime: '2019-05-16 13:20:26',
|
||||
})
|
||||
|
||||
// 订单记录数据
|
||||
const orderRecord = ref({
|
||||
orderSn: '7327328627526903',
|
||||
steps: [
|
||||
{
|
||||
id: 1,
|
||||
title: '客户下订单',
|
||||
time: '2019-05-16 12:20:26',
|
||||
status: 'completed',
|
||||
photo: '',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '订单取消',
|
||||
time: '2019-05-16 13:30:26',
|
||||
status: 'completed',
|
||||
photo: '',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
// 复制订单编号
|
||||
function handleCopyOrderSn() {
|
||||
copy(orderData.value.orderSn)
|
||||
uni.showToast({
|
||||
title: '已复制',
|
||||
icon: 'success',
|
||||
})
|
||||
}
|
||||
|
||||
// 导航
|
||||
function handleNavigate() {
|
||||
if (orderData.value.latitude && orderData.value.longitude) {
|
||||
uni.openLocation({
|
||||
latitude: orderData.value.latitude,
|
||||
longitude: orderData.value.longitude,
|
||||
name: orderData.value.serviceName,
|
||||
address: orderData.value.address,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 查看订单记录
|
||||
function handleViewOrderRecord() {
|
||||
// 更新订单号
|
||||
orderRecord.value.orderSn = orderData.value.orderSn
|
||||
showOrderRecordPopup.value = true
|
||||
}
|
||||
|
||||
// 查看记录中的照片
|
||||
function handleViewRecordPhoto(photoPath: string) {
|
||||
if (photoPath) {
|
||||
uni.previewImage({
|
||||
current: 0,
|
||||
urls: [photoPath],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 删除订单
|
||||
function handleDeleteOrder() {
|
||||
message.confirm({
|
||||
title: '确定删除订单?',
|
||||
msg: '删除订单后无法恢复,是否确认删除订单?',
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
cancelButtonProps: {
|
||||
customClass: '!bg-[#F6F7F8] !text-[#303133] !text-32rpx !leading-44rpx !rounded-8rpx',
|
||||
},
|
||||
confirmButtonProps: {
|
||||
customClass: '!bg-[#4C9F44] !text-[#fff] !text-32rpx !leading-44rpx !rounded-8rpx',
|
||||
},
|
||||
}).then((res) => {
|
||||
if (res.action === 'confirm') {
|
||||
// TODO: 调用删除订单的 API
|
||||
console.log('确认删除订单')
|
||||
uni.showToast({
|
||||
title: '删除订单成功',
|
||||
icon: 'success',
|
||||
})
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 1500)
|
||||
}
|
||||
}).catch(() => {
|
||||
console.log('取消删除订单')
|
||||
})
|
||||
}
|
||||
|
||||
onLoad((args) => {
|
||||
// 从路由参数获取订单ID
|
||||
if (args.id) {
|
||||
// TODO: 根据ID获取订单详情
|
||||
console.log('订单ID:', args.id)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="cancelled-order-detail-page" :class="{ 'popup-open': showOrderRecordPopup }">
|
||||
<!-- 消息提示框 -->
|
||||
<wd-message-box selector="wd-message-box-slot" />
|
||||
|
||||
<!-- 导航栏 -->
|
||||
<navbar title="订单取消" custom-class="!bg-[#F6F7F8]" />
|
||||
|
||||
<scroll-view class="content-scroll" scroll-y>
|
||||
<!-- 取消提示消息 -->
|
||||
<view class="cancellation-message">
|
||||
<text class="message-text">订单已取消,期待您下次的精彩服务!</text>
|
||||
</view>
|
||||
|
||||
<!-- 订单卡片 -->
|
||||
<view class="order-card" style="position: relative;">
|
||||
<view class="price-btn" @click.stop>
|
||||
<price-format
|
||||
color="#FFFFFF" :first-size="32" :second-size="32" :subscript-size="24"
|
||||
:price="orderData.price"
|
||||
/>
|
||||
<wd-icon name="arrow-right" size="24rpx" color="#FFFFFF" class="ml-8rpx" />
|
||||
</view>
|
||||
<view class="order-card-header">
|
||||
<view class="order-icon-wrapper">
|
||||
<wd-img
|
||||
width="28rpx" height="28rpx" :src="`${OSS}images/chayishi/order-icon.png`"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</view>
|
||||
<text class="order-card-title">订单</text>
|
||||
</view>
|
||||
<view class="order-card-content">
|
||||
<text class="service-name">{{ orderData.serviceName }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 预约信息 -->
|
||||
<view class="info-section">
|
||||
<view class="section-title">
|
||||
预约信息
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">预约时间:</text>
|
||||
<text class="info-value">{{ orderData.appointmentTimeFull }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">预约时长:</text>
|
||||
<text class="info-value">{{ orderData.duration }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 茶艺服务 -->
|
||||
<view class="info-section">
|
||||
<view class="section-title">
|
||||
茶艺服务
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">服务人数</text>
|
||||
<text class="info-value">{{ orderData.servicePeople }}人</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">预定茶叶</text>
|
||||
<text class="info-value">{{ orderData.teaName }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">茶具使用</text>
|
||||
<text class="info-value">{{ orderData.teawareUsage }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 服务方式 -->
|
||||
<view class="info-card">
|
||||
<view class="info-card-title">
|
||||
服务方式
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">服务方式</text>
|
||||
<text class="info-value">{{ orderData.serviceType }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">服务地址</text>
|
||||
<view class="address-wrapper">
|
||||
<text class="info-value">{{ orderData.address }}</text>
|
||||
<wd-icon name="location" size="32rpx" color="#4C9F44" class="ml-16rpx" @click.stop="handleNavigate" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单记录 -->
|
||||
<view class="info-card order-record-card" @click="handleViewOrderRecord">
|
||||
<view class="order-record-wrapper">
|
||||
<text class="order-record-text">订单记录</text>
|
||||
<wd-icon name="arrow-right" size="24rpx" color="#909399" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单信息 -->
|
||||
<view class="info-card">
|
||||
<view class="info-card-title">
|
||||
订单信息
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">订单编号</text>
|
||||
<view class="order-sn-wrapper">
|
||||
<text class="info-value">{{ orderData.orderSn }}</text>
|
||||
<text class="copy-text" @click.stop="handleCopyOrderSn">|复制</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">交易方式</text>
|
||||
<text class="info-value">{{ orderData.paymentMethod }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">创建时间</text>
|
||||
<text class="info-value">{{ orderData.createTime }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">付款时间</text>
|
||||
<text class="info-value">{{ orderData.payTime }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部占位,避免内容被按钮遮挡 -->
|
||||
<view class="bottom-placeholder" />
|
||||
</scroll-view>
|
||||
|
||||
<!-- 订单记录弹窗 -->
|
||||
<wd-popup
|
||||
v-model="showOrderRecordPopup"
|
||||
lock-scroll
|
||||
custom-style="border-radius: 32rpx 32rpx 0rpx 0rpx;"
|
||||
position="bottom"
|
||||
:z-index="200"
|
||||
:close-on-click-overlay="true"
|
||||
>
|
||||
<view class="order-record-popup">
|
||||
<!-- 关闭按钮 -->
|
||||
<view class="close-btn" @click="showOrderRecordPopup = false">
|
||||
<wd-icon name="close" size="40rpx" color="#303133" />
|
||||
</view>
|
||||
|
||||
<!-- 标题 -->
|
||||
<view class="popup-title">
|
||||
订单记录
|
||||
</view>
|
||||
|
||||
<scroll-view class="record-content" scroll-y>
|
||||
<!-- 订单号 -->
|
||||
<view class="order-sn-display">
|
||||
<text class="order-sn-label">订单号:</text>
|
||||
<text class="order-sn-value">{{ orderRecord.orderSn }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 时间线 -->
|
||||
<view class="timeline-container">
|
||||
<view
|
||||
v-for="(step, index) in orderRecord.steps"
|
||||
:key="step.id"
|
||||
class="timeline-item"
|
||||
>
|
||||
<!-- 时间线节点 -->
|
||||
<view class="timeline-node-wrapper">
|
||||
<view
|
||||
class="timeline-node"
|
||||
:class="{ 'timeline-node-completed': step.status === 'completed', 'timeline-node-pending': step.status === 'pending' }"
|
||||
/>
|
||||
<!-- 连接线(最后一个不显示) -->
|
||||
<view
|
||||
v-if="index < orderRecord.steps.length - 1"
|
||||
class="timeline-line"
|
||||
:class="{ 'timeline-line-completed': step.status === 'completed' }"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 时间线内容 -->
|
||||
<view class="timeline-content">
|
||||
<view class="timeline-step-header">
|
||||
<text class="timeline-step-title">{{ step.title }}</text>
|
||||
<text v-if="step.time" class="timeline-step-time">{{ step.time }}</text>
|
||||
</view>
|
||||
<!-- 照片(如果有) -->
|
||||
<view v-if="step.photo" class="timeline-photo" @click="handleViewRecordPhoto(step.photo)">
|
||||
<wd-img
|
||||
width="120rpx"
|
||||
height="120rpx"
|
||||
:src="step.photo"
|
||||
mode="aspectFill"
|
||||
radius="8rpx"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 确定按钮 -->
|
||||
<view class="record-confirm-btn" @click="showOrderRecordPopup = false">
|
||||
<wd-button
|
||||
type="primary"
|
||||
custom-class="!bg-[#4C9F44] !text-[#fff] !text-32rpx !px-32rpx !h-88rpx !leading-88rpx !rounded-8rpx !w-full"
|
||||
>
|
||||
确定
|
||||
</wd-button>
|
||||
</view>
|
||||
</view>
|
||||
</wd-popup>
|
||||
|
||||
<!-- 底部操作按钮 -->
|
||||
<view class="bottom-actions" @click.stop>
|
||||
<wd-button
|
||||
type="primary"
|
||||
custom-class="!bg-[#FF5951] !text-[#fff] !text-32rpx !px-32rpx !h-88rpx !leading-88rpx !rounded-8rpx !w-full"
|
||||
@click.stop="handleDeleteOrder"
|
||||
>
|
||||
删除订单
|
||||
</wd-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f5f5f5;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.cancelled-order-detail-page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.content-scroll {
|
||||
flex: 1;
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.cancellation-message {
|
||||
padding: 30rpx 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.message-text {
|
||||
font-size: 28rpx;
|
||||
color: #909399;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
|
||||
.price-btn {
|
||||
position: absolute;
|
||||
right: 0rpx;
|
||||
top: 0rpx;
|
||||
width: 200rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #ff5951;
|
||||
padding: 12rpx 24rpx;
|
||||
border-radius: 8rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(255, 89, 81, 0.3);
|
||||
min-width: 140rpx;
|
||||
}
|
||||
|
||||
.order-card {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.order-card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.order-icon-wrapper {
|
||||
position: relative;
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.order-card-title {
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.order-card-content {
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.service-name {
|
||||
font-size: 30rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-section {
|
||||
margin-top: 24rpx;
|
||||
padding-top: 24rpx;
|
||||
border-top: 2rpx solid #f6f7f9;
|
||||
|
||||
&:first-of-type {
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 16rpx;
|
||||
font-size: 28rpx;
|
||||
line-height: 40rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.info-label {
|
||||
color: #909399;
|
||||
margin-right: 16rpx;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
color: #606266;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.info-card-title {
|
||||
font-size: 30rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
margin-bottom: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.address-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.order-sn-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.copy-text {
|
||||
color: #4c9f44;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.order-record-card {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.order-record-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.order-record-text {
|
||||
font-size: 30rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.bottom-placeholder {
|
||||
height: 120rpx;
|
||||
}
|
||||
|
||||
.bottom-actions {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #fff;
|
||||
padding: 20rpx 30rpx;
|
||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
box-shadow: 0 -2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
// 当弹窗打开时,降低底部按钮的 z-index,确保被弹窗遮盖
|
||||
.cancelled-order-detail-page.popup-open .bottom-actions {
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
// 订单记录弹窗样式
|
||||
.order-record-popup {
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
border-radius: 32rpx 32rpx 0 0;
|
||||
max-height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 201;
|
||||
}
|
||||
|
||||
.record-content {
|
||||
flex: 1;
|
||||
padding: 0 30rpx;
|
||||
max-height: calc(80vh - 200rpx);
|
||||
}
|
||||
|
||||
.order-sn-display {
|
||||
padding: 30rpx 0;
|
||||
border-bottom: 2rpx solid #f6f7f9;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.order-sn-label {
|
||||
font-size: 28rpx;
|
||||
color: #909399;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.order-sn-value {
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.timeline-container {
|
||||
padding-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.timeline-item {
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.timeline-node-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-right: 24rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.timeline-node {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
border-radius: 50%;
|
||||
border: 4rpx solid #dcdfe6;
|
||||
background-color: #fff;
|
||||
flex-shrink: 0;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.timeline-node-completed {
|
||||
border-color: #4c9f44;
|
||||
background-color: #4c9f44;
|
||||
}
|
||||
|
||||
.timeline-node-pending {
|
||||
border-color: #dcdfe6;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.timeline-line {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 24rpx;
|
||||
transform: translateX(-50%);
|
||||
width: 2rpx;
|
||||
height: calc(100% + 30rpx);
|
||||
background-color: #dcdfe6;
|
||||
z-index: 1;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
|
||||
.timeline-line-completed {
|
||||
background-color: #4c9f44;
|
||||
}
|
||||
|
||||
.timeline-content {
|
||||
flex: 1;
|
||||
padding-top: 2rpx;
|
||||
}
|
||||
|
||||
.timeline-step-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.timeline-step-title {
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
line-height: 40rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.timeline-step-time {
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
line-height: 34rpx;
|
||||
}
|
||||
|
||||
.timeline-photo {
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
|
||||
.record-confirm-btn {
|
||||
padding: 20rpx 30rpx 30rpx;
|
||||
border-top: 2rpx solid #f6f7f9;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
position: absolute;
|
||||
top: 18rpx;
|
||||
right: 30rpx;
|
||||
z-index: 10;
|
||||
padding: 10rpx;
|
||||
}
|
||||
|
||||
.popup-title {
|
||||
text-align: center;
|
||||
font-size: 36rpx;
|
||||
font-weight: 500;
|
||||
color: #121212;
|
||||
line-height: 50rpx;
|
||||
padding: 50rpx 0 40rpx;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,755 +0,0 @@
|
||||
<route lang="jsonc" type="page">{
|
||||
"needLogin": false,
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}</route>
|
||||
|
||||
|
||||
<template>
|
||||
<view class="pb-100rpx">
|
||||
<!-- 用户订单备注内容 -->
|
||||
<wd-popup v-model="showOrderMarksPopup" lock-scroll custom-style="border-radius: 32rpx 32rpx 0rpx 0rpx;" position="bottom">
|
||||
<view class="relative pb-26rpx">
|
||||
<view class="absolute top-18rpx right-30rpx" @click="showOrderMarksPopup = false">
|
||||
<wd-img width="60rpx" height='60rpx' :src="`${OSS}icon/icon_close.png`"></wd-img>
|
||||
</view>
|
||||
|
||||
<view class="text-36rpx text-[#121212] leading-50rpx text-center pt-50rpx pb-40rpx">订单备注</view>
|
||||
<view>
|
||||
</view>
|
||||
</view>
|
||||
</wd-popup>
|
||||
|
||||
|
||||
<!-- 费用明细弹窗 -->
|
||||
<wd-popup v-model="showCostDetailPopup" lock-scroll custom-style="border-radius: 32rpx 32rpx 0rpx 0rpx;"
|
||||
position="bottom" :z-index="200" :close-on-click-overlay="true">
|
||||
<view class="cost-detail-popup">
|
||||
<!-- 关闭按钮 -->
|
||||
<view class="close-btn" @click="showCostDetailPopup = false">
|
||||
<wd-icon name="close" size="40rpx" color="#303133" />
|
||||
</view>
|
||||
|
||||
<!-- 标题 -->
|
||||
<view class="popup-title">
|
||||
费用明细
|
||||
</view>
|
||||
|
||||
<scroll-view class="cost-content !pb-40rpx" scroll-y :show-scrollbar="false" :enhanced="true">
|
||||
<!-- 订单总额 -->
|
||||
<view class="cost-item">
|
||||
<text class="cost-label">订单总额</text>
|
||||
<text class="cost-value">¥ {{ costDetail.orderTotal.toFixed(2) }}</text>
|
||||
</view>
|
||||
|
||||
<view class="bg-[#FBFBFB] py-24rpx px-30rpx rounded-16rpx">
|
||||
<!-- 服务费 -->
|
||||
<view class="cost-item">
|
||||
<text class="cost-label">服务费</text>
|
||||
<text class="cost-value">¥ {{ costDetail.serviceFee.toFixed(2) }}</text>
|
||||
</view>
|
||||
<view class="cost-sub-item">
|
||||
<text class="cost-sub-label">服务费 (¥ {{ costDetail.serviceFeePerHour }}元/小时)</text>
|
||||
<text class="cost-sub-value">x{{ costDetail.serviceHours }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 车马费 -->
|
||||
<view class="cost-item">
|
||||
<text class="cost-label">车马费</text>
|
||||
<text class="cost-value">¥ {{ costDetail.travelFee.toFixed(2) }}</text>
|
||||
</view>
|
||||
<view class="cost-sub-item">
|
||||
<text class="cost-sub-label">车马费 (¥ {{ costDetail.travelFeePerKm }}元/公里)</text>
|
||||
<text class="cost-sub-value">{{ costDetail.distance }}公里</text>
|
||||
</view>
|
||||
|
||||
<!-- 茶艺服务 -->
|
||||
<view class="cost-item">
|
||||
<text class="cost-label">茶艺服务</text>
|
||||
<text class="cost-value">¥ {{ costDetail.teaServiceFee.toFixed(2) }}</text>
|
||||
</view>
|
||||
<view class="cost-sub-item">
|
||||
<text class="cost-sub-label">{{ costDetail.teaName }}</text>
|
||||
<text class="cost-sub-value">¥ {{ costDetail.teaPrice }}</text>
|
||||
</view>
|
||||
<view class="cost-sub-item">
|
||||
<text class="cost-sub-label">茶具使用</text>
|
||||
<text class="cost-sub-value">¥ {{ costDetail.teawarePrice }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 优惠 -->
|
||||
<view class="cost-item">
|
||||
<text class="cost-label">优惠</text>
|
||||
<text class="cost-value discount">- ¥ {{ costDetail.discount.toFixed(2) }}</text>
|
||||
</view>
|
||||
<view class="cost-sub-item">
|
||||
<text class="cost-sub-label">优惠券</text>
|
||||
<text class="cost-sub-value discount">- ¥ {{ costDetail.couponDiscount }}</text>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 分隔线 -->
|
||||
<view class="cost-divider" />
|
||||
|
||||
<!-- 扣除费用区域 -->
|
||||
<view class="deduct-section rounded-16rpx">
|
||||
<view class="cost-item">
|
||||
<text class="cost-label">扣除费用</text>
|
||||
<text class="cost-value">¥ {{ costDetail.deductFee.toFixed(2) }}</text>
|
||||
</view>
|
||||
<view class="cost-sub-item">
|
||||
<text class="cost-sub-label">平台服务费</text>
|
||||
<text class="cost-sub-value">¥ {{ costDetail.platformFee.toFixed(2) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 实际收入 -->
|
||||
<view class="actual-income">
|
||||
<text class="actual-income-label">实际收入</text>
|
||||
<text class="actual-income-value">¥ {{ costDetail.actualIncome.toFixed(2) }}</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</wd-popup>
|
||||
|
||||
|
||||
<!-- 消息提示框 -->
|
||||
<wd-message-box selector="wd-message-box-slot" />
|
||||
|
||||
<!-- 导航栏 -->
|
||||
<navbar title="待接单" custom-class="!bg-[#F6F7F8]"></navbar>
|
||||
|
||||
<view class="mx-30rpx">
|
||||
<view class="h-374rpx bg-white rounded-16rpx">
|
||||
<!-- 订单卡片 -->
|
||||
<view class="order-card relative">
|
||||
<view class="price-btn" @click.stop="handlePriceClick">
|
||||
<price-format color="#FFFFFF" :first-size="32" :second-size="32" :subscript-size="24"
|
||||
:price="orderData.price" />
|
||||
<wd-icon name="arrow-right" size="24rpx" color="#FFFFFF" class="ml-8rpx" />
|
||||
</view>
|
||||
<view class="order-card-header">
|
||||
<view class="order-icon-wrapper ">
|
||||
<wd-img width="40rpx" height="40rpx" :src="`${OSS}images/chayishi/order-icon.png`"
|
||||
mode="aspectFill" />
|
||||
</view>
|
||||
<text class="order-card-title ml-10rpx">订单</text>
|
||||
</view>
|
||||
<view class="order-card-content ml-50rpx">
|
||||
<text class="service-name">{{ orderData.serviceName }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="border-2rpx border-dashed border-[#E5E5E5]"></view>
|
||||
|
||||
<!-- 预约信息 -->
|
||||
<view class="px-30rpx pt-20rpx pb-40rpx">
|
||||
<view class="info-card-title">
|
||||
预约信息
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">预约时间:</text>
|
||||
<text class="info-value">{{ orderData.appointmentTimeFull }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">预约时长:</text>
|
||||
<text class="info-value">{{ orderData.duration }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 茶艺服务 -->
|
||||
<view class="info-card">
|
||||
<view class="info-card-title">
|
||||
茶艺服务
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">服务人数</text>
|
||||
<text class="info-value">{{ orderData.servicePeople }}人</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">预定茶叶</text>
|
||||
<text class="info-value">{{ orderData.teaName }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">茶具使用</text>
|
||||
<text class="info-value">{{ orderData.teawareUsage }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- TODO 订单备注有内容在显示 -->
|
||||
<view class="bg-[#FFFDF7] px-30rpx py-20rpx rounded-16rpx mt-20rpx" @click="showOrderMarksPopup = true">
|
||||
<view class="info-card-title">
|
||||
<wd-img :src="`${OSS}icon/icon_tips2.png`" width="40rpx" height="40rpx"></wd-img>
|
||||
<view class="ml-12rpx">订单备注</view>
|
||||
</view>
|
||||
<view class="flex items-start">
|
||||
<text class="text-28rpx leading-40rpx text-[#606266]">备注信息</text>
|
||||
<text class="text-28rpx text-[#303133] ml-50rpx line-2 w-450rpx">12311231231231231221231123123123123122123112312312312312212311231231231231221231123123123123122123112312312312312212311231231231231221231123123123123122123112312312312312212311231231231231221231123123123123122</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 服务方式 -->
|
||||
<view class="info-card">
|
||||
<view class="info-card-title">
|
||||
服务方式
|
||||
</view>
|
||||
<view class="info-item flex items-center">
|
||||
<view class="info-label">服务方式</view>
|
||||
<view class="info-value">{{ orderData.serviceType }}</view>
|
||||
</view>
|
||||
<view class="info-item flex items-center">
|
||||
<view class="info-label mt-12rpx">服务地址</view>
|
||||
<view class="address-wrapper flex items-center">
|
||||
<view class="info-value w-200rpx line-1">{{ orderData.address }}</view>
|
||||
<wd-img :src="`${OSS}icon/icon_nav.png`" width="64rpx" height="64rpx" @click.stop="handleNavigate"></wd-img>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单信息 -->
|
||||
<view class="info-card">
|
||||
<view class="info-card-title">
|
||||
订单信息
|
||||
</view>
|
||||
<view class="info-item flex justify-between items-center">
|
||||
<text class="info-label">订单编号</text>
|
||||
<view class="order-sn-wrapper">
|
||||
<text class="info-value">{{ orderData.orderSn }}</text>
|
||||
<text class="copy-text" @click.stop="handleCopyOrderSn">|复制</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-item flex items-center justify-between">
|
||||
<view class="info-label">交易方式</view>
|
||||
<view class="info-value text-right">{{ orderData.paymentMethod }}</view>
|
||||
</view>
|
||||
<view class="info-item flex items-center justify-between">
|
||||
<view class="info-label">创建时间</view>
|
||||
<view class="info-value text-right">{{ orderData.createTime }}</view>
|
||||
</view>
|
||||
<view class="info-item flex items-center justify-between">
|
||||
<view class="info-label">付款时间</view>
|
||||
<view class="info-value text-right">{{ orderData.payTime }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部占位,避免内容被按钮遮挡 -->
|
||||
<view class="bottom-placeholder" />
|
||||
</view>
|
||||
|
||||
<view class="w-full fixed bottom-0 left-0 right-0 bg-white h-152rpx flex justify-between items-center px-58rpx">
|
||||
<view class="w-112rpx h-90rpx text-[#606266] text-28rpx leading-90rpx">放弃接单</view>
|
||||
<view class="w-360rpx h-90rpx bg-[#4C9F44] rounded-8rpx text-[#fff] text-center leading-90rpx">立即接单</view>
|
||||
</view>
|
||||
<!-- 底部操作按钮 -->
|
||||
<!-- <view class="bottom-actions" @click.stop>
|
||||
<wd-button type="default" plain
|
||||
custom-class="!border-[#dcdfe6] !text-[#909399] !bg-[#F6F7F8] !border-2rpx !text-32rpx !px-32rpx !h-88rpx !leading-88rpx !rounded-8rpx !flex-1"
|
||||
@click.stop="handleDecline">
|
||||
放弃接单
|
||||
</wd-button>
|
||||
<wd-button type="primary"
|
||||
custom-class="!bg-[#4C9F44] !text-[#fff] !text-32rpx !px-32rpx !h-88rpx !leading-88rpx !rounded-8rpx !flex-1 !ml-20rpx"
|
||||
@click.stop="handleAccept">
|
||||
立即接单
|
||||
</wd-button>
|
||||
</view> -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useMessage } from 'wot-design-uni'
|
||||
import PriceFormat from '@/components/PriceFormat.vue'
|
||||
import { copy } from '@/utils/tools'
|
||||
|
||||
const OSS = inject('OSS')
|
||||
|
||||
// 订单备注
|
||||
const showOrderMarksPopup = ref<boolean>(false)
|
||||
|
||||
// 消息提示框
|
||||
const message = useMessage('wd-message-box-slot')
|
||||
|
||||
// 费用明细弹窗
|
||||
const showCostDetailPopup = ref(false)
|
||||
|
||||
// 费用明细数据
|
||||
const costDetail = ref({
|
||||
orderTotal: 828.90,
|
||||
serviceFee: 640.00,
|
||||
serviceFeePerHour: 160,
|
||||
serviceHours: 4,
|
||||
travelFee: 30.90,
|
||||
travelFeePerKm: 3.00,
|
||||
distance: 10.3,
|
||||
teaServiceFee: 178.00,
|
||||
teaName: '红茶/绿茶/福鼎白茶/铁观音',
|
||||
teaPrice: 158,
|
||||
teawarePrice: 20,
|
||||
discount: 20.00,
|
||||
couponDiscount: 20,
|
||||
deductFee: 130.00,
|
||||
platformFee: 130.00,
|
||||
actualIncome: 698.90,
|
||||
})
|
||||
|
||||
// 订单数据
|
||||
const orderData = ref({
|
||||
id: 1,
|
||||
serviceName: '苓苑共享茶室空间',
|
||||
serviceType: '到店服务',
|
||||
price: 212.20,
|
||||
appointmentTimeFull: '2025-03-18 09:00-12:00',
|
||||
duration: '3小时',
|
||||
servicePeople: 1,
|
||||
teaName: '福鼎白茶 (3泡)',
|
||||
teawareUsage: '客户自备',
|
||||
notes: '', // 如果为空则不显示备注卡片
|
||||
address: '青浦区仓桥路478号',
|
||||
orderSn: '7327328627526903',
|
||||
paymentMethod: '微信支付',
|
||||
createTime: '2019-05-16 12:20:26',
|
||||
payTime: '2019-05-16 13:20:26',
|
||||
// 倒计时相关(秒)
|
||||
countdownSeconds: 9 * 3600 + 30 * 60 + 48, // 09:30:48
|
||||
})
|
||||
|
||||
// 倒计时
|
||||
const countdownTime = ref('09:30:48')
|
||||
let countdownTimer: any = null
|
||||
|
||||
// 格式化倒计时
|
||||
function formatCountdown(seconds: number) {
|
||||
const hours = Math.floor(seconds / 3600)
|
||||
const minutes = Math.floor((seconds % 3600) / 60)
|
||||
const secs = seconds % 60
|
||||
return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(secs).padStart(2, '0')}`
|
||||
}
|
||||
|
||||
// 开始倒计时
|
||||
function startCountdown() {
|
||||
if (countdownTimer) {
|
||||
clearInterval(countdownTimer)
|
||||
}
|
||||
|
||||
countdownTimer = setInterval(() => {
|
||||
if (orderData.value.countdownSeconds > 0) {
|
||||
orderData.value.countdownSeconds--
|
||||
countdownTime.value = formatCountdown(orderData.value.countdownSeconds)
|
||||
}
|
||||
else {
|
||||
clearInterval(countdownTimer)
|
||||
// 倒计时结束,可以触发自动取消逻辑
|
||||
console.log('订单自动取消')
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
// 复制订单编号
|
||||
function handleCopyOrderSn() {
|
||||
copy(orderData.value.orderSn)
|
||||
uni.showToast({
|
||||
title: '已复制',
|
||||
icon: 'success',
|
||||
})
|
||||
}
|
||||
|
||||
// 导航
|
||||
function handleNavigate() {
|
||||
// TODO: 实现导航功能
|
||||
console.log('导航到:', orderData.value.address)
|
||||
uni.showToast({
|
||||
title: '导航功能待实现',
|
||||
icon: 'none',
|
||||
})
|
||||
}
|
||||
|
||||
// 价格点击(查看详情)
|
||||
function handlePriceClick() {
|
||||
showCostDetailPopup.value = true
|
||||
}
|
||||
|
||||
// 放弃接单
|
||||
function handleDecline() {
|
||||
message.confirm({
|
||||
title: '确定放弃接单?',
|
||||
msg: '放弃接单后无法恢复,确认放弃吗?',
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
cancelButtonProps: {
|
||||
customClass: '!bg-[#F6F7F8] !text-[#303133] !text-32rpx !leading-44rpx !rounded-8rpx',
|
||||
},
|
||||
confirmButtonProps: {
|
||||
customClass: '!bg-[#4C9F44] !text-[#fff] !text-32rpx !leading-44rpx !rounded-8rpx',
|
||||
},
|
||||
}).then((res) => {
|
||||
if (res.action === 'confirm') {
|
||||
// TODO: 调用放弃接单的 API
|
||||
console.log('确认放弃接单')
|
||||
uni.showToast({
|
||||
title: '放弃接单成功',
|
||||
icon: 'success',
|
||||
})
|
||||
// 可以返回上一页
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 1500)
|
||||
}
|
||||
}).catch(() => {
|
||||
console.log('取消放弃接单')
|
||||
})
|
||||
}
|
||||
|
||||
// 立即接单
|
||||
function handleAccept() {
|
||||
// TODO: 调用接单的 API
|
||||
console.log('立即接单')
|
||||
uni.showToast({
|
||||
title: '接单成功',
|
||||
icon: 'success',
|
||||
})
|
||||
// 可以返回上一页
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 1500)
|
||||
}
|
||||
|
||||
onLoad((args) => {
|
||||
// 从路由参数获取订单ID
|
||||
if (args.id) {
|
||||
// TODO: 根据ID获取订单详情
|
||||
console.log('订单ID:', args.id)
|
||||
}
|
||||
// 初始化倒计时
|
||||
countdownTime.value = formatCountdown(orderData.value.countdownSeconds)
|
||||
startCountdown()
|
||||
})
|
||||
|
||||
onUnload(() => {
|
||||
// 清理倒计时
|
||||
if (countdownTimer) {
|
||||
clearInterval(countdownTimer)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: $cz-page-background;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.navbar-right-icons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.content-scroll {
|
||||
flex: 1;
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.countdown-tip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 24rpx 0;
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.countdown-text {
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.countdown-time {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
color: #ff5951;
|
||||
margin: 0 8rpx;
|
||||
}
|
||||
|
||||
.order-card {
|
||||
// background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.order-card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.order-icon-wrapper {
|
||||
position: relative;
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.order-icon-circle {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
border: 2rpx solid #4c9f44;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.order-icon-line {
|
||||
width: 2rpx;
|
||||
height: 12rpx;
|
||||
background-color: #4c9f44;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.order-card-title {
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.order-card-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.service-name {
|
||||
font-size: 30rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.price-btn {
|
||||
position: absolute;
|
||||
right: 0rpx;
|
||||
top: 0rpx;
|
||||
width: 200rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #ff5951;
|
||||
padding: 12rpx 24rpx;
|
||||
border-radius: 8rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(255, 89, 81, 0.3);
|
||||
min-width: 140rpx;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.info-card-title {
|
||||
font-size: 30rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
margin-bottom: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 20rpx;
|
||||
font-size: 28rpx;
|
||||
line-height: 40rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.info-label {
|
||||
color: #909399;
|
||||
margin-right: 16rpx;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
color: #606266;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.address-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.order-sn-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.copy-text {
|
||||
color: #4c9f44;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.bottom-placeholder {
|
||||
height: 120rpx;
|
||||
}
|
||||
|
||||
.bottom-actions {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #fff;
|
||||
padding: 20rpx 30rpx;
|
||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-shadow: 0 -2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
// 当弹窗打开时,降低底部按钮的 z-index,确保被弹窗遮盖
|
||||
.pending-order-detail-page.popup-open .bottom-actions {
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
// 费用明细弹窗样式
|
||||
.cost-detail-popup {
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
border-radius: 32rpx 32rpx 0 0;
|
||||
max-height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 201;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
position: absolute;
|
||||
top: 18rpx;
|
||||
right: 30rpx;
|
||||
z-index: 10;
|
||||
padding: 10rpx;
|
||||
}
|
||||
|
||||
.popup-title {
|
||||
text-align: center;
|
||||
font-size: 36rpx;
|
||||
font-weight: 500;
|
||||
color: #121212;
|
||||
line-height: 50rpx;
|
||||
padding: 50rpx 0 40rpx;
|
||||
}
|
||||
|
||||
.cost-content {
|
||||
flex: 1;
|
||||
padding: 0 30rpx 30rpx;
|
||||
max-height: calc(80vh - 140rpx);
|
||||
}
|
||||
|
||||
.cost-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.cost-label {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
line-height: 42rpx;
|
||||
}
|
||||
|
||||
.cost-value {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
line-height: 42rpx;
|
||||
|
||||
&.discount {
|
||||
color: #4c9f44;
|
||||
}
|
||||
}
|
||||
|
||||
.cost-sub-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-left: 20rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.cost-sub-label {
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
color: #909399;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
|
||||
.cost-sub-value {
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
color: #303133;
|
||||
line-height: 40rpx;
|
||||
|
||||
&.discount {
|
||||
color: #4c9f44;
|
||||
}
|
||||
}
|
||||
|
||||
.cost-divider {
|
||||
height: 2rpx;
|
||||
background-color: #f6f7f9;
|
||||
margin: 30rpx 0;
|
||||
}
|
||||
|
||||
.deduct-section {
|
||||
background-color: #f6f7f9;
|
||||
border-radius: 16rpx;
|
||||
padding: 20rpx;
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
|
||||
.actual-income {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 40rpx;
|
||||
padding-top: 30rpx;
|
||||
}
|
||||
|
||||
.actual-income-label {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
line-height: 42rpx;
|
||||
}
|
||||
|
||||
.actual-income-value {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
line-height: 42rpx;
|
||||
}
|
||||
|
||||
.line-2 {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
word-break: break-all;
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,806 +0,0 @@
|
||||
<route lang="jsonc" type="page">
|
||||
{
|
||||
"needLogin": false,
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useMessage } from 'wot-design-uni'
|
||||
import PriceFormat from '@/components/PriceFormat.vue'
|
||||
import { copy, router } from '@/utils/tools'
|
||||
|
||||
const OSS = inject('OSS')
|
||||
|
||||
// 消息提示框
|
||||
const message = useMessage('wd-message-box-slot')
|
||||
|
||||
// 费用明细弹窗
|
||||
const showCostDetailPopup = ref(false)
|
||||
|
||||
// 费用明细数据
|
||||
const costDetail = ref({
|
||||
orderTotal: 828.90,
|
||||
serviceFee: 640.00,
|
||||
serviceFeePerHour: 160,
|
||||
serviceHours: 4,
|
||||
travelFee: 30.90,
|
||||
travelFeePerKm: 3.00,
|
||||
distance: 10.3,
|
||||
teaServiceFee: 178.00,
|
||||
teaName: '红茶/绿茶/福鼎白茶/铁观音',
|
||||
teaPrice: 158,
|
||||
teawarePrice: 20,
|
||||
discount: 20.00,
|
||||
couponDiscount: 20,
|
||||
deductFee: 130.00,
|
||||
platformFee: 130.00,
|
||||
actualIncome: 698.90,
|
||||
})
|
||||
|
||||
// 订单状态
|
||||
const orderStatus = ref('waiting') // waiting 或 waiting_arrived
|
||||
|
||||
// 订单数据
|
||||
const orderData = ref({
|
||||
id: 2,
|
||||
serviceName: '苓苑共享茶室空间',
|
||||
serviceType: '到店服务',
|
||||
price: 212.20,
|
||||
appointmentTimeFull: '2025-03-18 09:00-12:00',
|
||||
duration: '3小时',
|
||||
servicePeople: 1,
|
||||
teaName: '福鼎白茶 (3泡)',
|
||||
teawareUsage: '客户自备',
|
||||
notes: '这里是客户留言信息部分,客户未留言,隐藏这块信息', // 如果有备注则显示
|
||||
address: '青浦区仓桥路478号',
|
||||
latitude: 31.2304, // 纬度
|
||||
longitude: 121.4737, // 经度
|
||||
distance: 5, // 距离(公里)
|
||||
estimatedTime: 20, // 预计时间(分钟)
|
||||
orderSn: '7327328627526903',
|
||||
paymentMethod: '微信支付',
|
||||
createTime: '2019-05-16 12:20:26',
|
||||
payTime: '2019-05-16 13:20:26',
|
||||
})
|
||||
|
||||
// 价格点击(查看详情)
|
||||
function handlePriceClick() {
|
||||
showCostDetailPopup.value = true
|
||||
}
|
||||
|
||||
// 复制订单编号
|
||||
function handleCopyOrderSn() {
|
||||
copy(orderData.value.orderSn)
|
||||
uni.showToast({
|
||||
title: '已复制',
|
||||
icon: 'success',
|
||||
})
|
||||
}
|
||||
|
||||
// 导航
|
||||
function handleNavigate() {
|
||||
if (orderData.value.latitude && orderData.value.longitude) {
|
||||
uni.openLocation({
|
||||
latitude: orderData.value.latitude,
|
||||
longitude: orderData.value.longitude,
|
||||
name: orderData.value.serviceName,
|
||||
address: orderData.value.address,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 查看订单记录
|
||||
function handleViewOrderRecord() {
|
||||
// TODO: 跳转到订单记录页面
|
||||
console.log('查看订单记录')
|
||||
uni.showToast({
|
||||
title: '订单记录功能待实现',
|
||||
icon: 'none',
|
||||
})
|
||||
}
|
||||
|
||||
// 立即出发/已到达
|
||||
function handleDepart() {
|
||||
if (orderStatus.value === 'waiting') {
|
||||
// TODO: 调用出发的 API
|
||||
console.log('立即出发')
|
||||
uni.showToast({
|
||||
title: '出发成功',
|
||||
icon: 'success',
|
||||
})
|
||||
// 可以返回上一页或跳转到服务中页面
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 1500)
|
||||
}
|
||||
else if (orderStatus.value === 'waiting_arrived') {
|
||||
// 弹出确认到达对话框
|
||||
message.confirm({
|
||||
title: '确定到达',
|
||||
msg: '确认到达后需拍照记录,否则无法开始服务计时',
|
||||
confirmButtonText: '去拍照',
|
||||
cancelButtonText: '取消',
|
||||
cancelButtonProps: {
|
||||
customClass: '!bg-[#F6F7F8] !text-[#303133] !text-32rpx !leading-44rpx !rounded-8rpx',
|
||||
},
|
||||
confirmButtonProps: {
|
||||
customClass: '!bg-[#4C9F44] !text-[#fff] !text-32rpx !leading-44rpx !rounded-8rpx',
|
||||
},
|
||||
}).then((res) => {
|
||||
if (res.action === 'confirm') {
|
||||
// 调用拍照功能
|
||||
handleTakePhoto()
|
||||
}
|
||||
}).catch(() => {
|
||||
// 点击取消按钮
|
||||
console.log('取消到达确认')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 拍照功能
|
||||
function handleTakePhoto() {
|
||||
// #ifdef MP-WEIXIN
|
||||
// 微信小程序使用 chooseMedia
|
||||
uni.chooseMedia({
|
||||
count: 1,
|
||||
mediaType: ['image'],
|
||||
sourceType: ['camera'], // 只使用相机拍照
|
||||
success: (res) => {
|
||||
const file = res.tempFiles[0]
|
||||
if (file) {
|
||||
console.log('拍照成功:', file.tempFilePath)
|
||||
// TODO: 上传照片并调用已到达的 API
|
||||
// 这里可以上传照片到服务器
|
||||
uni.showToast({
|
||||
title: '拍照成功',
|
||||
icon: 'success',
|
||||
})
|
||||
// 跳转到服务中页面,传递照片路径
|
||||
setTimeout(() => {
|
||||
router.navigateTo(`/pages/order/serving-detail?id=${orderData.value.id}&photoPath=${encodeURIComponent(file.tempFilePath)}`)
|
||||
}, 1500)
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('拍照失败:', err)
|
||||
if (err.errMsg && !err.errMsg.includes('cancel')) {
|
||||
uni.showToast({
|
||||
title: '拍照失败',
|
||||
icon: 'none',
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifndef MP-WEIXIN
|
||||
// 非微信小程序使用 chooseImage
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sizeType: ['compressed'],
|
||||
sourceType: ['camera'], // 只使用相机拍照
|
||||
success: (res) => {
|
||||
if (res.tempFilePaths && res.tempFilePaths.length > 0) {
|
||||
console.log('拍照成功:', res.tempFilePaths[0])
|
||||
// TODO: 上传照片并调用已到达的 API
|
||||
// 这里可以上传照片到服务器
|
||||
uni.showToast({
|
||||
title: '拍照成功',
|
||||
icon: 'success',
|
||||
})
|
||||
// 跳转到服务中页面,传递照片路径
|
||||
setTimeout(() => {
|
||||
router.navigateTo(`/pages/order/serving-detail?id=${orderData.value.id}&photoPath=${encodeURIComponent(res.tempFilePaths[0])}`)
|
||||
}, 1500)
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('拍照失败:', err)
|
||||
if (err.errMsg && !err.errMsg.includes('cancel')) {
|
||||
uni.showToast({
|
||||
title: '拍照失败',
|
||||
icon: 'none',
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
|
||||
onLoad((args) => {
|
||||
console.log('args', args)
|
||||
// 从路由参数获取订单ID和状态
|
||||
if (args.id) {
|
||||
// TODO: 根据ID获取订单详情
|
||||
console.log('订单ID:', args.id)
|
||||
}
|
||||
if (args.status) {
|
||||
orderStatus.value = args.status
|
||||
console.log('订单状态:', args.status)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="waiting-service-detail-page" :class="{ 'popup-open': showCostDetailPopup }">
|
||||
<!-- 消息提示框 -->
|
||||
<wd-message-box selector="wd-message-box-slot" />
|
||||
|
||||
<!-- 导航栏 -->
|
||||
<navbar title="待服务" custom-class="!bg-[#F6F7F8]" />
|
||||
|
||||
<scroll-view class="content-scroll" scroll-y>
|
||||
<!-- 提示文字 -->
|
||||
<view class="tip-text">
|
||||
请务必提前确认服务日程,妥善安排好时间
|
||||
</view>
|
||||
|
||||
<!-- 订单卡片 -->
|
||||
<view style="position: relative;" class="order-card">
|
||||
<view class="price-btn" @click.stop="handlePriceClick">
|
||||
<price-format
|
||||
color="#FFFFFF" :first-size="32" :second-size="32" :subscript-size="24"
|
||||
:price="orderData.price"
|
||||
/>
|
||||
<wd-icon name="arrow-right" size="24rpx" color="#FFFFFF" class="ml-8rpx" />
|
||||
</view>
|
||||
<view class="order-card-header">
|
||||
<view class="order-icon-wrapper">
|
||||
<wd-img
|
||||
width="28rpx" height="28rpx" :src="`${OSS}images/chayishi/order-icon.png`"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</view>
|
||||
<text class="order-card-title">订单</text>
|
||||
</view>
|
||||
<view class="order-card-content">
|
||||
<text class="service-name">{{ orderData.serviceName }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 预约信息 -->
|
||||
<view class="info-section">
|
||||
<view class="section-title">
|
||||
预约信息
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">预约时间:</text>
|
||||
<text class="info-value">{{ orderData.appointmentTimeFull }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">预约时长:</text>
|
||||
<text class="info-value">{{ orderData.duration }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 茶艺服务 -->
|
||||
<view class="info-section">
|
||||
<view class="section-title">
|
||||
茶艺服务
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">服务人数</text>
|
||||
<text class="info-value">{{ orderData.servicePeople }}人</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">预定茶叶</text>
|
||||
<text class="info-value">{{ orderData.teaName }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">茶具使用</text>
|
||||
<text class="info-value">{{ orderData.teawareUsage }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单备注 -->
|
||||
<view v-if="orderData.notes" class="info-card">
|
||||
<view class="info-card-title">
|
||||
<wd-icon name="chat" size="32rpx" color="#303133" class="mr-8rpx" />
|
||||
订单备注
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">备注信息</text>
|
||||
<text class="info-value">{{ orderData.notes }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 服务方式 -->
|
||||
<view class="info-card">
|
||||
<view class="info-card-title">
|
||||
服务方式
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">服务方式</text>
|
||||
<text class="info-value">{{ orderData.serviceType }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">服务地址</text>
|
||||
<view class="address-wrapper">
|
||||
<text class="info-value">{{ orderData.address }}</text>
|
||||
<wd-icon name="location" size="32rpx" color="#4C9F44" class="ml-16rpx" @click.stop="handleNavigate" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单记录 -->
|
||||
<view class="info-card order-record-card" @click="handleViewOrderRecord">
|
||||
<view class="order-record-wrapper">
|
||||
<text class="order-record-text">订单记录</text>
|
||||
<wd-icon name="arrow-right" size="24rpx" color="#909399" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单信息 -->
|
||||
<view class="info-card">
|
||||
<view class="info-card-title">
|
||||
订单信息
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">订单编号</text>
|
||||
<view class="order-sn-wrapper">
|
||||
<text class="info-value">{{ orderData.orderSn }}</text>
|
||||
<text class="copy-text" @click.stop="handleCopyOrderSn">|复制</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">交易方式</text>
|
||||
<text class="info-value">{{ orderData.paymentMethod }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">创建时间</text>
|
||||
<text class="info-value">{{ orderData.createTime }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">付款时间</text>
|
||||
<text class="info-value">{{ orderData.payTime }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部占位,避免内容被按钮遮挡 -->
|
||||
<view class="bottom-placeholder" />
|
||||
</scroll-view>
|
||||
|
||||
<!-- 费用明细弹窗 -->
|
||||
<wd-popup
|
||||
v-model="showCostDetailPopup"
|
||||
lock-scroll
|
||||
custom-style="border-radius: 32rpx 32rpx 0rpx 0rpx;"
|
||||
position="bottom"
|
||||
:z-index="200"
|
||||
:close-on-click-overlay="true"
|
||||
>
|
||||
<view class="cost-detail-popup">
|
||||
<!-- 关闭按钮 -->
|
||||
<view class="close-btn" @click="showCostDetailPopup = false">
|
||||
<wd-icon name="close" size="40rpx" color="#303133" />
|
||||
</view>
|
||||
|
||||
<!-- 标题 -->
|
||||
<view class="popup-title">
|
||||
费用明细
|
||||
</view>
|
||||
|
||||
<scroll-view class="cost-content" scroll-y>
|
||||
<!-- 订单总额 -->
|
||||
<view class="cost-item">
|
||||
<text class="cost-label">订单总额</text>
|
||||
<text class="cost-value">¥ {{ costDetail.orderTotal.toFixed(2) }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 服务费 -->
|
||||
<view class="cost-item">
|
||||
<text class="cost-label">服务费</text>
|
||||
<text class="cost-value">¥ {{ costDetail.serviceFee.toFixed(2) }}</text>
|
||||
</view>
|
||||
<view class="cost-sub-item">
|
||||
<text class="cost-sub-label">服务费 (¥ {{ costDetail.serviceFeePerHour }}元/小时)</text>
|
||||
<text class="cost-sub-value">x{{ costDetail.serviceHours }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 车马费 -->
|
||||
<view class="cost-item">
|
||||
<text class="cost-label">车马费</text>
|
||||
<text class="cost-value">¥ {{ costDetail.travelFee.toFixed(2) }}</text>
|
||||
</view>
|
||||
<view class="cost-sub-item">
|
||||
<text class="cost-sub-label">车马费 (¥ {{ costDetail.travelFeePerKm }}元/公里)</text>
|
||||
<text class="cost-sub-value">{{ costDetail.distance }}公里</text>
|
||||
</view>
|
||||
|
||||
<!-- 茶艺服务 -->
|
||||
<view class="cost-item">
|
||||
<text class="cost-label">茶艺服务</text>
|
||||
<text class="cost-value">¥ {{ costDetail.teaServiceFee.toFixed(2) }}</text>
|
||||
</view>
|
||||
<view class="cost-sub-item">
|
||||
<text class="cost-sub-label">{{ costDetail.teaName }}</text>
|
||||
<text class="cost-sub-value">¥ {{ costDetail.teaPrice }}</text>
|
||||
</view>
|
||||
<view class="cost-sub-item">
|
||||
<text class="cost-sub-label">茶具使用</text>
|
||||
<text class="cost-sub-value">¥ {{ costDetail.teawarePrice }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 优惠 -->
|
||||
<view class="cost-item">
|
||||
<text class="cost-label">优惠</text>
|
||||
<text class="cost-value discount">- ¥ {{ costDetail.discount.toFixed(2) }}</text>
|
||||
</view>
|
||||
<view class="cost-sub-item">
|
||||
<text class="cost-sub-label">优惠券</text>
|
||||
<text class="cost-sub-value discount">- ¥ {{ costDetail.couponDiscount }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 分隔线 -->
|
||||
<view class="cost-divider" />
|
||||
|
||||
<!-- 扣除费用区域 -->
|
||||
<view class="deduct-section">
|
||||
<view class="cost-item">
|
||||
<text class="cost-label">扣除费用</text>
|
||||
<text class="cost-value">¥ {{ costDetail.deductFee.toFixed(2) }}</text>
|
||||
</view>
|
||||
<view class="cost-sub-item">
|
||||
<text class="cost-sub-label">平台服务费</text>
|
||||
<text class="cost-sub-value">¥ {{ costDetail.platformFee.toFixed(2) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 实际收入 -->
|
||||
<view class="actual-income">
|
||||
<text class="actual-income-label">实际收入</text>
|
||||
<text class="actual-income-value">¥ {{ costDetail.actualIncome.toFixed(2) }}</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</wd-popup>
|
||||
|
||||
<!-- 底部操作按钮 -->
|
||||
<view class="bottom-actions" @click.stop>
|
||||
<wd-button
|
||||
type="primary"
|
||||
custom-class="!bg-[#4C9F44] !text-[#fff] !text-32rpx !px-32rpx !h-88rpx !leading-88rpx !rounded-8rpx !w-full"
|
||||
@click.stop="handleDepart"
|
||||
>
|
||||
{{ orderStatus === 'waiting_arrived' ? '已到达' : '立即出发' }}
|
||||
</wd-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f5f5f5;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.waiting-service-detail-page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.price-btn {
|
||||
position: absolute;
|
||||
right: 30rpx;
|
||||
top: 0rpx;
|
||||
width: 200rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #ff5951;
|
||||
padding: 12rpx 24rpx;
|
||||
border-radius: 8rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(255, 89, 81, 0.3);
|
||||
min-width: 140rpx;
|
||||
}
|
||||
|
||||
.content-scroll {
|
||||
flex: 1;
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
line-height: 34rpx;
|
||||
padding: 20rpx 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.order-card {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.order-card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.order-icon-wrapper {
|
||||
position: relative;
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.order-card-title {
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.order-card-content {
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.service-name {
|
||||
font-size: 30rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-section {
|
||||
margin-top: 24rpx;
|
||||
padding-top: 24rpx;
|
||||
border-top: 2rpx solid #f6f7f9;
|
||||
|
||||
&:first-of-type {
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 16rpx;
|
||||
font-size: 28rpx;
|
||||
line-height: 40rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.info-label {
|
||||
color: #909399;
|
||||
margin-right: 16rpx;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
color: #606266;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.info-card-title {
|
||||
font-size: 30rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
margin-bottom: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.address-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.order-sn-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.copy-text {
|
||||
color: #4c9f44;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.map-section {
|
||||
margin-top: 20rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.map-container {
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
}
|
||||
|
||||
.map-info {
|
||||
padding: 20rpx 30rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.map-info-text {
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
line-height: 34rpx;
|
||||
}
|
||||
|
||||
.order-record-card {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.order-record-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.order-record-text {
|
||||
font-size: 30rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.bottom-placeholder {
|
||||
height: 120rpx;
|
||||
}
|
||||
|
||||
.bottom-actions {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #fff;
|
||||
padding: 20rpx 30rpx;
|
||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
box-shadow: 0 -2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
// 当弹窗打开时,降低底部按钮的 z-index,确保被弹窗遮盖
|
||||
.waiting-service-detail-page.popup-open .bottom-actions {
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
// 费用明细弹窗样式
|
||||
.cost-detail-popup {
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
border-radius: 32rpx 32rpx 0 0;
|
||||
max-height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 201;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
position: absolute;
|
||||
top: 18rpx;
|
||||
right: 30rpx;
|
||||
z-index: 10;
|
||||
padding: 10rpx;
|
||||
}
|
||||
|
||||
.popup-title {
|
||||
text-align: center;
|
||||
font-size: 36rpx;
|
||||
font-weight: 500;
|
||||
color: #121212;
|
||||
line-height: 50rpx;
|
||||
padding: 50rpx 0 40rpx;
|
||||
}
|
||||
|
||||
.cost-content {
|
||||
flex: 1;
|
||||
padding: 0 30rpx 30rpx;
|
||||
max-height: calc(80vh - 140rpx);
|
||||
}
|
||||
|
||||
.cost-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.cost-label {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
line-height: 42rpx;
|
||||
}
|
||||
|
||||
.cost-value {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
line-height: 42rpx;
|
||||
|
||||
&.discount {
|
||||
color: #4c9f44;
|
||||
}
|
||||
}
|
||||
|
||||
.cost-sub-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-left: 20rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.cost-sub-label {
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
color: #909399;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
|
||||
.cost-sub-value {
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
color: #303133;
|
||||
line-height: 40rpx;
|
||||
|
||||
&.discount {
|
||||
color: #4c9f44;
|
||||
}
|
||||
}
|
||||
|
||||
.cost-divider {
|
||||
height: 2rpx;
|
||||
background-color: #f6f7f9;
|
||||
margin: 30rpx 0;
|
||||
}
|
||||
|
||||
.deduct-section {
|
||||
background-color: #f6f7f9;
|
||||
border-radius: 16rpx;
|
||||
padding: 20rpx;
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
|
||||
.actual-income {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 40rpx;
|
||||
padding-top: 30rpx;
|
||||
}
|
||||
|
||||
.actual-income-label {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
line-height: 42rpx;
|
||||
}
|
||||
|
||||
.actual-income-value {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
line-height: 42rpx;
|
||||
}
|
||||
</style>
|
||||
@ -1,186 +0,0 @@
|
||||
<route lang="jsonc" type="page">{
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}</route>
|
||||
|
||||
<template>
|
||||
<view class="pb-40rpx">
|
||||
<view>
|
||||
<navbar title="设备控制" custom-class='!bg-[#F6F7F8]'></navbar>
|
||||
</view>
|
||||
|
||||
<view class="mt-50rpx mx-40rpx">
|
||||
<view>
|
||||
<view class="font-bold text-36rpx leading-50rpx text-[#303133]">大门</view>
|
||||
<view class="relative mt-30rpx">
|
||||
<wd-img width="670rpx" height="202rpx" :src="`${OSS}images/store/store/image1.png`" mode="aspectFill" />
|
||||
<view class="absolute top-64rpx left-0 px-46rpx flex items-center justify-between w-full">
|
||||
<view class="flex items-center">
|
||||
<wd-img width="96rpx" height="96rpx" :src="`${OSS}images/store/store/image4.png`" mode="aspectFill" />
|
||||
<view class="font-bold text-34rpx leading-48rpx text-[#303133] ml-32rpx">门锁</view>
|
||||
</view>
|
||||
<view class="relative h-64rpx">
|
||||
<wd-img width="224rpx" height="64rpx" :src="`${OSS}images/reserve_room/reserve_room_image5.png`"/>
|
||||
<view
|
||||
class="text-[#4C9F44] font-bold text-32rpx leading-44rpx absolute top-[50%] transform translate-y-[-50%] left-74rpx"
|
||||
v-if="device.is_lock == 1" @click="Device.handleOpenLock('door')">
|
||||
点击开锁
|
||||
</view>
|
||||
<view
|
||||
class="text-[#4C9F44] font-bold text-32rpx leading-44rpx absolute top-[50%] transform translate-y-[-50%] left-74rpx"
|
||||
v-if="device.is_lock == 0">
|
||||
暂无门锁
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="mt-30rpx">
|
||||
<view class="mb-40rpx" v-for="(item, index) in device.roomDevice" :key="index">
|
||||
<view class="font-bold text-36rpx leading-50rpx text-[#303133] mb-30rpx">{{ item.title }}</view>
|
||||
<view class="flex items-center justify-between">
|
||||
<view class="w-240rpx h-280rpx bg-white rounded-32rpx flex flex-col items-center justify-center">
|
||||
<view class="">
|
||||
<wd-img width="90rpx" height="90rpx" :src="`${OSS}images/store/store/image2.png`" mode="aspectFill" />
|
||||
</view>
|
||||
<view class="font-bold text-34rpx text-[#303133] leading-48rpx">门锁</view>
|
||||
<view class="bg-[#4C9F44] rounded-20rpx w-168rpx h-60rpx text-center leading-60rpx text-[#fff] mt-10rpx"
|
||||
@click="Device.handleOpenLock('room', item)">
|
||||
开锁
|
||||
</view>
|
||||
</view>
|
||||
<view class="w-410rpx h-280rpx bg-white rounded-16rpx pl-60rpx pr-34rpx">
|
||||
<view class="flex items-top justify-between px-20rpx py-4rpx pt-40rpx">
|
||||
<wd-img width="90rpx" height="90rpx" :src="`${OSS}images/store/store/image3.png`" mode="aspectFill" />
|
||||
<view class="text-28rpx leading-40rpx text-[#303133] mt-12rpx">{{ item.is_open ? 'OFF' : 'ON' }}</view>
|
||||
</view>
|
||||
<view class="font-bold text-28rpx text-[#303133] leading-40rpx mt-34rpx flex items-center justify-between">
|
||||
<view class="font-bold text-34rpx leading-48rpx text-[#303133]">插座空开</view>
|
||||
<wd-switch v-model="item.is_open" size="48rpx" active-color="#4C9F44" @change="Device.handleToggleSocket($event, item)"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getDeviceList, openLock, openPower } from '@/api/store'
|
||||
import { router } from '@/utils/tools'
|
||||
import { useStoreStore } from '@/store'
|
||||
import { toast } from '@/utils/toast'
|
||||
|
||||
const OSS = inject('OSS')
|
||||
const useStore = useStoreStore()
|
||||
|
||||
// 设备
|
||||
const device = ref({
|
||||
store_id: useStore.defaultStore.id,
|
||||
is_lock: 0, //是否存在大门门锁 0:不存在 1:存在
|
||||
lock_no: '', // 门锁编号
|
||||
roomDevice: [
|
||||
{
|
||||
room_id: 0, // 包间ID
|
||||
title: '', // 包间名称
|
||||
lock_no: '', // 门锁编号
|
||||
is_open: false, //空开状态:后端返回的是 0关闭 1打开,前端转换为数字
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
onLoad((args) => {
|
||||
Device.handleGetDeviceList()
|
||||
})
|
||||
|
||||
onUnload(() => {
|
||||
})
|
||||
|
||||
const Device = {
|
||||
/**
|
||||
* 初始化设备列表
|
||||
*/
|
||||
handleGetDeviceList: async () => {
|
||||
const res = await getDeviceList(useStore.defaultStore.id)
|
||||
device.value = res
|
||||
device.value.roomDevice.map((item) => {
|
||||
item.is_open = Boolean(item.is_open)
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 开门锁
|
||||
* @params type 类型 door:大门门锁 room:包间门锁
|
||||
* @params item 设备项
|
||||
*/
|
||||
handleOpenLock: async (type: string, item: any = null) => {
|
||||
let params = {
|
||||
type: 0,
|
||||
lock_no: '',
|
||||
store_id: device.value.store_id,
|
||||
room_id: 0
|
||||
}
|
||||
if (type === 'door') {
|
||||
params.type = 1
|
||||
params.lock_no = device.value.lock_no
|
||||
} else if (type === 'room') {
|
||||
params.type = 2
|
||||
params.lock_no = item.lock_no
|
||||
params.room_id = item.room_id
|
||||
}
|
||||
|
||||
uni.showLoading({
|
||||
title: '开锁中...',
|
||||
mask: true,
|
||||
})
|
||||
try {
|
||||
uni.hideLoading
|
||||
await openLock(params)
|
||||
Device.handleGetDeviceList()
|
||||
toast.success('开锁成功')
|
||||
} catch(e) {
|
||||
uni.hideLoading
|
||||
toast.info('开锁失败,请稍后重试')
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 插座空开
|
||||
* @params event 事件参数
|
||||
* @params item 设备项
|
||||
*/
|
||||
handleToggleSocket: async (event: {value: boolean}, item: any) => {
|
||||
let params = {
|
||||
device_id: item.device_id,
|
||||
state: Number(event.value),
|
||||
room_id: item.room_id
|
||||
}
|
||||
|
||||
uni.showLoading({
|
||||
title: '操作中...',
|
||||
mask: true,
|
||||
})
|
||||
try {
|
||||
uni.hideLoading
|
||||
await openPower(params)
|
||||
Device.handleGetDeviceList()
|
||||
toast.success('操作成功')
|
||||
} catch(e) {
|
||||
uni.hideLoading
|
||||
toast.info('操作失败,请稍后重试')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: $cz-page-background;
|
||||
}
|
||||
</style>
|
||||
@ -1,179 +0,0 @@
|
||||
<route lang="jsonc" type="page">{
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}</route>
|
||||
|
||||
<template>
|
||||
<view class="pb-40rpx">
|
||||
<view>
|
||||
<navbar title="包间预定" custom-class='!bg-[#F6F7F8]'></navbar>
|
||||
</view>
|
||||
|
||||
<view class="mt-38rpx bg-white rounded-16rpx py-22rpx px-30rpx mx-30rpx">
|
||||
<view class="">
|
||||
<view class="text-26rpx leading-32rpx text-[#606266] mb-20rpx">包厢选择</view>
|
||||
<view class="">
|
||||
<wd-picker :columns="columns" value-key="label" value-name="id" v-model="roomName" use-default-slot @confirm="Reserve.handleConfirmRoom">
|
||||
<wd-input type="text" v-model="roomName" placeholder="请选择包厢" readonly>
|
||||
<template #suffix>
|
||||
<wd-icon name="arrow-down" size="32rpx" color="#D8D8D8"></wd-icon>
|
||||
</template>
|
||||
</wd-input>
|
||||
</wd-picker>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- <view class="mt-22rpx">
|
||||
<view class="text-26rpx leading-32rpx text-[#606266] mb-20rpx">包厢价格</view>
|
||||
<view class="">
|
||||
<wd-input type="text" v-model="form.price" placeholder="请输入包厢价格">
|
||||
<template #prefix>
|
||||
<text class="">¥</text>
|
||||
</template>
|
||||
</wd-input>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<view class="mt-22rpx">
|
||||
<view class="text-26rpx leading-32rpx text-[#606266] mb-20rpx">预定时间</view>
|
||||
<view class="" @click="showBookTimePopup = true">
|
||||
<wd-input type="text" v-model="displayTime" placeholder="请选择预定时间" readonly no-border>
|
||||
<template #suffix>
|
||||
<wd-icon name="arrow-down" size="32rpx" color="#D8D8D8"></wd-icon>
|
||||
</template>
|
||||
</wd-input>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bg-[#4C9F44] w-630rpx h-90rpx text-[#fff] text-center leading-90rpx rounded-8rpx mx-auto mt-50rpx" @click="Reserve.handleConfirm">确定</view>
|
||||
|
||||
<!-- 选择预定时间 -->
|
||||
<booking-time v-model="showBookTimePopup" :day="sevenDay" @selectedTime="Reserve.handleChooseReserveTime"></booking-time>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { router, getCurrentDate } from '@/utils/tools'
|
||||
import type { ITeaSpecialistFuture7DaysResult } from '@/api/types/tea'
|
||||
import { getNext7Days, getTeaRoomDetail } from '@/api/tea-room'
|
||||
import { getAllRoomList, reserveRoom, getRoomDetails } from '@/api/store'
|
||||
import { useStoreStore } from '@/store'
|
||||
import { toast } from '@/utils/toast'
|
||||
|
||||
const useStore = useStoreStore()
|
||||
|
||||
const columns = ref<Array<{label: string, id: number}>>([])
|
||||
|
||||
// 选择预定时间
|
||||
const showBookTimePopup = ref<boolean>(false)
|
||||
const sevenDay = reactive<ITeaSpecialistFuture7DaysResult>({
|
||||
minimum_time: 0,
|
||||
time: []
|
||||
})
|
||||
const reserveTime = ref<any>({})
|
||||
const dayTitle = ref<string>('') // 周三03/18
|
||||
const dayTime = ref<string>('') // 2024-03-18
|
||||
const timeSlots = ref<Array<string>>([]) // 连续选择的预约时间
|
||||
const dayHours = ref<string>('') // 预定时长00:00,00:30
|
||||
const displayTime = ref<string>('') // 2024-03-18,00:00,00:30
|
||||
|
||||
const form = ref({
|
||||
room_id: 0, // 包间ID
|
||||
hours: 0, // 预定小时数
|
||||
timeslot: '', // 预定时间段
|
||||
day_time: '', // 预定日期
|
||||
day_title: '', // 预定日期标题
|
||||
})
|
||||
|
||||
const roomName = ref<string>('')
|
||||
|
||||
onLoad(async (args) => {
|
||||
// 获取包厢列表
|
||||
const res = await getAllRoomList(useStore.defaultStore.id)
|
||||
columns.value = res.list.map((item: any) => ({
|
||||
label: item.title,
|
||||
id: item.id
|
||||
}))
|
||||
})
|
||||
|
||||
onUnload(() => {
|
||||
})
|
||||
|
||||
const Reserve = {
|
||||
/**
|
||||
* 选中包厢
|
||||
* @param params
|
||||
*/
|
||||
handleConfirmRoom: async (item) => {
|
||||
form.value.room_id = item.selectedItems.id
|
||||
const res = await getRoomDetails(form.value.room_id)
|
||||
|
||||
// 预定时间
|
||||
const next7 = await getNext7Days(form.value.room_id, getCurrentDate())
|
||||
Object.assign(sevenDay, next7.data)
|
||||
Object.assign(sevenDay, {minimum_time: res.details.room.hours})
|
||||
},
|
||||
|
||||
/**
|
||||
* 选中预定时间
|
||||
*/
|
||||
handleChooseReserveTime: (params: any) => {
|
||||
reserveTime.value = params
|
||||
timeSlots.value = params.selectedTimestamps
|
||||
dayTitle.value = params.dayTitle
|
||||
dayTime.value = params.dayTime
|
||||
|
||||
const times = params.selectedTime.map(item => {
|
||||
return item.time
|
||||
}).join(',')
|
||||
dayHours.value = times
|
||||
|
||||
displayTime.value = params.dayTime + ',' + times
|
||||
},
|
||||
|
||||
/**
|
||||
* 确认预定
|
||||
*/
|
||||
handleConfirm: async () => {
|
||||
if (!form.value.room_id) {
|
||||
toast.info('请选择包厢')
|
||||
return
|
||||
}
|
||||
|
||||
if (reserveTime.value.length === 0) {
|
||||
toast.info('请选择预定时间')
|
||||
return
|
||||
}
|
||||
|
||||
form.value.hours = reserveTime.value.countSelectedTime
|
||||
form.value.timeslot = timeSlots.value.join(',')
|
||||
form.value.day_time = reserveTime.value.dayTime
|
||||
form.value.day_title = dayTitle.value,
|
||||
|
||||
|
||||
uni.showLoading({
|
||||
title: '操作中...',
|
||||
mask: true
|
||||
})
|
||||
try {
|
||||
await reserveRoom(form.value)
|
||||
uni.hideLoading()
|
||||
toast.info('预定成功')
|
||||
router.navigateBack(1, 500)
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: $cz-page-background;
|
||||
}
|
||||
</style>
|
||||
@ -1,779 +0,0 @@
|
||||
<route lang="jsonc" type="page">{
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}</route>
|
||||
|
||||
<template>
|
||||
<view class="pb-180rpx">
|
||||
<view>
|
||||
<navbar title="修改包间信息" custom-class="!bg-[#fff]" />
|
||||
</view>
|
||||
|
||||
<view class="store-tabs">
|
||||
<wd-tabs v-model="tab" @change="RoomDetail.handleChangeTab">
|
||||
<wd-tab title="基础信息" />
|
||||
<wd-tab title="规格与价格" />
|
||||
<wd-tab title="套餐详情" />
|
||||
<!-- <wd-tab title="购买须知" /> -->
|
||||
</wd-tabs>
|
||||
</view>
|
||||
|
||||
<view class="h-64rpx bg-[#FFF6EB] px-30rpx text-26rpx text-[#111827] font-400 leading-64rpx">
|
||||
带"<text class="text-[#ED2D2D]">*</text>"的为必填项
|
||||
</view>
|
||||
|
||||
<view class="mt-20rpx bg-white p-30rpx">
|
||||
<!-- 基础信息 -->
|
||||
<view v-if="tab === 0">
|
||||
<view class="text-34rpx text-[#303133] font-bold leading-48rpx">
|
||||
基本信息
|
||||
</view>
|
||||
|
||||
<!-- 包间名称 -->
|
||||
<view class="mt-28rpx add-textarea">
|
||||
<view class="mb-20rpx flex items-center">
|
||||
<view class="mr-10rpx text-32rpx text-[#303133] font-bold leading-44rpx">
|
||||
包间名称
|
||||
</view>
|
||||
<view class="flex items-center">
|
||||
<wd-img width="16rpx" height="16rpx" :src="`${OSS}icon/icon_validate.png`" />
|
||||
</view>
|
||||
</view>
|
||||
<wd-input v-model="form.title" no-border placeholder="请输入包间名称" :maxlength="10" show-word-limit
|
||||
custom-class="!bg-[#F6F7F8] !rounded-16rpx !px-28rpx !py-20rpx" />
|
||||
</view>
|
||||
|
||||
<!-- 包间标签 -->
|
||||
<view class="mt-28rpx">
|
||||
<view class="mb-20rpx flex items-center justify-between">
|
||||
<view class="flex items-center">
|
||||
<view class="mr-10rpx text-32rpx text-[#303133] font-bold leading-44rpx">
|
||||
包间标签
|
||||
</view>
|
||||
<view class="flex items-center">
|
||||
<wd-img width="16rpx" height="16rpx" :src="`${OSS}icon/icon_validate.png`" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="text-24rpx text-[#9CA3AF] font-400 leading-34rpx">
|
||||
可选择1~2个标签,每个标签不超过5个字
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex flex-wrap items-center gap-16rpx">
|
||||
<view v-for="(tag, index) in tags" :key="index"
|
||||
class="flex items-center rounded-20rpx bg-[#F6F7F8] px-20rpx py-8rpx">
|
||||
<view class="mr-8rpx text-26rpx text-[#303133] leading-36rpx">
|
||||
{{ tag.label_name }}
|
||||
</view>
|
||||
<wd-icon name="close" size="14px" color="#909399"
|
||||
@click="RoomDetail.handleRemoveTag(index)" />
|
||||
</view>
|
||||
<view v-if="form.tags.length < 2"
|
||||
class="flex items-center border-2rpx border-[#E5E5E5] rounded-20rpx border-dashed px-20rpx py-8rpx"
|
||||
@click="RoomDetail.handleAddTag">
|
||||
<wd-icon name="add" size="16px" color="#909399" class="mr-8rpx" />
|
||||
<view class="text-26rpx text-[#909399] leading-36rpx">
|
||||
添加标签
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 团购视频 -->
|
||||
<!-- <view class="mt-28rpx">
|
||||
<view class="mb-28rpx flex items-center">
|
||||
<view class="mr-10rpx text-32rpx text-[#303133] font-bold leading-44rpx">
|
||||
团购视频
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="form.video" class="relative h-184rpx w-184rpx overflow-hidden rounded-16rpx">
|
||||
<wd-img width="100%" height="100%" :src="form.video.thumb" mode="aspectFill" />
|
||||
<view class="absolute inset-0 flex items-center justify-center">
|
||||
<wd-icon name="play" size="48rpx" color="#fff" />
|
||||
</view>
|
||||
<view
|
||||
class="absolute right-8rpx top-8rpx h-32rpx w-32rpx flex items-center justify-center rounded-full bg-black bg-opacity-50"
|
||||
@click="RoomDetail.handleRemoveVideo">
|
||||
<wd-icon name="close" size="14px" color="#fff" />
|
||||
</view>
|
||||
</view>
|
||||
<wd-upload v-else :file-list="[]" :limit="1" image-mode="scaleToFill" accept="video"
|
||||
:action="action" @change="RoomDetail.handleUploadVideo">
|
||||
<view
|
||||
class="h-184rpx w-184rpx flex flex-col items-center justify-center border-2rpx border-[#E5E5E5] rounded-16rpx border-dashed">
|
||||
<wd-img width="64rpx" height="64rpx" :src="`${OSS}icon/icon_video.png`" mode="aspectFill" />
|
||||
<view class="mt-12rpx text-26rpx text-[#303133] font-400 leading-36rpx">
|
||||
添加视频
|
||||
</view>
|
||||
</view>
|
||||
</wd-upload>
|
||||
</view> -->
|
||||
|
||||
<!-- 包间图片 -->
|
||||
<view class="mt-28rpx">
|
||||
<view class="mb-28rpx flex items-center justify-between">
|
||||
<view class="flex items-center">
|
||||
<view class="mr-10rpx text-32rpx text-[#303133] font-bold leading-44rpx">
|
||||
包间图片
|
||||
</view>
|
||||
<view class="flex items-center">
|
||||
<wd-img width="16rpx" height="16rpx" :src="`${OSS}icon/icon_validate.png`" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="text-26rpx text-[#9CA3AF] font-400 leading-36rpx">
|
||||
可添加1张图片
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex flex-wrap items-center gap-16rpx">
|
||||
<wd-upload
|
||||
:header="{'token': token}"
|
||||
:file-list="fileList"
|
||||
:limit="1"
|
||||
image-mode="scaleToFill"
|
||||
:action="action"
|
||||
@success="RoomDetail.handleUploadSuccess">
|
||||
<wd-img width="184rpx" height="184rpx" :src="form.img || `${OSS}images/store/my/image1.png`" mode="aspectFill" radius="16rpx" />
|
||||
</wd-upload>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 规格与价格 -->
|
||||
<view v-if="tab === 1">
|
||||
<view class="mb-30rpx text-34rpx text-[#303133] font-bold leading-48rpx">
|
||||
规格与价格
|
||||
</view>
|
||||
|
||||
<!-- 价格 -->
|
||||
<view class="mb-28rpx">
|
||||
<view class="mb-20rpx flex items-center">
|
||||
<view class="mr-10rpx text-30rpx text-[#303133] font-bold leading-44rpx">
|
||||
价格
|
||||
</view>
|
||||
<view class="flex items-center">
|
||||
<wd-img width="16rpx" height="16rpx" :src="`${OSS}icon/icon_validate.png`" />
|
||||
</view>
|
||||
</view>
|
||||
<wd-input v-model="form.price" no-border placeholder="价格" type="digit"
|
||||
custom-class="!bg-[#F6F7F8] !rounded-16rpx !px-28rpx !py-20rpx">
|
||||
<template #prefix>
|
||||
<view class="mr-8rpx text-28rpx text-[#303133]">
|
||||
¥
|
||||
</view>
|
||||
</template>
|
||||
</wd-input>
|
||||
</view>
|
||||
|
||||
<!-- 起订时间 -->
|
||||
<view class="mb-28rpx">
|
||||
<view class="mb-20rpx flex items-center justify-between">
|
||||
<view class="flex items-center">
|
||||
<view class="mr-10rpx text-30rpx text-[#303133] font-bold leading-44rpx">
|
||||
起订时间
|
||||
</view>
|
||||
<view class="flex items-center">
|
||||
<wd-img width="16rpx" height="16rpx" :src="`${OSS}icon/icon_validate.png`" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="text-24rpx text-[#9CA3AF] font-400 leading-34rpx">
|
||||
<!-- 范围1~5 -->
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex items-center">
|
||||
<wd-input v-model="form.hours" no-border placeholder="请输入起订时间" type="number" :max="5"
|
||||
:min="1" custom-class="!bg-[#F6F7F8] !rounded-16rpx !px-28rpx !py-20rpx" />
|
||||
<view class="ml-16rpx text-28rpx text-[#303133]">
|
||||
小时
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 库存 -->
|
||||
<!-- <view>
|
||||
<view class="mb-20rpx flex items-center justify-between">
|
||||
<view class="flex items-center">
|
||||
<view class="mr-10rpx text-30rpx text-[#303133] font-bold leading-44rpx">
|
||||
库存
|
||||
</view>
|
||||
<view class="flex items-center">
|
||||
<wd-img width="16rpx" height="16rpx" :src="`${OSS}icon/icon_validate.png`" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="text-24rpx text-[#9CA3AF] font-400 leading-34rpx">
|
||||
输入范围1-999
|
||||
</view>
|
||||
</view>
|
||||
<wd-input v-model="form.inventory" no-border placeholder="请输入库存" type="number" :max="999" :min="1"
|
||||
custom-class="!bg-[#F6F7F8] !rounded-16rpx !px-28rpx !py-20rpx" />
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
<!-- 套餐详情 -->
|
||||
<view v-if="tab === 2">
|
||||
<view class="mb-30rpx text-34rpx text-[#303133] font-bold leading-48rpx">
|
||||
套餐详情
|
||||
</view>
|
||||
|
||||
<!-- 套餐介绍 -->
|
||||
<!-- <view class="add-textarea mb-28rpx">
|
||||
<view class="mb-20rpx flex items-center justify-between">
|
||||
<view class="flex items-center">
|
||||
<view class="mr-10rpx text-30rpx text-[#303133] font-bold leading-44rpx">
|
||||
套餐介绍
|
||||
</view>
|
||||
<view class="flex items-center">
|
||||
<wd-img width="16rpx" height="16rpx" :src="`${OSS}icon/icon_validate.png`" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="text-24rpx text-[#9CA3AF] font-400 leading-34rpx">
|
||||
每条内容之间需要换行输入
|
||||
</view>
|
||||
</view>
|
||||
<wd-textarea v-model="form.packageIntro"
|
||||
custom-class="!rounded-18rpx !border-2rpx !border-[#EFF0EF] !bg-[#F8F9FA] !mt-20rpx"
|
||||
custom-textarea-class="!bg-[#F8F9FA]" placeholder="请输入套餐介绍,每条内容换行输入" />
|
||||
</view> -->
|
||||
|
||||
<!-- 其他说明 -->
|
||||
<view class="add-textarea mt-30rpx">
|
||||
<view class="mb-20rpx flex items-center">
|
||||
<view class="mr-10rpx text-30rpx text-[#303133] font-bold leading-44rpx">
|
||||
其他说明
|
||||
</view>
|
||||
</view>
|
||||
<wd-textarea v-model="form.other_describe"
|
||||
custom-class="!rounded-18rpx !border-2rpx !border-[#EFF0EF] !bg-[#F8F9FA] !mt-20rpx"
|
||||
custom-textarea-class="!bg-[#F8F9FA]" placeholder="请输入其他说明" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 购买须知 -->
|
||||
<view v-if="tab === 3">
|
||||
<!-- <view class="mb-30rpx text-34rpx text-[#303133] font-bold leading-48rpx">
|
||||
购买须知
|
||||
</view> -->
|
||||
|
||||
<!-- 使用人数 -->
|
||||
<!-- <view class="mb-28rpx">
|
||||
<view class="mb-20rpx flex items-center">
|
||||
<view class="mr-10rpx text-30rpx text-[#303133] font-bold leading-44rpx">
|
||||
使用人数
|
||||
</view>
|
||||
<view class="flex items-center">
|
||||
<wd-img width="16rpx" height="16rpx" :src="`${OSS}icon/icon_validate.png`" />
|
||||
</view>
|
||||
</view>
|
||||
<wd-input v-model="form.userCount" no-border placeholder="建议4~6人使用"
|
||||
custom-class="!bg-[#F6F7F8] !rounded-16rpx !px-28rpx !py-20rpx" />
|
||||
</view> -->
|
||||
|
||||
<!-- 退改说明 -->
|
||||
<!-- <view class="add-textarea mt-28rpx">
|
||||
<view class="mb-20rpx flex items-center">
|
||||
<view class="mr-10rpx text-32rpx text-[#303133] font-bold leading-44rpx">
|
||||
退改说明
|
||||
</view>
|
||||
<view class="flex items-center">
|
||||
<wd-img width="16rpx" height="16rpx" :src="`${OSS}icon/icon_validate.png`" />
|
||||
</view>
|
||||
</view>
|
||||
<wd-textarea v-model="form.refundPolicy"
|
||||
custom-class="!rounded-18rpx !border-2rpx !border-[#EFF0EF] !bg-[#F8F9FA] !mt-20rpx"
|
||||
custom-textarea-class="!bg-[#F8F9FA]" placeholder="请输入退改说明" />
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部保存按钮 -->
|
||||
<view class="fixed bottom-0 left-0 right-0 h-152rpx bg-white">
|
||||
<view class="mt-34rpx flex items-center justify-center">
|
||||
<wd-button custom-class="!text-32rpx !w-630rpx !h-90rpx !bg-[#4C9F44] !rounded-8rpx !text-[#fff]"
|
||||
@click="RoomDetail.handleSave">
|
||||
保存
|
||||
</wd-button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 选择标签弹窗 -->
|
||||
<wd-popup v-model="showTagSelectPopup" lock-scroll custom-style="border-radius: 32rpx 32rpx 0rpx 0rpx;"
|
||||
position="bottom" @close="RoomDetail.handleCloseTagSelect">
|
||||
<view class="relative bg-white px-30rpx pb-56rpx pt-50rpx">
|
||||
<!-- 关闭按钮 -->
|
||||
<view class="absolute right-30rpx top-18rpx" @click="RoomDetail.handleCloseTagSelect">
|
||||
<wd-icon name="close" size="20px" color="#C0C4CC" />
|
||||
</view>
|
||||
|
||||
<!-- 标题 -->
|
||||
<view class="mb-40rpx text-center text-36rpx text-[#121212] leading-50rpx">
|
||||
选择标签
|
||||
</view>
|
||||
|
||||
<!-- 我的标签标题和管理/退出管理 -->
|
||||
<view class="mb-20rpx flex items-center justify-between">
|
||||
<view class="text-32rpx text-[#303133] font-bold leading-44rpx">
|
||||
我的标签
|
||||
</view>
|
||||
<view class="text-28rpx text-[#4C9F44] leading-40rpx"
|
||||
@click="isTagManageMode ? RoomDetail.handleExitManagement() : RoomDetail.handleEnterManagement()">
|
||||
{{ isTagManageMode ? '退出管理' : '管理' }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 说明文字 -->
|
||||
<view class="mb-28rpx text-24rpx text-[#9CA3AF] leading-34rpx">
|
||||
可选择1~2个标签, 每个标签不超过5个字
|
||||
</view>
|
||||
|
||||
<!-- 标签列表 -->
|
||||
<view class="flex flex-wrap gap-16rpx">
|
||||
<view v-for="(item, index) in availableTags" :key="item.id"
|
||||
class="flex items-center rounded-20rpx px-20rpx py-8rpx"
|
||||
:class="selectedTags.includes(index) ? 'bg-[#4C9F44]' : 'bg-[#F6F7F8]'"
|
||||
@click="RoomDetail.handleSelectTag(index)">
|
||||
<view class="text-26rpx leading-36rpx"
|
||||
:class="selectedTags.includes(index) ? 'text-[#fff]' : 'text-[#303133]'"
|
||||
:style="{ marginRight: isTagManageMode ? '8rpx' : '0' }">
|
||||
{{ item.label_name }}
|
||||
</view>
|
||||
<wd-icon v-if="isTagManageMode" name="close-circle-filled" size="14px"
|
||||
:color="selectedTags.includes(index) ? '#fff' : '#909399'"
|
||||
@click.stop="RoomDetail.handleRemoveTagFromList(index, $event)" />
|
||||
</view>
|
||||
<!-- 新建标签按钮 -->
|
||||
<view v-if="!isTagManageMode"
|
||||
class="flex items-center border-2rpx border-[#E5E5E5] rounded-20rpx border-dashed px-20rpx py-8rpx"
|
||||
@click="RoomDetail.handleShowCreateTag">
|
||||
<wd-icon name="add" size="16px" color="#909399" class="mr-8rpx" />
|
||||
<view class="text-26rpx text-[#909399] leading-36rpx">
|
||||
新建标签
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 确认按钮 -->
|
||||
<view
|
||||
class="mt-40rpx h-90rpx rounded-8rpx bg-[#4C9F44] text-center text-30rpx text-[#fff] leading-90rpx"
|
||||
:class="isTagManageMode ? 'opacity-0 pointer-events-none' : ''"
|
||||
@click="RoomDetail.handleConfirmTags">
|
||||
确认
|
||||
</view>
|
||||
</view>
|
||||
</wd-popup>
|
||||
|
||||
<!-- 新建标签弹窗 -->
|
||||
<wd-popup v-model="showCreateTagPopup" lock-scroll custom-style="border-radius: 32rpx 32rpx 0rpx 0rpx;"
|
||||
position="bottom" @close="RoomDetail.handleCloseCreateTag">
|
||||
<view class="relative bg-white px-30rpx pb-78rpx pt-50rpx">
|
||||
<!-- 导航栏 -->
|
||||
<view class="mb-40rpx flex items-center justify-between">
|
||||
<view class="flex items-center" @click="RoomDetail.handleCloseCreateTag">
|
||||
<wd-icon name="arrow-left" size="20px" color="#303133" />
|
||||
</view>
|
||||
<view class="text-center text-36rpx text-[#121212] leading-50rpx">
|
||||
新建标签
|
||||
</view>
|
||||
<view class="flex items-center" @click="RoomDetail.handleCloseCreateTag">
|
||||
<wd-icon name="close" size="20px" color="#C0C4CC" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 输入框 -->
|
||||
<view class="mb-40rpx">
|
||||
<wd-input v-model="newTagName" no-border placeholder="标签名称" :maxlength="5"
|
||||
custom-class="!bg-[#F6F7F8] !rounded-16rpx !px-28rpx !py-20rpx" />
|
||||
</view>
|
||||
|
||||
<!-- 完成按钮 -->
|
||||
<view class="h-90rpx rounded-8rpx bg-[#4C9F44] text-center text-30rpx text-[#fff] leading-90rpx"
|
||||
@click="RoomDetail.handleCompleteCreateTag">
|
||||
完成
|
||||
</view>
|
||||
</view>
|
||||
</wd-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getRoomDetails, getRoomLabelList, handleCreateTag, handleDeleteTag, editRoom } from '@/api/store'
|
||||
import { updateUserInfo } from '@/api/user'
|
||||
import { router } from '@/utils/tools'
|
||||
import { toast } from '@/utils/toast'
|
||||
import { useStoreStore } from '@/store'
|
||||
|
||||
const OSS = inject('OSS')
|
||||
const token = ref<string>('') // 用户token
|
||||
const useStore = useStoreStore()
|
||||
|
||||
// tab
|
||||
const tab = ref<number>(0)
|
||||
|
||||
// 上传文件
|
||||
const fileList = ref<any[]>([])
|
||||
const action = import.meta.env.VITE_UPLOAD_BASEURL
|
||||
|
||||
// 标签相关
|
||||
const showTagSelectPopup = ref(false)
|
||||
const showCreateTagPopup = ref(false)
|
||||
const newTagName = ref('')
|
||||
const isTagManageMode = ref(false) // 是否处于管理模式
|
||||
const selectedTags = ref<number[]>([]) // 临时选中的标签,点击确认后才回填到表单
|
||||
// Mock 已有标签列表
|
||||
const availableTags = ref<Array<{
|
||||
id: number
|
||||
label_name: string
|
||||
}>>([
|
||||
{id: 0, label_name: ''}
|
||||
])
|
||||
|
||||
const roomId = ref<number>(0) // 包间ID
|
||||
// 表单
|
||||
const form = reactive({
|
||||
title: '',
|
||||
image: '',
|
||||
tags: [] as string[],
|
||||
price: '',
|
||||
hours: '',
|
||||
video: null as any,
|
||||
other_describe: '',
|
||||
})
|
||||
const tags = ref<Array<{ id: number, label_name: string, index: number }>>([])
|
||||
const roomLabelId = ref<string>('')
|
||||
|
||||
onLoad(async (args) => {
|
||||
token.value = uni.getStorageSync('token')
|
||||
|
||||
roomId.value = args.id || 0
|
||||
await RoomDetail.handleGetRoomDetails()
|
||||
await RoomDetail.handleGetRoomLabels()
|
||||
})
|
||||
|
||||
const RoomDetail = {
|
||||
/**
|
||||
* 初始化信息
|
||||
*/
|
||||
handleGetRoomDetails: async () => {
|
||||
const res = await getRoomDetails(roomId.value)
|
||||
fileList.value = [{url: res.details.room.img, name: res.details.room.img }]
|
||||
roomLabelId.value = res.details.room.label_id
|
||||
|
||||
form.title = res.details.room.title
|
||||
form.image = res.details.room.img
|
||||
form.price = res.details.room.price.toString()
|
||||
form.hours = res.details.room.hours.toString()
|
||||
form.other_describe = res.details.room.other_describe || ''
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取包间标签列表
|
||||
*/
|
||||
handleGetRoomLabels: async () => {
|
||||
|
||||
const res = await getRoomLabelList(useStore.defaultStore.id)
|
||||
availableTags.value = res.list
|
||||
|
||||
if (roomLabelId.value) {
|
||||
const labelIds = roomLabelId.value.split(',').map((id: string) => parseInt(id))
|
||||
tags.value = labelIds.map((id: number) => {
|
||||
const tagIndex = availableTags.value.findIndex(tag => tag.id === id)
|
||||
const tag = availableTags.value[tagIndex]
|
||||
return {
|
||||
id: tag.id,
|
||||
label_name: tag.label_name,
|
||||
index: tagIndex
|
||||
}
|
||||
})
|
||||
|
||||
// 设置已选择的标签
|
||||
selectedTags.value = []
|
||||
labelIds.forEach((id: number) => {
|
||||
const index = availableTags.value.findIndex(tag => tag.id === id)
|
||||
if (index !== -1) {
|
||||
selectedTags.value.push(index)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
console.log("🚀 ~ availableTags.value:", availableTags.value)
|
||||
},
|
||||
|
||||
/**
|
||||
* 切换tab
|
||||
*/
|
||||
handleChangeTab: (e: any) => {
|
||||
tab.value = e.name
|
||||
},
|
||||
|
||||
/**
|
||||
* 添加标签 - 显示选择标签弹窗
|
||||
*/
|
||||
handleAddTag: () => {
|
||||
// 初始化临时选中的标签为当前表单中的标签
|
||||
// selectedTags.value = availableTags.value
|
||||
showTagSelectPopup.value = true
|
||||
},
|
||||
|
||||
/**
|
||||
* 上传图片
|
||||
*/
|
||||
handleUploadSuccess: async (e: any) => {
|
||||
try {
|
||||
const response = JSON.parse(e.file.response)
|
||||
if (response.code) {
|
||||
const avatarUrl = response.data.url
|
||||
await updateUserInfo({ avatar: avatarUrl })
|
||||
form.image = avatarUrl
|
||||
toast.info('图片上传成功')
|
||||
} else {
|
||||
throw new Error('上传失败')
|
||||
}
|
||||
} catch (error) {
|
||||
toast.info('上传失败')
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 关闭选择标签弹窗
|
||||
*/
|
||||
handleCloseTagSelect: () => {
|
||||
showTagSelectPopup.value = false
|
||||
isTagManageMode.value = false // 关闭时重置管理模式
|
||||
// selectedTags.value = [] // 清空临时选中的标签
|
||||
},
|
||||
|
||||
/**
|
||||
* 选择标签(临时选择,不直接修改表单)
|
||||
*/
|
||||
handleSelectTag: (id: number) => {
|
||||
if (isTagManageMode.value) {
|
||||
// 管理模式时,点击标签不进行选择操作
|
||||
return
|
||||
}
|
||||
if (selectedTags.value.includes(id)) {
|
||||
// 如果已选择,则取消选择
|
||||
const index = selectedTags.value.indexOf(id)
|
||||
selectedTags.value.splice(index, 1)
|
||||
}
|
||||
else {
|
||||
// 如果未选择,则添加
|
||||
if (selectedTags.value.length >= 2) {
|
||||
toast.info('最多只能选择2个标签')
|
||||
return
|
||||
}
|
||||
selectedTags.value.push(id)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 从选择列表删除标签
|
||||
*/
|
||||
handleRemoveTagFromList: async (index: number, event: any) => {
|
||||
event.stopPropagation()
|
||||
uni.showLoading({
|
||||
title: '操作中...',
|
||||
mask: true
|
||||
})
|
||||
|
||||
try {
|
||||
const tagId = availableTags.value[index].id
|
||||
availableTags.value.splice(index, 1)
|
||||
await handleDeleteTag(tagId)
|
||||
tags.value = tags.value.filter(tag => tag.id !== tagId)
|
||||
uni.hideLoading()
|
||||
|
||||
toast.info('删除成功')
|
||||
} catch(e) {
|
||||
uni.hideLoading()
|
||||
toast.info('删除失败,请稍后重试')
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 确认选择标签
|
||||
*/
|
||||
handleConfirmTags: () => {
|
||||
tags.value = selectedTags.value.map(index => {
|
||||
return {
|
||||
id: availableTags.value[index].id,
|
||||
label_name: availableTags.value[index].label_name,
|
||||
index
|
||||
}
|
||||
})
|
||||
|
||||
showTagSelectPopup.value = false
|
||||
isTagManageMode.value = false
|
||||
// selectedTags.value = []
|
||||
},
|
||||
|
||||
/**
|
||||
* 进入管理模式
|
||||
*/
|
||||
handleEnterManagement: () => {
|
||||
isTagManageMode.value = true
|
||||
selectedTags.value = []
|
||||
},
|
||||
|
||||
/**
|
||||
* 退出管理模式
|
||||
*/
|
||||
handleExitManagement: () => {
|
||||
isTagManageMode.value = false
|
||||
},
|
||||
|
||||
/**
|
||||
* 显示新建标签弹窗
|
||||
*/
|
||||
handleShowCreateTag: () => {
|
||||
showTagSelectPopup.value = false
|
||||
showCreateTagPopup.value = true
|
||||
},
|
||||
|
||||
/**
|
||||
* 关闭新建标签弹窗
|
||||
*/
|
||||
handleCloseCreateTag: () => {
|
||||
showCreateTagPopup.value = false
|
||||
newTagName.value = ''
|
||||
},
|
||||
|
||||
/**
|
||||
* 完成新建标签
|
||||
*/
|
||||
handleCompleteCreateTag: async () => {
|
||||
const tagName = newTagName.value.trim()
|
||||
if (!tagName) {
|
||||
toast.info('请输入标签名称')
|
||||
return
|
||||
}
|
||||
if (tagName.length > 5) {
|
||||
toast.info('标签不能超过5个字')
|
||||
return
|
||||
}
|
||||
|
||||
uni.showLoading({
|
||||
title: '操作者中...'
|
||||
})
|
||||
try {
|
||||
await handleCreateTag({
|
||||
store_id: useStore.defaultStore.id,
|
||||
label_name: tagName
|
||||
})
|
||||
uni.hideLoading()
|
||||
|
||||
RoomDetail.handleGetRoomLabels()
|
||||
|
||||
showCreateTagPopup.value = false
|
||||
newTagName.value = ''
|
||||
showTagSelectPopup.value = true
|
||||
toast.info('标签创建成功')
|
||||
} catch (e) {
|
||||
uni.hideLoading()
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除标签
|
||||
*/
|
||||
handleRemoveTag: (index: number) => {
|
||||
tags.value.splice(index, 1)
|
||||
},
|
||||
|
||||
/**
|
||||
* 上传视频
|
||||
*/
|
||||
handleUploadVideo: (event: any) => {
|
||||
if (event.fileList && event.fileList.length > 0) {
|
||||
form.video = event.fileList[0]
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除视频
|
||||
*/
|
||||
handleRemoveVideo: () => {
|
||||
form.video = null
|
||||
},
|
||||
|
||||
/**
|
||||
* 保存
|
||||
*/
|
||||
handleSave: async () => {
|
||||
// TODO: 实现保存功能
|
||||
if (!form.title) {
|
||||
toast.info('请输入包间名称')
|
||||
return
|
||||
}
|
||||
|
||||
if (tags.value.length === 0) {
|
||||
toast.info('请选择包间标签')
|
||||
return
|
||||
}
|
||||
|
||||
if (!form.image) {
|
||||
toast.info('请上传团购图片')
|
||||
return
|
||||
}
|
||||
|
||||
if (!form.price) {
|
||||
toast.info('请输入价格')
|
||||
return
|
||||
}
|
||||
|
||||
if (!form.hours) {
|
||||
toast.info('请输入起订时间')
|
||||
return
|
||||
}
|
||||
|
||||
let params = {
|
||||
id: roomId.value,
|
||||
img: form.image,
|
||||
title: form.title,
|
||||
label_id: tags.value.map(tag => tag.id).join(','),
|
||||
price: Number(form.price),
|
||||
hours: Number(form.hours),
|
||||
other_describe: form.other_describe,
|
||||
}
|
||||
|
||||
uni.showLoading({
|
||||
title: '保存中...',
|
||||
mask: true
|
||||
})
|
||||
try {
|
||||
await editRoom(params)
|
||||
uni.hideLoading()
|
||||
toast.info('修改成功')
|
||||
router.navigateBack(1, 500)
|
||||
} catch (e) {
|
||||
toast.info('修改失败,请稍后重试')
|
||||
uni.hideLoading()
|
||||
return
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background: #f6f7f8;
|
||||
}
|
||||
|
||||
|
||||
.store-tabs {
|
||||
:deep() {
|
||||
.wd-tabs__line {
|
||||
background-color: #4c9f44 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-textarea {
|
||||
:deep() {
|
||||
.wd-input__value,
|
||||
.wd-input__count {
|
||||
background: transparent !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,256 +0,0 @@
|
||||
<route lang="jsonc" type="page">{
|
||||
"layout": "default",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}</route>
|
||||
|
||||
<template>
|
||||
<view>
|
||||
<!-- 导航栏 -->
|
||||
<view>
|
||||
<navbar title="包间管理" custom-class="!bg-white" />
|
||||
</view>
|
||||
|
||||
<!-- 房间列表 -->
|
||||
<view class="px-30rpx pb-40rpx pt-30rpx">
|
||||
<mescroll-body ref="mescrollItem0" @init="mescrollInit" @down="downCallback" @up="RoomManage.upCallback" :down="downOption" :up="upOption">
|
||||
|
||||
<view class="grid grid-cols-2 gap-24rpx">
|
||||
<view v-for="(room, index) in list" :key="room.id"
|
||||
class="flex flex-col overflow-hidden rounded-16rpx bg-white"
|
||||
@click="RoomManage.handleClickRoom(room)">
|
||||
<!-- 房间图片 -->
|
||||
<view class="relative aspect-[4/3] w-full h-316rpx">
|
||||
<wd-img width="100%" height="316rpx" :src="room.img" mode="aspectFill" />
|
||||
<!-- 编辑图标覆盖层 -->
|
||||
<view
|
||||
class="absolute right-16rpx top-16rpx h-48rpx w-48rpx flex items-center justify-center rounded-24rpx bg-black bg-opacity-40"
|
||||
@click.stop="RoomManage.handleEditImage(room, $event)">
|
||||
<wd-icon name="edit" size="16px" color="#fff" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 房间信息 -->
|
||||
<view class="flex flex-col p-24rpx">
|
||||
<!-- 房间名称 -->
|
||||
<view class="mb-0rpx text-center text-28rpx text-[#303133] leading-40rpx">
|
||||
{{ room.title }}
|
||||
</view>
|
||||
|
||||
<!-- 状态指示器 -->
|
||||
<view class="flex items-baseline justify-center align-middle" @click.stop="RoomManage.handleEditRoomStatus(room, index)">
|
||||
<!-- 状态点 -->
|
||||
<view class="mr-8rpx h-12rpx w-12rpx flex-shrink-0 rounded-full"
|
||||
:style="{ backgroundColor: RoomManage.handleGetStatusConfig(room.status).color }" />
|
||||
<!-- 状态文字 -->
|
||||
<view class="text-32rpx text-[#303133] leading-34rpx"
|
||||
:style="{ color: RoomManage.handleGetStatusConfig(room.status).color }">
|
||||
{{ RoomManage.handleGetStatusConfig(room.status).text }}
|
||||
</view>
|
||||
<!-- 右箭头 -->
|
||||
<view class="ml-8rpx">
|
||||
<wd-icon name="arrow-right" size="12px" :color="RoomManage.handleGetStatusConfig(room.status).color" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</mescroll-body>
|
||||
</view>
|
||||
|
||||
<!-- 状态修改弹窗 -->
|
||||
<wd-action-sheet v-model="showActionMenu" :actions="actions" @select="RoomManage.handleSelectAction" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
|
||||
import useMescroll from "@/uni_modules/mescroll-uni/hooks/useMescroll.js"
|
||||
import { getRoomList, editRoom } from '@/api/store'
|
||||
import { router } from '@/utils/tools'
|
||||
import { toast } from '@/utils/toast'
|
||||
import { useStoreStore } from '@/store'
|
||||
|
||||
const useStore = useStoreStore()
|
||||
|
||||
// 房间状态枚举
|
||||
enum RoomStatus {
|
||||
WAIT_CLEANING = 1, // 待打扫 - 灰色
|
||||
AVAILABLE = 2, // 空闲中 - 绿色
|
||||
MAINTENANCE = 3, // 维护中 - 红色
|
||||
CLEANING = 4, // 打扫中 - 橙色
|
||||
IN_USE = 5, // 使用中 - 蓝色
|
||||
}
|
||||
|
||||
// 房间状态配置
|
||||
const statusConfig = {
|
||||
[RoomStatus.WAIT_CLEANING]: {
|
||||
text: '待打扫',
|
||||
color: '#818CA9', // 灰色
|
||||
},
|
||||
[RoomStatus.AVAILABLE]: {
|
||||
text: '空闲中',
|
||||
color: '#4C9F44', // 绿色
|
||||
},
|
||||
[RoomStatus.MAINTENANCE]: {
|
||||
text: '维护中',
|
||||
color: '#F65353', // 红色
|
||||
},
|
||||
[RoomStatus.CLEANING]: {
|
||||
text: '打扫中',
|
||||
color: '#F29747', // 橙色
|
||||
},
|
||||
[RoomStatus.IN_USE]: {
|
||||
text: '使用中',
|
||||
color: '#1890FF', // 蓝色
|
||||
},
|
||||
}
|
||||
|
||||
// 房间数据
|
||||
const showActionMenu = ref<boolean>(false)
|
||||
const actions = ref([
|
||||
{
|
||||
name: '待打扫',
|
||||
value: RoomStatus.WAIT_CLEANING
|
||||
},
|
||||
{
|
||||
name: '空闲中',
|
||||
value: RoomStatus.AVAILABLE
|
||||
},
|
||||
{
|
||||
name: '维护中',
|
||||
value: RoomStatus.MAINTENANCE
|
||||
},
|
||||
{
|
||||
name: '打扫中',
|
||||
value: RoomStatus.CLEANING
|
||||
},
|
||||
{
|
||||
name: '使用中',
|
||||
value: RoomStatus.IN_USE
|
||||
}
|
||||
])
|
||||
const selectRoom = ref<{
|
||||
id: number,
|
||||
index: number
|
||||
}>({
|
||||
id: 0,
|
||||
index: -1
|
||||
})
|
||||
|
||||
// mescroll
|
||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom) // 调用mescroll的hook
|
||||
const downOption = {
|
||||
auto: true
|
||||
}
|
||||
const upOption = {
|
||||
auto: true,
|
||||
textNoMore: '~ 已经到底啦 ~', //无更多数据的提示
|
||||
}
|
||||
const orderStatus = ref<string>('')
|
||||
const list = ref<Array<any>>([]) // 茶室列表
|
||||
|
||||
const RoomManage = {
|
||||
/**
|
||||
* 分页加载
|
||||
* @param mescroll
|
||||
*/
|
||||
upCallback: (mescroll) => {
|
||||
// 需要留一下数据为空的时候显示的空数据图标内容
|
||||
const filter = {
|
||||
page: mescroll.num,
|
||||
size: mescroll.size,
|
||||
store_id: useStore.defaultStore.id,
|
||||
}
|
||||
|
||||
getRoomList(filter).then((res) => {
|
||||
const curPageData = res.list || [] // 当前页数据
|
||||
if(mescroll.num == 1) list.value = [] // 第一页需手动制空列表
|
||||
list.value = list.value.concat(curPageData) //追加新数据
|
||||
mescroll.endSuccess(curPageData.length, Boolean(res.more))
|
||||
}).catch(() => {
|
||||
mescroll.endErr() // 请求失败, 结束加载
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 点击房间卡片
|
||||
*/
|
||||
handleClickRoom: (room: any) => {
|
||||
router.navigateTo(`/bundle/tea-room/detail?id=${room.id}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* 点击编辑房间图片
|
||||
*/
|
||||
handleEditImage: (room: any, event: any) => {
|
||||
// event.stopPropagation()
|
||||
// TODO: 实现编辑房间图片功能
|
||||
console.log('编辑房间图片:', room.id)
|
||||
router.navigateTo(`/pages/store/room-detail?id=${room.id}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* 点击更多选项
|
||||
*/
|
||||
handleMore: () => {
|
||||
// TODO: 实现更多选项功能
|
||||
console.log('更多选项')
|
||||
},
|
||||
|
||||
/**
|
||||
* 点击目标图标
|
||||
*/
|
||||
handleTarget: () => {
|
||||
// TODO: 实现目标功能
|
||||
console.log('目标功能')
|
||||
},
|
||||
|
||||
/**
|
||||
* 点击编辑房间状态
|
||||
*/
|
||||
handleEditRoomStatus: (item: any, index: number) => {
|
||||
selectRoom.value.id = item.id
|
||||
selectRoom.value.index = index
|
||||
showActionMenu.value = true
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取房间状态
|
||||
*/
|
||||
handleGetStatusConfig: (status: RoomStatus) => {
|
||||
return statusConfig[status] || statusConfig[RoomStatus.AVAILABLE]
|
||||
},
|
||||
|
||||
/**
|
||||
* 修改房间选择状态
|
||||
*/
|
||||
handleSelectAction: async (action: any) => {
|
||||
uni.showLoading({
|
||||
title: '修改中...'
|
||||
})
|
||||
try {
|
||||
const status = action.item.value
|
||||
await editRoom({
|
||||
id: selectRoom.value.id,
|
||||
status
|
||||
})
|
||||
uni.hideLoading()
|
||||
toast.success('修改状态成功')
|
||||
|
||||
list.value[selectRoom.value.index].status = status
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
toast.info('修改状态失败')
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background: #f6f7f8;
|
||||
}
|
||||
</style>
|
||||
@ -1,102 +0,0 @@
|
||||
<route lang="jsonc" type="page">{
|
||||
"layout": "tabbar",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}</route>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { router } from '@/utils/tools'
|
||||
|
||||
const OSS = inject('OSS')
|
||||
const navbarHeight = inject('navbarHeight')
|
||||
|
||||
console.log(`${OSS}/images/store/store/room.png`)
|
||||
// 功能卡片数据
|
||||
const storeMenus = ref([
|
||||
{
|
||||
id: 1,
|
||||
title: '包间管理',
|
||||
icon: `${OSS}images/store/store/room.png`,
|
||||
path: '/pages/store/room-manage',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '设备控制',
|
||||
icon: `${OSS}images/store/store/device.png`,
|
||||
path: '/pages/store/device',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: '包间预定',
|
||||
icon: `${OSS}images/store/store/bookroom.png`,
|
||||
path: '/pages/store/reserve',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: '订单续订',
|
||||
icon: `${OSS}images/store/store/renew.png`,
|
||||
path: '/pages/store/renew',
|
||||
},
|
||||
])
|
||||
|
||||
const Store = {
|
||||
/**
|
||||
* 点击功能卡片
|
||||
*/
|
||||
handleClickMenu: (item: any) => {
|
||||
router.navigateTo(item.path)
|
||||
},
|
||||
|
||||
/**
|
||||
* 点击更多选项
|
||||
*/
|
||||
handleMore: () => {
|
||||
// TODO: 实现更多选项功能
|
||||
console.log('更多选项')
|
||||
},
|
||||
|
||||
/**
|
||||
* 点击目标图标
|
||||
*/
|
||||
handleTarget: () => {
|
||||
// TODO: 实现目标功能
|
||||
console.log('目标功能')
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view>
|
||||
<!-- 导航栏 -->
|
||||
<view>
|
||||
<navbar title="门店管理" custom-class="!bg-white" />
|
||||
</view>
|
||||
|
||||
<!-- 功能卡片网格 -->
|
||||
<view class="px-30rpx pt-40rpx">
|
||||
<view class="grid grid-cols-2 gap-30rpx">
|
||||
<view v-for="item in storeMenus" :key="item.id"
|
||||
class="flex flex-col items-center rounded-16rpx bg-white p-40rpx"
|
||||
@click="Store.handleClickMenu(item)">
|
||||
<!-- 图标区域 -->
|
||||
<view
|
||||
class="mb-24rpx h-160rpx w-160rpx flex items-center justify-center rounded-16rpx bg-[#F0F9FF]">
|
||||
<wd-img width="120rpx" height="120rpx" :src="item.icon" mode="aspectFit" />
|
||||
</view>
|
||||
<!-- 标题 -->
|
||||
<view class="text-30rpx text-[#303133] leading-42rpx">
|
||||
{{ item.title }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: $cz-page-background;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user