feat(M08-A): 增加权益可视化选择器

This commit is contained in:
Codex
2026-06-25 23:05:11 +08:00
parent 59c4ef330e
commit 47016744d4
11 changed files with 249 additions and 17 deletions
+114 -2
View File
@@ -32,15 +32,82 @@ Page({
packageHoldingId: '',
packageMinutes: '',
packageCreditYuan: '',
benefitLoading: false,
availableCoupons: [],
availablePackages: [],
selectedCouponName: '',
selectedPackageName: '',
},
onLoad(options) {
this.setData({
storeId: options.storeId || '',
roomId: options.roomId || '',
})
this.loadBenefitOptions()
},
updateBenefitField(event) {
async loadBenefitOptions() {
this.setData({ benefitLoading: true })
try {
await ensureLogin()
const response = await request('/profile/benefits')
this.setData({
availableCoupons: (response.data.coupons || [])
.filter((item) => canUseCoupon(item, this.data.storeId, this.data.roomId))
.map(formatCouponOption),
availablePackages: (response.data.packages || [])
.filter((item) => canUsePackage(item, this.data.storeId, this.data.roomId))
.map(formatPackageOption),
})
} catch (error) {
this.setData({ errorMessage: error.message || '权益加载失败' })
} finally {
this.setData({ benefitLoading: false })
}
},
selectCoupon(event) {
const couponGrantId = event.currentTarget.dataset.id || ''
const current = this.data.couponGrantId === couponGrantId
const selected = current
? null
: this.data.availableCoupons.find((item) => item.couponGrantId === couponGrantId)
this.setData({
couponGrantId: current ? '' : couponGrantId,
selectedCouponName: selected ? selected.name : '',
order: null,
payment: null,
successMessage: '',
errorMessage: '',
})
},
selectPackage(event) {
const packageHoldingId = event.currentTarget.dataset.id || ''
const current = this.data.packageHoldingId === packageHoldingId
const selected = current
? null
: this.data.availablePackages.find((item) => item.packageHoldingId === packageHoldingId)
this.setData({
packageHoldingId: current ? '' : packageHoldingId,
selectedPackageName: selected ? selected.name : '',
packageMinutes: selected && selected.remainingMinutes > 0
? String(Math.min(selected.remainingMinutes, this.data.durationMinutes))
: '',
packageCreditYuan: selected && selected.remainingAmountCents > 0
? yuanInput(Math.min(
selected.remainingAmountCents,
this.data.quote?.totalCents || selected.remainingAmountCents
))
: '',
order: null,
payment: null,
successMessage: '',
errorMessage: '',
})
},
updatePackageUsage(event) {
const field = event.currentTarget.dataset.field
if (!field) return
this.setData({
@@ -95,7 +162,52 @@ Page({
if (!this.data.order || !this.data.order.orderId) {
this.setData({ errorMessage: '请先预占订单' })
return
}
}
function canUseCoupon(item, storeId, roomId) {
return item.status === 'AVAILABLE'
&& Number(item.remainingUses || 0) > 0
&& (!item.storeId || String(item.storeId) === String(storeId))
&& (!item.roomId || String(item.roomId) === String(roomId))
}
function canUsePackage(item, storeId, roomId) {
return item.status === 'ACTIVE'
&& (Number(item.remainingMinutes || 0) > 0 || Number(item.remainingAmountCents || 0) > 0)
&& (!item.storeId || String(item.storeId) === String(storeId))
&& (!item.roomId || String(item.roomId) === String(roomId))
}
function formatCouponOption(item) {
const isTime = item.couponType === 'TIME'
return {
...item,
valueText: isTime ? `${item.timeMinutes || 0}分钟` : cents(item.discountAmountCents),
thresholdText: Number(item.minOrderAmountCents || 0) > 0
? `${cents(item.minOrderAmountCents)}可用`
: '无门槛',
scopeText: scopeText(item),
}
}
function formatPackageOption(item) {
return {
...item,
remainingAmountText: cents(item.remainingAmountCents),
scopeText: scopeText(item),
}
}
function scopeText(item) {
if (item.roomId) return `房间 ${item.roomId}`
if (item.roomCategoryId) return `房型 ${item.roomCategoryId}`
if (item.storeId) return `门店 ${item.storeId}`
return item.holidayOnly ? '节假日' : '通用'
}
function yuanInput(centsValue) {
return (Number(centsValue || 0) / 100).toFixed(2)
}
await this.withRequest(async () => {
const response = await request('/payments', {
method: 'POST',