refactor(user): 优化用户订单相关功能
- 移除 coupon API 中的 SERVER_API_URL,直接使用相对路径 - 优化 order 页面的搜索和重置逻辑- 更新 OrderList 组件,支持空订单时显示 Empty 组件- 调整 UserCard 中的用户统计数据加载逻辑 - 修改 UserOrder 组件中的订单状态文本和链接
This commit is contained in:
@@ -1,14 +1,13 @@
|
||||
import request from '@/utils/request';
|
||||
import type { ApiResult, PageResult } from '@/api/index';
|
||||
import type { UserCoupon, UserCouponParam } from './model';
|
||||
import {SERVER_API_URL} from "@/utils/server";
|
||||
|
||||
/**
|
||||
* 分页查询用户优惠券
|
||||
*/
|
||||
export async function pageUserCoupon(params: UserCouponParam) {
|
||||
const res = await request.get<ApiResult<PageResult<UserCoupon>>>(
|
||||
SERVER_API_URL + '/sys/user-coupon/page',
|
||||
'/sys/user-coupon/page',
|
||||
params
|
||||
);
|
||||
if (res.code === 0) {
|
||||
@@ -22,7 +21,7 @@ export async function pageUserCoupon(params: UserCouponParam) {
|
||||
*/
|
||||
export async function listUserCoupon(params?: UserCouponParam) {
|
||||
const res = await request.get<ApiResult<UserCoupon[]>>(
|
||||
SERVER_API_URL + '/sys/user-coupon',
|
||||
'/sys/user-coupon',
|
||||
params
|
||||
);
|
||||
if (res.code === 0 && res.data) {
|
||||
@@ -41,7 +40,7 @@ export async function getUserCouponCount(userId: number) {
|
||||
used: number;
|
||||
expired: number;
|
||||
}>>(
|
||||
SERVER_API_URL + '/sys/user-coupon/count',
|
||||
'/sys/user-coupon/count',
|
||||
{ userId }
|
||||
);
|
||||
if (res.code === 0 && res.data) {
|
||||
@@ -55,7 +54,7 @@ export async function getUserCouponCount(userId: number) {
|
||||
*/
|
||||
export async function getUserCoupon(id: number) {
|
||||
const res = await request.get<ApiResult<UserCoupon>>(
|
||||
SERVER_API_URL + '/sys/user-coupon/' + id
|
||||
'/sys/user-coupon/' + id
|
||||
);
|
||||
if (res.code === 0 && res.data) {
|
||||
return res.data;
|
||||
@@ -68,7 +67,7 @@ export async function getUserCoupon(id: number) {
|
||||
*/
|
||||
export async function useCoupon(couponId: number, orderId: number) {
|
||||
const res = await request.put<ApiResult<unknown>>(
|
||||
SERVER_API_URL + '/sys/user-coupon/use',
|
||||
'/sys/user-coupon/use',
|
||||
{ couponId, orderId }
|
||||
);
|
||||
if (res.code === 0) {
|
||||
|
||||
@@ -71,7 +71,7 @@ function UserCard() {
|
||||
|
||||
// 加载用户统计数据
|
||||
if (data.userId) {
|
||||
// loadUserStats(data.userId)
|
||||
loadUserStats(data.userId)
|
||||
}
|
||||
|
||||
// 获取openId
|
||||
|
||||
@@ -51,10 +51,10 @@ function UserOrder() {
|
||||
<View className={'item flex justify-center flex-col items-center'}
|
||||
onClick={() => navTo('/user/order/order?statusFilter=5', true)}>
|
||||
<Comment size={24} className={'text-gray-500 font-normal'}/>
|
||||
<Text className={'text-sm text-gray-600 py-1'}>待评价</Text>
|
||||
<Text className={'text-sm text-gray-600 py-1'}>已完成</Text>
|
||||
</View>
|
||||
<View className={'item flex justify-center flex-col items-center'}
|
||||
onClick={() => navTo('/user/order/order?statusFilter=7', true)}>
|
||||
onClick={() => navTo('/user/order/order?statusFilter=6', true)}>
|
||||
<Refund size={26} className={'font-normal text-gray-500'}/>
|
||||
<Text className={'text-sm text-gray-600 py-1'}>退货/售后</Text>
|
||||
</View>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Avatar, Cell, Space, Tabs, Button, TabPane, Image} from '@nutui/nutui-react-taro'
|
||||
import {Avatar, Cell, Space, Empty, Tabs, Button, TabPane, Image} from '@nutui/nutui-react-taro'
|
||||
import {useEffect, useState, CSSProperties} from "react";
|
||||
import {View} from '@tarojs/components'
|
||||
import Taro from '@tarojs/taro';
|
||||
@@ -27,7 +27,7 @@ const tabs = [
|
||||
key: '全部',
|
||||
title: '全部',
|
||||
description: '所有订单',
|
||||
statusFilter: undefined // 不传statusFilter,显示所有订单
|
||||
statusFilter: -1 // 使用-1表示全部订单
|
||||
},
|
||||
{
|
||||
index: 1,
|
||||
@@ -59,9 +59,9 @@ const tabs = [
|
||||
},
|
||||
{
|
||||
index: 5,
|
||||
key: '已取消',
|
||||
title: '已取消',
|
||||
description: '已取消/退款的订单',
|
||||
key: '退货/售后',
|
||||
title: '退货/售后',
|
||||
description: '退货/售后的订单',
|
||||
statusFilter: 6 // 对应后端:order_status = 6 (已退款)
|
||||
}
|
||||
]
|
||||
@@ -84,10 +84,6 @@ function OrderList(props: OrderListProps) {
|
||||
// 根据传入的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;
|
||||
}
|
||||
@@ -117,7 +113,7 @@ function OrderList(props: OrderListProps) {
|
||||
// 已付款后检查发货状态
|
||||
if (order.deliveryStatus === 10) return '待发货';
|
||||
if (order.deliveryStatus === 20) return '待收货';
|
||||
if (order.deliveryStatus === 30) return '已收货';
|
||||
if (order.deliveryStatus === 30) return '已完成';
|
||||
|
||||
// 最后检查订单完成状态
|
||||
if (order.orderStatus === 1) return '已完成';
|
||||
@@ -161,6 +157,7 @@ function OrderList(props: OrderListProps) {
|
||||
if (currentTab && currentTab.statusFilter !== undefined) {
|
||||
params.statusFilter = currentTab.statusFilter;
|
||||
}
|
||||
// 注意:当statusFilter为undefined时,不要添加到params中,这样API请求就不会包含这个参数
|
||||
|
||||
console.log(`Tab ${index} (${currentTab?.title}) 筛选参数:`, params);
|
||||
return params;
|
||||
@@ -172,16 +169,21 @@ function OrderList(props: OrderListProps) {
|
||||
const currentPage = resetPage ? 1 : (targetPage || page);
|
||||
const statusParams = getOrderStatusParams(tapIndex);
|
||||
// 合并搜索条件,tab的statusFilter优先级更高
|
||||
const searchConditions = {
|
||||
const searchConditions: any = {
|
||||
page: currentPage,
|
||||
userId: statusParams.userId, // 用户ID
|
||||
...props.searchParams, // 搜索关键词等其他条件
|
||||
statusFilter: statusParams.statusFilter // tab的statusFilter优先级最高
|
||||
};
|
||||
|
||||
// statusFilter总是添加到搜索条件中(包括-1表示全部)
|
||||
if (statusParams.statusFilter !== undefined) {
|
||||
searchConditions.statusFilter = statusParams.statusFilter;
|
||||
}
|
||||
console.log('订单筛选条件:', {
|
||||
tapIndex,
|
||||
statusParams,
|
||||
searchConditions
|
||||
searchConditions,
|
||||
finalStatusFilter: searchConditions.statusFilter
|
||||
});
|
||||
|
||||
try {
|
||||
@@ -198,7 +200,7 @@ function OrderList(props: OrderListProps) {
|
||||
const batchResults = await Promise.all(
|
||||
batch.map(async (order) => {
|
||||
try {
|
||||
const orderGoods = await listShopOrderGoods({ orderId: order.orderId });
|
||||
const orderGoods = await listShopOrderGoods({orderId: order.orderId});
|
||||
return {
|
||||
...order,
|
||||
orderGoods: orderGoods || []
|
||||
@@ -306,10 +308,34 @@ function OrderList(props: OrderListProps) {
|
||||
reload(true).then(); // 首次加载或tab切换时重置页码
|
||||
}, [tapIndex]); // 监听tapIndex变化
|
||||
|
||||
// 监听外部statusFilter变化,同步更新tab索引
|
||||
useEffect(() => {
|
||||
// 当外部传入的搜索参数变化时(不包括statusFilter,因为tab切换会处理)
|
||||
// 获取当前的statusFilter,如果未定义则默认为-1(全部)
|
||||
const currentStatusFilter = props.searchParams?.statusFilter !== undefined
|
||||
? props.searchParams.statusFilter
|
||||
: -1;
|
||||
|
||||
const tab = tabs.find(t => t.statusFilter === currentStatusFilter);
|
||||
const targetTabIndex = tab ? tab.index : 0;
|
||||
|
||||
console.log('外部statusFilter变化:', {
|
||||
statusFilter: currentStatusFilter,
|
||||
originalStatusFilter: props.searchParams?.statusFilter,
|
||||
currentTapIndex: tapIndex,
|
||||
targetTabIndex,
|
||||
shouldUpdate: targetTabIndex !== tapIndex
|
||||
});
|
||||
|
||||
if (targetTabIndex !== tapIndex) {
|
||||
setTapIndex(targetTabIndex);
|
||||
// 不需要调用reload,因为tapIndex变化会触发reload
|
||||
}
|
||||
}, [props.searchParams?.statusFilter]); // 监听statusFilter变化
|
||||
|
||||
useEffect(() => {
|
||||
// 当外部传入的搜索参数变化时(不包括statusFilter,因为上面已经处理)
|
||||
// 只有当搜索关键词等其他条件变化时才重新加载
|
||||
const { statusFilter, ...otherParams } = props.searchParams || {};
|
||||
const {statusFilter, ...otherParams} = props.searchParams || {};
|
||||
|
||||
// 检查是否有除statusFilter外的其他搜索条件变化
|
||||
const hasOtherSearchParams = Object.keys(otherParams).some(key =>
|
||||
@@ -385,18 +411,28 @@ function OrderList(props: OrderListProps) {
|
||||
</>
|
||||
}
|
||||
loadMoreText={
|
||||
list.length === 0 ? (
|
||||
<Empty style={{ backgroundColor: 'transparent' }} description="您还没有订单哦"/>
|
||||
) : (
|
||||
<View className={'h-24'}>
|
||||
没有更多了
|
||||
</View>
|
||||
)
|
||||
}
|
||||
>
|
||||
{list?.map((item, index) => {
|
||||
|
||||
{/* 订单列表 */}
|
||||
{list.length > 0 && list?.map((item, index) => {
|
||||
return (
|
||||
<Cell key={index} style={{padding: '16px'}} onClick={() => Taro.navigateTo({url: `/shop/orderDetail/index?orderId=${item.orderId}`})}>
|
||||
<Cell key={index} style={{padding: '16px'}}
|
||||
onClick={() => Taro.navigateTo({url: `/shop/orderDetail/index?orderId=${item.orderId}`})}>
|
||||
<Space direction={'vertical'} className={'w-full flex flex-col'}>
|
||||
<View className={'order-no flex justify-between'}>
|
||||
<View className={'text-gray-600 font-bold text-sm'}
|
||||
onClick={(e) => {e.stopPropagation(); copyText(`${item.orderNo}`)}}>{item.orderNo}</View>
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copyText(`${item.orderNo}`)
|
||||
}}>{item.orderNo}</View>
|
||||
<View className={`${getOrderStatusColor(item)} font-medium`}>{getOrderStatusText(item)}</View>
|
||||
</View>
|
||||
<div
|
||||
@@ -444,17 +480,29 @@ function OrderList(props: OrderListProps) {
|
||||
{/* 待付款状态:显示取消订单和立即支付 */}
|
||||
{(!item.payStatus) && item.orderStatus !== 2 && (
|
||||
<Space>
|
||||
<Button size={'small'} onClick={(e) => {e.stopPropagation(); cancelOrder(item)}}>取消订单</Button>
|
||||
<Button size={'small'} type="primary" onClick={(e) => {e.stopPropagation(); console.log('立即支付')}}>立即支付</Button>
|
||||
<Button size={'small'} onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
cancelOrder(item)
|
||||
}}>取消订单</Button>
|
||||
<Button size={'small'} type="primary" onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
console.log('立即支付')
|
||||
}}>立即支付</Button>
|
||||
</Space>
|
||||
)}
|
||||
{/* 待收货状态:显示确认收货 */}
|
||||
{item.deliveryStatus === 20 && (
|
||||
<Button size={'small'} type="primary" onClick={(e) => {e.stopPropagation(); confirmReceive(item)}}>确认收货</Button>
|
||||
<Button size={'small'} type="primary" onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
confirmReceive(item)
|
||||
}}>确认收货</Button>
|
||||
)}
|
||||
{/* 已完成状态:显示申请退款 */}
|
||||
{item.orderStatus === 1 && (
|
||||
<Button size={'small'} onClick={(e) => {e.stopPropagation(); console.log('申请退款')}}>申请退款</Button>
|
||||
<Button size={'small'} onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
console.log('申请退款')
|
||||
}}>申请退款</Button>
|
||||
)}
|
||||
{/* 退款相关状态的按钮可以在这里添加 */}
|
||||
</Space>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {useState, useCallback, useRef} from "react";
|
||||
import Taro, {useDidShow} from '@tarojs/taro'
|
||||
import {useState, useCallback, useRef, useEffect} from "react";
|
||||
import Taro from '@tarojs/taro'
|
||||
import {Space, NavBar, Button, Input} from '@nutui/nutui-react-taro'
|
||||
import {Search, Filter, ArrowLeft} from '@nutui/icons-react-taro'
|
||||
import {View} from '@tarojs/components';
|
||||
@@ -32,26 +32,27 @@ function Order() {
|
||||
searchTimeoutRef.current = setTimeout(() => {
|
||||
if (keyword.trim()) {
|
||||
handleSearch({keywords: keyword.trim()});
|
||||
} else {
|
||||
// 如果搜索关键词为空,清除keywords参数
|
||||
const newSearchParams = { ...searchParams };
|
||||
delete newSearchParams.keywords;
|
||||
setSearchParams(newSearchParams);
|
||||
reload(newSearchParams).then();
|
||||
}
|
||||
}, 500); // 500ms防抖延迟
|
||||
}, []);
|
||||
}, [searchParams]);
|
||||
|
||||
// 处理搜索
|
||||
const handleSearch = (where: ShopOrderParam) => {
|
||||
setSearchParams(where)
|
||||
reload(where).then()
|
||||
// 合并搜索参数,保留当前的statusFilter
|
||||
const newSearchParams = {
|
||||
...searchParams, // 保留当前的所有参数(包括statusFilter)
|
||||
...where // 应用新的搜索条件
|
||||
};
|
||||
setSearchParams(newSearchParams)
|
||||
reload(newSearchParams).then()
|
||||
}
|
||||
|
||||
// 重置搜索
|
||||
const handleResetSearch = () => {
|
||||
setSearchKeyword(''); // 清空搜索关键词
|
||||
setSearchParams({
|
||||
statusFilter: params.statusFilter != undefined && params.statusFilter != '' ? parseInt(params.statusFilter) : -1
|
||||
}); // 重置搜索参数,但保留初始状态筛选
|
||||
reload().then()
|
||||
}
|
||||
|
||||
useDidShow(() => {
|
||||
useEffect(() => {
|
||||
// 获取状态栏高度
|
||||
Taro.getSystemInfo({
|
||||
success: (res) => {
|
||||
@@ -69,7 +70,7 @@ function Order() {
|
||||
});
|
||||
|
||||
reload().then()
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<View className="bg-gray-50 min-h-screen">
|
||||
@@ -142,38 +143,11 @@ function Order() {
|
||||
>
|
||||
搜索
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setSearchKeyword('');
|
||||
handleResetSearch();
|
||||
}}
|
||||
>
|
||||
重置
|
||||
</Button>
|
||||
</Space>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
{/*暂无订单*/}
|
||||
{/*{list.length == 0 && (*/}
|
||||
{/* <ConfigProvider>*/}
|
||||
{/* <div className={'h-full flex flex-col justify-center items-center'} style={{*/}
|
||||
{/* height: showSearch ? 'calc(100vh - 200px)' : 'calc(100vh - 150px)',*/}
|
||||
{/* marginTop: showSearch ? '60px' : '0'*/}
|
||||
{/* }}>*/}
|
||||
{/* <Empty*/}
|
||||
{/* style={{*/}
|
||||
{/* backgroundColor: 'transparent'*/}
|
||||
{/* }}*/}
|
||||
{/* description="您还没有订单哦"*/}
|
||||
{/* />*/}
|
||||
{/* <Space>*/}
|
||||
{/* <Button type="success" fill="dashed"*/}
|
||||
{/* onClick={() => Taro.switchTab({url: '/pages/index/index'})}>去挑选商品</Button>*/}
|
||||
{/* </Space>*/}
|
||||
{/* </div>*/}
|
||||
{/* </ConfigProvider>*/}
|
||||
{/*)}*/}
|
||||
|
||||
{/*订单列表*/}
|
||||
<OrderList
|
||||
onReload={() => reload(searchParams)}
|
||||
|
||||
Reference in New Issue
Block a user