Files
beauty-miniapp-uni/pages/orders/detail.vue
T
2026-06-29 10:54:33 +08:00

256 lines
6.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="container">
<view class="card head">
<view class="row between">
<view
class="st"
:class="{
w: o.status === '待付款',
g: o.status === '已完成',
d: o.status === '已取消',
p: o.status !== '待付款' && o.status !== '已完成' && o.status !== '已取消'
}"
>
{{ o.status }}
</view>
<view class="muted">订单号 {{ o.id }}</view>
</view>
<view class="name">{{ o.projectName }}</view>
<view class="muted meta">{{ typeLabel(o.orderType) }} · ¥{{ o.amount }}</view>
<view class="muted meta" v-if="o.orderType === 'booking'">
{{ o.appointmentDate }} {{ o.appointmentSlot }} · {{ o.technicianName }}
</view>
<view class="muted meta" v-else>剩余次数{{ o.remainingTimes }}</view>
</view>
<view class="card block">
<view class="title">核销码</view>
<view class="code row between">
<view class="c">{{ o.verifyCode }}</view>
<view class="tag" @tap="copy(o.verifyCode)">复制</view>
</view>
<view class="muted hint">到店出示核销码由门店扫码/输码核销此处为原型演示)。</view>
<view class="btn btn-ghost more" @tap="openCode">查看大码</view>
</view>
<view class="card block" v-if="o.note">
<view class="title">备注</view>
<view class="muted">{{ o.note }}</view>
</view>
<view class="actions">
<view v-if="o.status === '待付款'" class="btn btn-primary" @tap="pay">模拟支付</view>
<view v-if="o.status === '待核销'" class="btn btn-primary" @tap="verify">模拟核销</view>
<view v-if="o.orderType === 'booking' && o.status === '待核销'" class="btn btn-ghost" @tap="reschedule">改约</view>
<view v-if="o.status !== '已取消' && o.status !== '已完成'" class="btn btn-ghost" @tap="cancel">取消订单</view>
</view>
<AiFloat />
</view>
</template>
<script>
import AiFloat from '@/components/AiFloat.vue'
import { demoOrders } from '@/common/demoOrders'
function safeJsonParse(s) {
try {
return JSON.parse(s)
} catch (e) {
return null
}
}
const __DBG_URL = 'http://127.0.0.1:7777/event'
export default {
components: { AiFloat },
data() {
return {
order: null
}
},
onLoad(query) {
//#region debug-point orders-detail-load
try {
uni.request({
url: __DBG_URL,
method: 'POST',
timeout: 2000,
data: {
sessionId: 'orders-detail-blank',
runId: 'pre-fix',
hypothesisId: 'H2',
msg: 'orders/detail onLoad',
queryKeys: query ? Object.keys(query) : [],
payloadLen: query && query.payload ? String(query.payload).length : 0
}
})
} catch (e) {}
//#endregion debug-point orders-detail-load
const raw = query.payload ? safeJsonParse(decodeURIComponent(query.payload)) : null
if (raw) this.order = raw
},
computed: {
o() {
return this.order || demoOrders[0] || {}
}
},
onReady() {
//#region debug-point orders-detail-ready
try {
uni.request({
url: __DBG_URL,
method: 'POST',
timeout: 2000,
data: {
sessionId: 'orders-detail-blank',
runId: 'pre-fix',
hypothesisId: 'H2',
msg: 'orders/detail onReady',
hasOrder: !!this.order,
oKeys: this.o ? Object.keys(this.o) : []
}
})
} catch (e) {}
//#endregion debug-point orders-detail-ready
},
onError(err) {
//#region debug-point orders-detail-error
try {
uni.request({
url: __DBG_URL,
method: 'POST',
timeout: 2000,
data: {
sessionId: 'orders-detail-blank',
runId: 'pre-fix',
hypothesisId: 'H2',
msg: 'orders/detail onError',
err: String(err || '')
}
})
} catch (e) {}
//#endregion debug-point orders-detail-error
},
methods: {
typeLabel(t) {
return t === 'booking' ? '预约订单' : '购买卡券'
},
openCode() {
const payload = encodeURIComponent(JSON.stringify(this.o))
uni.navigateTo({ url: `/pages/verify/code?payload=${payload}` })
},
copy(text) {
uni.setClipboardData({ data: text })
},
pay() {
this.order = { ...this.o, status: '待核销', paidAt: Date.now() }
uni.showToast({ title: '支付成功(模拟)', icon: 'none' })
setTimeout(() => {
const payload = encodeURIComponent(JSON.stringify(this.o))
uni.navigateTo({ url: `/pages/verify/code?payload=${payload}` })
}, 200)
},
verify() {
if (this.o.orderType === 'coupon') {
const left = Math.max(0, (this.o.remainingTimes || 0) - 1)
this.order = { ...this.o, remainingTimes: left, status: left === 0 ? '已完成' : '待核销' }
uni.showToast({ title: left === 0 ? '已核销完成' : '核销成功,已扣次', icon: 'none' })
return
}
this.order = { ...this.o, status: '已完成', verifiedAt: Date.now() }
uni.showToast({ title: '已核销完成(模拟)', icon: 'none' })
},
reschedule() {
uni.navigateTo({ url: `/pages/booking/create?projectId=${this.o.projectId}` })
},
cancel() {
uni.showModal({
title: '确认取消',
content: '原型演示:取消后订单状态将变为已取消。',
success: (res) => {
if (!res.confirm) return
this.order = { ...this.o, status: '已取消', canceledAt: Date.now() }
}
})
},
goMember() {
uni.switchTab({ url: '/pages/member/index' })
}
}
}
</script>
<style lang="scss" scoped>
.head {
padding: 24rpx;
}
.st {
padding: 10rpx 14rpx;
border-radius: 999rpx;
font-size: 24rpx;
font-weight: 900;
}
.w {
background: rgba(245, 158, 11, 0.16);
color: #b45309;
}
.p {
background: rgba(59, 130, 246, 0.16);
color: #1d4ed8;
}
.g {
background: rgba(16, 185, 129, 0.16);
color: #047857;
}
.d {
background: rgba(239, 68, 68, 0.12);
color: #b91c1c;
}
.name {
margin-top: 14rpx;
font-size: 38rpx;
font-weight: 950;
}
.meta {
margin-top: 10rpx;
font-size: 26rpx;
}
.block {
padding: 22rpx;
margin-top: 18rpx;
}
.title {
font-weight: 950;
font-size: 30rpx;
margin-bottom: 14rpx;
}
.code {
padding: 16rpx;
border-radius: 18rpx;
background: rgba(17, 24, 39, 0.04);
border: 1rpx dashed rgba(17, 24, 39, 0.18);
}
.c {
font-size: 36rpx;
font-weight: 900;
letter-spacing: 1rpx;
}
.hint {
margin-top: 12rpx;
font-size: 24rpx;
}
.more {
margin-top: 16rpx;
}
.actions {
margin-top: 24rpx;
display: flex;
flex-direction: column;
gap: 16rpx;
}
</style>