From 46a555b27a3d5dedac8cb640b7128ec0939afcfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Mon, 11 Aug 2025 22:31:08 +0800 Subject: [PATCH] =?UTF-8?q?feat(user/order):=20=E4=BC=98=E5=8C=96=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E5=88=97=E8=A1=A8=E5=8A=9F=E8=83=BD=E5=92=8C=E6=80=A7?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加防抖搜索功能,提高搜索性能 - 优化筛选逻辑,保留初始状态筛选 - 重构订单数据加载逻辑,支持分批加载 - 完善错误处理和用户提示 - 优化取消订单功能,增加确认对话框 -调整订单状态显示逻辑 --- src/user/order/components/OrderList.tsx | 196 +++++++++++++++++------- src/user/order/order.tsx | 38 +++-- 2 files changed, 170 insertions(+), 64 deletions(-) diff --git a/src/user/order/components/OrderList.tsx b/src/user/order/components/OrderList.tsx index b22b56b..293c4c2 100644 --- a/src/user/order/components/OrderList.tsx +++ b/src/user/order/components/OrderList.tsx @@ -81,8 +81,25 @@ function OrderList(props: OrderListProps) { const [list, setList] = useState([]) const [page, setPage] = useState(1) const [hasMore, setHasMore] = useState(true) - const [tapIndex, setTapIndex] = useState(0) + // 根据传入的statusFilter设置初始tab索引 + const getInitialTabIndex = () => { + if (props.searchParams?.statusFilter !== undefined) { + // 如果statusFilter为-1,表示全部,对应index为0 + if (props.searchParams.statusFilter === -1) { + return 0; + } + const tab = tabs.find(t => t.statusFilter === props.searchParams?.statusFilter); + return tab ? tab.index : 0; + } + return 0; + }; + const [tapIndex, setTapIndex] = useState(() => { + const initialIndex = getInitialTabIndex(); + console.log('初始化tapIndex:', initialIndex, '对应statusFilter:', props.searchParams?.statusFilter); + return initialIndex; + }) const [loading, setLoading] = useState(false) + const [error, setError] = useState(null) // 获取订单状态文本 const getOrderStatusText = (order: ShopOrder) => { @@ -149,9 +166,10 @@ function OrderList(props: OrderListProps) { return params; }; - const reload = async (resetPage = false) => { + const reload = async (resetPage = false, targetPage?: number) => { setLoading(true); - const currentPage = resetPage ? 1 : page; + setError(null); // 清除之前的错误 + const currentPage = resetPage ? 1 : (targetPage || page); const statusParams = getOrderStatusParams(tapIndex); const searchConditions = { page: currentPage, @@ -169,30 +187,40 @@ function OrderList(props: OrderListProps) { let newList: OrderWithGoods[] = []; if (res?.list && res?.list.length > 0) { - // 为每个订单获取商品信息 - const ordersWithGoods = await Promise.all( - res.list.map(async (order) => { - try { - const orderGoods = await listShopOrderGoods({ orderId: order.orderId }); - return { - ...order, - orderGoods: orderGoods || [] - }; - } catch (error) { - console.error('获取订单商品失败:', error); - return { - ...order, - orderGoods: [] - }; - } - }) - ); + // 批量获取订单商品信息,限制并发数量 + const batchSize = 3; // 限制并发数量为3 + const ordersWithGoods: OrderWithGoods[] = []; + + for (let i = 0; i < res.list.length; i += batchSize) { + const batch = res.list.slice(i, i + batchSize); + const batchResults = await Promise.all( + batch.map(async (order) => { + try { + const orderGoods = await listShopOrderGoods({ orderId: order.orderId }); + return { + ...order, + orderGoods: orderGoods || [] + }; + } catch (error) { + console.error('获取订单商品失败:', error); + return { + ...order, + orderGoods: [] + }; + } + }) + ); + ordersWithGoods.push(...batchResults); + } // 合并数据 newList = resetPage ? ordersWithGoods : list?.concat(ordersWithGoods); - setHasMore(true); + + // 正确判断是否还有更多数据 + const hasMoreData = res.list.length >= 10; // 假设每页10条数据 + setHasMore(hasMoreData); } else { - newList = []; + newList = resetPage ? [] : list; setHasMore(false); } @@ -202,12 +230,20 @@ function OrderList(props: OrderListProps) { } catch (error) { console.error('加载订单失败:', error); setLoading(false); + setError('加载订单失败,请重试'); + // 添加错误提示 + Taro.showToast({ + title: '加载失败,请重试', + icon: 'none' + }); } }; const reloadMore = async () => { - setPage(page + 1); - reload(); + if (loading || !hasMore) return; // 防止重复加载 + const nextPage = page + 1; + setPage(nextPage); + await reload(false, nextPage); }; // 确认收货 @@ -233,9 +269,25 @@ function OrderList(props: OrderListProps) { // 取消订单 const cancelOrder = async (order: ShopOrder) => { try { - await removeShopOrder(order.orderId); + // 显示确认对话框 + const result = await Taro.showModal({ + title: '确认取消', + content: '确定要取消这个订单吗?', + confirmText: '确认取消', + cancelText: '我再想想' + }); + + if (!result.confirm) return; + + // 更新订单状态为已取消,而不是删除订单 + await updateShopOrder({ + ...order, + orderStatus: 2 // 已取消 + }); + Taro.showToast({ - title: '订单已删除', + title: '订单已取消', + icon: 'success' }); reload(true).then(); // 重新加载列表 props.onReload?.(); // 通知父组件刷新 @@ -243,6 +295,7 @@ function OrderList(props: OrderListProps) { console.error('取消订单失败:', error); Taro.showToast({ title: '取消订单失败', + icon: 'error' }); } }; @@ -252,6 +305,30 @@ function OrderList(props: OrderListProps) { }, [tapIndex]); // 监听tapIndex变化 useEffect(() => { + // 当外部传入的statusFilter改变时,更新对应的tab索引 + if (props.searchParams?.statusFilter !== undefined) { + let targetTabIndex = 0; + + // 如果statusFilter为-1,表示全部,对应index为0 + if (props.searchParams.statusFilter === -1) { + targetTabIndex = 0; + } else { + const tab = tabs.find(t => t.statusFilter === props.searchParams?.statusFilter); + targetTabIndex = tab ? tab.index : 0; + } + + console.log('searchParams变化:', { + statusFilter: props.searchParams.statusFilter, + currentTapIndex: tapIndex, + targetTabIndex, + shouldUpdate: targetTabIndex !== tapIndex + }); + + if (targetTabIndex !== tapIndex) { + setTapIndex(targetTabIndex); + return; // 避免重复调用reload + } + } reload(true).then(); // 搜索参数变化时重置页码 }, [props.searchParams]); // 监听搜索参数变化 @@ -278,36 +355,48 @@ function OrderList(props: OrderListProps) { tabs?.map((item, index) => { return ( ) }) }
- { - - }} - onScrollToUpper={() => { - - }} - loadingText={ - <> - 加载中 - - } - loadMoreText={ - <> - 没有更多了 - - } - > - {list?.map((item, index) => { + {error ? ( +
+
{error}
+ +
+ ) : ( + { + + }} + onScrollToUpper={() => { + + }} + loadingText={ + <> + 加载中 + + } + loadMoreText={ + <> + 没有更多了 + + } + > + {list?.map((item, index) => { return ( Taro.navigateTo({url: `/shop/orderDetail/index?orderId=${item.orderId}`})}> @@ -378,8 +467,9 @@ function OrderList(props: OrderListProps) { ) - })} - + })} +
+ )}
) diff --git a/src/user/order/order.tsx b/src/user/order/order.tsx index 18ca8b1..e0fe796 100644 --- a/src/user/order/order.tsx +++ b/src/user/order/order.tsx @@ -1,4 +1,4 @@ -import {useState} from "react"; +import {useState, useCallback, useRef} from "react"; import Taro, {useDidShow} from '@tarojs/taro' import {Space, NavBar, Button, Input} from '@nutui/nutui-react-taro' import {Search, Filter, ArrowLeft} from '@nutui/icons-react-taro' @@ -10,18 +10,32 @@ import './order.scss' function Order() { const {params} = useRouter(); - const [statusBarHeight, setStatusBarHeight] = useState() + const [statusBarHeight, setStatusBarHeight] = useState(0) // 默认值为0 const [searchParams, setSearchParams] = useState({ statusFilter: params.statusFilter != undefined && params.statusFilter != '' ? parseInt(params.statusFilter) : -1 }) const [showSearch, setShowSearch] = useState(false) const [searchKeyword, setSearchKeyword] = useState('') + const searchTimeoutRef = useRef() const reload = async (where?: ShopOrderParam) => { console.log(where,'where...') setSearchParams(prev => ({ ...prev, ...where })) } + // 防抖搜索函数 + const debouncedSearch = useCallback((keyword: string) => { + if (searchTimeoutRef.current) { + clearTimeout(searchTimeoutRef.current); + } + + searchTimeoutRef.current = setTimeout(() => { + if (keyword.trim()) { + handleSearch({keywords: keyword.trim()}); + } + }, 500); // 500ms防抖延迟 + }, []); + // 处理搜索 const handleSearch = (where: ShopOrderParam) => { setSearchParams(where) @@ -30,7 +44,10 @@ function Order() { // 重置搜索 const handleResetSearch = () => { - setSearchParams({}) + setSearchKeyword(''); // 清空搜索关键词 + setSearchParams({ + statusFilter: params.statusFilter != undefined && params.statusFilter != '' ? parseInt(params.statusFilter) : -1 + }); // 重置搜索参数,但保留初始状态筛选 reload().then() } @@ -56,10 +73,10 @@ function Order() { return ( - +
@@ -80,16 +97,12 @@ function Order() { {/* 搜索和筛选工具栏 */} - setShowSearch(!showSearch)} - /> setShowSearch(!showSearch)} /> + 筛选 @@ -101,7 +114,10 @@ function Order() { { + setSearchKeyword(value); + debouncedSearch(value); // 使用防抖搜索 + }} onConfirm={() => { if (searchKeyword.trim()) { handleSearch({keywords: searchKeyword.trim()});