优化订单履约分流与后台筛选
This commit is contained in:
@@ -2,14 +2,20 @@ 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 { useEffect, useMemo } from 'react'
|
||||
import { useNavigate, useSearchParams } from 'react-router'
|
||||
|
||||
import { AdminRangePicker } from '@/components/admin/AdminDatePicker'
|
||||
import PageHeader from '@/components/admin/PageHeader'
|
||||
import StatusTag from '@/components/admin/StatusTag'
|
||||
import dayjs from '@/lib/dayjs'
|
||||
import { fetchAdminOrders } from '@/services/admin'
|
||||
import type { AdminOrderListItem } from '@/types/admin'
|
||||
import { adminPayStatusOptions } from '@/utils/admin-options'
|
||||
import {
|
||||
adminOrderExecutorOptions,
|
||||
adminPayStatusOptions,
|
||||
adminTaskStatusOptions,
|
||||
} from '@/utils/admin-options'
|
||||
import {
|
||||
ADMIN_DEFAULT_PAGE_SIZE,
|
||||
buildAdminTablePagination,
|
||||
@@ -18,25 +24,40 @@ import {
|
||||
import { formatAdminDateTime } from '@/utils/admin-time'
|
||||
|
||||
type OrderFilterForm = {
|
||||
platformOrderId?: string
|
||||
keyword?: string
|
||||
executorKey?: string
|
||||
payStatus?: string
|
||||
skuCode?: string
|
||||
taskStatus?: string
|
||||
dateRange?: unknown
|
||||
}
|
||||
|
||||
export default function AdminOrdersPage() {
|
||||
const navigate = useNavigate()
|
||||
const [form] = Form.useForm<OrderFilterForm>()
|
||||
const [searchParams, setSearchParams] = useSearchParams()
|
||||
const page = Number(searchParams.get('page') || 1) || 1
|
||||
const pageSize = resolveAdminPageSize(searchParams.get('pageSize'), ADMIN_DEFAULT_PAGE_SIZE)
|
||||
const filters = {
|
||||
platformOrderId: searchParams.get('platformOrderId') || '',
|
||||
keyword: searchParams.get('keyword') || '',
|
||||
executorKey: searchParams.get('executorKey') || '',
|
||||
payStatus: searchParams.get('payStatus') || '',
|
||||
skuCode: searchParams.get('skuCode') || '',
|
||||
taskStatus: searchParams.get('taskStatus') || '',
|
||||
dateFrom: searchParams.get('dateFrom') || '',
|
||||
dateTo: searchParams.get('dateTo') || '',
|
||||
}
|
||||
|
||||
const queryParams = useMemo(
|
||||
() => ({ page, pageSize, ...filters }),
|
||||
[filters.platformOrderId, filters.payStatus, filters.skuCode, page, pageSize],
|
||||
[
|
||||
filters.dateFrom,
|
||||
filters.dateTo,
|
||||
filters.executorKey,
|
||||
filters.keyword,
|
||||
filters.payStatus,
|
||||
filters.taskStatus,
|
||||
page,
|
||||
pageSize,
|
||||
],
|
||||
)
|
||||
const query = useQuery({
|
||||
queryKey: ['admin-orders', queryParams],
|
||||
@@ -44,6 +65,27 @@ export default function AdminOrdersPage() {
|
||||
})
|
||||
const data = query.data?.data
|
||||
|
||||
useEffect(() => {
|
||||
form.setFieldsValue({
|
||||
keyword: filters.keyword || undefined,
|
||||
executorKey: filters.executorKey || undefined,
|
||||
payStatus: filters.payStatus || undefined,
|
||||
taskStatus: filters.taskStatus || undefined,
|
||||
dateRange:
|
||||
filters.dateFrom && filters.dateTo
|
||||
? [dayjs(filters.dateFrom), dayjs(filters.dateTo)]
|
||||
: undefined,
|
||||
})
|
||||
}, [
|
||||
filters.dateFrom,
|
||||
filters.dateTo,
|
||||
filters.executorKey,
|
||||
filters.keyword,
|
||||
filters.payStatus,
|
||||
filters.taskStatus,
|
||||
form,
|
||||
])
|
||||
|
||||
const columns: TableColumnsType<AdminOrderListItem> = [
|
||||
{
|
||||
title: '订单信息',
|
||||
@@ -96,10 +138,24 @@ export default function AdminOrdersPage() {
|
||||
]
|
||||
|
||||
function applyFilters(values: OrderFilterForm) {
|
||||
setSearchParams(cleanParams({ ...values, page: 1, pageSize }))
|
||||
const { dateRange, ...restValues } = values
|
||||
const [dateFrom, dateTo] = Array.isArray(dateRange)
|
||||
? dateRange.map((item: { format?: (pattern: string) => string }) =>
|
||||
item?.format ? item.format('YYYY-MM-DD') : '',
|
||||
)
|
||||
: ['', '']
|
||||
|
||||
setSearchParams(cleanParams({ ...restValues, dateFrom, dateTo, page: 1, pageSize }))
|
||||
}
|
||||
|
||||
function resetFilters() {
|
||||
form.setFieldsValue({
|
||||
keyword: undefined,
|
||||
executorKey: undefined,
|
||||
payStatus: undefined,
|
||||
taskStatus: undefined,
|
||||
dateRange: undefined,
|
||||
})
|
||||
setSearchParams(cleanParams({ page: 1, pageSize }))
|
||||
}
|
||||
|
||||
@@ -109,13 +165,25 @@ export default function AdminOrdersPage() {
|
||||
|
||||
<Card>
|
||||
<Form<OrderFilterForm>
|
||||
form={form}
|
||||
layout="inline"
|
||||
initialValues={filters}
|
||||
onFinish={applyFilters}
|
||||
className="filter-form"
|
||||
>
|
||||
<Form.Item name="platformOrderId">
|
||||
<Input allowClear placeholder="平台订单号" />
|
||||
<Form.Item name="keyword">
|
||||
<Input
|
||||
allowClear
|
||||
placeholder="订单号 / 商品标题 / SKU 标题 / 买家 / 店铺"
|
||||
style={{ width: 320 }}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="executorKey">
|
||||
<Select
|
||||
allowClear
|
||||
placeholder="履约渠道"
|
||||
options={adminOrderExecutorOptions}
|
||||
style={{ minWidth: 150 }}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="payStatus">
|
||||
<Select
|
||||
@@ -125,8 +193,18 @@ export default function AdminOrdersPage() {
|
||||
style={{ minWidth: 140 }}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="skuCode">
|
||||
<Input allowClear placeholder="SKU 标识" />
|
||||
<Form.Item name="taskStatus">
|
||||
<Select
|
||||
allowClear
|
||||
showSearch
|
||||
optionFilterProp="label"
|
||||
placeholder="任务状态"
|
||||
options={adminTaskStatusOptions}
|
||||
style={{ minWidth: 170 }}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="dateRange">
|
||||
<AdminRangePicker />
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Space>
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
} from 'antd'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useNavigate, useSearchParams } from 'react-router'
|
||||
|
||||
import { AdminRangePicker } from '@/components/admin/AdminDatePicker'
|
||||
@@ -37,7 +37,7 @@ import {
|
||||
} from '@/services/admin'
|
||||
import type { AdminTaskActionResponse, AdminTaskListItem } from '@/types/admin'
|
||||
import { hasAdminRole } from '@/utils/admin-auth'
|
||||
import { adminTaskStatusOptions } from '@/utils/admin-options'
|
||||
import { adminOrderExecutorOptions, adminTaskStatusOptions } from '@/utils/admin-options'
|
||||
import {
|
||||
ADMIN_DEFAULT_PAGE_SIZE,
|
||||
buildAdminTablePagination,
|
||||
@@ -46,11 +46,9 @@ import {
|
||||
import { formatAdminDateTime } from '@/utils/admin-time'
|
||||
|
||||
type TaskFilterForm = {
|
||||
keyword?: string
|
||||
executorKey?: string
|
||||
status?: string
|
||||
platformOrderId?: string
|
||||
taskNo?: string
|
||||
skuCode?: string
|
||||
roleId?: string
|
||||
dateRange?: unknown
|
||||
}
|
||||
|
||||
@@ -67,6 +65,7 @@ type TaskListBlocker = {
|
||||
export default function AdminTasksPage() {
|
||||
const navigate = useNavigate()
|
||||
const { message, modal } = App.useApp()
|
||||
const [form] = Form.useForm<TaskFilterForm>()
|
||||
const [searchParams, setSearchParams] = useSearchParams()
|
||||
const [actionLoadingId, setActionLoadingId] = useState<number | null>(null)
|
||||
const [lastClaimUrl, setLastClaimUrl] = useState('')
|
||||
@@ -77,11 +76,15 @@ export default function AdminTasksPage() {
|
||||
const canRebindRole = hasAdminRole('support')
|
||||
const canCloseTasks = hasAdminRole('support')
|
||||
const filters = {
|
||||
keyword:
|
||||
searchParams.get('keyword') ||
|
||||
searchParams.get('taskNo') ||
|
||||
searchParams.get('platformOrderId') ||
|
||||
searchParams.get('skuCode') ||
|
||||
searchParams.get('roleId') ||
|
||||
'',
|
||||
executorKey: searchParams.get('executorKey') || '',
|
||||
status: searchParams.get('status') || '',
|
||||
platformOrderId: searchParams.get('platformOrderId') || '',
|
||||
taskNo: searchParams.get('taskNo') || '',
|
||||
skuCode: searchParams.get('skuCode') || '',
|
||||
roleId: searchParams.get('roleId') || '',
|
||||
dateFrom: searchParams.get('dateFrom') || '',
|
||||
dateTo: searchParams.get('dateTo') || '',
|
||||
}
|
||||
@@ -91,11 +94,9 @@ export default function AdminTasksPage() {
|
||||
[
|
||||
filters.dateFrom,
|
||||
filters.dateTo,
|
||||
filters.platformOrderId,
|
||||
filters.roleId,
|
||||
filters.skuCode,
|
||||
filters.executorKey,
|
||||
filters.keyword,
|
||||
filters.status,
|
||||
filters.taskNo,
|
||||
page,
|
||||
pageSize,
|
||||
],
|
||||
@@ -106,6 +107,18 @@ export default function AdminTasksPage() {
|
||||
})
|
||||
const data = query.data?.data
|
||||
|
||||
useEffect(() => {
|
||||
form.setFieldsValue({
|
||||
keyword: filters.keyword || undefined,
|
||||
executorKey: filters.executorKey || undefined,
|
||||
status: filters.status || undefined,
|
||||
dateRange:
|
||||
filters.dateFrom && filters.dateTo
|
||||
? [dayjs(filters.dateFrom), dayjs(filters.dateTo)]
|
||||
: undefined,
|
||||
})
|
||||
}, [filters.dateFrom, filters.dateTo, filters.executorKey, filters.keyword, filters.status, form])
|
||||
|
||||
const columns: TableColumnsType<AdminTaskListItem> = [
|
||||
{
|
||||
title: '任务 / 订单',
|
||||
@@ -381,6 +394,12 @@ export default function AdminTasksPage() {
|
||||
}
|
||||
|
||||
function resetFilters() {
|
||||
form.setFieldsValue({
|
||||
keyword: undefined,
|
||||
executorKey: undefined,
|
||||
status: undefined,
|
||||
dateRange: undefined,
|
||||
})
|
||||
setSearchParams(cleanParams({ page: 1, pageSize }))
|
||||
}
|
||||
|
||||
@@ -390,37 +409,36 @@ export default function AdminTasksPage() {
|
||||
|
||||
<Card>
|
||||
<Form<TaskFilterForm>
|
||||
form={form}
|
||||
layout="inline"
|
||||
initialValues={{
|
||||
...filters,
|
||||
dateRange:
|
||||
filters.dateFrom && filters.dateTo
|
||||
? [dayjs(filters.dateFrom), dayjs(filters.dateTo)]
|
||||
: undefined,
|
||||
}}
|
||||
onFinish={applyFilters}
|
||||
className="filter-form"
|
||||
>
|
||||
<Form.Item name="keyword">
|
||||
<Input
|
||||
allowClear
|
||||
placeholder="任务号 / 订单号 / 商品标题 / SKU / 角色"
|
||||
style={{ width: 330 }}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="executorKey">
|
||||
<Select
|
||||
allowClear
|
||||
placeholder="履约渠道"
|
||||
options={adminOrderExecutorOptions}
|
||||
style={{ minWidth: 150 }}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="status">
|
||||
<Select
|
||||
allowClear
|
||||
showSearch
|
||||
optionFilterProp="label"
|
||||
placeholder="任务状态"
|
||||
options={adminTaskStatusOptions}
|
||||
style={{ minWidth: 170 }}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="platformOrderId">
|
||||
<Input allowClear placeholder="平台订单号" />
|
||||
</Form.Item>
|
||||
<Form.Item name="taskNo">
|
||||
<Input allowClear placeholder="任务号" />
|
||||
</Form.Item>
|
||||
<Form.Item name="roleId">
|
||||
<Input allowClear placeholder="角色 ID" />
|
||||
</Form.Item>
|
||||
<Form.Item name="skuCode">
|
||||
<Input allowClear placeholder="商品名 / SKU" />
|
||||
</Form.Item>
|
||||
<Form.Item name="dateRange">
|
||||
<AdminRangePicker />
|
||||
</Form.Item>
|
||||
|
||||
@@ -6,17 +6,30 @@ export const adminPayStatusOptions = [
|
||||
{ label: '已退款', value: 'refunded' },
|
||||
]
|
||||
|
||||
export const adminOrderExecutorOptions = [
|
||||
{ label: '乐玩云', value: 'kuaishou_ct_assisted' },
|
||||
{ label: '飞飞', value: 'kuaishou_feifei' },
|
||||
{ label: 'Affiliate Dash', value: 'affiliate_dash' },
|
||||
{ label: '行业凭证', value: 'kuaishou-industry' },
|
||||
{ label: '人工履约', value: 'manual_dispatch' },
|
||||
]
|
||||
|
||||
export const adminTaskStatusOptions = [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '待支付', value: 'pending_payment' },
|
||||
{ label: '已支付', value: 'paid' },
|
||||
{ label: '已生成链接', value: 'link_generated' },
|
||||
{ label: '已创建会话', value: 'claimed' },
|
||||
{ label: '待准备绑定', value: 'pending_binding_prepare' },
|
||||
{ label: '待客户绑定', value: 'waiting_binding' },
|
||||
{ label: '已确认角色', value: 'role_confirmed' },
|
||||
{ label: '兑换中', value: 'redeeming' },
|
||||
{ label: '待退还号码', value: 'dispatched_pending_return' },
|
||||
{ label: '已完成', value: 'completed' },
|
||||
{ label: '已兑换', value: 'redeemed' },
|
||||
{ label: '待重试', value: 'retry_pending' },
|
||||
{ label: '人工处理', value: 'manual_review' },
|
||||
{ label: '失败', value: 'failed' },
|
||||
{ label: '已过期', value: 'expired' },
|
||||
{ label: '已关闭', value: 'closed' },
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user