Files
xinlong-shop-taro/src/components/common/OrderCard/index.tsx
赵忠林 147802dbe9 fix(order): 统一线下付款已发货未付款状态显示
- 用户端订单卡的已发货待收款状态调整,线下付款且未付款状态显示红色标识
- 用户端订单详情新增该状态的红色展示和提示信息
- 门店端订单列表状态文案和颜色同步更新,保持与用户端一致
- 门店端订单操作按钮逻辑调整,未付款已发货订单显示“确认完成”按钮
- 解决线下付款先发货后付款订单的状态显示和按钮操作不一致问题
2026-07-17 15:51:22 +08:00

172 lines
7.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from 'react'
import { View, Text, Image } from '@tarojs/components'
import Taro from '@tarojs/taro'
import type { ShopOrder } from '@/api/shop/shopOrder/model'
import Price from '../Price'
import { getCompressedImageUrl } from '@/utils/image'
interface OrderCardProps {
order: ShopOrder
onClick?: () => void
onCloseOrder?: (order: ShopOrder) => void
}
/** 综合 payStatus + deliveryStatus + orderStatus + payType 计算列表卡片状态文案 */
const getCardStatus = (order: ShopOrder): { text: string; color: string } => {
const { payStatus, deliveryStatus, orderStatus, payType } = order
const isCod = payType === 8 // 货到付款
if (orderStatus === 2) return { text: '已取消', color: '#999' }
if (orderStatus === 3) return { text: '取消中', color: '#ff7d00' }
if (orderStatus === 6) return { text: '已退款', color: '#999' }
if (orderStatus === 4 || orderStatus === 7) return { text: '退款申请中', color: '#ee0a24' }
if (orderStatus === 5) return { text: '退款被拒绝', color: '#ee0a24' }
// 终态orderStatus=1 必须最先判断,盖过 deliveryStatus/payStatus
if (orderStatus === 1) return { text: '已完成', color: '#0e932e' }
// 线下付款(9)已发货但未确认收款:显示"已发货待收款"(红色),与门店端一致
if (!payStatus && payType === 9 && deliveryStatus === 20) return { text: '已发货待收款', color: '#ee0a24' }
// 物流状态优先于付款状态(已发货/已收货的订单,即使未付款也显示物流状态)
if (deliveryStatus === 20) return { text: '待收货', color: '#4b9cf5' }
if (deliveryStatus === 30) return { text: '已收货', color: '#0e932e' }
// 货到付款(8):下单时后端已 setPayStatus(true),不会走到这里
// 线下付款(9):保持 payStatus=false待商家确认收款应显示"待付款"与 Tab 一致
if (!payStatus && !isCod) return { text: '待付款', color: '#ee0a24' }
if (deliveryStatus === 10) return { text: '待发货', color: '#4b9cf5' }
return { text: '已付款', color: '#0e932e' }
}
const OrderCard: React.FC<OrderCardProps> = ({ order, onClick, onCloseOrder }) => {
const handleClick = () => {
if (onClick) {
onClick()
return
}
Taro.navigateTo({ url: `/pages/order/detail?id=${order.orderId}` })
}
const handleClose = (e: any) => {
e?.stopPropagation?.()
onCloseOrder?.(order)
}
const { text: statusText, color: statusColor } = getCardStatus(order)
// 仅未付款/待确认收款的订单payStatus=false才显示取消按钮
// 已付款的待发货订单需到详情页申请退款
const showCloseButton = order.deliveryStatus === 10 && !order.payStatus && order.orderStatus !== 2 && order.orderStatus !== 3
// 获取首个商品图片作为封面,或显示默认占位
const coverImage = order.orderGoods?.[0]?.image || ''
const hasGoods = (order.orderGoods?.length || 0) > 0
return (
<View className='bg-white rounded-lg p-3 mb-3 shadow-sm' onClick={handleClick}>
{/* 头部:订单号 + 状态 */}
<View className='flex justify-between items-center mb-3'>
<Text className='text-sm font-medium text-gray-800'>
: {order.orderNo}
</Text>
<Text className='text-sm font-medium' style={{ color: statusColor }}>
{statusText}
</Text>
</View>
{/* 商品信息区域 */}
{hasGoods ? (
<View className='mb-3'>
{order.orderGoods?.map((item, idx) => (
<View key={idx} className='flex flex-row items-start mb-2 last:mb-0'>
{/* 商品缩略图 */}
<View className='w-16 h-16 rounded-md bg-gray-100 flex-shrink-0 overflow-hidden'>
{item.image ? (
<Image
className='w-full h-full'
src={getCompressedImageUrl(item.image)}
mode='aspectFill'
/>
) : (
<View className='w-full h-full flex items-center justify-center'>
<Text className='text-xs text-gray-400'></Text>
</View>
)}
</View>
{/* 商品信息 */}
<View className='flex-1 ml-2 flex flex-col justify-between h-16'>
<View>
<Text className='text-sm text-gray-800 font-medium line-clamp-1'>
{item.goodsName || '未知商品'}
</Text>
{item.spec ? (
<Text className='text-xs text-gray-500 mt-1'>
: {item.spec}
</Text>
) : null}
</View>
<View className='flex justify-between items-center'>
<Price price={item.price || '0'} size='small' />
<Text className='text-xs text-gray-500'>
x{item.totalNum || 1}
</Text>
</View>
</View>
</View>
))}
</View>
) : (
/* 无商品信息时的 fallback */
<View className='flex flex-row items-start mb-3'>
<View className='w-16 h-16 rounded-md bg-gray-100 flex-shrink-0 flex items-center justify-center overflow-hidden'>
{coverImage ? (
<Image className='w-full h-full' src={getCompressedImageUrl(coverImage)} mode='aspectFill' />
) : (
<Text className='text-xs text-gray-400'></Text>
)}
</View>
<View className='flex-1 ml-2 flex flex-col justify-center h-16'>
<Text className='text-sm text-gray-800 font-medium line-clamp-2'>
{order.title || '订单商品'}
</Text>
<Text className='text-xs text-gray-500 mt-1'>
{order.totalNum || 0}
</Text>
</View>
</View>
)}
{/* 底部:日期 + 金额汇总 + 操作按钮 */}
<View className='flex justify-between items-center pt-2 border-t border-gray-50'>
<Text className='text-xs text-gray-500'>
: {order.createTime?.replace('T', ' ').slice(0, 16)}
</Text>
<View className='flex items-center'>
<Text className='text-xs text-gray-500 mr-1'>
{order.totalNum || order.orderGoods?.reduce((sum, g) => sum + (g.totalNum || 1), 0) || 0}
</Text>
<Text className='text-xs text-gray-500 mr-1'></Text>
<Price price={order.payPrice || order.totalPrice || '0'} size='small' />
</View>
</View>
{/* 操作按钮区 */}
{showCloseButton && onCloseOrder && (
<View className='flex justify-end mt-3 pt-2 border-t border-gray-50'>
<View
className='px-3 py-1 rounded-full border border-gray-300'
onClick={handleClose}
>
<Text className='text-xs text-gray-600'></Text>
</View>
</View>
)}
</View>
)
}
export default OrderCard