ai-c/pages/order-detail/order-detail.js
2026-02-02 18:21:32 +08:00

332 lines
8.5 KiB
JavaScript

// pages/order-detail/order-detail.js
// 订单详情页面 - 对接后端API
const api = require('../../utils/api')
// 评价标签预设
const REVIEW_TAGS = [
'专业', '耐心', '温暖', '有效果', '善于倾听',
'有同理心', '高效', '支持', '不评判', '细心',
'温柔', '有帮助', '值得信赖', '回复及时'
]
Page({
data: {
statusBarHeight: 44,
navBarHeight: 44,
totalNavHeight: 88,
loading: true,
order: null,
// 评价弹窗相关
showReviewModal: false,
reviewRating: 5,
reviewContent: '',
reviewTags: REVIEW_TAGS,
selectedTags: [],
isAnonymous: false,
submittingReview: false
},
onLoad(options) {
const systemInfo = wx.getSystemInfoSync()
const statusBarHeight = systemInfo.statusBarHeight || 44
const menuButton = wx.getMenuButtonBoundingClientRect()
const navBarHeight = menuButton.height + (menuButton.top - statusBarHeight) * 2
const totalNavHeight = statusBarHeight + navBarHeight
const orderId = options.id
this.setData({
statusBarHeight,
navBarHeight,
totalNavHeight
})
if (orderId) {
this.loadOrderDetail(orderId)
} else {
wx.showToast({ title: '参数错误', icon: 'none' })
setTimeout(() => wx.navigateBack(), 1500)
}
},
/**
* 加载订单详情
*/
async loadOrderDetail(id) {
this.setData({ loading: true })
try {
const res = await api.order.getDetail(id)
if (res.success && res.data) {
const order = this.transformOrder(res.data)
this.setData({ order, loading: false })
} else {
throw new Error(res.message || '加载失败')
}
} catch (err) {
console.error('加载订单详情失败', err)
this.setData({ loading: false })
wx.showToast({ title: '加载失败', icon: 'none' })
}
},
/**
* 转换订单数据格式
*/
transformOrder(data) {
const typeConfig = {
recharge: { typeName: '爱心充值', icon: '/images/icon-heart.png', iconBg: 'pink' },
vip: { typeName: '会员服务', icon: '/images/icon-star.png', iconBg: 'purple' },
gift: { typeName: '礼物购买', icon: '/images/icon-gift.png', iconBg: 'orange' },
companion: { typeName: '陪聊服务', icon: '/images/icon-chat.png', iconBg: 'blue' }
}
const config = typeConfig[data.type] || typeConfig.recharge
const statusMap = {
pending: '待支付',
paid: '交易成功',
completed: '交易成功',
cancelled: '已取消',
refunded: '已退款',
in_service: '服务中'
}
const statusDescMap = {
pending: '请尽快完成支付',
paid: '您的订单已完成支付',
completed: '订单已完成',
cancelled: '订单已取消',
refunded: '订单已退款',
in_service: '服务进行中'
}
return {
id: data.id,
typeName: config.typeName,
icon: config.icon,
iconBg: config.iconBg,
status: statusMap[data.status] || data.status,
statusDesc: statusDescMap[data.status] || '',
productName: data.product_name || data.description || '',
priceSymbol: data.currency === 'flower' ? '🌿' : '¥',
price: data.amount || data.price || '0',
payMethod: data.payment_method === 'wechat' ? '微信支付' : (data.payment_method === 'flower' ? '爱心支付' : data.payment_method || ''),
orderNo: data.order_no || data.id,
createTime: this.formatTime(data.created_at),
payTime: data.paid_at ? this.formatTime(data.paid_at) : '',
canRefund: data.status === 'paid' && data.can_refund !== false,
canCancel: data.status === 'pending',
canReview: data.status === 'completed' && !data.reviewed
}
},
/**
* 格式化时间
*/
formatTime(dateStr) {
if (!dateStr) return ''
const date = new Date(dateStr)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hour = String(date.getHours()).padStart(2, '0')
const minute = String(date.getMinutes()).padStart(2, '0')
const second = String(date.getSeconds()).padStart(2, '0')
return `${year}-${month}-${day} ${hour}:${minute}:${second}`
},
goBack() {
wx.navigateBack()
},
onCopyOrderNo() {
const { orderNo } = this.data.order
wx.setClipboardData({
data: String(orderNo),
success: () => {
wx.showToast({
title: '已复制订单号',
icon: 'success'
})
}
})
},
onContactService() {
wx.navigateTo({
url: '/pages/service/service'
})
},
/**
* 取消订单
*/
async onCancel() {
const confirmed = await this.showConfirm('取消订单', '确定要取消订单吗?')
if (!confirmed) return
wx.showLoading({ title: '取消中...' })
try {
const res = await api.order.cancel(this.data.order.id)
wx.hideLoading()
if (res.success) {
wx.showToast({ title: '订单已取消', icon: 'success' })
// 刷新订单详情
this.loadOrderDetail(this.data.order.id)
} else {
wx.showToast({ title: res.message || '取消失败', icon: 'none' })
}
} catch (err) {
wx.hideLoading()
wx.showToast({ title: '取消失败', icon: 'none' })
}
},
/**
* 申请退款
*/
async onRefund() {
const confirmed = await this.showConfirm('申请退款', '确定要申请退款吗?')
if (!confirmed) return
wx.showLoading({ title: '提交中...' })
try {
const res = await api.order.cancel(this.data.order.id, '用户申请退款')
wx.hideLoading()
if (res.success) {
wx.showToast({ title: '退款申请已提交', icon: 'success' })
this.loadOrderDetail(this.data.order.id)
} else {
wx.showToast({ title: res.message || '申请失败', icon: 'none' })
}
} catch (err) {
wx.hideLoading()
wx.showToast({ title: '申请失败', icon: 'none' })
}
},
/**
* 评价订单 - 打开评价弹窗
*/
onReview() {
this.setData({
showReviewModal: true,
reviewRating: 5,
reviewContent: '',
selectedTags: [],
isAnonymous: false
})
},
/**
* 关闭评价弹窗
*/
closeReviewModal() {
this.setData({ showReviewModal: false })
},
/**
* 选择评分
*/
selectRating(e) {
const rating = e.currentTarget.dataset.rating
this.setData({ reviewRating: rating })
},
/**
* 切换标签选择
*/
toggleTag(e) {
const tag = e.currentTarget.dataset.tag
const { selectedTags } = this.data
const index = selectedTags.indexOf(tag)
if (index > -1) {
selectedTags.splice(index, 1)
} else {
if (selectedTags.length < 5) {
selectedTags.push(tag)
} else {
wx.showToast({ title: '最多选择5个标签', icon: 'none' })
return
}
}
this.setData({ selectedTags })
},
/**
* 输入评价内容
*/
onReviewInput(e) {
this.setData({ reviewContent: e.detail.value })
},
/**
* 切换匿名评价
*/
toggleAnonymous() {
this.setData({ isAnonymous: !this.data.isAnonymous })
},
/**
* 提交评价
*/
async submitReview() {
const { order, reviewRating, reviewContent, selectedTags, isAnonymous } = this.data
if (this.data.submittingReview) return
this.setData({ submittingReview: true })
wx.showLoading({ title: '提交中...' })
try {
const res = await api.order.review(order.id, {
rating: reviewRating,
content: reviewContent,
tags: selectedTags,
isAnonymous: isAnonymous
})
wx.hideLoading()
this.setData({ submittingReview: false })
if (res.success) {
wx.showToast({ title: '评价成功', icon: 'success' })
this.setData({ showReviewModal: false })
// 刷新订单详情
this.loadOrderDetail(order.id)
} else {
wx.showToast({ title: res.message || res.error || '评价失败', icon: 'none' })
}
} catch (err) {
wx.hideLoading()
this.setData({ submittingReview: false })
console.error('提交评价失败', err)
wx.showToast({ title: '评价失败', icon: 'none' })
}
},
/**
* 显示确认弹窗
*/
showConfirm(title, content) {
return new Promise((resolve) => {
wx.showModal({
title,
content,
success: (res) => resolve(res.confirm)
})
})
}
})