功能:增加订单搜索与状态筛选

This commit is contained in:
yml2213
2026-08-13 12:58:06 +08:00
parent 2b3a1b111b
commit ac44fda08b
5 changed files with 79 additions and 8 deletions
+2 -2
View File
@@ -89,9 +89,9 @@ func (h *MerchantHandler) UpdateProductStatus(c *gin.Context) {
func (h *MerchantHandler) ListOrders(c *gin.Context) {
page, size := pageParams(c)
orderSource := strings.TrimSpace(c.Query("order_source"))
list, total, err := h.fulfillmentSvc.ListOrders(middleware.GetMerchantID(c), page, size, c.Query("order_status"), orderSource)
list, total, err := h.fulfillmentSvc.ListOrders(middleware.GetMerchantID(c), page, size, c.Query("order_status"), orderSource, c.Query("keyword"))
if err != nil {
if orderSource != "" && err.Error() == "无效的订单来源" {
if err.Error() == "无效的订单来源" || err.Error() == "无效的订单状态" {
response.BadRequest(c, err.Error())
return
}
+11 -1
View File
@@ -2,6 +2,7 @@ package service
import (
"errors"
"strings"
"time"
"affiliate_dash/internal/model"
@@ -23,10 +24,15 @@ func (s *FulfillmentService) GetOrder(merchantID uint, orderNo string) (*model.F
return &order, nil
}
func (s *FulfillmentService) ListOrders(merchantID uint, page, size int, orderStatus, orderSource string) ([]model.FulfillmentOrder, int64, error) {
func (s *FulfillmentService) ListOrders(merchantID uint, page, size int, orderStatus, orderSource, keyword string) ([]model.FulfillmentOrder, int64, error) {
page, size = normalizePage(page, size)
tx := s.db.Model(&model.FulfillmentOrder{}).Where("merchant_id = ?", merchantID)
if orderStatus != "" {
switch orderStatus {
case model.OrderStatusPaid, model.OrderStatusDelivering, model.OrderStatusDelivered, model.OrderStatusShipFailed, model.OrderStatusCancelled:
default:
return nil, 0, errors.New("无效的订单状态")
}
tx = tx.Where("order_status = ?", orderStatus)
}
if orderSource != "" {
@@ -37,6 +43,10 @@ func (s *FulfillmentService) ListOrders(merchantID uint, page, size int, orderSt
return nil, 0, errors.New("无效的订单来源")
}
}
if keyword = strings.TrimSpace(keyword); keyword != "" {
like := "%" + keyword + "%"
tx = tx.Where("order_no LIKE ? OR client_order_no LIKE ?", like, like)
}
var total int64
if err := tx.Count(&total).Error; err != nil {
return nil, 0, err
+16 -5
View File
@@ -65,6 +65,7 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
const [products, setProducts] = useState<PageResult<MerchantProduct>>({ list: [], total: 0, page: 1, size: 10 })
const [orders, setOrders] = useState<PageResult<FulfillmentOrder>>({ list: [], total: 0, page: 1, size: 10 })
const [orderSource, setOrderSource] = useState<'api' | 'manual'>('api')
const [orderFilters, setOrderFilters] = useState<{ keyword: string; order_status: string }>({ keyword: '', order_status: '' })
const [ledger, setLedger] = useState<PageResult<WalletLedgerEntry>>({ list: [], total: 0, page: 1, size: 10 })
const [wallet, setWallet] = useState<WalletAccount | null>(null)
const [apiClients, setApiClients] = useState<ApiClient[]>([])
@@ -163,10 +164,15 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
setProducts(data)
}, [products.page, products.size])
const loadOrders = useCallback(async (page = orders.page, size = orders.size, source = orderSource) => {
const data = await merchantApi.orders({ page, size, order_source: source })
const loadOrders = useCallback(async (
page = orders.page,
size = orders.size,
source = orderSource,
filters = orderFilters,
) => {
const data = await merchantApi.orders({ page, size, order_source: source, ...filters })
setOrders(data)
}, [orderSource, orders.page, orders.size])
}, [orderFilters, orderSource, orders.page, orders.size])
const loadWallet = useCallback(async (
page = ledger.page,
@@ -341,7 +347,12 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
const changeOrderSource = (source: 'api' | 'manual') => {
setOrderSource(source)
loadOrders(1, orders.size, source).catch((e) => message.error(e instanceof Error ? e.message : '订单加载失败'))
loadOrders(1, orders.size, source, orderFilters).catch((e) => message.error(e instanceof Error ? e.message : '订单加载失败'))
}
const changeOrderFilters = (filters: { keyword: string; order_status: string }) => {
setOrderFilters(filters)
loadOrders(1, orders.size, orderSource, filters).catch((e) => message.error(e instanceof Error ? e.message : '订单加载失败'))
}
const submitAPIClient = async () => {
@@ -499,7 +510,7 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
<ProductsTab loading={loading} products={products} canManage={canManage} onToggleProduct={openProductToggle} onLoadProducts={loadProducts} />
) },
{ key: 'orders', label: '发货订单', disabled: !hasFeature('orders'), children: (
<OrdersTab loading={loading} orders={orders} orderSource={orderSource} canManage={canOrderManage} onCreateManualOrder={openManualOrderCreate} onOrderSourceChange={changeOrderSource} onLoadOrders={loadOrders} onCopyLink={copyDeliveryLink} onOpenLink={openDeliveryLink} onRevokeLink={revokeDeliveryLink} onRestoreLink={restoreDeliveryLink} />
<OrdersTab loading={loading} orders={orders} orderSource={orderSource} filters={orderFilters} canManage={canOrderManage} onCreateManualOrder={openManualOrderCreate} onOrderSourceChange={changeOrderSource} onFilterChange={changeOrderFilters} onLoadOrders={loadOrders} onCopyLink={copyDeliveryLink} onOpenLink={openDeliveryLink} onRevokeLink={revokeDeliveryLink} onRestoreLink={restoreDeliveryLink} />
) },
{ key: 'wallet', label: '钱包', disabled: !hasFeature('wallet'), children: (
<WalletTab loading={loading} wallet={wallet} canFinance={canFinance} ledger={ledger} form={walletFilterForm} onFilter={handleWalletFilter} onResetFilter={handleWalletFilterReset} onLoadLedger={handleLoadLedger} />
+41
View File
@@ -1,3 +1,4 @@
import { useEffect, useState } from 'react'
import { Button, Card, Col, Form, Input, Popconfirm, Row, Select, Space, Table, Tabs, Tag, Typography, message } from 'antd'
import type { FormInstance } from 'antd'
import {
@@ -30,6 +31,7 @@ import {
defaultCallbackFormValues,
eventOptions,
money,
orderStatusOptions,
orderStatusMap,
pageConfig,
rolePermissionText,
@@ -171,9 +173,11 @@ export function OrdersTab({
loading,
orders,
orderSource,
filters,
canManage,
onCreateManualOrder,
onOrderSourceChange,
onFilterChange,
onLoadOrders,
onCopyLink,
onOpenLink,
@@ -183,15 +187,25 @@ export function OrdersTab({
loading: boolean
orders: PageResult<FulfillmentOrder>
orderSource: 'api' | 'manual'
filters: { keyword: string; order_status: string }
canManage: boolean
onCreateManualOrder: () => void
onOrderSourceChange: (source: 'api' | 'manual') => void
onFilterChange: (filters: { keyword: string; order_status: string }) => void
onLoadOrders: (page?: number, size?: number) => void
onCopyLink: (orderNo: string) => void
onOpenLink: (orderNo: string) => void
onRevokeLink: (orderNo: string) => void
onRestoreLink: (orderNo: string) => void
}) {
const [keyword, setKeyword] = useState(filters.keyword)
useEffect(() => {
setKeyword(filters.keyword)
}, [filters.keyword])
const submitKeyword = () => onFilterChange({ ...filters, keyword: keyword.trim() })
const orderColumns: ColumnsType<FulfillmentOrder> = [
{
title: '平台订单号',
@@ -253,6 +267,33 @@ export function OrdersTab({
</Space>
)}
</Space>
<Card size="small" style={{ borderRadius: 8 }}>
<Space direction="vertical" size="middle" style={{ width: '100%' }}>
<Space wrap>
<Input.Search
value={keyword}
onChange={(event) => setKeyword(event.target.value)}
onSearch={submitKeyword}
placeholder="搜索平台订单号或商户单号"
allowClear
onClear={() => onFilterChange({ ...filters, keyword: '' })}
style={{ width: 300, maxWidth: '100%' }}
/>
</Space>
<Space wrap size={[8, 8]}>
{orderStatusOptions.map((option) => (
<Button
key={option.value || 'all'}
type={filters.order_status === option.value ? 'primary' : 'text'}
onClick={() => onFilterChange({ ...filters, order_status: option.value })}
style={{ minWidth: 76 }}
>
{option.label}
</Button>
))}
</Space>
</Space>
</Card>
<Table
rowKey="id"
loading={loading}
@@ -8,6 +8,15 @@ export const orderStatusMap: Record<string, { color: string; text: string }> = {
cancelled: { color: 'default', text: '已取消' },
}
export const orderStatusOptions = [
{ value: '', label: '全部' },
{ value: 'paid', label: '待发货' },
{ value: 'delivering', label: '发货中' },
{ value: 'delivered', label: '已交付' },
{ value: 'ship_failed', label: '发货失败' },
{ value: 'cancelled', label: '已取消' },
]
export const memberRoleOptions = [
{ value: 'owner', label: '负责人' },
{ value: 'operator', label: '运营' },