feat(order): 对齐退款流程并支持状态 6 申请退款中
This commit is contained in:
@@ -12,21 +12,35 @@ const STATUS_FILTERS = [
|
||||
{ name: '全部', value: 0 },
|
||||
{ name: '待支付', value: 1 },
|
||||
{ name: '已支付', value: 2 },
|
||||
{ name: '申请退款中', value: 6 },
|
||||
{ name: '已取消', value: 3 },
|
||||
{ name: '已过期', value: 4 },
|
||||
{ name: '已退款', value: 5 },
|
||||
]
|
||||
|
||||
const STATUS_TEXT: Record<number, string> = { 1: '待支付', 2: '已支付', 3: '已取消', 4: '已过期', 5: '已退款' }
|
||||
// 零彩色状态语义:待支付 = 实心黑;已支付/已退款 = 描边;已取消/已过期 = 降透明
|
||||
const STATUS_TEXT: Record<number, string> = { 1: '待支付', 2: '已支付', 3: '已取消', 4: '已过期', 5: '已退款', 6: '申请退款中' }
|
||||
// 零彩色状态语义:待支付/申请退款中 = 实心黑(进行中);已支付/已退款 = 描边;已取消/已过期 = 降透明
|
||||
const STATUS_CLS: Record<number, string> = {
|
||||
1: 'pill--ink',
|
||||
2: 'pill--line',
|
||||
3: 'pill--dim',
|
||||
4: 'pill--dim',
|
||||
5: 'pill--line pill--dim',
|
||||
6: 'pill--ink',
|
||||
}
|
||||
|
||||
// 退款结果轮询间隔:仅在列表存在「申请退款中」订单时才发请求
|
||||
const REFUND_POLL_MS = 10 * 1000
|
||||
|
||||
// 设备是否 iOS:iOS 虚拟支付订单退款需走 App Store(后端返回 71004),前端不展示退款入口
|
||||
const IS_IOS = (() => {
|
||||
try {
|
||||
return wx.getSystemInfoSync().platform === 'ios'
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
})()
|
||||
|
||||
Page({
|
||||
data: {
|
||||
filters: STATUS_FILTERS,
|
||||
@@ -62,19 +76,22 @@ Page({
|
||||
onShow() {
|
||||
this.refresh()
|
||||
this.startCountdown()
|
||||
this.startRefundWatch()
|
||||
},
|
||||
|
||||
onHide() {
|
||||
this.stopCountdown()
|
||||
this.stopRefundWatch()
|
||||
},
|
||||
|
||||
onUnload() {
|
||||
this.stopCountdown()
|
||||
this.stopRefundWatch()
|
||||
},
|
||||
|
||||
refresh() {
|
||||
refresh(): Promise<void> {
|
||||
this.setData({ page: 1, hasMore: true, loading: this.data.list.length === 0 })
|
||||
this.fetchList(1)
|
||||
return this.fetchList(1)
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
@@ -112,7 +129,67 @@ Page({
|
||||
if (changed) this.setData({ list: next })
|
||||
},
|
||||
|
||||
fetchList(page: number) {
|
||||
// ===== 退款结果跟踪:申请退款中的订单只等待结果(不可再次发起退款),定期核对是否已出结果 =====
|
||||
startRefundWatch() {
|
||||
this.stopRefundWatch()
|
||||
;(this as any).refundTimer = setInterval(() => this.pollRefunding(), REFUND_POLL_MS)
|
||||
},
|
||||
|
||||
stopRefundWatch() {
|
||||
const timer = (this as any).refundTimer
|
||||
if (timer) {
|
||||
clearInterval(timer)
|
||||
;(this as any).refundTimer = null
|
||||
}
|
||||
},
|
||||
|
||||
// 仅当列表存在「申请退款中」订单时才发请求:命中说明仍未出结果,缺失即视为状态已流转
|
||||
pollRefunding() {
|
||||
const tracked = this.data.list.filter((it) => it.order_status === 6).map((it) => it.order_no)
|
||||
if (!tracked.length) return
|
||||
request<PagedResult<OrderItem>>({
|
||||
url: '/order',
|
||||
data: { status: 6, page: 1, page_size: 50 },
|
||||
showError: false,
|
||||
})
|
||||
.then((res) => {
|
||||
const still = new Set(normalizePaged<OrderItem>(res).list.map((it) => it.order_no))
|
||||
const changed = tracked.filter((no) => !still.has(no))
|
||||
if (changed.length) this.settleRefundResult(changed)
|
||||
})
|
||||
.catch((e: any) => logger.warn(LOG, '退款结果轮询失败(静默降级), code=', e && e.code))
|
||||
},
|
||||
|
||||
// 核对流转后的最新状态并刷新列表:5=退款成功(终态)、2=退款未通过可重新申请;仍为 6 则继续等待
|
||||
settleRefundResult(orderNos: string[]) {
|
||||
request<PagedResult<OrderItem>>({ url: '/order', data: { page: 1, page_size: 50 }, showError: false })
|
||||
.then((res) => {
|
||||
const list = normalizePaged<OrderItem>(res).list
|
||||
orderNos.forEach((no) => {
|
||||
const latest = list.find((it) => it.order_no === no)
|
||||
if (!latest) {
|
||||
logger.warn(LOG, '退款结果核对:未定位到订单最新状态,仅刷新列表, orderNo=', no)
|
||||
return
|
||||
}
|
||||
if (latest.order_status === 6) return
|
||||
if (latest.order_status === 5) {
|
||||
logger.info(LOG, '退款成功, orderNo=', no)
|
||||
wx.showToast({ title: '退款成功', icon: 'success' })
|
||||
} else if (latest.order_status === 2) {
|
||||
logger.info(LOG, '退款未通过,可重新申请, orderNo=', no)
|
||||
wx.showToast({ title: '退款未通过,可重新申请', icon: 'none' })
|
||||
} else {
|
||||
logger.info(LOG, '退款状态已更新, orderNo=', no, 'status=', latest.order_status)
|
||||
wx.showToast({ title: '退款状态已更新', icon: 'none' })
|
||||
}
|
||||
})
|
||||
this.refresh()
|
||||
})
|
||||
.catch((e: any) => logger.warn(LOG, '退款结果核对失败(静默降级), code=', e && e.code))
|
||||
},
|
||||
|
||||
// 返回列表请求的 Promise:退款结果核对后需要等列表刷新完成
|
||||
fetchList(page: number): Promise<void> {
|
||||
const params: Record<string, any> = { page, page_size: this.data.pageSize }
|
||||
const filter = this.data.activeFilter
|
||||
if (filter > 0) params.status = filter
|
||||
@@ -122,7 +199,7 @@ Page({
|
||||
;(this as any).reqSeq = seq
|
||||
if (page > 1) this.setData({ loadingMore: true })
|
||||
|
||||
request<PagedResult<OrderItem>>({ url: '/order', data: params })
|
||||
return request<PagedResult<OrderItem>>({ url: '/order', data: params })
|
||||
.then((res) => {
|
||||
if ((this as any).reqSeq !== seq) return
|
||||
const { list: raw, total } = normalizePaged<OrderItem>(res)
|
||||
@@ -138,6 +215,8 @@ Page({
|
||||
_countdown: it.order_status === 1 && it.expire_time > now ? formatCountdown(it.expire_time - now) : '',
|
||||
_benefit: it.member_days > 0 ? `${it.member_days} 天会员` : '',
|
||||
_canCancel: it.order_status === 1 && it.pay_channel !== 2,
|
||||
// 退款入口:仅「已支付」可申请;iOS 虚拟支付订单需走 App Store(后端 71004),不展示入口
|
||||
_canRefund: it.order_status === 2 && !(it.pay_channel === 2 && IS_IOS),
|
||||
_payChannelText: it.pay_channel === 2 ? '虚拟支付' : '',
|
||||
}))
|
||||
const merged = mergePaged(this.data.list, list, page === 1)
|
||||
|
||||
@@ -57,10 +57,18 @@
|
||||
<view class="btn btn--ink btn--sm" data-no="{{item.order_no}}" bindtap="onPay">去支付</view>
|
||||
</block>
|
||||
<block wx:elif="{{item.order_status === 2}}">
|
||||
<view class="btn btn--ghost btn--sm" data-no="{{item.order_no}}" bindtap="onRefund">申请退款</view>
|
||||
<view
|
||||
wx:if="{{item._canRefund}}"
|
||||
class="btn btn--ghost btn--sm"
|
||||
data-no="{{item.order_no}}"
|
||||
bindtap="onRefund"
|
||||
>申请退款</view>
|
||||
</block>
|
||||
<!-- 状态 6「申请退款中」为纯等待态:不提供任何操作入口(不可再次发起退款,后端也拒绝重复申请) -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{item.order_status === 6}}" class="od-note">退款审核中,审核结果将通过站内通知告知</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
@@ -90,6 +90,13 @@
|
||||
font-family: var(--serif);
|
||||
}
|
||||
|
||||
/* 状态 6「申请退款中」纯等待提示(无任何操作入口) */
|
||||
.od-note {
|
||||
margin-top: 18rpx;
|
||||
font-size: 23rpx;
|
||||
color: var(--ink-3);
|
||||
}
|
||||
|
||||
.od-refund-input {
|
||||
margin: 0 var(--pad);
|
||||
width: auto;
|
||||
|
||||
@@ -92,7 +92,7 @@ export interface OrderItem {
|
||||
unit_price: number // 分
|
||||
pay_amount: number // 分
|
||||
pay_channel: number // 1 微信支付 2 虚拟支付
|
||||
order_status: number // 1 待支付 2 已支付 3 已取消 4 已过期 5 已退款
|
||||
order_status: number // 1 待支付 2 已支付 3 已取消 4 已过期 5 已退款 6 申请退款中
|
||||
member_days: number
|
||||
expire_time: number // 秒
|
||||
pay_time: number
|
||||
|
||||
@@ -38,6 +38,7 @@ export enum OrderStatus {
|
||||
CANCELLED = 3, // 已取消
|
||||
EXPIRED = 4, // 已过期
|
||||
REFUNDED = 5, // 已退款
|
||||
REFUNDING = 6, // 申请退款中(纯等待态,不可再次申请退款)
|
||||
}
|
||||
|
||||
// 额度类型
|
||||
|
||||
Reference in New Issue
Block a user