From 6db0b5e03f16bde3460a2b9c5886e93e51cdb82e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Tue, 19 Aug 2025 13:15:12 +0800 Subject: [PATCH] =?UTF-8?q?feat(order):=20=E6=B7=BB=E5=8A=A0=E6=94=AF?= =?UTF-8?q?=E4=BB=98=E5=80=92=E8=AE=A1=E6=97=B6=E7=BB=84=E4=BB=B6=E5=B9=B6?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=AE=A2=E5=8D=95=E7=9B=B8=E5=85=B3=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 PaymentCountdown 组件用于显示支付倒计时 - 实现 usePaymentCountdown Hook 以支持倒计时逻辑 - 添加 useOrderStats Hook 用于获取订单统计信息 - 在订单列表和详情页面集成支付倒计时功能 - 优化订单状态显示和相关操作逻辑 --- src/components/PaymentCountdown.md | 168 +++++++++++++++++++++++ src/components/PaymentCountdown.scss | 170 ++++++++++++++++++++++++ src/components/PaymentCountdown.tsx | 89 +++++++++++++ src/hooks/useOrderStats.ts | 117 ++++++++++++++++ src/hooks/usePaymentCountdown.ts | 163 +++++++++++++++++++++++ src/pages/user/components/UserOrder.tsx | 81 ++++++++--- src/shop/orderDetail/index.tsx | 41 +++++- src/user/order/components/OrderList.tsx | 54 ++++---- 8 files changed, 833 insertions(+), 50 deletions(-) create mode 100644 src/components/PaymentCountdown.md create mode 100644 src/components/PaymentCountdown.scss create mode 100644 src/components/PaymentCountdown.tsx create mode 100644 src/hooks/useOrderStats.ts create mode 100644 src/hooks/usePaymentCountdown.ts diff --git a/src/components/PaymentCountdown.md b/src/components/PaymentCountdown.md new file mode 100644 index 0000000..abe4137 --- /dev/null +++ b/src/components/PaymentCountdown.md @@ -0,0 +1,168 @@ +# PaymentCountdown 支付倒计时组件 + +基于订单创建时间的支付倒计时组件,支持静态显示和实时更新两种模式。 + +## 功能特性 + +- ✅ **双模式支持**:静态显示(列表页)和实时更新(详情页) +- ✅ **智能状态判断**:自动判断紧急程度并应用不同样式 +- ✅ **过期自动处理**:倒计时结束后触发回调 +- ✅ **灵活样式**:支持徽章模式和纯文本模式 +- ✅ **性能优化**:避免不必要的重渲染 + +## 使用方法 + +### 基础用法 + +```tsx +import PaymentCountdown from '@/components/PaymentCountdown'; + +// 订单列表页 - 静态显示 + + +// 订单详情页 - 实时更新 + { + console.log('支付已过期'); + }} +/> +``` + +### 高级用法 + +```tsx +// 自定义超时时间(12小时) + + +// 纯文本模式 + +``` + +## API 参数 + +| 参数 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| createTime | string | - | 订单创建时间 | +| payStatus | boolean | false | 支付状态 | +| realTime | boolean | false | 是否实时更新 | +| timeoutHours | number | 24 | 超时小时数 | +| showSeconds | boolean | false | 是否显示秒数 | +| className | string | '' | 自定义样式类名 | +| onExpired | function | - | 过期回调函数 | +| mode | 'badge' \| 'text' | 'badge' | 显示模式 | + +## 样式状态 + +### 正常状态 +- 红色渐变背景 +- 白色文字 +- 轻微阴影效果 + +### 紧急状态(< 1小时) +- 更深的红色背景 +- 脉冲动画效果 + +### 非常紧急状态(< 10分钟) +- 最深的红色背景 +- 快速闪烁动画 + +### 过期状态 +- 灰色背景 +- 无动画效果 + +## Hook 使用 + +如果需要单独使用倒计时逻辑,可以直接使用 Hook: + +```tsx +import { usePaymentCountdown, formatCountdownText } from '@/hooks/usePaymentCountdown'; + +const MyComponent = ({ order }) => { + const timeLeft = usePaymentCountdown( + order.createTime, + order.payStatus, + true, // 实时更新 + 24 // 24小时超时 + ); + + const countdownText = formatCountdownText(timeLeft, true); + + return ( +
+ 剩余时间:{countdownText} +
+ ); +}; +``` + +## 工具函数 + +```tsx +import { + formatCountdownText, + isUrgentCountdown, + isCriticalCountdown +} from '@/hooks/usePaymentCountdown'; + +// 格式化倒计时文本 +const text = formatCountdownText(timeLeft, true); // "2小时30分15秒" + +// 判断是否紧急 +const isUrgent = isUrgentCountdown(timeLeft); // < 1小时 + +// 判断是否非常紧急 +const isCritical = isCriticalCountdown(timeLeft); // < 10分钟 +``` + +## 注意事项 + +1. **性能考虑**:列表页建议使用 `realTime={false}` 避免过多定时器 +2. **内存泄漏**:组件会自动清理定时器,无需手动处理 +3. **时区问题**:确保 `createTime` 格式正确,建议使用 ISO 格式 +4. **过期处理**:`onExpired` 回调只在实时模式下触发 + +## 样式定制 + +可以通过 CSS 变量或覆盖样式类来自定义外观: + +```scss +.custom-countdown { + .payment-countdown-badge { + background: linear-gradient(135deg, #your-color-1, #your-color-2); + border-radius: 8px; + + &.urgent { + animation: customPulse 1.5s infinite; + } + } +} + +@keyframes customPulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.8; } +} +``` diff --git a/src/components/PaymentCountdown.scss b/src/components/PaymentCountdown.scss new file mode 100644 index 0000000..6602c3f --- /dev/null +++ b/src/components/PaymentCountdown.scss @@ -0,0 +1,170 @@ +/* 支付倒计时样式 */ + +/* 徽章模式样式 */ +.payment-countdown-badge { + display: inline-block; + background: linear-gradient(135deg, #ff4757, #ff3838); + color: white; + padding: 4px 8px; + border-radius: 12px; + font-size: 12px; + font-weight: 500; + box-shadow: 0 2px 4px rgba(255, 71, 87, 0.3); + margin-left: 8px; + + .countdown-text { + color: white; + font-size: 12px; + font-weight: 500; + } + + /* 紧急状态(少于1小时) */ + &.urgent { + background: linear-gradient(135deg, #ff6b6b, #ee5a52); + animation: pulse 2s infinite; + } + + /* 非常紧急状态(少于10分钟) */ + &.critical { + background: linear-gradient(135deg, #ff4757, #c44569); + animation: flash 1s infinite; + } + + /* 过期状态 */ + &.expired { + background: linear-gradient(135deg, #95a5a6, #7f8c8d); + animation: none; + } +} + +/* 纯文本模式样式 */ +.payment-countdown-text { + color: #ff4757; + font-size: 12px; + font-weight: 500; + + /* 紧急状态 */ + &.urgent { + color: #ff6b6b; + animation: textPulse 2s infinite; + } + + /* 非常紧急状态 */ + &.critical { + color: #ff4757; + animation: textFlash 1s infinite; + } + + /* 过期状态 */ + &.expired { + color: #95a5a6; + animation: none; + } +} + +/* 动画效果 */ +@keyframes pulse { + 0% { + opacity: 1; + transform: scale(1); + } + 50% { + opacity: 0.8; + transform: scale(1.02); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + +@keyframes flash { + 0% { + opacity: 1; + transform: scale(1); + } + 25% { + opacity: 0.7; + transform: scale(1.05); + } + 50% { + opacity: 1; + transform: scale(1); + } + 75% { + opacity: 0.7; + transform: scale(1.05); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + +@keyframes textPulse { + 0% { opacity: 1; } + 50% { opacity: 0.7; } + 100% { opacity: 1; } +} + +@keyframes textFlash { + 0% { opacity: 1; } + 25% { opacity: 0.5; } + 50% { opacity: 1; } + 75% { opacity: 0.5; } + 100% { opacity: 1; } +} + +/* 响应式调整 */ +@media (max-width: 375px) { + .payment-countdown-badge { + font-size: 11px; + padding: 3px 6px; + + .countdown-text { + font-size: 11px; + } + } + + .payment-countdown-text { + font-size: 11px; + } +} + +/* 详情页专用样式 */ +.order-detail-countdown { + .payment-countdown-badge { + font-size: 14px; + padding: 6px 12px; + border-radius: 16px; + margin: 8px 0; + + .countdown-text { + font-size: 14px; + font-weight: 600; + } + } + + .payment-countdown-text { + font-size: 14px; + font-weight: 600; + } +} + +/* 列表页专用样式 */ +.order-list-countdown { + .payment-countdown-badge { + font-size: 11px; + padding: 2px 6px; + border-radius: 10px; + margin-left: 6px; + + .countdown-text { + font-size: 11px; + } + } + + .payment-countdown-text { + font-size: 11px; + } +} diff --git a/src/components/PaymentCountdown.tsx b/src/components/PaymentCountdown.tsx new file mode 100644 index 0000000..b1b55c9 --- /dev/null +++ b/src/components/PaymentCountdown.tsx @@ -0,0 +1,89 @@ +import React from 'react'; +import { View, Text } from '@tarojs/components'; +import { + usePaymentCountdown, + formatCountdownText, + isUrgentCountdown, + isCriticalCountdown +} from '@/hooks/usePaymentCountdown'; +import './PaymentCountdown.scss'; + +export interface PaymentCountdownProps { + /** 订单创建时间 */ + createTime?: string; + /** 支付状态 */ + payStatus?: boolean; + /** 是否实时更新(详情页用true,列表页用false) */ + realTime?: boolean; + /** 超时小时数,默认24小时 */ + timeoutHours?: number; + /** 是否显示秒数 */ + showSeconds?: boolean; + /** 自定义样式类名 */ + className?: string; + /** 过期回调 */ + onExpired?: () => void; + /** 显示模式:badge(徽章模式) | text(纯文本模式) */ + mode?: 'badge' | 'text'; +} + +const PaymentCountdown: React.FC = ({ + createTime, + payStatus = false, + realTime = false, + timeoutHours = 24, + showSeconds = false, + className = '', + onExpired, + mode = 'badge' +}) => { + const timeLeft = usePaymentCountdown(createTime, payStatus, realTime, timeoutHours); + + // 如果已支付或没有创建时间,不显示倒计时 + if (payStatus || !createTime) { + return null; + } + + // 如果已过期,触发回调并显示过期状态 + if (timeLeft.isExpired) { + onExpired?.(); + if (mode === 'text') { + return ( + + 支付已过期 + + ); + } + return ( + + 支付已过期 + + ); + } + + // 判断紧急程度 + const isUrgent = isUrgentCountdown(timeLeft); + const isCritical = isCriticalCountdown(timeLeft); + + // 格式化倒计时文本 + const countdownText = formatCountdownText(timeLeft, showSeconds); + const fullText = `等待付款 ${countdownText}`; + + // 纯文本模式 + if (mode === 'text') { + return ( + + {fullText} + + ); + } + + // 徽章模式 + return ( + + {fullText} + + ); +}; + +export default PaymentCountdown; diff --git a/src/hooks/useOrderStats.ts b/src/hooks/useOrderStats.ts new file mode 100644 index 0000000..14b4c05 --- /dev/null +++ b/src/hooks/useOrderStats.ts @@ -0,0 +1,117 @@ +import { useState, useEffect, useCallback } from 'react'; +import { UserOrderStats } from '@/api/user'; +import Taro from '@tarojs/taro'; +import {pageShopOrder} from "@/api/shop/shopOrder"; + +/** + * 订单统计Hook + * 用于管理用户订单各状态的数量统计 + */ +export const useOrderStats = () => { + const [orderStats, setOrderStats] = useState({ + pending: 0, // 待付款 + paid: 0, // 待发货 + shipped: 0, // 待收货 + completed: 0, // 已完成 + refund: 0, // 退货/售后 + total: 0 // 总订单数 + }); + + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + /** + * 获取订单统计数据 + */ + const fetchOrderStats = useCallback(async (showToast = false) => { + try { + setLoading(true); + setError(null); + + // TODO 读取订单数量 + const pending = await pageShopOrder({ page: 1, limit: 1, userId: Taro.getStorageSync('UserId'), statusFilter: 0}) + const paid = await pageShopOrder({ page: 1, limit: 1, userId: Taro.getStorageSync('UserId'), statusFilter: 1}) + const shipped = await pageShopOrder({ page: 1, limit: 1, userId: Taro.getStorageSync('UserId'), statusFilter: 3}) + const completed = await pageShopOrder({ page: 1, limit: 1, userId: Taro.getStorageSync('UserId'), statusFilter: 5}) + const refund = await pageShopOrder({ page: 1, limit: 1, userId: Taro.getStorageSync('UserId'), statusFilter: 6}) + const total = await pageShopOrder({ page: 1, limit: 1, userId: Taro.getStorageSync('UserId')}) + setOrderStats({ + pending: pending?.count || 0, + paid: paid?.count || 0, + shipped: shipped?.count || 0, + completed: completed?.count || 0, + refund: refund?.count || 0, + total: total?.count || 0 + }) + + if (showToast) { + Taro.showToast({ + title: '数据已更新', + icon: 'success', + duration: 1500 + }); + } + } catch (err: any) { + const errorMessage = err.message || '获取订单统计失败'; + setError(errorMessage); + + console.error('获取订单统计失败:', err); + + if (showToast) { + Taro.showToast({ + title: errorMessage, + icon: 'error', + duration: 2000 + }); + } + } finally { + setLoading(false); + } + }, []); + + /** + * 刷新订单统计数据 + */ + const refreshOrderStats = useCallback(() => { + return fetchOrderStats(true); + }, [fetchOrderStats]); + + /** + * 获取指定状态的订单数量 + */ + const getOrderCount = useCallback((status: keyof UserOrderStats) => { + return orderStats[status] || 0; + }, [orderStats]); + + /** + * 检查是否有待处理的订单 + */ + const hasPendingOrders = useCallback(() => { + return orderStats.pending > 0 || orderStats.paid > 0 || orderStats.shipped > 0; + }, [orderStats]); + + /** + * 获取总的待处理订单数量 + */ + const getTotalPendingCount = useCallback(() => { + return orderStats.pending + orderStats.paid + orderStats.shipped; + }, [orderStats]); + + // 组件挂载时自动获取数据 + useEffect(() => { + fetchOrderStats(); + }, [fetchOrderStats]); + + return { + orderStats, + loading, + error, + fetchOrderStats, + refreshOrderStats, + getOrderCount, + hasPendingOrders, + getTotalPendingCount + }; +}; + +export default useOrderStats; diff --git a/src/hooks/usePaymentCountdown.ts b/src/hooks/usePaymentCountdown.ts new file mode 100644 index 0000000..a4caa5f --- /dev/null +++ b/src/hooks/usePaymentCountdown.ts @@ -0,0 +1,163 @@ +import { useState, useEffect, useMemo } from 'react'; +import dayjs from 'dayjs'; +import duration from 'dayjs/plugin/duration'; + +// 扩展dayjs支持duration +dayjs.extend(duration); + +export interface CountdownTime { + hours: number; + minutes: number; + seconds: number; + isExpired: boolean; + totalMinutes: number; // 总剩余分钟数 +} + +/** + * 支付倒计时Hook + * @param createTime 订单创建时间 + * @param payStatus 支付状态 + * @param realTime 是否实时更新(详情页用true,列表页用false) + * @param timeoutHours 超时小时数,默认24小时 + */ +export const usePaymentCountdown = ( + createTime?: string, + payStatus?: boolean, + realTime: boolean = false, + timeoutHours: number = 24 +): CountdownTime => { + const [timeLeft, setTimeLeft] = useState({ + hours: 0, + minutes: 0, + seconds: 0, + isExpired: false, + totalMinutes: 0 + }); + + // 计算剩余时间的函数 + const calculateTimeLeft = useMemo(() => { + return (): CountdownTime => { + if (!createTime || payStatus) { + return { + hours: 0, + minutes: 0, + seconds: 0, + isExpired: false, + totalMinutes: 0 + }; + } + + const createTimeObj = dayjs(createTime); + const expireTime = createTimeObj.add(timeoutHours, 'hour'); + const now = dayjs(); + const diff = expireTime.diff(now); + + if (diff <= 0) { + return { + hours: 0, + minutes: 0, + seconds: 0, + isExpired: true, + totalMinutes: 0 + }; + } + + const durationObj = dayjs.duration(diff); + const hours = Math.floor(durationObj.asHours()); + const minutes = durationObj.minutes(); + const seconds = durationObj.seconds(); + const totalMinutes = Math.floor(durationObj.asMinutes()); + + return { + hours, + minutes, + seconds, + isExpired: false, + totalMinutes + }; + }; + }, [createTime, payStatus, timeoutHours]); + + useEffect(() => { + if (!createTime || payStatus) { + setTimeLeft({ + hours: 0, + minutes: 0, + seconds: 0, + isExpired: false, + totalMinutes: 0 + }); + return; + } + + // 立即计算一次 + const initialTime = calculateTimeLeft(); + setTimeLeft(initialTime); + + // 如果不需要实时更新,直接返回 + if (!realTime) { + return; + } + + // 如果需要实时更新,设置定时器 + const timer = setInterval(() => { + const newTimeLeft = calculateTimeLeft(); + setTimeLeft(newTimeLeft); + + // 如果已过期,清除定时器 + if (newTimeLeft.isExpired) { + clearInterval(timer); + } + }, 1000); + + return () => clearInterval(timer); + }, [createTime, payStatus, realTime, calculateTimeLeft]); + + return timeLeft; +}; + +/** + * 格式化倒计时文本 + * @param timeLeft 倒计时时间对象 + * @param showSeconds 是否显示秒数 + */ +export const formatCountdownText = ( + timeLeft: CountdownTime, + showSeconds: boolean = false +): string => { + if (timeLeft.isExpired) { + return '已过期'; + } + + if (timeLeft.hours > 0) { + if (showSeconds) { + return `${timeLeft.hours}小时${timeLeft.minutes}分${timeLeft.seconds}秒`; + } else { + return `${timeLeft.hours}小时${timeLeft.minutes}分钟`; + } + } else if (timeLeft.minutes > 0) { + if (showSeconds) { + return `${timeLeft.minutes}分${timeLeft.seconds}秒`; + } else { + return `${timeLeft.minutes}分钟`; + } + } else { + return `${timeLeft.seconds}秒`; + } +}; + +/** + * 判断是否为紧急状态(剩余时间少于1小时) + */ +export const isUrgentCountdown = (timeLeft: CountdownTime): boolean => { + return !timeLeft.isExpired && timeLeft.totalMinutes < 60; +}; + +/** + * 判断是否为非常紧急状态(剩余时间少于10分钟) + */ +export const isCriticalCountdown = (timeLeft: CountdownTime): boolean => { + return !timeLeft.isExpired && timeLeft.totalMinutes < 10; +}; + +export default usePaymentCountdown; diff --git a/src/pages/user/components/UserOrder.tsx b/src/pages/user/components/UserOrder.tsx index c34fa78..c5da9e3 100644 --- a/src/pages/user/components/UserOrder.tsx +++ b/src/pages/user/components/UserOrder.tsx @@ -1,19 +1,17 @@ -import {useEffect} from "react"; import navTo from "@/utils/common"; import {View, Text} from '@tarojs/components'; import {Badge} from '@nutui/nutui-react-taro'; import {ArrowRight, Wallet, Comment, Transit, Refund, Package} from '@nutui/icons-react-taro'; +import {useOrderStats} from "@/hooks/useOrderStats"; function UserOrder() { + const { orderStats, refreshOrderStats } = useOrderStats(); - const reload = () => { - + // 处理长按刷新 + const handleLongPress = () => { + refreshOrderStats(); }; - useEffect(() => { - reload() - }, []); - return ( <> @@ -29,45 +27,90 @@ function UserOrder() { > 我的订单 - navTo('/user/order/order', true)}> + navTo('/user/order/order', true)} + onLongPress={handleLongPress} + > 全部订单 - - - navTo('/user/order/order?statusFilter=0', true)}/> + {/* 待付款 */} + {orderStats.pending > 0 ? ( + + + navTo('/user/order/order?statusFilter=0', true)}/> + 待付款 + + + ) : ( + navTo('/user/order/order?statusFilter=0', true)}> + 待付款 - - + )} + + {/* 待发货 */} + {orderStats.paid > 0 ? ( + + navTo('/user/order/order?statusFilter=1', true)}> + + 待发货 + + + ) : ( navTo('/user/order/order?statusFilter=1', true)}> 待发货 - - + )} + + {/* 待收货 */} + {orderStats.shipped > 0 ? ( + + navTo('/user/order/order?statusFilter=3', true)}> + + 待收货 + + + ) : ( navTo('/user/order/order?statusFilter=3', true)}> 待收货 - + )} + + {/* 已完成 - 不显示badge */} navTo('/user/order/order?statusFilter=5', true)}> 已完成 - + + {/* 退货/售后 */} + {orderStats.refund > 0 ? ( + + navTo('/user/order/order?statusFilter=6', true)}> + + 退货/售后 + + + ) : ( navTo('/user/order/order?statusFilter=6', true)}> 退货/售后 - + )} diff --git a/src/shop/orderDetail/index.tsx b/src/shop/orderDetail/index.tsx index 379a8c1..6657390 100644 --- a/src/shop/orderDetail/index.tsx +++ b/src/shop/orderDetail/index.tsx @@ -2,10 +2,11 @@ import {useEffect, useState} from "react"; import {Cell, CellGroup, Image, Space, Button} from '@nutui/nutui-react-taro' import Taro from '@tarojs/taro' import {ShopOrder} from "@/api/shop/shopOrder/model"; -import {getShopOrder} from "@/api/shop/shopOrder"; +import {getShopOrder, updateShopOrder} from "@/api/shop/shopOrder"; import {listShopOrderGoods} from "@/api/shop/shopOrderGoods"; import {ShopOrderGoods} from "@/api/shop/shopOrderGoods/model"; import dayjs from "dayjs"; +import PaymentCountdown from "@/components/PaymentCountdown"; import './index.scss' const OrderDetail = () => { @@ -14,6 +15,30 @@ const OrderDetail = () => { const router = Taro.getCurrentInstance().router; const orderId = router?.params?.orderId; + // 处理支付超时 + const handlePaymentExpired = async () => { + if (!order) return; + + try { + // 自动取消过期订单 + await updateShopOrder({ + ...order, + orderStatus: 2 // 已取消 + }); + + // 更新本地状态 + setOrder(prev => prev ? { ...prev, orderStatus: 2 } : null); + + Taro.showToast({ + title: '订单已自动取消', + icon: 'none', + duration: 2000 + }); + } catch (error) { + console.error('自动取消订单失败:', error); + } + }; + const getOrderStatusText = (order: ShopOrder) => { // 优先检查订单状态 if (order.orderStatus === 2) return '已取消'; @@ -74,6 +99,20 @@ const OrderDetail = () => { return (
+ {/* 支付倒计时显示 - 详情页实时更新 */} + {!order.payStatus && order.orderStatus !== 2 && ( +
+ +
+ )} + diff --git a/src/user/order/components/OrderList.tsx b/src/user/order/components/OrderList.tsx index 2c81f9e..5d57a43 100644 --- a/src/user/order/components/OrderList.tsx +++ b/src/user/order/components/OrderList.tsx @@ -9,6 +9,7 @@ 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"; const getInfiniteUlStyle = (showSearch: boolean = false): CSSProperties => ({ marginTop: showSearch ? '0' : '0', // 如果显示搜索框,增加更多的上边距 @@ -188,7 +189,7 @@ function OrderList(props: OrderListProps) { try { const res = await pageShopOrder(searchConditions); - let newList: OrderWithGoods[] = []; + let newList: OrderWithGoods[]; if (res?.list && res?.list.length > 0) { // 批量获取订单商品信息,限制并发数量 @@ -261,7 +262,7 @@ function OrderList(props: OrderListProps) { Taro.showToast({ title: '确认收货成功', }); - reload(true); // 重新加载列表 + await reload(true); // 重新加载列表 props.onReload?.(); // 通知父组件刷新 } catch (error) { Taro.showToast({ @@ -293,7 +294,7 @@ function OrderList(props: OrderListProps) { title: '订单已取消', icon: 'success' }); - reload(true).then(); // 重新加载列表 + void reload(true); // 重新加载列表 props.onReload?.(); // 通知父组件刷新 } catch (error) { console.error('取消订单失败:', error); @@ -305,7 +306,7 @@ function OrderList(props: OrderListProps) { }; useEffect(() => { - reload(true).then(); // 首次加载或tab切换时重置页码 + void reload(true); // 首次加载或tab切换时重置页码 }, [tapIndex]); // 监听tapIndex变化 // 监听外部statusFilter变化,同步更新tab索引 @@ -332,25 +333,7 @@ function OrderList(props: OrderListProps) { } }, [props.searchParams?.statusFilter]); // 监听statusFilter变化 - useEffect(() => { - // 当外部传入的搜索参数变化时(不包括statusFilter,因为上面已经处理) - // 只有当搜索关键词等其他条件变化时才重新加载 - const {statusFilter, ...otherParams} = props.searchParams || {}; - - // 检查是否有除statusFilter外的其他搜索条件变化 - const hasOtherSearchParams = Object.keys(otherParams).some(key => - otherParams[key] !== undefined && otherParams[key] !== '' - ); - - console.log('searchParams变化 (非statusFilter):', { - otherParams, - hasOtherSearchParams - }); - if (hasOtherSearchParams) { - reload(true).then(); // 只有其他搜索条件变化时才重新加载 - } - }, [props.searchParams?.keywords, props.searchParams?.orderNo]); // 只监听具体的搜索字段 return ( <> @@ -367,7 +350,6 @@ function OrderList(props: OrderListProps) { }} value={tapIndex} onChange={(paneKey) => { - console.log('Tab切换到:', paneKey, '对应状态:', tabs[paneKey]?.title, 'statusFilter:', tabs[paneKey]?.statusFilter); setTapIndex(paneKey) }} > @@ -428,11 +410,23 @@ function OrderList(props: OrderListProps) { onClick={() => Taro.navigateTo({url: `/shop/orderDetail/index?orderId=${item.orderId}`})}> - { - e.stopPropagation(); - copyText(`${item.orderNo}`) - }}>{item.orderNo} + + { + e.stopPropagation(); + copyText(`${item.orderNo}`) + }}>{item.orderNo} + {/* 添加倒计时显示 - 列表页不实时更新 */} + + + + {getOrderStatusText(item)}
)} {/* 已完成状态:显示申请退款 */}