import React, { useState, useEffect, useCallback } from 'react' import { View, Text, Image, ScrollView } from '@tarojs/components' import Taro from '@tarojs/taro' import { Button } from '@nutui/nutui-react-taro' import { getShopOrder, prepayShopOrder, updateShopOrder, repairOrder, removeShopOrder } from '@/api/shop/shopOrder' import { listShopOrderGoodsByOrderId } from '@/api/shop/shopOrderGoods' import type { ShopOrder } from '@/api/shop/shopOrder/model' import { OrderStatus, OrderStatusText } from '@/types/order' import Price from '@/components/common/Price' import { getCompressedImageUrl } from '@/utils/image' definePageConfig({ navigationBarTitleText: '订单详情', }) // 支付方式映射 const PAY_TYPE_MAP: Record = { 0: '余额支付', 1: '微信支付', 2: '支付宝', 3: '银联支付', 4: '现金支付', 5: 'POS机', 6: '免费', 7: '积分支付', 8: '货到付款', 9: '线下付款', } // 发票状态映射 const INVOICE_STATUS_MAP: Record = { 0: '未开票', 1: '已开票', 2: '不可开票', } // 发货状态映射 const DELIVERY_STATUS_MAP: Record = { 10: '未发货', 20: '已发货', 30: '部分发货', } // 配送方式映射: 0=快递配送, 1=无需发货/自提, 2=商家送货 const DELIVERY_TYPE_MAP: Record = { 0: '快递配送', 1: '自提', 2: '商家送货', } /** 根据订单状态计算展示用的状态标签 */ const getOrderDisplayStatus = (order: ShopOrder): { title: string; bgColor: string; subtitle: string } => { const { payStatus, deliveryStatus, orderStatus, payType } = order const isCod = payType === 8 // 货到付款 const isOffline = payType === 9 // 线下付款 // 退款/取消相关状态 if (orderStatus === OrderStatus.Cancelled) { return { bgColor: '#999', title: '已取消', subtitle: '订单已取消' } } if (orderStatus === OrderStatus.Cancelling) { return { bgColor: '#ff7d00', title: '取消中', subtitle: '退款处理中' } } if (orderStatus === OrderStatus.RefundSuccess) { return { bgColor: '#999', title: '已退款', subtitle: '退款已原路返回' } } if (orderStatus === OrderStatus.RefundApply || orderStatus === OrderStatus.ClientRefundApply) { return { bgColor: '#ee0a24', title: '退款申请中', subtitle: '商家正在处理退款' } } if (orderStatus === OrderStatus.RefundRejected) { return { bgColor: '#ee0a24', title: '退款被拒绝', subtitle: '退款申请已被拒绝' } } // 正常订单流程 if (!payStatus && !isCod && !isOffline) { return { bgColor: '#ff7d00', title: '待付款', subtitle: '请尽快完成支付' } } if (isOffline && !payStatus) { return { bgColor: '#4b9cf5', title: '待发货', subtitle: '请通过微信转账完成付款,商家确认后发货' } } if (isCod && !payStatus) { return { bgColor: '#4b9cf5', title: '待发货', subtitle: '送达时支付' } } if (deliveryStatus === 10) { return { bgColor: '#4b9cf5', title: '待发货', subtitle: '商家正在准备商品' } } if (deliveryStatus === 20 || deliveryStatus === 30) { return { bgColor: '#4b9cf5', title: '待收货', subtitle: '商品运输中,请注意查收' } } if (orderStatus === OrderStatus.Completed) { return { bgColor: '#0e932e', title: '已完成', subtitle: '交易已完成,感谢购买' } } if (orderStatus === OrderStatus.Unused) { return { bgColor: '#0e932e', title: '已付款', subtitle: '订单已支付' } } // 默认 return { bgColor: '#999', title: OrderStatusText[orderStatus ?? 0] || '未知', subtitle: '' } } /** 根据订单状态判断当前操作阶段 */ type OrderPhase = 'unpaid' | 'offline_pending' | 'unshipped' | 'shipped' | 'completed' | 'cancelled' | 'refund' const getOrderPhase = (order: ShopOrder): OrderPhase => { const { payStatus, deliveryStatus, orderStatus, payType } = order const isCod = payType === 8 // 货到付款 const isOffline = payType === 9 // 线下付款 // 退款/取消 if ([OrderStatus.Cancelled, OrderStatus.Cancelling, OrderStatus.RefundSuccess, OrderStatus.RefundApply, OrderStatus.ClientRefundApply, OrderStatus.RefundRejected].includes(orderStatus as OrderStatus)) { return orderStatus === OrderStatus.Cancelled || orderStatus === OrderStatus.RefundSuccess ? 'cancelled' : 'refund' } // 线下付款且未确认收款:等待商家确认,不显示"立即支付"按钮 if (isOffline && !payStatus) return 'offline_pending' // 货到付款订单:payStatus=true 但还未实际付款,直接进入 unshipped 阶段(不需要"立即支付"按钮) if (!payStatus && !isCod) return 'unpaid' if (deliveryStatus === 10) return 'unshipped' if (deliveryStatus === 20 || deliveryStatus === 30) return 'shipped' if (orderStatus === OrderStatus.Completed) return 'completed' return 'unshipped' } const OrderDetailPage: React.FC = () => { const { id } = Taro.getCurrentInstance().router?.params || {} const [order, setOrder] = useState(null) const [loading, setLoading] = useState(false) const loadOrder = useCallback(async () => { if (!id) return try { const orderData = await getShopOrder(Number(id)) // 如果订单中没有商品清单,则单独加载 if (!orderData.orderGoods || orderData.orderGoods.length === 0) { try { const goods = await listShopOrderGoodsByOrderId(Number(id)) orderData.orderGoods = goods } catch { // 忽略加载商品失败 } } setOrder(orderData) } catch { Taro.showToast({ title: '加载失败', icon: 'none' }) } }, [id]) useEffect(() => { loadOrder() }, [loadOrder]) // 格式化时间 const formatTime = (time: string | undefined) => { if (!time) return '-' return time.replace('T', ' ').slice(0, 19) } // 取消订单 const handleCancelOrder = () => { Taro.showModal({ title: '确认取消', content: '确定要取消该订单吗?', confirmColor: '#ee0a24', success: async (res) => { if (res.confirm && order) { try { await updateShopOrder({ ...order, orderStatus: OrderStatus.Cancelled }) Taro.showToast({ title: '订单已取消', icon: 'success' }) loadOrder() } catch { Taro.showToast({ title: '取消失败', icon: 'none' }) } } } }) } // 立即支付 const handlePay = async () => { if (!order || loading) return setLoading(true) try { const payResult = await prepayShopOrder({ orderId: order.orderId!, payType: 1 }) if (payResult) { await Taro.requestPayment({ timeStamp: payResult.timeStamp, nonceStr: payResult.nonceStr, package: payResult.package, signType: payResult.signType, paySign: payResult.paySign, }) Taro.showToast({ title: '支付成功', icon: 'success' }) loadOrder() } } catch (err: any) { if (err?.message !== 'requestPayment:fail cancel') { Taro.showToast({ title: err?.message || '支付失败', icon: 'none' }) } } finally { setLoading(false) } } // 确认收货 const handleConfirmReceive = () => { Taro.showModal({ title: '确认收货', content: '确认已收到商品?', confirmColor: '#0e932e', success: async (res) => { if (res.confirm && order) { try { await updateShopOrder({ ...order, orderStatus: OrderStatus.Completed }) Taro.showToast({ title: '已确认收货', icon: 'success' }) loadOrder() } catch { Taro.showToast({ title: '操作失败', icon: 'none' }) } } } }) } // 删除订单 const handleDeleteOrder = () => { Taro.showModal({ title: '删除订单', content: '确定要删除该订单吗?删除后不可恢复', confirmColor: '#ee0a24', success: async (res) => { if (res.confirm && order) { try { await removeShopOrder(order.orderId) Taro.showToast({ title: '订单已删除', icon: 'success' }) setTimeout(() => Taro.navigateBack(), 1000) } catch { Taro.showToast({ title: '删除失败', icon: 'none' }) } } } }) } if (!order) { return ( 加载中... ) } const displayStatus = getOrderDisplayStatus(order) const phase = getOrderPhase(order) // deliveryType: 0=快递配送, 1=无需发货/自提, 2=商家送货 const isExpress = order.deliveryType === 0 || order.deliveryType === 2 || order.deliveryType === undefined const goodsCount = order.orderGoods?.reduce((sum, g) => sum + (g.totalNum || 1), 0) || 0 return ( {/* 状态卡片 */} {displayStatus.title} {displayStatus.subtitle} {phase === 'shipped' && ( Taro.navigateTo({ url: `/pages/order/logistics?orderId=${order.orderId}` })} > 查看物流 )} {/* 收货信息 */} {isExpress ? ( {order.deliveryType === 2 ? '🛵' : '📦'} {order.realName || '未知'} {order.mobile || order.phone || '-'} {order.address || '未填写收货地址'} {order.deliveryType === 2 && order.expressMerchantName && ( 配送门店: {order.expressMerchantName} )} {(order.sendStartTime || order.sendEndTime) && ( 期望配送: {order.sendStartTime?.slice(0, 10)} ~ {order.sendEndTime?.slice(0, 10)} )} ) : ( 🏪 {order.selfTakeMerchantName || '自提点'} {order.address || '-'} {order.selfTakeCode && ( 自提码: {order.selfTakeCode} )} )} {/* 商品列表 */} 商品清单 ({goodsCount}件) {order.orderGoods?.map((item, idx) => ( item.goodsId && Taro.navigateTo({ url: `/pages/shop/product-detail?id=${item.goodsId}` })} > {item.image ? ( ) : ( 暂无 )} {item.goodsName || '未知商品'} {item.spec ? ( 规格: {item.spec} ) : null} x{item.totalNum || 1} ))} {/* 金额明细 */} 金额明细 商品总额 ¥{order.totalPrice || '0.00'} {Number(order.reducePrice || 0) > 0 && ( 优惠 -¥{order.reducePrice} )} 实付金额 支付方式 {PAY_TYPE_MAP[order.payType ?? 0] || '未知'} {/* 订单信息 */} 订单信息 订单编号 {order.orderNo} { Taro.setClipboardData({ data: order.orderNo || '' }) Taro.showToast({ title: '已复制', icon: 'none' }) }} > 复制 发货状态 {DELIVERY_STATUS_MAP[order.deliveryStatus ?? 10]} 配送方式 {DELIVERY_TYPE_MAP[order.deliveryType ?? 0] || '未知'} 创建时间 {formatTime(order.createTime)} {order.payTime && ( 支付时间 {formatTime(order.payTime)} )} {order.deliveryTime && ( 发货时间 {formatTime(order.deliveryTime)} )} {order.comments && ( 备注 {order.comments} )} 发票状态 {INVOICE_STATUS_MAP[order.isInvoice ?? 0]} {/* 底部操作按钮(根据订单阶段动态显示) */} {/* 待付款: 取消 + 支付 */} {phase === 'unpaid' && ( <> )} {/* 线下付款·待确认: 取消 + 联系客服 */} {phase === 'offline_pending' && ( <> )} {/* 待发货: 退款 + 联系客服 */} {phase === 'unshipped' && ( <> )} {/* 待收货: 物流 + 确认收货 */} {phase === 'shipped' && ( <> )} {/* 已完成: 售后 + 删除 */} {phase === 'completed' && ( <> )} {/* 已取消/已退款: 删除 */} {phase === 'cancelled' && ( )} ) } export default OrderDetailPage