初始化
This commit is contained in:
@@ -0,0 +1,233 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="card filters">
|
||||
<view class="row sc">
|
||||
<view v-for="s in tabs" :key="s.value" class="chip" :class="{ on: s.value === active }" hover-class="none" @tap="setActive(s.value)">
|
||||
{{ s.label }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="list">
|
||||
<view v-for="c in viewList" :key="c.id" class="card item" @tap="open(c.id)">
|
||||
<view class="row between">
|
||||
<view class="n">{{ c.projectName }}</view>
|
||||
<view class="tag">剩余 {{ c.remainingTimes }}</view>
|
||||
</view>
|
||||
<view class="muted meta">核销码:{{ c.verifyCode }}</view>
|
||||
<view class="muted meta" v-if="c.validText">有效期:{{ c.validText }}</view>
|
||||
<view class="row between meta2">
|
||||
<view class="muted">状态:{{ c.uiStatus }}</view>
|
||||
<view class="amt">¥{{ c.amount }}</view>
|
||||
</view>
|
||||
<view class="row between ops" v-if="c.uiStatus === '未使用'">
|
||||
<view class="btn btn-ghost ob" @tap.stop="book(c)">去使用(预约)</view>
|
||||
<view class="btn btn-primary ob" @tap.stop="openCode(c)">核销码</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<AiFloat />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AiFloat from '@/components/AiFloat.vue'
|
||||
import { demoOrders } from '@/common/demoOrders'
|
||||
|
||||
function buildCoupons() {
|
||||
const now = Date.now()
|
||||
const extra = [
|
||||
{
|
||||
id: 'cp_demo_unused_001',
|
||||
createdAt: now - 2 * 24 * 60 * 60 * 1000,
|
||||
status: '待核销',
|
||||
amount: 299,
|
||||
projectId: 'p9',
|
||||
projectName: '新客体验套餐 · 3 次',
|
||||
durationMin: 60,
|
||||
orderType: 'coupon',
|
||||
couponTitle: '新客体验套餐 · 3 次',
|
||||
couponPlanKey: 'package',
|
||||
couponPlanLabel: '套餐',
|
||||
validText: '有效期 90 天',
|
||||
remainingTimes: 3,
|
||||
verifyCode: 'VCCP20260621001'
|
||||
},
|
||||
{
|
||||
id: 'cp_demo_pending_001',
|
||||
createdAt: now - 6 * 24 * 60 * 60 * 1000,
|
||||
status: '待付款',
|
||||
amount: 168,
|
||||
projectId: 'p2',
|
||||
projectName: '深层清洁黑头管理',
|
||||
durationMin: 75,
|
||||
orderType: 'coupon',
|
||||
couponTitle: '深层清洁黑头管理',
|
||||
couponPlanKey: 'single',
|
||||
couponPlanLabel: '单次券',
|
||||
validText: '有效期 30 天',
|
||||
remainingTimes: 1,
|
||||
verifyCode: 'VCCP20260621002'
|
||||
},
|
||||
{
|
||||
id: 'cp_demo_used_001',
|
||||
createdAt: now - 18 * 24 * 60 * 60 * 1000,
|
||||
status: '已完成',
|
||||
amount: 899,
|
||||
projectId: 'p5',
|
||||
projectName: '皮肤管理次卡 5 次',
|
||||
durationMin: 60,
|
||||
orderType: 'coupon',
|
||||
couponTitle: '皮肤管理次卡 5 次',
|
||||
couponPlanKey: 'times5',
|
||||
couponPlanLabel: '次卡 5 次',
|
||||
validText: '有效期 180 天',
|
||||
remainingTimes: 0,
|
||||
verifyCode: 'VCCP20260621003'
|
||||
},
|
||||
{
|
||||
id: 'cp_demo_expired_001',
|
||||
createdAt: now - 65 * 24 * 60 * 60 * 1000,
|
||||
status: '已过期',
|
||||
amount: 99,
|
||||
projectId: 'p1',
|
||||
projectName: '水氧净透体验',
|
||||
durationMin: 60,
|
||||
orderType: 'coupon',
|
||||
couponTitle: '水氧净透体验',
|
||||
couponPlanKey: 'single',
|
||||
couponPlanLabel: '单次券',
|
||||
validText: '已过期(原型演示)',
|
||||
remainingTimes: 1,
|
||||
verifyCode: 'VCCP20260621004'
|
||||
}
|
||||
]
|
||||
|
||||
const all = [...demoOrders.filter((x) => x.orderType === 'coupon'), ...extra]
|
||||
return all.map((x) => {
|
||||
const uiStatus = x.status === '待核销' ? '未使用' : x.status === '已完成' ? '已核销' : x.status === '待付款' ? '待付款' : '已过期'
|
||||
const group = uiStatus === '已核销' ? 'used' : uiStatus === '待付款' ? 'pending' : uiStatus === '已过期' ? 'expired' : 'unused'
|
||||
return { ...x, uiStatus, group }
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
components: { AiFloat },
|
||||
data() {
|
||||
const coupons = buildCoupons()
|
||||
const init = coupons.filter((x) => x.group === 'unused')
|
||||
return {
|
||||
tabs: [
|
||||
{ value: 'unused', label: '未使用' },
|
||||
{ value: 'used', label: '已核销' },
|
||||
{ value: 'pending', label: '待付款' },
|
||||
{ value: 'expired', label: '已过期' }
|
||||
],
|
||||
active: 'unused',
|
||||
coupons,
|
||||
viewList: init && init.length ? init : coupons.slice(0, 3)
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.apply()
|
||||
},
|
||||
onShow() {
|
||||
this.coupons = buildCoupons()
|
||||
this.apply()
|
||||
},
|
||||
methods: {
|
||||
apply() {
|
||||
const v = this.coupons.filter((x) => x.group === this.active)
|
||||
this.viewList = v && v.length ? v : this.coupons.slice(0, 3)
|
||||
},
|
||||
setActive(v) {
|
||||
if (!v || v === this.active) return
|
||||
this.active = v
|
||||
this.apply()
|
||||
},
|
||||
open(id) {
|
||||
const c = this.coupons.find((x) => x.id === id) || this.coupons[0]
|
||||
const payload = encodeURIComponent(JSON.stringify(c))
|
||||
uni.navigateTo({ url: `/pages/orders/detail?payload=${payload}` })
|
||||
},
|
||||
book(c) {
|
||||
uni.navigateTo({ url: `/pages/booking/create?projectId=${c.projectId}` })
|
||||
},
|
||||
openCode(c) {
|
||||
const payload = encodeURIComponent(JSON.stringify(c))
|
||||
uni.navigateTo({ url: `/pages/verify/code?payload=${payload}` })
|
||||
},
|
||||
goProjects() {
|
||||
uni.switchTab({ url: '/pages/projects/list' })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.filters {
|
||||
padding: 16rpx;
|
||||
}
|
||||
.sc {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.chip {
|
||||
padding: 14rpx 18rpx;
|
||||
margin-right: 12rpx;
|
||||
border-radius: 999rpx;
|
||||
font-size: 26rpx;
|
||||
background: rgba(17, 24, 39, 0.06);
|
||||
color: #111827;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.on {
|
||||
background: rgba(59, 130, 246, 0.14);
|
||||
color: #1d4ed8;
|
||||
}
|
||||
.empty {
|
||||
margin-top: 18rpx;
|
||||
padding: 26rpx;
|
||||
}
|
||||
.e1 {
|
||||
font-size: 36rpx;
|
||||
font-weight: 950;
|
||||
}
|
||||
.e2 {
|
||||
margin-top: 10rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
.ebtn {
|
||||
margin-top: 18rpx;
|
||||
}
|
||||
.list {
|
||||
margin-top: 18rpx;
|
||||
}
|
||||
.item {
|
||||
padding: 22rpx;
|
||||
margin-bottom: 18rpx;
|
||||
}
|
||||
.n {
|
||||
font-size: 32rpx;
|
||||
font-weight: 950;
|
||||
max-width: 520rpx;
|
||||
}
|
||||
.meta {
|
||||
margin-top: 12rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
.meta2 {
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
.ops {
|
||||
margin-top: 16rpx;
|
||||
gap: 14rpx;
|
||||
}
|
||||
.ob {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
}
|
||||
.amt {
|
||||
font-weight: 950;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user