重命名前端目录
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
import { SearchOutlined, ReloadOutlined } from '@ant-design/icons'
|
||||
import { Button, Card, Form, Input, Select, Space, Table, Typography } from 'antd'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useMemo } from 'react'
|
||||
import { useNavigate, useSearchParams } from 'react-router'
|
||||
|
||||
import PageHeader from '@/components/admin/PageHeader'
|
||||
import StatusTag from '@/components/admin/StatusTag'
|
||||
import { fetchAdminOrders } from '@/services/admin'
|
||||
import type { AdminOrderListItem } from '@/types/admin'
|
||||
import { adminPayStatusOptions } from '@/utils/admin-options'
|
||||
import { formatAdminDateTime } from '@/utils/admin-time'
|
||||
|
||||
type OrderFilterForm = {
|
||||
platformOrderId?: string
|
||||
payStatus?: string
|
||||
skuCode?: string
|
||||
}
|
||||
|
||||
export default function AdminOrdersPage() {
|
||||
const navigate = useNavigate()
|
||||
const [searchParams, setSearchParams] = useSearchParams()
|
||||
const page = Number(searchParams.get('page') || 1) || 1
|
||||
const pageSize = Number(searchParams.get('pageSize') || 20) || 20
|
||||
const filters = {
|
||||
platformOrderId: searchParams.get('platformOrderId') || '',
|
||||
payStatus: searchParams.get('payStatus') || '',
|
||||
skuCode: searchParams.get('skuCode') || '',
|
||||
}
|
||||
|
||||
const queryParams = useMemo(
|
||||
() => ({ page, pageSize, ...filters }),
|
||||
[filters.platformOrderId, filters.payStatus, filters.skuCode, page, pageSize],
|
||||
)
|
||||
const query = useQuery({
|
||||
queryKey: ['admin-orders', queryParams],
|
||||
queryFn: () => fetchAdminOrders(queryParams),
|
||||
})
|
||||
const data = query.data?.data
|
||||
|
||||
const columns: TableColumnsType<AdminOrderListItem> = [
|
||||
{
|
||||
title: '订单信息',
|
||||
dataIndex: 'platformOrderId',
|
||||
minWidth: 220,
|
||||
render: (_, row) => (
|
||||
<div className="cell-stack">
|
||||
<Typography.Link onClick={() => navigate(`/admin/orders/${row.orderId}`)}>
|
||||
{row.platformOrderId}
|
||||
</Typography.Link>
|
||||
<span className="muted">{row.shopName || row.shopId || row.provider}</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '商品 / 任务',
|
||||
minWidth: 220,
|
||||
render: (_, row) => (
|
||||
<div className="cell-stack">
|
||||
<span>{row.itemSummary || '-'}</span>
|
||||
<span className="muted">
|
||||
商品 {row.itemCount} · 数量 {row.totalQuantity} · 任务 {row.taskCount}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
minWidth: 220,
|
||||
render: (_, row) => (
|
||||
<Space size={[0, 6]} wrap>
|
||||
<StatusTag value={row.payStatus} kind="pay" />
|
||||
<StatusTag value={row.resourceStatus} kind="resource" />
|
||||
<StatusTag value={row.customerStatus} kind="customer" />
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '金额 / 时间',
|
||||
minWidth: 180,
|
||||
render: (_, row) => (
|
||||
<div className="cell-stack">
|
||||
<strong>{row.totalAmount || '0.00'} {row.currency}</strong>
|
||||
<span className="muted">{formatAdminDateTime(row.createdAt)}</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
function applyFilters(values: OrderFilterForm) {
|
||||
setSearchParams(cleanParams({ ...values, page: 1, pageSize }))
|
||||
}
|
||||
|
||||
function resetFilters() {
|
||||
setSearchParams(cleanParams({ page: 1, pageSize }))
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="page-stack">
|
||||
<PageHeader title="订单" description="查看订单入库、商品匹配和任务拆分情况。" />
|
||||
|
||||
<Card>
|
||||
<Form<OrderFilterForm>
|
||||
layout="inline"
|
||||
initialValues={filters}
|
||||
onFinish={applyFilters}
|
||||
className="filter-form"
|
||||
>
|
||||
<Form.Item name="platformOrderId">
|
||||
<Input allowClear placeholder="平台订单号" />
|
||||
</Form.Item>
|
||||
<Form.Item name="payStatus">
|
||||
<Select
|
||||
allowClear
|
||||
placeholder="支付状态"
|
||||
options={adminPayStatusOptions}
|
||||
style={{ minWidth: 140 }}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="skuCode">
|
||||
<Input allowClear placeholder="SKU 标识" />
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Space>
|
||||
<Button type="primary" icon={<SearchOutlined />} htmlType="submit">
|
||||
查询
|
||||
</Button>
|
||||
<Button icon={<ReloadOutlined />} onClick={resetFilters}>
|
||||
重置
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<Table<AdminOrderListItem>
|
||||
rowKey="orderId"
|
||||
loading={query.isLoading || query.isFetching}
|
||||
columns={columns}
|
||||
dataSource={data?.items || []}
|
||||
scroll={{ x: 900 }}
|
||||
pagination={{
|
||||
current: data?.pagination.page || page,
|
||||
pageSize: data?.pagination.pageSize || pageSize,
|
||||
total: data?.pagination.total || 0,
|
||||
showSizeChanger: true,
|
||||
showTotal: (total) => `共 ${total} 条`,
|
||||
onChange: (nextPage, nextPageSize) => {
|
||||
setSearchParams(cleanParams({ ...filters, page: nextPage, pageSize: nextPageSize }))
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Card>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
function cleanParams(params: Record<string, unknown>) {
|
||||
const next = new URLSearchParams()
|
||||
Object.entries(params).forEach(([key, value]) => {
|
||||
const normalized = String(value ?? '').trim()
|
||||
if (normalized) {
|
||||
next.set(key, normalized)
|
||||
}
|
||||
})
|
||||
return next
|
||||
}
|
||||
Reference in New Issue
Block a user