优化接单工单筛选布局

This commit is contained in:
yml2213
2026-08-14 15:40:17 +08:00
parent 78d6c2f8a1
commit 951d0574b1
11 changed files with 112 additions and 129 deletions
@@ -28,7 +28,6 @@ import {
saveAdminWorkProductRule,
saveAdminWorkerLevel,
submitAdminWorkOrderMaterial,
syncAdminWorkerOrdersFromSource,
unpublishAdminWorkOrder,
updateAdminWorkOrder,
updateAdminWorkOrderSharing,
@@ -304,22 +303,6 @@ router.post(
}),
)
router.post(
'/worker-platform/source-orders/sync',
requireAdminRoles(['admin', 'operator']),
createJsonHandler((req) => syncAdminWorkerOrdersFromSource(req.body || {}), {
successMessage: '源订单同步完成',
errorMessage: '同步源订单失败',
scope: '[admin/worker-platform/source-orders/sync]',
audit: (_req, data) => ({
action: 'work_order_source_synced',
targetType: 'source_order',
targetId: '',
data: data && typeof data === 'object' ? (data as Record<string, unknown>) : {},
}),
}),
)
router.post(
'/worker-platform/orders/:workOrderId/material',
requireAdminRoles(['admin', 'operator', 'support']),
@@ -2,8 +2,6 @@ import crypto from 'node:crypto'
import { runtimeConfig } from '../../config/runtime.js'
import { WORK_ORDER_STATUS } from '../../domain/work-order-status.js'
import { listOrderItemsByOrderId } from '../../repositories/order-item-repo.js'
import { findLatestOrderByAnyPlatformOrderId, getOrderById } from '../../repositories/order-repo.js'
import {
acceptWorkOrderAndSettle,
addWorkerWalletCredit,
@@ -688,16 +686,6 @@ export async function submitAdminWorkOrderMaterial(
return { order: mapWorkOrderAdmin(updated || workOrder), complete }
}
export async function syncAdminWorkerOrdersFromSource(payload: JsonObject = {}) {
const order = await resolveSourceOrder(payload)
const orderItems = await listOrderItemsByOrderId(order.id)
const result = await syncWorkerOrdersForSourceOrder(order, orderItems, {
source: 'admin_manual_sync',
autoOnly: false,
})
return result
}
export async function createAdminMockWorkOrder(payload: JsonObject = {}) {
const defaults = await ensureWorkerPlatformDefaults()
const now = nowIso()
@@ -1149,34 +1137,3 @@ export async function syncWorkerOrdersForSourceOrder(
skippedCount: skipped.length,
}
}
async function resolveSourceOrder(payload: JsonObject): Promise<OrderRow> {
const orderId = normalizeOptionalId(payload.orderId || payload.sourceOrderId)
if (orderId) {
const order = await getOrderById(orderId)
if (order) {
return order
}
throw createHttpError('源订单不存在', {
statusCode: 404,
errorCode: 'source_order_not_found',
})
}
const platformOrderId = String(payload.platformOrderId || payload.orderNo || '').trim()
if (!platformOrderId) {
throw createHttpError('请填写源订单号', {
statusCode: 400,
errorCode: 'source_order_no_required',
})
}
const order = await findLatestOrderByAnyPlatformOrderId(platformOrderId)
if (!order) {
throw createHttpError('未找到源订单,请确认订单号是否正确', {
statusCode: 404,
errorCode: 'source_order_not_found',
})
}
return order
}
@@ -61,7 +61,6 @@ import {
saveAdminWorkProductRule,
saveAdminWorkerLevel,
submitAdminWorkOrderMaterial,
syncAdminWorkerOrdersFromSource,
unpublishAdminWorkOrder,
updateAdminWorkOrderSharing,
} from '@/services/admin'
@@ -165,4 +164,3 @@ function SummaryCards() {
</div>
)
}
@@ -61,7 +61,6 @@ import {
saveAdminWorkProductRule,
saveAdminWorkerLevel,
submitAdminWorkOrderMaterial,
syncAdminWorkerOrdersFromSource,
unpublishAdminWorkOrder,
updateAdminWorkOrderSharing,
} from '@/services/admin'
@@ -259,4 +258,3 @@ export default function CategoriesPanel() {
</section>
)
}
@@ -61,7 +61,6 @@ import {
saveAdminWorkProductRule,
saveAdminWorkerLevel,
submitAdminWorkOrderMaterial,
syncAdminWorkerOrdersFromSource,
unpublishAdminWorkOrder,
updateAdminWorkOrderSharing,
} from '@/services/admin'
@@ -61,7 +61,6 @@ import {
saveAdminWorkProductRule,
saveAdminWorkerLevel,
submitAdminWorkOrderMaterial,
syncAdminWorkerOrdersFromSource,
unpublishAdminWorkOrder,
updateAdminWorkOrderSharing,
} from '@/services/admin'
@@ -299,4 +298,3 @@ export default function LevelsPanel() {
</section>
)
}
@@ -65,7 +65,6 @@ import {
saveAdminWorkProductRule,
saveAdminWorkerLevel,
submitAdminWorkOrderMaterial,
syncAdminWorkerOrdersFromSource,
unpublishAdminWorkOrder,
updateAdminWorkOrderSharing,
} from '@/services/admin'
@@ -5,8 +5,8 @@ import {
FormOutlined,
PlusOutlined,
ReloadOutlined,
SearchOutlined,
SendOutlined,
SyncOutlined,
TeamOutlined,
WarningOutlined,
} from '@ant-design/icons'
@@ -66,7 +66,6 @@ import {
saveAdminWorkProductRule,
saveAdminWorkerLevel,
submitAdminWorkOrderMaterial,
syncAdminWorkerOrdersFromSource,
unpublishAdminWorkOrder,
updateAdminWorkOrder,
updateAdminWorkOrderSharing,
@@ -115,6 +114,8 @@ export default function WorkOrdersPanel() {
const navigate = useNavigate()
const queryClient = useQueryClient()
const [status, setStatus] = useState('')
const [keyword, setKeyword] = useState('')
const [keywordInput, setKeywordInput] = useState('')
const [page, setPage] = useState(1)
const [pageSize, setPageSize] = useState(ADMIN_DEFAULT_PAGE_SIZE)
const [detailOrder, setDetailOrder] = useState<WorkOrder | null>(null)
@@ -147,8 +148,8 @@ export default function WorkOrdersPanel() {
}>()
const ordersQuery = useQuery({
queryKey: ['admin-worker-platform-orders', status, page, pageSize],
queryFn: () => fetchAdminWorkOrders({ status, page, pageSize }),
queryKey: ['admin-worker-platform-orders', status, keyword, page, pageSize],
queryFn: () => fetchAdminWorkOrders({ status, keyword, page, pageSize }),
})
const ordersPagination = ordersQuery.data?.data.pagination
const categoriesQuery = useQuery({
@@ -295,18 +296,16 @@ export default function WorkOrdersPanel() {
setMaterialScreenshots([])
}
async function submitSourceSync(values: { platformOrderId?: string }) {
try {
const result = await syncAdminWorkerOrdersFromSource({
platformOrderId: String(values.platformOrderId || '').trim(),
})
message.success(
`同步完成,新增 ${result.data.createdCount} 个,跳过 ${result.data.skippedCount}`,
)
await refreshAll()
} catch (error) {
message.error(error instanceof Error ? error.message : '同步失败')
function searchOrders() {
setKeyword(keywordInput.trim())
setPage(1)
}
function clearOrderFilters() {
setKeywordInput('')
setKeyword('')
setStatus('')
setPage(1)
}
function openMaterialModal(row: WorkOrder) {
@@ -636,32 +635,17 @@ export default function WorkOrdersPanel() {
return (
<section className="platform-panel-stack">
<Card title="从源订单同步" bordered={false}>
<Form layout="inline" onFinish={submitSourceSync}>
<Form.Item
label="平台订单号"
name="platformOrderId"
rules={[{ required: true, message: '请输入平台订单号' }]}
>
<Card title="订单搜索与筛选" bordered={false}>
<div className="worker-orders-toolbar">
<Space wrap className="filter-form worker-orders-search-controls">
<Input
placeholder="用户填写链接 A 的订单号"
style={{ width: 260 }}
allowClear
value={keywordInput}
placeholder="订单号、工单号或商品名"
style={{ width: 280 }}
onChange={(event) => setKeywordInput(event.target.value)}
onPressEnter={searchOrders}
/>
</Form.Item>
<Form.Item>
<Button type="primary" icon={<SyncOutlined />} htmlType="submit">
</Button>
</Form.Item>
</Form>
</Card>
<Card title="生成本地接单工单 Mock" bordered={false}>
<MockWorkOrderForm onCreated={refreshAll} />
</Card>
<Card
title="接单工单"
extra={
<Space>
<Select
value={status}
style={{ width: 150 }}
@@ -681,6 +665,21 @@ export default function WorkOrdersPanel() {
setPage(1)
}}
/>
<Button type="primary" icon={<SearchOutlined />} onClick={searchOrders}>
</Button>
<Button onClick={clearOrderFilters}></Button>
</Space>
<div className="worker-orders-mock">
<Typography.Text type="secondary"> Mock</Typography.Text>
<MockWorkOrderForm onCreated={refreshAll} />
</div>
</div>
</Card>
<Card
title="接单工单"
extra={
<Space>
<Button
icon={<ReloadOutlined />}
loading={ordersQuery.isFetching}
@@ -709,7 +708,6 @@ export default function WorkOrdersPanel() {
scroll={{ x: 1240 }}
/>
</Card>
<Drawer
title={
detailOrder
@@ -1320,6 +1318,7 @@ function MockWorkOrderForm({ onCreated }: { onCreated: () => Promise<void> }) {
return (
<Form
className="worker-order-mock-form"
layout="inline"
initialValues={{
productName: '指挥官秘钥1个',
@@ -1328,23 +1327,24 @@ function MockWorkOrderForm({ onCreated }: { onCreated: () => Promise<void> }) {
}}
onFinish={submit}
>
<Form.Item label="订单号" name="platformOrderId">
<Input placeholder="留空自动生成" style={{ width: 180 }} />
<Form.Item className="worker-order-mock-field-order" label="订单号" name="platformOrderId">
<Input placeholder="留空自动生成" />
</Form.Item>
<Form.Item label="商品" name="productName">
<Input style={{ width: 220 }} />
<Form.Item className="worker-order-mock-field-product" label="商品" name="productName">
<Input />
</Form.Item>
<Form.Item label="接单金额" name="rewardAmount">
<Form.Item className="worker-order-mock-field-amount" label="接单金额" name="rewardAmount">
<InputNumber min={0.01} step={1} addonAfter="元" />
</Form.Item>
<Form.Item
className="worker-order-mock-field-complete"
label="资料完整"
name="materialComplete"
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item>
<Form.Item className="worker-order-mock-action">
<Button
type="primary"
icon={<PlusOutlined />}
@@ -61,7 +61,6 @@ import {
saveAdminWorkProductRule,
saveAdminWorkerLevel,
submitAdminWorkOrderMaterial,
syncAdminWorkerOrdersFromSource,
unpublishAdminWorkOrder,
updateAdminWorkOrderSharing,
} from '@/services/admin'
@@ -355,4 +354,3 @@ export default function WorkersPanel() {
</Card>
)
}
@@ -199,18 +199,6 @@ export function createAdminMockWorkOrder(payload: {
)
}
export function syncAdminWorkerOrdersFromSource(payload: {
platformOrderId?: string
orderId?: number
}) {
return apiPost<{
created: WorkOrder[]
skipped: Array<{ orderItemId: number; reason: string }>
createdCount: number
skippedCount: number
}>('/api/v1/admin/worker-platform/source-orders/sync', payload)
}
export function submitAdminWorkOrderMaterial(
workOrderId: number,
fields: Record<string, string>,
+65
View File
@@ -1462,6 +1462,58 @@ select {
min-width: 0;
}
.worker-orders-toolbar {
display: flex;
align-items: center;
gap: 24px;
min-width: 0;
}
.worker-orders-search-controls {
flex: 0 0 auto;
}
.worker-orders-mock {
flex: 1;
min-width: 0;
display: flex;
align-items: center;
gap: 12px;
padding-left: 24px;
border-left: 1px solid #edf0f5;
}
.worker-orders-mock > .ant-typography {
flex: 0 0 auto;
white-space: nowrap;
}
.worker-order-mock-form {
flex: 1;
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 12px;
min-width: 0;
}
.worker-order-mock-form .ant-form-item {
min-width: 0;
margin: 0;
}
.worker-order-mock-field-order .ant-input {
width: 150px;
}
.worker-order-mock-field-product .ant-input {
width: 190px;
}
.worker-order-mock-field-amount .ant-input-number {
width: 116px;
}
.worker-order-detail-stack {
display: grid;
gap: 16px;
@@ -1728,6 +1780,19 @@ select {
grid-template-columns: 1fr;
}
.worker-orders-toolbar {
flex-direction: column;
align-items: stretch;
gap: 12px;
}
.worker-orders-mock {
padding-top: 12px;
padding-left: 0;
border-top: 1px solid #edf0f5;
border-left: 0;
}
.kuaishou-industry-split {
grid-template-columns: 1fr;
}