diff --git a/src/pages/order/components/OrderSearch.scss b/src/pages/order/components/OrderSearch.scss new file mode 100644 index 0000000..0f7862b --- /dev/null +++ b/src/pages/order/components/OrderSearch.scss @@ -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; + } +} diff --git a/src/pages/order/components/OrderSearch.tsx b/src/pages/order/components/OrderSearch.tsx new file mode 100644 index 0000000..e82b80d --- /dev/null +++ b/src/pages/order/components/OrderSearch.tsx @@ -0,0 +1,266 @@ +import React, { useState } from 'react'; +import { View } from '@tarojs/components'; +import { + Input, + Button, + Popup, + Cell, + CellGroup, + Radio, + Space, + DatePicker, + Picker +} from '@nutui/nutui-react-taro'; +import { Search, Filter, Close } from '@nutui/icons-react-taro'; +import { ShopOrderParam } from '@/api/shop/shopOrder/model'; +import dayjs from 'dayjs'; +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 = ({ onSearch, onReset }) => { + const [showFilter, setShowFilter] = useState(false); + const [searchParams, setSearchParams] = useState({ + 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 && searchParams.orderStatus !== '') { + filterParams.orderStatus = Number(searchParams.orderStatus); + } + if (searchParams.payStatus !== undefined && searchParams.payStatus !== '') { + filterParams.payStatus = Number(searchParams.payStatus); + } + if (searchParams.payType !== undefined && searchParams.payType !== '') { + filterParams.payType = Number(searchParams.payType); + } + + onSearch(filterParams); + setShowFilter(false); + }; + + return ( + + {/* 搜索栏 */} + + + + setSearchParams(prev => ({ ...prev, keywords: value }))} + onConfirm={handleKeywordSearch} + className="flex-1 bg-transparent border-none" + style={{ padding: 0 }} + /> + + + setShowFilter(true)} + > + + + + + {/* 筛选弹窗 */} + setShowFilter(false)} + style={{ width: '80%', height: '100%' }} + > + + {/* 头部 */} + + 筛选条件 + setShowFilter(false)} /> + + + {/* 筛选内容 */} + + + {/* 订单号 */} + + + 订单号 + setSearchParams(prev => ({ ...prev, orderNo: value }))} + /> + + + + {/* 手机号 */} + + + 手机号 + setSearchParams(prev => ({ ...prev, phone: value }))} + /> + + + + {/* 订单状态 */} + + + 订单状态 + setSearchParams(prev => ({ ...prev, orderStatus: value }))} + > + + {orderStatusOptions.map((option) => ( + + {option.text} + + ))} + + + + + + {/* 支付状态 */} + + + 支付状态 + setSearchParams(prev => ({ ...prev, payStatus: value }))} + > + + {payStatusOptions.map((option) => ( + + {option.text} + + ))} + + + + + + {/* 支付方式 */} + + + 支付方式 + setSearchParams(prev => ({ ...prev, payType: value }))} + > + + {payTypeOptions.map((option) => ( + + {option.text} + + ))} + + + + + + + + {/* 底部按钮 */} + + + + + + + + + + ); +}; + +export default OrderSearch; diff --git a/订单筛选查询功能说明.md b/订单筛选查询功能说明.md new file mode 100644 index 0000000..9665730 --- /dev/null +++ b/订单筛选查询功能说明.md @@ -0,0 +1,176 @@ +# 订单筛选及查询功能实现说明 + +## 功能概述 + +为订单页面实现了完整的筛选及查询功能,包括关键词搜索、状态筛选、支付方式筛选等多种筛选条件。 + +## 实现的功能 + +### 1. 关键词搜索 +- 支持按订单号搜索 +- 支持按商品名称搜索 +- 实时搜索,按回车键或点击搜索按钮触发 + +### 2. Tabs订单状态筛选 ✅ 已修复完成 + 排除已取消订单 +- **全部订单** - 显示所有订单 (不添加筛选条件) +- **待付款** - 筛选未付款且未取消的订单 (payStatus = 0, 排除已取消) +- **待发货** - 筛选已付款但未发货且未取消的订单 (payStatus = 1, deliveryStatus = 10, 排除已取消) +- **待收货** - 筛选已发货且未取消的订单 (deliveryStatus = 20, 排除已取消) +- **已完成** - 筛选已完成订单 (orderStatus = 1) +- **已取消** - 筛选已取消/退款的订单 (orderStatus = 2,3,4,6,7) + +### 3. 已取消订单状态说明 +为了避免已取消的订单出现在正常流程的tab中,系统会自动排除以下状态的订单: +- `orderStatus = 2`: 已取消 +- `orderStatus = 3`: 取消中 +- `orderStatus = 4`: 退款申请中 +- `orderStatus = 6`: 退款成功 +- `orderStatus = 7`: 客户端申请退款 + +### 4. 后端筛选逻辑对应关系 +根据实际的API参数,各tab对应的筛选逻辑如下: + +| Tab索引 | Tab名称 | API参数 | 前端筛选 | 说明 | +|---------|---------|---------|----------|------| +| 0 | 全部订单 | 无额外参数 | 无 | 显示所有订单 | +| 1 | 待付款 | `payStatus=0` | 排除已取消 | 未付款且未取消的订单 | +| 2 | 待发货 | `payStatus=1&deliveryStatus=10` | 排除已取消 | 已付款但未发货且未取消 | +| 3 | 待收货 | `deliveryStatus=20` | 排除已取消 | 已发货且未取消 | +| 4 | 已完成 | `orderStatus=1` | 无 | 订单已完成 | +| 5 | 已取消 | 无额外参数 | 只显示已取消 | 已取消/退款的订单 | + +### 4. Tabs功能特性 +- 点击不同tab自动筛选对应状态的订单 +- 使用后端标准的statusFilter参数 +- 显示当前筛选状态和订单数量 +- 加载状态指示器 +- 平滑的切换动画效果 + +### 3. 支付状态筛选 +- 全部 +- 未付款 +- 已付款 + +### 4. 支付方式筛选 +- 全部 +- 余额支付 +- 微信支付 +- 会员卡支付 +- 支付宝 +- 现金 +- POS机 + +## 文件结构 + +``` +src/pages/order/ +├── order.tsx # 主订单页面 +├── components/ +│ ├── OrderList.tsx # 订单列表组件 +│ ├── OrderSearch.tsx # 搜索筛选组件 +│ └── OrderSearch.scss # 搜索组件样式 +└── order.scss # 订单页面样式 +``` + +## 主要修改 + +### 1. 扩展API接口参数 +- 在 `src/api/shop/shopOrder/model/index.ts` 中扩展了 `ShopOrderParam` 接口 +- 添加了 `deliveryStatus` 字段支持发货状态筛选 + +### 2. 更新订单页面 (order.tsx) +- 添加搜索状态管理 +- 集成搜索组件 +- 实现搜索和重置功能 +- 将搜索参数传递给订单列表组件 + +### 3. 更新订单列表组件 (OrderList.tsx) ✅ 重点修复 +- **修复tabs筛选逻辑** - 解决tapIndex类型不匹配问题 +- **完善筛选参数映射** - 每个tab对应正确的API筛选条件 +- **添加筛选状态提示** - 显示当前筛选的tab和订单数量 +- **优化用户体验** - 添加加载状态和视觉反馈 +- **支持搜索参数** - 监听搜索参数变化并重新加载数据 +- **调试信息** - 添加console.log便于调试筛选逻辑 + +### 4. 创建搜索组件 (OrderSearch.tsx) +- 实现关键词搜索界面 +- 实现高级筛选弹窗 +- 支持多种筛选条件组合 +- 响应式设计,适配移动端 + +### 5. 样式优化 +- 优化tabs的视觉效果 +- 添加筛选提示的动画效果 +- 改进搜索框的样式和交互 + +## 使用方法 + +### 基础搜索 +1. 点击导航栏的搜索图标或筛选图标 +2. 在搜索框中输入订单号或商品名称 +3. 按回车键或点击搜索按钮 + +### 高级筛选 +1. 点击筛选图标打开筛选弹窗 +2. 选择需要的筛选条件: + - 输入具体订单号 + - 输入手机号 + - 选择订单状态 + - 选择支付状态 + - 选择支付方式 +3. 点击确定按钮应用筛选 + +### 重置搜索 +- 点击重置按钮清空所有搜索条件 +- 返回显示所有订单 + +## 技术特点 + +### 1. 类型安全 +- 使用TypeScript确保类型安全 +- 定义了完整的接口类型 + +### 2. 组件化设计 +- 搜索功能独立封装为组件 +- 便于维护和复用 + +### 3. 响应式设计 +- 适配移动端界面 +- 使用Tailwind CSS实现响应式布局 + +### 4. 用户体验优化 +- 实时搜索反馈 +- 清晰的筛选界面 +- 便捷的重置功能 + +## 扩展建议 + +### 1. 日期范围筛选 +可以添加订单创建时间、支付时间等日期范围筛选功能。 + +### 2. 金额范围筛选 +支持按订单金额范围进行筛选。 + +### 3. 商户筛选 +如果有多商户,可以添加按商户筛选的功能。 + +### 4. 搜索历史 +保存用户的搜索历史,提供快速搜索选项。 + +### 5. 导出功能 +支持将筛选结果导出为Excel或PDF格式。 + +## 注意事项 + +1. 搜索功能依赖后端API支持相应的查询参数 +2. 筛选条件会影响分页加载,需要在切换筛选条件时重置页码 +3. 建议在生产环境中添加搜索防抖功能,避免频繁请求 +4. 可以考虑添加搜索结果缓存,提升用户体验 + +## 测试建议 + +1. 测试各种搜索条件的组合 +2. 测试搜索结果的准确性 +3. 测试重置功能是否正常 +4. 测试在不同设备上的显示效果 +5. 测试搜索性能,特别是大数据量情况下