173 lines
6.1 KiB
TypeScript
173 lines
6.1 KiB
TypeScript
import apiManager from '../../utils/api'
|
|
import logger from '../../utils/logger'
|
|
|
|
Page({
|
|
data: {
|
|
orders: [] as Array<any>,
|
|
page: 1,
|
|
size: 20,
|
|
total: 0,
|
|
hasMore: true,
|
|
isLoading: false,
|
|
refundDialogVisible: false,
|
|
refundOrderId: '',
|
|
refundAmountCents: 0,
|
|
selectedReasons: [] as Array<string>,
|
|
reasonText: '',
|
|
reasonMax: 200
|
|
},
|
|
|
|
onLoad() {
|
|
this.loadOrders(1)
|
|
},
|
|
|
|
onPullDownRefresh() {
|
|
this.setData({ page: 1 })
|
|
this.loadOrders(1).finally(() => wx.stopPullDownRefresh())
|
|
},
|
|
|
|
onReachBottom() {
|
|
if (this.data.hasMore && !this.data.isLoading) {
|
|
const next = this.data.page + 1
|
|
this.loadOrders(next)
|
|
}
|
|
},
|
|
|
|
async loadOrders(page: number) {
|
|
this.setData({ isLoading: page === 1 })
|
|
try {
|
|
const res = await apiManager.listOrders(page, this.data.size)
|
|
const items = (res.items || []).map((it: any) => ({
|
|
...it,
|
|
displayTime: this.formatTime(it.created_time),
|
|
displayAmount: this.formatAmount(it.amount_cents),
|
|
refund_display: this.formatRefundStatusText(it.refund_status),
|
|
refund_class: this.formatRefundStatusClass(it.refund_status)
|
|
}))
|
|
logger.info(items)
|
|
if (page === 1) {
|
|
this.setData({ orders: items, page, total: res.total || items.length, hasMore: page * this.data.size < (res.total || items.length), isLoading: false })
|
|
} else {
|
|
const merged = [...this.data.orders, ...items]
|
|
this.setData({ orders: merged, page, total: res.total || merged.length, hasMore: page * this.data.size < (res.total || merged.length), isLoading: false })
|
|
}
|
|
} catch (e) {
|
|
this.setData({ isLoading: false })
|
|
wx.showToast({ title: '加载失败', icon: 'none' })
|
|
}
|
|
},
|
|
|
|
formatTime(t: string) {
|
|
try {
|
|
const d = new Date(t)
|
|
const y = d.getFullYear()
|
|
const m = `${d.getMonth() + 1}`.padStart(2, '0')
|
|
const dd = `${d.getDate()}`.padStart(2, '0')
|
|
const hh = `${d.getHours()}`.padStart(2, '0')
|
|
const mm = `${d.getMinutes()}`.padStart(2, '0')
|
|
return `${y}-${m}-${dd} ${hh}:${mm}`
|
|
} catch (_) {
|
|
return t
|
|
}
|
|
},
|
|
|
|
formatAmount(cents: number) {
|
|
if (!cents && cents !== 0) return ''
|
|
return (cents / 100).toFixed(2)
|
|
},
|
|
|
|
formatRefundStatusText(s: string | null | undefined) {
|
|
const v = String(s || '').trim().toUpperCase()
|
|
if (!v) return '未申请退款'
|
|
if (v === 'REFUND') return '已退款'
|
|
if (v === 'FAIL') return '退款失败'
|
|
if (v === 'CLOSED') return '退款已关闭'
|
|
if (v === 'ABNORMAL') return '退款异常'
|
|
return s as string
|
|
},
|
|
|
|
formatRefundStatusClass(s: string | null | undefined) {
|
|
const v = String(s || '').trim().toUpperCase()
|
|
if (v === 'REFUND') return 'status-success'
|
|
if (v === 'FAIL') return 'status-failed'
|
|
if (v === 'CLOSED') return 'status-closed'
|
|
if (v === 'ABNORMAL') return 'status-abnormal'
|
|
return 'status-default'
|
|
},
|
|
|
|
async onRefundTap(e: any) {
|
|
const id = e.currentTarget.dataset.id
|
|
try {
|
|
const detail = await apiManager.getOrderDetail(id)
|
|
const updated = this.data.orders.map((it: any) => it.id === id ? {
|
|
...it,
|
|
refund_status: detail.refund_status || it.refund_status,
|
|
refund_display: this.formatRefundStatusText(detail.refund_status || it.refund_status),
|
|
refund_class: this.formatRefundStatusClass(detail.refund_status || it.refund_status),
|
|
amount_cents: detail.amount_cents ?? it.amount_cents,
|
|
displayAmount: this.formatAmount(detail.amount_cents ?? it.amount_cents),
|
|
refundable_amount_cents: detail.refundable_amount_cents ?? it.refundable_amount_cents,
|
|
displayRefundable: this.formatAmount(detail.refundable_amount_cents ?? 0),
|
|
can_refund: detail.can_refund ?? it.can_refund
|
|
} : it)
|
|
this.setData({ orders: updated })
|
|
if (detail.refund_status) {
|
|
wx.showToast({ title: `退款状态:${detail.refund_status}`, icon: 'none' })
|
|
return
|
|
}
|
|
if (detail.can_refund) {
|
|
this.setData({ refundOrderId: id, refundAmountCents: Number(detail.refundable_amount_cents || 0), selectedReasons: [], reasonText: '', refundDialogVisible: true })
|
|
} else {
|
|
wx.showToast({ title: '当前订单不可退款', icon: 'none' })
|
|
}
|
|
} catch (_) {
|
|
wx.showToast({ title: '获取订单详情失败', icon: 'none' })
|
|
}
|
|
},
|
|
|
|
onReasonGroupChange(e: any) {
|
|
this.setData({ selectedReasons: e.detail.value || [] })
|
|
},
|
|
|
|
onReasonTextInput(e: any) {
|
|
const v = e.detail.value || ''
|
|
const max = this.data.reasonMax
|
|
this.setData({ reasonText: v.length > max ? v.slice(0, max) : v })
|
|
},
|
|
|
|
closeRefundDialog() {
|
|
this.setData({ refundDialogVisible: false })
|
|
},
|
|
|
|
async confirmRefundDialog() {
|
|
const sel = this.data.selectedReasons
|
|
const txt = (this.data.reasonText || '').trim()
|
|
if ((!sel || sel.length === 0) && !txt) {
|
|
wx.showToast({ title: '请至少选择或填写一项理由', icon: 'none' })
|
|
return
|
|
}
|
|
const reason = [...sel, txt].filter(Boolean).join('|')
|
|
try {
|
|
const r = await apiManager.refund(this.data.refundOrderId, reason, this.data.refundAmountCents)
|
|
wx.showToast({ title: '已提交退款申请', icon: 'none' })
|
|
this.setData({ refundDialogVisible: false })
|
|
const outRefundNo = r && (r.out_refund_no || (r.data && r.data.out_refund_no))
|
|
if (outRefundNo) {
|
|
setTimeout(async () => {
|
|
try {
|
|
const s = await apiManager.getRefundStatus(outRefundNo)
|
|
const status = s && (s.status || '')
|
|
const updated = this.data.orders.map((it: any) => it.id === this.data.refundOrderId ? { ...it, refund_status: status, refund_display: this.formatRefundStatusText(status), refund_class: this.formatRefundStatusClass(status), can_refund: false } : it)
|
|
this.setData({ orders: updated })
|
|
wx.showToast({ title: status ? `退款状态:${status}` : '查询成功', icon: 'none' })
|
|
} catch (_) {
|
|
wx.showToast({ title: '查询失败', icon: 'none' })
|
|
}
|
|
}, 1000)
|
|
}
|
|
} catch (e) {
|
|
wx.showToast({ title: '提交失败', icon: 'none' })
|
|
}
|
|
}
|
|
})
|