refactor(order): 优化订单商品数据显示逻辑

- 将订单模型中的 orderGoods 类型从 OrderGoods 改为 ShopOrderGoods
- 移除 OrderWithGoods 接口定义和 normalizeOrderGoodsList 函数
- 直接使用订单分页接口返回的 orderGoods 字段渲染商品信息
- 添加 utils/orderGoods.ts 工具函数处理订单商品数据标准化
- 在骑手端订单页面实现商品名称汇总显示功能
- 优化再次购买和支付功能中的商品数据获取逻辑
This commit is contained in:
2026-02-01 12:21:55 +08:00
parent dea40268fe
commit 945bf9af8d
4 changed files with 71 additions and 57 deletions

View File

@@ -7,7 +7,6 @@ import dayjs from "dayjs";
import {pageShopOrder, updateShopOrder, createOrder} from "@/api/shop/shopOrder";
import {ShopOrder, ShopOrderParam} from "@/api/shop/shopOrder/model";
import {listShopOrderGoods} from "@/api/shop/shopOrderGoods";
import {ShopOrderGoods} from "@/api/shop/shopOrderGoods/model";
import {copyText} from "@/utils/common";
import PaymentCountdown from "@/components/PaymentCountdown";
import {PaymentType} from "@/utils/payment";
@@ -78,36 +77,6 @@ const tabs = [
}
]
// 扩展订单接口,包含商品信息
interface OrderWithGoods extends ShopOrder {
// 避免与 ShopOrder.orderGoods (OrderGoods[]) 冲突:这里使用单独字段保存接口返回的商品明细
orderGoodsList?: ShopOrderGoods[];
}
// 后端订单分页接口通常已返回 orderGoods订单商品明细
// 这里把各种可能的字段名做一次归一化,避免再为每个订单额外请求一次“订单商品”接口。
const normalizeOrderGoodsList = (order: any): ShopOrderGoods[] => {
const raw =
order?.orderGoods ||
order?.orderGoodsList ||
order?.goodsList ||
order?.goods ||
[];
if (!Array.isArray(raw)) return [];
return raw.map((g: any) => ({
...g,
goodsId: g?.goodsId ?? g?.itemId ?? g?.goods_id,
skuId: g?.skuId ?? g?.sku_id,
// 当接口只返回了最小字段时,用订单标题兜底,避免列表出现空白商品名
goodsName: g?.goodsName ?? g?.goodsTitle ?? g?.title ?? g?.name ?? order?.title ?? '商品',
image: g?.image ?? g?.goodsImage ?? g?.cover ?? g?.pic,
spec: g?.spec ?? g?.specInfo ?? g?.spec_name,
totalNum: g?.totalNum ?? g?.quantity ?? g?.num ?? g?.count,
price: g?.price ?? g?.payPrice ?? g?.goodsPrice ?? g?.unitPrice
}));
};
interface OrderListProps {
onReload?: () => void;
searchParams?: ShopOrderParam;
@@ -122,7 +91,7 @@ interface OrderListProps {
}
function OrderList(props: OrderListProps) {
const [list, setList] = useState<OrderWithGoods[]>([])
const [list, setList] = useState<ShopOrder[]>([])
const pageRef = useRef(1)
const [hasMore, setHasMore] = useState(true)
const [payingOrderId, setPayingOrderId] = useState<number | null>(null)
@@ -254,20 +223,17 @@ function OrderList(props: OrderListProps) {
const res = await pageShopOrder(searchConditions);
if (res?.list && res?.list.length > 0) {
// 订单分页接口已返回 orderGoods直接读取并归一化,避免 N+1 请求导致列表加载慢
const ordersWithGoods: OrderWithGoods[] = res.list.map((order: any) => ({
...order,
orderGoodsList: normalizeOrderGoodsList(order)
}));
// 订单分页接口已返回 orderGoods列表直接使用该字段
const incoming = res.list as ShopOrder[];
// 使用函数式更新避免依赖 list
setList(prevList => {
const newList = resetPage ? ordersWithGoods : (prevList || []).concat(ordersWithGoods);
const newList = resetPage ? incoming : (prevList || []).concat(incoming);
return newList;
});
// 正确判断是否还有更多数据
const hasMoreData = res.list.length >= 10; // 假设每页10条数据
const hasMoreData = incoming.length >= 10; // 假设每页10条数据
setHasMore(hasMoreData);
} else {
setList(prevList => resetPage ? [] : prevList);
@@ -377,9 +343,9 @@ function OrderList(props: OrderListProps) {
};
// 再次购买 (已完成状态)
const buyAgain = (order: OrderWithGoods) => {
const buyAgain = (order: ShopOrder) => {
console.log('再次购买:', order);
const goodsId = order.orderGoodsList?.[0]?.goodsId
const goodsId = order.orderGoods?.[0]?.goodsId
if (!goodsId) {
Taro.showToast({
title: '订单商品信息缺失',
@@ -437,7 +403,7 @@ function OrderList(props: OrderListProps) {
};
// 立即支付
const payOrder = async (order: OrderWithGoods) => {
const payOrder = async (order: ShopOrder) => {
try {
if (!order.orderId || !order.orderNo) {
Taro.showToast({
@@ -480,8 +446,8 @@ function OrderList(props: OrderListProps) {
Taro.showLoading({title: '发起支付...'});
// 构建商品数据:优先使用列表已加载的商品信息缺失时再补拉一次避免goodsItems为空导致后端拒绝/再次支付失败
let orderGoods = order.orderGoodsList || [];
// 构建商品数据:优先使用订单分页接口返回的 orderGoods缺失时再补拉一次避免goodsItems为空导致后端拒绝/再次支付失败
let orderGoods = order.orderGoods || [];
if (!orderGoods.length) {
try {
orderGoods = (await listShopOrderGoods({orderId: order.orderId})) || [];
@@ -492,13 +458,13 @@ function OrderList(props: OrderListProps) {
}
const goodsItems = orderGoods
.filter(g => !!g.goodsId)
.filter(g => !!(g as any).goodsId || !!(g as any).itemId)
.map(goods => ({
goodsId: goods.goodsId as number,
quantity: goods.totalNum || 1,
goodsId: (goods.goodsId ?? (goods as any).itemId) as number,
quantity: ((goods as any).quantity ?? goods.totalNum ?? 1) as number,
// 若后端按SKU计算价格/库存补齐SKU/规格信息更安全
skuId: (goods as any).skuId,
specInfo: (goods as any).spec || (goods as any).specInfo
skuId: (goods as any).skuId ?? (goods as any).sku_id,
specInfo: (goods as any).specInfo ?? (goods as any).spec
}));
if (!goodsItems.length) {
@@ -753,8 +719,8 @@ function OrderList(props: OrderListProps) {
{/* 商品信息 */}
<View className={'goods-info'}>
{item.orderGoodsList && item.orderGoodsList.length > 0 ? (
item.orderGoodsList.map((goods, goodsIndex) => (
{item.orderGoods && item.orderGoods.length > 0 ? (
item.orderGoods.map((goods, goodsIndex) => (
<View key={goodsIndex} className={'flex items-center mb-2'}>
<Image
src={goods.image || '/default-goods.png'}
@@ -764,11 +730,15 @@ function OrderList(props: OrderListProps) {
className={'rounded'}
/>
<View className={'ml-2 flex flex-col flex-1'}>
<Text className={'text-sm font-bold'}>{goods.goodsName}</Text>
{goods.spec && <Text className={'text-gray-500 text-xs'}>{goods.spec}</Text>}
<Text className={'text-gray-500 text-xs'}>{goods.totalNum}</Text>
<Text className={'text-sm font-bold'}>
{goods.goodsName || (goods as any).goodsTitle || (goods as any).title || item.title || '订单商品'}
</Text>
{(goods.spec || (goods as any).specInfo) && (
<Text className={'text-gray-500 text-xs'}>{goods.spec || (goods as any).specInfo}</Text>
)}
<Text className={'text-gray-500 text-xs'}>{(goods as any).quantity ?? goods.totalNum}</Text>
</View>
<Text className={'text-sm'}>{goods.price}</Text>
<Text className={'text-sm'}>{goods.price || (goods as any).payPrice}</Text>
</View>
))
) : (