From 8c058d71b11a46921e1fb4371764ac676a27ef57 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Fri, 21 Aug 2026 18:21:04 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8B=86=E5=88=86=E5=B7=A5=E5=8D=95=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E6=98=A0=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/services/worker-platform/mappers.ts | 115 +----------------- .../work-order-event-mappers.ts | 110 +++++++++++++++++ 2 files changed, 111 insertions(+), 114 deletions(-) create mode 100644 apps/backend/src/services/worker-platform/work-order-event-mappers.ts diff --git a/apps/backend/src/services/worker-platform/mappers.ts b/apps/backend/src/services/worker-platform/mappers.ts index 80bf4017..78cd2c24 100644 --- a/apps/backend/src/services/worker-platform/mappers.ts +++ b/apps/backend/src/services/worker-platform/mappers.ts @@ -1158,117 +1158,4 @@ export const IGNORABLE_WORKER_AUTH_ERROR_CODES = new Set([ 'worker_auth_device_revoked', ]) -export type WorkOrderEventView = { - id: number - time: string - actorType: string - actorName: string - eventType: string - fromStatus: string - toStatus: string - payload: JsonObject - /** 仅管理端流转记录返回,供查看事件涉及的打手信息。 */ - worker?: { - workerId: number - displayName: string - username: string - workerType: string - levelName: string - status: string - } -} - -/** - * 将工单事件原始行映射为带操作人显示名的视图。 - * admin 事件的操作人来自 actor_id(管理员用户名);worker 事件按打手表解析显示名。 - */ -export async function mapWorkOrderEvents( - events: Array<{ - id: number - actor_type: string - actor_id: string - event_type: string - from_status: string - to_status: string - payload_json: string | Record - created_at: string - }>, - options: { includeWorkerSummary?: boolean } = {}, -): Promise { - const workerIds = [ - ...new Set( - events.map(resolveWorkOrderEventWorkerId).filter((id) => Number.isFinite(id) && id > 0), - ), - ] - const workers = await Promise.all(workerIds.map((workerId) => getWorkerUserById(workerId))) - const workerById = new Map( - workers - .filter((worker): worker is WorkerUserRow => Boolean(worker)) - .map((worker) => [Number(worker.id), worker]), - ) - const workerNameById = new Map( - [...workerById.entries()].map(([workerId, worker]) => [ - workerId, - worker.display_name || worker.username || `打手#${workerId}`, - ]), - ) - - return events.map((event) => { - const workerId = resolveWorkOrderEventWorkerId(event) - const worker = workerById.get(workerId) - return { - id: Number(event.id), - time: new Date(event.created_at).toISOString(), - actorType: event.actor_type, - actorName: resolveWorkOrderEventActorName(event, workerNameById), - eventType: event.event_type, - fromStatus: event.from_status, - toStatus: event.to_status, - payload: safeParseJson(event.payload_json), - ...(options.includeWorkerSummary && worker - ? { - worker: { - workerId: Number(worker.id), - displayName: worker.display_name || worker.username || `打手#${worker.id}`, - username: worker.username, - workerType: normalizeWorkerType(worker.worker_type), - levelName: worker.level_name || '-', - status: worker.status, - }, - } - : {}), - } - }) -} - -/** 操作人优先,其次读取事件载荷中的关联打手。 */ -function resolveWorkOrderEventWorkerId(event: { - actor_type: string - actor_id: string - payload_json: string | Record -}) { - const actorWorkerId = event.actor_type === 'worker' ? Number(event.actor_id) : 0 - if (Number.isInteger(actorWorkerId) && actorWorkerId > 0) return actorWorkerId - const payloadWorkerId = Number(safeParseJson(event.payload_json).workerId || 0) - return Number.isInteger(payloadWorkerId) && payloadWorkerId > 0 ? payloadWorkerId : 0 -} - -function resolveWorkOrderEventActorName( - event: { actor_type: string; actor_id: string }, - workerNameById: Map, -) { - const actorId = String(event.actor_id || '').trim() - if (event.actor_type === 'worker') { - return workerNameById.get(Number(actorId)) || (actorId ? `打手#${actorId}` : '打手') - } - if (event.actor_type === 'admin') { - return actorId || '管理员' - } - if (event.actor_type === 'system') { - return '系统' - } - if (event.actor_type === 'collect') { - return '采集' - } - return actorId || '未知' -} +export { mapWorkOrderEvents, type WorkOrderEventView } from './work-order-event-mappers.js' diff --git a/apps/backend/src/services/worker-platform/work-order-event-mappers.ts b/apps/backend/src/services/worker-platform/work-order-event-mappers.ts new file mode 100644 index 00000000..684aa38c --- /dev/null +++ b/apps/backend/src/services/worker-platform/work-order-event-mappers.ts @@ -0,0 +1,110 @@ +import { getWorkerUserById, type WorkerUserRow } from '../../repositories/worker-platform/index.js' +import type { JsonObject } from '../../types/json.js' +import { safeParseJson } from '../admin/admin-query-utils.js' + +export type WorkOrderEventView = { + id: number + time: string + actorType: string + actorName: string + eventType: string + fromStatus: string + toStatus: string + payload: JsonObject + /** 仅管理端流转记录返回,供查看事件涉及的打手信息。 */ + worker?: { + workerId: number + displayName: string + username: string + workerType: string + levelName: string + status: string + } +} + +export async function mapWorkOrderEvents( + events: Array<{ + id: number + actor_type: string + actor_id: string + event_type: string + from_status: string + to_status: string + payload_json: string | Record + created_at: string + }>, + options: { includeWorkerSummary?: boolean } = {}, +): Promise { + const workerIds = [ + ...new Set( + events.map(resolveWorkOrderEventWorkerId).filter((id) => Number.isFinite(id) && id > 0), + ), + ] + const workers = await Promise.all(workerIds.map((workerId) => getWorkerUserById(workerId))) + const workerById = new Map( + workers + .filter((worker): worker is WorkerUserRow => Boolean(worker)) + .map((worker) => [Number(worker.id), worker]), + ) + const workerNameById = new Map( + [...workerById.entries()].map(([workerId, worker]) => [ + workerId, + worker.display_name || worker.username || `打手#${workerId}`, + ]), + ) + return events.map((event) => { + const workerId = resolveWorkOrderEventWorkerId(event) + const worker = workerById.get(workerId) + return { + id: Number(event.id), + time: new Date(event.created_at).toISOString(), + actorType: event.actor_type, + actorName: resolveWorkOrderEventActorName(event, workerNameById), + eventType: event.event_type, + fromStatus: event.from_status, + toStatus: event.to_status, + payload: safeParseJson(event.payload_json), + ...(options.includeWorkerSummary && worker + ? { + worker: { + workerId: Number(worker.id), + displayName: worker.display_name || worker.username || `打手#${worker.id}`, + username: worker.username, + workerType: normalizeWorkerType(worker.worker_type), + levelName: worker.level_name || '-', + status: worker.status, + }, + } + : {}), + } + }) +} + +function normalizeWorkerType(value: unknown): 'internal' | 'external' { + return String(value || '').trim() === 'internal' ? 'internal' : 'external' +} + +function resolveWorkOrderEventWorkerId(event: { + actor_type: string + actor_id: string + payload_json: string | Record +}) { + const actorWorkerId = event.actor_type === 'worker' ? Number(event.actor_id) : 0 + if (Number.isInteger(actorWorkerId) && actorWorkerId > 0) return actorWorkerId + const payloadWorkerId = Number(safeParseJson(event.payload_json).workerId || 0) + return Number.isInteger(payloadWorkerId) && payloadWorkerId > 0 ? payloadWorkerId : 0 +} + +function resolveWorkOrderEventActorName( + event: { actor_type: string; actor_id: string }, + workerNameById: Map, +) { + const actorId = String(event.actor_id || '').trim() + if (event.actor_type === 'worker') { + return workerNameById.get(Number(actorId)) || (actorId ? `打手#${actorId}` : '打手') + } + if (event.actor_type === 'admin') return actorId || '管理员' + if (event.actor_type === 'system') return '系统' + if (event.actor_type === 'collect') return '采集' + return actorId || '未知' +}