forked from gxwebsoft/mp-10550
refactor(app): 重构用户中心和订单相关页面
-调整了 app.config.ts 中的页面路径和顺序 - 移除了 article 页面 - 重构了 cart、find、order 和 user 页面的布局和功能 - 优化了导航栏和订单状态的显示逻辑 - 统一了页面样式和图标使用
This commit is contained in:
391
src/user/order/components/OrderList.tsx
Normal file
391
src/user/order/components/OrderList.tsx
Normal file
@@ -0,0 +1,391 @@
|
||||
import {Avatar, Cell, Space, 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';
|
||||
import {InfiniteLoading} from '@nutui/nutui-react-taro'
|
||||
import dayjs from "dayjs";
|
||||
import {pageShopOrder, removeShopOrder, updateShopOrder} 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";
|
||||
|
||||
const getInfiniteUlStyle = (showSearch: boolean = false): CSSProperties => ({
|
||||
marginTop: showSearch ? '65px' : '44px', // 如果显示搜索框,增加更多的上边距
|
||||
height: showSearch ? '75vh' : '82vh', // 相应调整高度
|
||||
width: '100%',
|
||||
padding: '0',
|
||||
overflowY: 'auto',
|
||||
overflowX: 'hidden',
|
||||
boxShadow: '0 0 10px rgba(0, 0, 0, 0.1)',
|
||||
})
|
||||
|
||||
// 统一的订单状态标签配置,与后端 statusFilter 保持一致
|
||||
const tabs = [
|
||||
{
|
||||
index: 0,
|
||||
key: '全部',
|
||||
title: '全部',
|
||||
description: '所有订单',
|
||||
statusFilter: undefined // 不传statusFilter,显示所有订单
|
||||
},
|
||||
{
|
||||
index: 1,
|
||||
key: '待付款',
|
||||
title: '待付款',
|
||||
description: '等待付款的订单',
|
||||
statusFilter: 0 // 对应后端:pay_status = false
|
||||
},
|
||||
{
|
||||
index: 2,
|
||||
key: '待发货',
|
||||
title: '待发货',
|
||||
description: '已付款待发货的订单',
|
||||
statusFilter: 1 // 对应后端:pay_status = true AND delivery_status = 10
|
||||
},
|
||||
{
|
||||
index: 3,
|
||||
key: '待收货',
|
||||
title: '待收货',
|
||||
description: '已发货待收货的订单',
|
||||
statusFilter: 3 // 对应后端:pay_status = true AND delivery_status = 20
|
||||
},
|
||||
{
|
||||
index: 4,
|
||||
key: '已完成',
|
||||
title: '已完成',
|
||||
description: '已完成的订单',
|
||||
statusFilter: 5 // 对应后端:order_status = 1
|
||||
},
|
||||
{
|
||||
index: 5,
|
||||
key: '已取消',
|
||||
title: '已取消',
|
||||
description: '已取消/退款的订单',
|
||||
statusFilter: 6 // 对应后端:order_status = 6 (已退款)
|
||||
}
|
||||
]
|
||||
|
||||
// 扩展订单接口,包含商品信息
|
||||
interface OrderWithGoods extends ShopOrder {
|
||||
orderGoods?: ShopOrderGoods[];
|
||||
}
|
||||
|
||||
interface OrderListProps {
|
||||
data: ShopOrder[];
|
||||
onReload?: () => void;
|
||||
searchParams?: ShopOrderParam;
|
||||
showSearch?: boolean;
|
||||
}
|
||||
|
||||
function OrderList(props: OrderListProps) {
|
||||
const [list, setList] = useState<OrderWithGoods[]>([])
|
||||
const [page, setPage] = useState(1)
|
||||
const [hasMore, setHasMore] = useState(true)
|
||||
const [tapIndex, setTapIndex] = useState<string | number>(0)
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
// 获取订单状态文本
|
||||
const getOrderStatusText = (order: ShopOrder) => {
|
||||
console.log(order,'order')
|
||||
|
||||
// 优先检查订单状态
|
||||
if (order.orderStatus === 2) return '已取消';
|
||||
if (order.orderStatus === 4) return '退款申请中';
|
||||
if (order.orderStatus === 5) return '退款被拒绝';
|
||||
if (order.orderStatus === 6) return '退款成功';
|
||||
if (order.orderStatus === 7) return '客户端申请退款';
|
||||
|
||||
// 检查支付状态 (payStatus为boolean类型,false/0表示未付款,true/1表示已付款)
|
||||
if (!order.payStatus) return '等待买家付款';
|
||||
|
||||
// 已付款后检查发货状态
|
||||
if (order.deliveryStatus === 10) return '待发货';
|
||||
if (order.deliveryStatus === 20) return '待收货';
|
||||
if (order.deliveryStatus === 30) return '已收货';
|
||||
|
||||
// 最后检查订单完成状态
|
||||
if (order.orderStatus === 1) return '已完成';
|
||||
if (order.orderStatus === 0) return '未使用';
|
||||
|
||||
return '未知状态';
|
||||
};
|
||||
|
||||
// 获取订单状态颜色
|
||||
const getOrderStatusColor = (order: ShopOrder) => {
|
||||
// 优先检查订单状态
|
||||
if (order.orderStatus === 2) return 'text-gray-500'; // 已取消
|
||||
if (order.orderStatus === 4) return 'text-orange-500'; // 退款申请中
|
||||
if (order.orderStatus === 5) return 'text-red-500'; // 退款被拒绝
|
||||
if (order.orderStatus === 6) return 'text-green-500'; // 退款成功
|
||||
if (order.orderStatus === 7) return 'text-orange-500'; // 客户端申请退款
|
||||
|
||||
// 检查支付状态
|
||||
if (!order.payStatus) return 'text-orange-500'; // 等待买家付款
|
||||
|
||||
// 已付款后检查发货状态
|
||||
if (order.deliveryStatus === 10) return 'text-blue-500'; // 待发货
|
||||
if (order.deliveryStatus === 20) return 'text-purple-500'; // 待收货
|
||||
if (order.deliveryStatus === 30) return 'text-green-500'; // 已收货
|
||||
|
||||
// 最后检查订单完成状态
|
||||
if (order.orderStatus === 1) return 'text-green-600'; // 已完成
|
||||
if (order.orderStatus === 0) return 'text-gray-500'; // 未使用
|
||||
|
||||
return 'text-gray-600'; // 默认颜色
|
||||
};
|
||||
|
||||
// 使用后端统一的 statusFilter 进行筛选
|
||||
const getOrderStatusParams = (index: string | number) => {
|
||||
let params: ShopOrderParam = {};
|
||||
// 添加用户ID过滤
|
||||
params.userId = Taro.getStorageSync('UserId');
|
||||
|
||||
// 获取当前tab的statusFilter配置
|
||||
const currentTab = tabs.find(tab => tab.index === Number(index));
|
||||
if (currentTab && currentTab.statusFilter !== undefined) {
|
||||
params.statusFilter = currentTab.statusFilter;
|
||||
}
|
||||
|
||||
console.log(`Tab ${index} (${currentTab?.title}) 筛选参数:`, params);
|
||||
return params;
|
||||
};
|
||||
|
||||
const reload = async (resetPage = false) => {
|
||||
setLoading(true);
|
||||
const currentPage = resetPage ? 1 : page;
|
||||
const statusParams = getOrderStatusParams(tapIndex);
|
||||
const searchConditions = {
|
||||
page: currentPage,
|
||||
...statusParams,
|
||||
...props.searchParams
|
||||
};
|
||||
console.log('订单筛选条件:', {
|
||||
tapIndex,
|
||||
statusParams,
|
||||
searchConditions
|
||||
});
|
||||
|
||||
try {
|
||||
const res = await pageShopOrder(searchConditions);
|
||||
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: []
|
||||
};
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// 合并数据
|
||||
newList = resetPage ? ordersWithGoods : list?.concat(ordersWithGoods);
|
||||
setHasMore(true);
|
||||
} else {
|
||||
newList = [];
|
||||
setHasMore(false);
|
||||
}
|
||||
|
||||
setList(newList || []);
|
||||
setPage(currentPage);
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
console.error('加载订单失败:', error);
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const reloadMore = async () => {
|
||||
setPage(page + 1);
|
||||
reload();
|
||||
};
|
||||
|
||||
// 确认收货
|
||||
const confirmReceive = async (order: ShopOrder) => {
|
||||
try {
|
||||
await updateShopOrder({
|
||||
...order,
|
||||
deliveryStatus: 30, // 已收货
|
||||
orderStatus: 1 // 已完成
|
||||
});
|
||||
Taro.showToast({
|
||||
title: '确认收货成功',
|
||||
});
|
||||
reload(true); // 重新加载列表
|
||||
props.onReload?.(); // 通知父组件刷新
|
||||
} catch (error) {
|
||||
Taro.showToast({
|
||||
title: '确认收货失败',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 取消订单
|
||||
const cancelOrder = async (order: ShopOrder) => {
|
||||
try {
|
||||
await removeShopOrder(order.orderId);
|
||||
Taro.showToast({
|
||||
title: '订单已删除',
|
||||
});
|
||||
reload(true); // 重新加载列表
|
||||
props.onReload?.(); // 通知父组件刷新
|
||||
} catch (error) {
|
||||
console.error('取消订单失败:', error);
|
||||
Taro.showToast({
|
||||
title: '取消订单失败',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
reload(true); // 首次加载或tab切换时重置页码
|
||||
}, [tapIndex]); // 监听tapIndex变化
|
||||
|
||||
useEffect(() => {
|
||||
reload(true); // 搜索参数变化时重置页码
|
||||
}, [props.searchParams]); // 监听搜索参数变化
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tabs
|
||||
align={'left'}
|
||||
className={'fixed left-0'}
|
||||
style={{
|
||||
top: '44px',
|
||||
zIndex: 998,
|
||||
borderBottom: '1px solid #e5e5e5'
|
||||
}}
|
||||
tabStyle={{
|
||||
backgroundColor: '#ffffff',
|
||||
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
|
||||
}}
|
||||
value={tapIndex}
|
||||
onChange={(paneKey) => {
|
||||
console.log('Tab切换到:', paneKey, '对应状态:', tabs[paneKey]?.title);
|
||||
setTapIndex(paneKey)
|
||||
}}
|
||||
>
|
||||
{
|
||||
tabs?.map((item, index) => {
|
||||
return (
|
||||
<TabPane
|
||||
key={index}
|
||||
title={loading && tapIndex === index ? `${item.title}...` : item.title}
|
||||
></TabPane>
|
||||
)
|
||||
})
|
||||
}
|
||||
</Tabs>
|
||||
<div style={getInfiniteUlStyle(props.showSearch)} id="scroll">
|
||||
<InfiniteLoading
|
||||
target="scroll"
|
||||
hasMore={hasMore}
|
||||
onLoadMore={reloadMore}
|
||||
onScroll={() => {
|
||||
|
||||
}}
|
||||
onScrollToUpper={() => {
|
||||
|
||||
}}
|
||||
loadingText={
|
||||
<>
|
||||
加载中
|
||||
</>
|
||||
}
|
||||
loadMoreText={
|
||||
<>
|
||||
没有更多了
|
||||
</>
|
||||
}
|
||||
>
|
||||
{list?.map((item, index) => {
|
||||
return (
|
||||
<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>
|
||||
<View className={`${getOrderStatusColor(item)} font-medium`}>{getOrderStatusText(item)}</View>
|
||||
</View>
|
||||
<div
|
||||
className={'create-time text-gray-400 text-xs'}>{dayjs(item.createTime).format('YYYY年MM月DD日 HH:mm:ss')}</div>
|
||||
|
||||
{/* 商品信息 */}
|
||||
<div className={'goods-info'}>
|
||||
{item.orderGoods && item.orderGoods.length > 0 ? (
|
||||
item.orderGoods.map((goods, goodsIndex) => (
|
||||
<div key={goodsIndex} className={'flex items-center mb-2'}>
|
||||
<Image
|
||||
src={goods.image || '/default-goods.png'}
|
||||
width="50"
|
||||
height="50"
|
||||
lazyLoad={false}
|
||||
className={'rounded'}
|
||||
/>
|
||||
<div className={'ml-2 flex-1'}>
|
||||
<div className={'text-sm font-bold'}>{goods.goodsName}</div>
|
||||
{goods.spec && <div className={'text-gray-500 text-xs'}>规格:{goods.spec}</div>}
|
||||
<div className={'text-gray-500 text-xs'}>数量:{goods.totalNum}</div>
|
||||
</div>
|
||||
<div className={'text-sm'}>¥{goods.price}</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className={'flex items-center'}>
|
||||
<Avatar
|
||||
src='/default-goods.png'
|
||||
size={'50'}
|
||||
shape={'square'}
|
||||
/>
|
||||
<div className={'ml-2'}>
|
||||
<div className={'text-sm'}>{item.title || '订单商品'}</div>
|
||||
<div className={'text-gray-400 text-xs'}>{item.totalNum}件商品</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={'w-full text-right'}>实付金额:¥{item.payPrice}</div>
|
||||
|
||||
{/* 操作按钮 */}
|
||||
<Space className={'btn flex justify-end'}>
|
||||
{/* 待付款状态:显示取消订单和立即支付 */}
|
||||
{(!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>
|
||||
</Space>
|
||||
)}
|
||||
{/* 待收货状态:显示确认收货 */}
|
||||
{item.deliveryStatus === 20 && (
|
||||
<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>
|
||||
)}
|
||||
{/* 退款相关状态的按钮可以在这里添加 */}
|
||||
</Space>
|
||||
</Space>
|
||||
</Cell>
|
||||
)
|
||||
})}
|
||||
</InfiniteLoading>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default OrderList
|
||||
47
src/user/order/components/OrderSearch.scss
Normal file
47
src/user/order/components/OrderSearch.scss
Normal file
@@ -0,0 +1,47 @@
|
||||
.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
Normal file
263
src/user/order/components/OrderSearch.tsx
Normal file
@@ -0,0 +1,263 @@
|
||||
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;
|
||||
4
src/user/order/order.config.ts
Normal file
4
src/user/order/order.config.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '订单列表',
|
||||
navigationStyle: 'custom'
|
||||
})
|
||||
72
src/user/order/order.scss
Normal file
72
src/user/order/order.scss
Normal file
@@ -0,0 +1,72 @@
|
||||
page {
|
||||
background: linear-gradient(to bottom, #f3f3f3, #f9fafb);
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
transition: all 0.3s ease;
|
||||
|
||||
.nut-input {
|
||||
background-color: #f8f9fa !important;
|
||||
border: 1px solid #e5e5e5 !important;
|
||||
border-radius: 4px !important;
|
||||
|
||||
&:focus {
|
||||
border-color: #007bff !important;
|
||||
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.nut-button {
|
||||
border-radius: 4px !important;
|
||||
|
||||
&--primary {
|
||||
background: linear-gradient(135deg, #007bff, #0056b3) !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
&--small {
|
||||
padding: 6px 12px !important;
|
||||
font-size: 12px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tabs样式优化
|
||||
.nut-tabs {
|
||||
.nut-tabs__titles {
|
||||
background: #ffffff !important;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1) !important;
|
||||
|
||||
.nut-tabs__titles-item {
|
||||
font-size: 14px !important;
|
||||
font-weight: 500 !important;
|
||||
|
||||
&--active {
|
||||
color: #007bff !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.nut-tabs__line {
|
||||
background: #007bff !important;
|
||||
height: 3px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 筛选提示样式
|
||||
.filter-tip {
|
||||
animation: slideDown 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes slideDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
156
src/user/order/order.tsx
Normal file
156
src/user/order/order.tsx
Normal file
@@ -0,0 +1,156 @@
|
||||
import {useState} from "react";
|
||||
import Taro, {useDidShow} from '@tarojs/taro'
|
||||
import {Space, Empty, Button, ConfigProvider, Input} from '@nutui/nutui-react-taro'
|
||||
import {Search, Filter} from '@nutui/icons-react-taro'
|
||||
import { View } from '@tarojs/components';
|
||||
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 './order.scss'
|
||||
|
||||
function Order() {
|
||||
const [list, setList] = useState<ShopOrder[]>([])
|
||||
const [searchParams, setSearchParams] = useState<ShopOrderParam>({})
|
||||
const [showSearch, setShowSearch] = useState(false)
|
||||
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 handleSearch = (params: ShopOrderParam) => {
|
||||
setSearchParams(params)
|
||||
reload(params)
|
||||
}
|
||||
|
||||
// 重置搜索
|
||||
const handleResetSearch = () => {
|
||||
setSearchParams({})
|
||||
reload()
|
||||
}
|
||||
|
||||
useDidShow(() => {
|
||||
// 设置导航栏标题
|
||||
Taro.setNavigationBarTitle({
|
||||
title: '我的订单'
|
||||
});
|
||||
|
||||
Taro.setNavigationBarColor({
|
||||
backgroundColor: '#ffffff',
|
||||
frontColor: '#000000',
|
||||
});
|
||||
|
||||
reload().then()
|
||||
});
|
||||
|
||||
return (
|
||||
<View className="bg-gray-50 min-h-screen">
|
||||
{/* 搜索和筛选工具栏 */}
|
||||
<View className="bg-white px-4 py-3 flex justify-between items-center border-b border-gray-100">
|
||||
<View className="flex items-center">
|
||||
<Search
|
||||
size={18}
|
||||
className="mr-3 text-gray-600"
|
||||
onClick={() => setShowSearch(!showSearch)}
|
||||
/>
|
||||
<Filter
|
||||
size={18}
|
||||
className="text-gray-600"
|
||||
onClick={() => setShowSearch(!showSearch)}
|
||||
/>
|
||||
</View>
|
||||
<View className="text-sm text-gray-500">
|
||||
共{list.length}个订单
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 搜索组件 */}
|
||||
{showSearch && (
|
||||
<View className="bg-white p-3 shadow-sm border-b border-gray-100">
|
||||
<View className="flex items-center">
|
||||
<View className="flex-1 mr-2">
|
||||
<Input
|
||||
placeholder="搜索订单号、商品名称"
|
||||
value={searchKeyword}
|
||||
onChange={setSearchKeyword}
|
||||
onConfirm={() => {
|
||||
if (searchKeyword.trim()) {
|
||||
handleSearch({ keywords: searchKeyword.trim() });
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
padding: '8px 12px',
|
||||
border: '1px solid #e5e5e5',
|
||||
borderRadius: '4px',
|
||||
backgroundColor: '#f8f9fa'
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
<Space>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
if (searchKeyword.trim()) {
|
||||
handleSearch({ keywords: searchKeyword.trim() });
|
||||
}
|
||||
}}
|
||||
>
|
||||
搜索
|
||||
</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' : '0px'
|
||||
}}>
|
||||
<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
|
||||
data={list}
|
||||
onReload={() => reload(searchParams)}
|
||||
searchParams={searchParams}
|
||||
showSearch={showSearch}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
export default Order;
|
||||
Reference in New Issue
Block a user