From 39aeb0baaa27eeae3b1d323ff29292953723a6ef Mon Sep 17 00:00:00 2001 From: yml2213 Date: Thu, 20 Aug 2026 18:02:13 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=BE=85=E9=AA=8C=E6=94=B6?= =?UTF-8?q?=E5=B7=A5=E5=8D=95=E6=8C=89VIP=E7=AD=89=E7=BA=A7=E7=AD=9B?= =?UTF-8?q?=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/repositories/worker-platform/types.ts | 2 + .../worker-platform/work-order-repo.ts | 22 +++++++++++ .../services/worker-platform/admin-service.ts | 5 +++ .../pages/admin/panels/WorkOrdersPanel.tsx | 38 ++++++++++++++++++- 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/apps/backend/src/repositories/worker-platform/types.ts b/apps/backend/src/repositories/worker-platform/types.ts index 99df4de1..2c0bffed 100644 --- a/apps/backend/src/repositories/worker-platform/types.ts +++ b/apps/backend/src/repositories/worker-platform/types.ts @@ -287,6 +287,8 @@ export type ListInput = { /** 打手类型筛选:internal 内部打手 / external 外部打手 */ workerType?: string workerId?: number + /** 后台待验收筛选:普通单按接单人,拼单按参与打手等级。 */ + workerLevelIds?: number[] categoryId?: number workerSharingId?: number visibleAfterIso?: string diff --git a/apps/backend/src/repositories/worker-platform/work-order-repo.ts b/apps/backend/src/repositories/worker-platform/work-order-repo.ts index 82635429..791df23a 100644 --- a/apps/backend/src/repositories/worker-platform/work-order-repo.ts +++ b/apps/backend/src/repositories/worker-platform/work-order-repo.ts @@ -1055,6 +1055,7 @@ export async function listWorkOrders({ workOrderId = 0, keyword = '', workerId = 0, + workerLevelIds = [], categoryId = 0, workerSharingId = 0, visibleAfterIso = '', @@ -1070,6 +1071,7 @@ export async function listWorkOrders({ workOrderId, keyword, workerId, + workerLevelIds, categoryId, workerSharingId, visibleAfterIso, @@ -3429,6 +3431,7 @@ function buildWorkOrderWhere({ workOrderId = 0, keyword = '', workerId = 0, + workerLevelIds = [], categoryId = 0, workerSharingId = 0, visibleAfterIso = '', @@ -3491,6 +3494,25 @@ function buildWorkOrderWhere({ ) )`) } + if (workerLevelIds.length > 0) { + params.push(workerLevelIds) + filters.push(`( + EXISTS ( + SELECT 1 + FROM worker_users wu + WHERE wu.id = wo.assigned_worker_id + AND wu.level_id = ANY($${params.length}::bigint[]) + ) + OR EXISTS ( + SELECT 1 + FROM work_order_shares wos + INNER JOIN worker_users wu ON wu.id = wos.worker_id + WHERE wos.work_order_id = wo.id + AND wos.status != 'cancelled' + AND wu.level_id = ANY($${params.length}::bigint[]) + ) + )`) + } if (categoryId) { params.push(categoryId) filters.push(`wo.category_id = $${params.length}`) diff --git a/apps/backend/src/services/worker-platform/admin-service.ts b/apps/backend/src/services/worker-platform/admin-service.ts index b5fe2ce6..a13bb83e 100644 --- a/apps/backend/src/services/worker-platform/admin-service.ts +++ b/apps/backend/src/services/worker-platform/admin-service.ts @@ -1307,6 +1307,9 @@ export async function listAdminWorkOrders(query: JsonObject = {}) { const pageSize = normalizePageSize(query.pageSize) const workOrderId = normalizeOptionalId(query.workOrderId ?? query.work_order_id) || 0 const workerId = normalizeOptionalId(query.workerId ?? query.worker_id) || 0 + const workerLevelIds = normalizeStatuses(query.workerLevelIds ?? query.worker_level_ids) + .map(normalizeOptionalId) + .filter((levelId): levelId is number => levelId !== null) const statuses = normalizeStatuses(query.status) const vipEvidencePending = normalizeBoolean(query.vipEvidencePending, false) const { items, total } = await listWorkOrders({ @@ -1316,6 +1319,7 @@ export async function listAdminWorkOrders(query: JsonObject = {}) { workOrderId, keyword: String(query.keyword || '').trim(), workerSharingId: workerId, + workerLevelIds, vipEvidencePending, useOperationalStatus: true, }) @@ -1324,6 +1328,7 @@ export async function listAdminWorkOrders(query: JsonObject = {}) { workOrderId, keyword: String(query.keyword || '').trim(), workerSharingId: workerId, + workerLevelIds, vipEvidencePending, useOperationalStatus: true, }) diff --git a/apps/frontend/src/pages/admin/panels/WorkOrdersPanel.tsx b/apps/frontend/src/pages/admin/panels/WorkOrdersPanel.tsx index b4e10288..d6541997 100644 --- a/apps/frontend/src/pages/admin/panels/WorkOrdersPanel.tsx +++ b/apps/frontend/src/pages/admin/panels/WorkOrdersPanel.tsx @@ -55,6 +55,7 @@ import { deleteAdminWorkOrder, fetchAdminWorkCategories, fetchAdminWorkOrderSharing, + fetchAdminWorkerLevels, fetchAdminWorkerUsers, fetchAdminWorkOrders, markAdminWorkOrderProblem, @@ -138,6 +139,7 @@ export default function WorkOrdersPanel() { const [keyword, setKeyword] = useState('') const [keywordInput, setKeywordInput] = useState('') const [workerId, setWorkerId] = useState() + const [workerLevelIds, setWorkerLevelIds] = useState([]) const [filterWorkerKeyword, setFilterWorkerKeyword] = useState('') const [assignWorkerKeyword, setAssignWorkerKeyword] = useState('') const [page, setPage] = useState(1) @@ -184,6 +186,7 @@ export default function WorkOrdersPanel() { (status) => status !== VIP_EVIDENCE_PENDING_STATUS, ) const vipEvidencePending = statuses.includes(VIP_EVIDENCE_PENDING_STATUS) + const showWorkerLevelFilter = statuses.includes('pending_acceptance') useEffect(() => { const workOrderId = Number(searchParams.get('workOrderId') || 0) @@ -193,6 +196,7 @@ export default function WorkOrdersPanel() { setKeyword('') setKeywordInput('') setWorkerId(undefined) + setWorkerLevelIds([]) setPage(1) setSearchParams( (current) => { @@ -209,6 +213,7 @@ export default function WorkOrdersPanel() { statuses.join(','), keyword, workerId, + workerLevelIds.join(','), targetWorkOrderId, page, pageSize, @@ -221,6 +226,8 @@ export default function WorkOrdersPanel() { workOrderId: targetWorkOrderId, keyword, workerId, + workerLevelIds: + showWorkerLevelFilter && workerLevelIds.length > 0 ? workerLevelIds.join(',') : undefined, page, pageSize, }), @@ -230,6 +237,11 @@ export default function WorkOrdersPanel() { queryKey: ['admin-worker-platform-categories'], queryFn: () => fetchAdminWorkCategories(), }) + const workerLevelsQuery = useQuery({ + queryKey: ['admin-worker-platform-levels'], + queryFn: () => fetchAdminWorkerLevels(), + enabled: showWorkerLevelFilter, + }) const filterWorkersQuery = useQuery({ queryKey: ['admin-worker-platform-workers', 'order-filter', filterWorkerKeyword], queryFn: () => @@ -258,7 +270,11 @@ export default function WorkOrdersPanel() { useEffect(() => { setSelectedAcceptanceOrderIds([]) - }, [statuses, keyword, workerId, targetWorkOrderId, page, pageSize]) + }, [statuses, keyword, workerId, workerLevelIds, targetWorkOrderId, page, pageSize]) + + useEffect(() => { + if (!showWorkerLevelFilter) setWorkerLevelIds([]) + }, [showWorkerLevelFilter]) function openAssignModal(row: WorkOrder) { setAssignOrder(row) @@ -567,6 +583,7 @@ export default function WorkOrdersPanel() { setKeyword('') setStatuses([]) setWorkerId(undefined) + setWorkerLevelIds([]) setPage(1) } @@ -1042,6 +1059,25 @@ export default function WorkOrdersPanel() { setPage(1) }} /> + {showWorkerLevelFilter ? ( +