Browse Source

refactor(user/order): 重构订单页面

- 移除了 OrderSearch 组件
- 简化了 OrderList 组件的接口- 优化了订单页面的逻辑结构
- 删除了未使用的 CSS 样式文件
master
科技小王子 2 weeks ago
parent
commit
8c10b4a66b
  1. 2
      src/pages/user/components/UserCard.tsx
  2. 8
      src/user/order/components/OrderList.tsx
  3. 47
      src/user/order/components/OrderSearch.scss
  4. 263
      src/user/order/components/OrderSearch.tsx
  5. 79
      src/user/order/order.tsx

2
src/pages/user/components/UserCard.tsx

@ -71,7 +71,7 @@ function UserCard() {
// 加载用户统计数据 // 加载用户统计数据
if (data.userId) { if (data.userId) {
loadUserStats(data.userId)
// loadUserStats(data.userId)
} }
// 获取openId // 获取openId

8
src/user/order/components/OrderList.tsx

@ -72,7 +72,6 @@ interface OrderWithGoods extends ShopOrder {
} }
interface OrderListProps { interface OrderListProps {
data: ShopOrder[];
onReload?: () => void; onReload?: () => void;
searchParams?: ShopOrderParam; searchParams?: ShopOrderParam;
showSearch?: boolean; showSearch?: boolean;
@ -87,7 +86,6 @@ function OrderList(props: OrderListProps) {
// 获取订单状态文本 // 获取订单状态文本
const getOrderStatusText = (order: ShopOrder) => { const getOrderStatusText = (order: ShopOrder) => {
console.log(order,'order')
// 优先检查订单状态 // 优先检查订单状态
if (order.orderStatus === 2) return '已取消'; if (order.orderStatus === 2) return '已取消';
@ -239,7 +237,7 @@ function OrderList(props: OrderListProps) {
Taro.showToast({ Taro.showToast({
title: '订单已删除', title: '订单已删除',
}); });
reload(true); // 重新加载列表
reload(true).then(); // 重新加载列表
props.onReload?.(); // 通知父组件刷新 props.onReload?.(); // 通知父组件刷新
} catch (error) { } catch (error) {
console.error('取消订单失败:', error); console.error('取消订单失败:', error);
@ -250,11 +248,11 @@ function OrderList(props: OrderListProps) {
}; };
useEffect(() => { useEffect(() => {
reload(true); // 首次加载或tab切换时重置页码
reload(true).then(); // 首次加载或tab切换时重置页码
}, [tapIndex]); // 监听tapIndex变化 }, [tapIndex]); // 监听tapIndex变化
useEffect(() => { useEffect(() => {
reload(true); // 搜索参数变化时重置页码
reload(true).then(); // 搜索参数变化时重置页码
}, [props.searchParams]); // 监听搜索参数变化 }, [props.searchParams]); // 监听搜索参数变化
return ( return (

47
src/user/order/components/OrderSearch.scss

@ -1,47 +0,0 @@
.order-search {
.search-bar {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.filter-popup {
.grid {
display: grid;
}
.grid-cols-2 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.gap-2 {
gap: 0.5rem;
}
.flex-wrap {
flex-wrap: wrap;
}
}
}
// 修复Radio按钮样式
.nut-radio {
&.nut-radio--button {
margin: 2px;
.nut-radio__label {
padding: 8px 12px;
border-radius: 4px;
font-size: 12px;
}
}
}
// 修复Input样式
.nut-input {
&.bg-transparent {
background: transparent !important;
}
&.border-none {
border: none !important;
}
}

263
src/user/order/components/OrderSearch.tsx

@ -1,263 +0,0 @@
import React, { useState } from 'react';
import { View } from '@tarojs/components';
import {
Input,
Button,
Popup,
Cell,
CellGroup,
Radio,
Space
} from '@nutui/nutui-react-taro';
import { Search, Filter, Close } from '@nutui/icons-react-taro';
import { ShopOrderParam } from '@/api/shop/shopOrder/model';
import './OrderSearch.scss';
interface OrderSearchProps {
onSearch: (params: ShopOrderParam) => void;
onReset: () => void;
}
// 订单状态选项
const orderStatusOptions = [
{ text: '全部', value: '' },
{ text: '未使用', value: 0 },
{ text: '已完成', value: 1 },
{ text: '已取消', value: 2 },
{ text: '取消中', value: 3 },
{ text: '退款申请中', value: 4 },
{ text: '退款被拒绝', value: 5 },
{ text: '退款成功', value: 6 },
{ text: '客户端申请退款', value: 7 }
];
// 支付状态选项
const payStatusOptions = [
{ text: '全部', value: '' },
{ text: '未付款', value: 0 },
{ text: '已付款', value: 1 }
];
// 支付方式选项
const payTypeOptions = [
{ text: '全部', value: '' },
{ text: '余额支付', value: 0 },
{ text: '微信支付', value: 1 },
{ text: '会员卡支付', value: 2 },
{ text: '支付宝', value: 3 },
{ text: '现金', value: 4 },
{ text: 'POS机', value: 5 }
];
const OrderSearch: React.FC<OrderSearchProps> = ({ onSearch, onReset }) => {
const [showFilter, setShowFilter] = useState(false);
const [searchParams, setSearchParams] = useState<ShopOrderParam>({
keywords: '',
orderNo: '',
phone: '',
orderStatus: undefined,
payStatus: undefined,
payType: undefined
});
// 搜索关键词
const handleKeywordSearch = () => {
if (!searchParams.keywords?.trim()) {
return;
}
onSearch({ keywords: searchParams.keywords.trim() });
};
// 重置搜索条件
const handleReset = () => {
setSearchParams({
keywords: '',
orderNo: '',
phone: '',
orderStatus: undefined,
payStatus: undefined,
payType: undefined
});
onReset();
};
// 应用筛选条件
const handleFilter = () => {
const filterParams: ShopOrderParam = {};
if (searchParams.orderNo?.trim()) {
filterParams.orderNo = searchParams.orderNo.trim();
}
if (searchParams.phone?.trim()) {
filterParams.phone = searchParams.phone.trim();
}
if (searchParams.orderStatus !== undefined) {
filterParams.orderStatus = searchParams.orderStatus;
}
if (searchParams.payStatus !== undefined) {
filterParams.payStatus = searchParams.payStatus;
}
if (searchParams.payType !== undefined) {
filterParams.payType = searchParams.payType;
}
onSearch(filterParams);
setShowFilter(false);
};
return (
<View className="order-search">
{/* 搜索栏 */}
<View className="search-bar flex items-center p-3 bg-white">
<View className="flex-1 flex items-center bg-gray-100 rounded-full px-3 py-2">
<Search size={16} className="text-gray-400 mr-2" />
<Input
placeholder="搜索订单号、商品名称"
value={searchParams.keywords}
onChange={(value) => setSearchParams(prev => ({ ...prev, keywords: value }))}
onConfirm={handleKeywordSearch}
className="flex-1 bg-transparent border-none"
style={{ padding: 0 }}
/>
</View>
<Button
type="primary"
size={'large'}
className="ml-2"
onClick={handleKeywordSearch}
>
</Button>
<View
className="ml-2 p-2 flex items-center justify-center"
onClick={() => setShowFilter(true)}
>
<Filter size={18} className="text-gray-600" />
</View>
</View>
{/* 筛选弹窗 */}
<Popup
visible={showFilter}
position="right"
onClose={() => setShowFilter(false)}
style={{ width: '80%', height: '100%' }}
>
<View className="filter-popup h-full flex flex-col">
{/* 头部 */}
<View className="flex items-center justify-between p-4 border-b">
<View className="text-lg font-medium"></View>
<Close size={20} onClick={() => setShowFilter(false)} />
</View>
{/* 筛选内容 */}
<View className="flex-1 overflow-y-auto">
<CellGroup>
{/* 订单号 */}
<Cell>
<View className="w-full">
<View className="text-sm text-gray-600 mb-2"></View>
<Input
placeholder="请输入订单号"
value={searchParams.orderNo}
onChange={(value) => setSearchParams(prev => ({ ...prev, orderNo: value }))}
/>
</View>
</Cell>
{/* 手机号 */}
<Cell>
<View className="w-full">
<View className="text-sm text-gray-600 mb-2"></View>
<Input
placeholder="请输入手机号"
value={searchParams.phone}
onChange={(value) => setSearchParams(prev => ({ ...prev, phone: value }))}
/>
</View>
</Cell>
{/* 订单状态 */}
<Cell>
<View className="w-full">
<View className="text-sm text-gray-600 mb-2"></View>
<Radio.Group
value={searchParams.orderStatus}
onChange={(value) => setSearchParams(prev => ({ ...prev, orderStatus: Number(value) }))}
>
<View className="grid grid-cols-2 gap-2">
{orderStatusOptions.map((option) => (
<Radio key={option.value} value={option.value} shape="button">
{option.text}
</Radio>
))}
</View>
</Radio.Group>
</View>
</Cell>
{/* 支付状态 */}
<Cell>
<View className="w-full">
<View className="text-sm text-gray-600 mb-2"></View>
<Radio.Group
value={searchParams.payStatus}
onChange={(value) => setSearchParams(prev => ({ ...prev, payStatus: Number(value) }))}
>
<View className="flex flex-wrap gap-2">
{payStatusOptions.map((option) => (
<Radio key={option.value} value={option.value} shape="button">
{option.text}
</Radio>
))}
</View>
</Radio.Group>
</View>
</Cell>
{/* 支付方式 */}
<Cell>
<View className="w-full">
<View className="text-sm text-gray-600 mb-2"></View>
<Radio.Group
value={searchParams.payType}
onChange={(value) => setSearchParams(prev => ({ ...prev, payType: Number(value) }))}
>
<View className="grid grid-cols-2 gap-2">
{payTypeOptions.map((option) => (
<Radio key={option.value} value={option.value} shape="button">
{option.text}
</Radio>
))}
</View>
</Radio.Group>
</View>
</Cell>
</CellGroup>
</View>
{/* 底部按钮 */}
<View className="p-4 border-t">
<Space className="w-full">
<Button
className="flex-1"
onClick={handleReset}
>
</Button>
<Button
type="primary"
className="flex-1"
onClick={handleFilter}
>
</Button>
</Space>
</View>
</View>
</Popup>
</View>
);
};
export default OrderSearch;

79
src/user/order/order.tsx

@ -1,42 +1,37 @@
import {useState} from "react"; import {useState} from "react";
import Taro, {useDidShow} from '@tarojs/taro' import Taro, {useDidShow} from '@tarojs/taro'
import {Space, NavBar, Empty, Button, ConfigProvider, Input} from '@nutui/nutui-react-taro'
import {Space, NavBar, Button, Input} from '@nutui/nutui-react-taro'
import {Search, Filter, ArrowLeft} from '@nutui/icons-react-taro' import {Search, Filter, ArrowLeft} from '@nutui/icons-react-taro'
import {View} from '@tarojs/components'; import {View} from '@tarojs/components';
import OrderList from "./components/OrderList"; import OrderList from "./components/OrderList";
// import OrderSearch from "./components/OrderSearch";
import {ShopOrder, ShopOrderParam} from "@/api/shop/shopOrder/model";
import {pageShopOrder} from "@/api/shop/shopOrder";
import {useRouter} from '@tarojs/taro'
import {ShopOrderParam} from "@/api/shop/shopOrder/model";
import './order.scss' import './order.scss'
function Order() { function Order() {
const {params} = useRouter();
const [statusBarHeight, setStatusBarHeight] = useState<number>() const [statusBarHeight, setStatusBarHeight] = useState<number>()
const [list, setList] = useState<ShopOrder[]>([])
const [searchParams, setSearchParams] = useState<ShopOrderParam>({})
const [searchParams, setSearchParams] = useState<ShopOrderParam>({
statusFilter: params.statusFilter != undefined && params.statusFilter != '' ? parseInt(params.statusFilter) : -1
})
const [showSearch, setShowSearch] = useState(false) const [showSearch, setShowSearch] = useState(false)
const [searchKeyword, setSearchKeyword] = useState('') const [searchKeyword, setSearchKeyword] = useState('')
const reload = async (params?: ShopOrderParam) => {
const searchConditions = {
userId: Taro.getStorageSync('UserId'),
...params
}
const orders = await pageShopOrder(searchConditions)
if (orders) {
setList(orders.list || [])
}
const reload = async (where?: ShopOrderParam) => {
console.log(where,'where...')
setSearchParams(prev => ({ ...prev, ...where }))
} }
// 处理搜索 // 处理搜索
const handleSearch = (params: ShopOrderParam) => {
setSearchParams(params)
reload(params)
const handleSearch = (where: ShopOrderParam) => {
setSearchParams(where)
reload(where).then()
} }
// 重置搜索 // 重置搜索
const handleResetSearch = () => { const handleResetSearch = () => {
setSearchParams({}) setSearchParams({})
reload()
reload().then()
} }
useDidShow(() => { useDidShow(() => {
@ -96,9 +91,6 @@ function Order() {
onClick={() => setShowSearch(!showSearch)} onClick={() => setShowSearch(!showSearch)}
/> />
</View> </View>
<View className="text-sm text-gray-500">
{list.length}
</View>
</View> </View>
{/* 搜索组件 */} {/* 搜索组件 */}
@ -147,36 +139,31 @@ function Order() {
</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>
)}
{/*{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>*/}
{/*)}*/}
{/*订单列表*/} {/*订单列表*/}
{
list.length > 0 && (
<OrderList <OrderList
data={list}
onReload={() => reload(searchParams)} onReload={() => reload(searchParams)}
searchParams={searchParams} searchParams={searchParams}
showSearch={showSearch} showSearch={showSearch}
/> />
)
}
</View> </View>
); );
} }

Loading…
Cancel
Save