拆分工单事件映射
This commit is contained in:
@@ -1158,117 +1158,4 @@ export const IGNORABLE_WORKER_AUTH_ERROR_CODES = new Set([
|
|||||||
'worker_auth_device_revoked',
|
'worker_auth_device_revoked',
|
||||||
])
|
])
|
||||||
|
|
||||||
export type WorkOrderEventView = {
|
export { mapWorkOrderEvents, type WorkOrderEventView } from './work-order-event-mappers.js'
|
||||||
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<string, unknown>
|
|
||||||
created_at: string
|
|
||||||
}>,
|
|
||||||
options: { includeWorkerSummary?: boolean } = {},
|
|
||||||
): Promise<WorkOrderEventView[]> {
|
|
||||||
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<string, unknown>
|
|
||||||
}) {
|
|
||||||
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<number, string>,
|
|
||||||
) {
|
|
||||||
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 || '未知'
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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<string, unknown>
|
||||||
|
created_at: string
|
||||||
|
}>,
|
||||||
|
options: { includeWorkerSummary?: boolean } = {},
|
||||||
|
): Promise<WorkOrderEventView[]> {
|
||||||
|
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<string, unknown>
|
||||||
|
}) {
|
||||||
|
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<number, string>,
|
||||||
|
) {
|
||||||
|
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 || '未知'
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user