fix: distinguish awaiting work order replies

This commit is contained in:
2026-07-27 14:58:29 +08:00
parent f8c79a2af3
commit ade88b4fbf
9 changed files with 143 additions and 49 deletions
@@ -5,7 +5,8 @@ import type {
ScheduledConditionReport,
ScheduledConditionRiskLevel,
ScheduledConditionStatus,
ScheduledConditionTaskId
ScheduledConditionTaskId,
ScheduledWorkOrderStatus
} from "../types";
export const SCHEDULED_CONDITION_REFRESH_INTERVAL_MS = 5_000;
@@ -16,6 +17,7 @@ const MODEL_NAME = "DrainFlow Realtime Simulator";
const GUARANTEED_RUNNING_TASK_ID: ConditionTaskId = "scada-diagnosis";
type ConditionTaskId = ScheduledConditionTaskId;
type WorkOrderPhase = "dispatch" | "execution" | "reply";
type ConditionTaskDefinition = {
id: ConditionTaskId;
@@ -332,6 +334,7 @@ function createUpcomingWorkOrders(now: Date, currentMinutesOfDay: number): Sched
.map((workOrder) => {
const scheduledAtDate = setMinutesOfDay(now, workOrder.startMinute);
const replyDeadlineMinute = workOrder.startMinute + workOrder.durationMinutes + workOrder.replyWindowMinutes;
const phase = getWorkOrderPhase(workOrder, currentMinutesOfDay);
return {
id: `manual-work-order-${workOrder.id}-${formatCompactLocalTime(scheduledAtDate)}`,
@@ -340,7 +343,7 @@ function createUpcomingWorkOrders(now: Date, currentMinutesOfDay: number): Sched
scheduledAt: formatLocalIsoWithOffset(scheduledAtDate),
title: workOrder.title,
summary: workOrder.summary,
status: currentMinutesOfDay < workOrder.startMinute ? ("pending" as const) : ("running" as const),
status: getWorkOrderStatus(phase),
riskLevel: workOrder.riskLevel,
updatedAt: now.getTime(),
detail: workOrder.detail,
@@ -352,7 +355,7 @@ function createUpcomingWorkOrders(now: Date, currentMinutesOfDay: number): Sched
assignee: workOrder.assignee,
priority: workOrder.priority,
replyWindowMinutes: workOrder.replyWindowMinutes,
stages: createWorkOrderStages(workOrder, now, scheduledAtDate, currentMinutesOfDay),
stages: createWorkOrderStages(workOrder, now, scheduledAtDate, phase),
replyRequirements:
currentMinutesOfDay > replyDeadlineMinute
? []
@@ -385,11 +388,38 @@ function getMockWorkOrderStartMinute(template: MockWorkOrderTemplate, currentMin
return currentMinutesOfDay - template.durationMinutes - Math.min(10, template.replyWindowMinutes - 5);
}
function getWorkOrderPhase(
workOrder: ManualWorkOrderDefinition,
currentMinutesOfDay: number
): WorkOrderPhase {
if (currentMinutesOfDay < workOrder.startMinute) {
return "dispatch";
}
if (currentMinutesOfDay < workOrder.startMinute + workOrder.durationMinutes) {
return "execution";
}
return "reply";
}
function getWorkOrderStatus(phase: WorkOrderPhase): ScheduledWorkOrderStatus {
if (phase === "dispatch") {
return "pending";
}
if (phase === "execution") {
return "running";
}
return "awaiting_reply";
}
function createWorkOrderStages(
workOrder: ManualWorkOrderDefinition,
now: Date,
scheduledAtDate: Date,
currentMinutesOfDay: number
phase: WorkOrderPhase
) {
const dispatchAt = setMinutesOfDay(now, Math.max(0, workOrder.startMinute - workOrder.dispatchLeadMinutes));
const executionEnd = setMinutesOfDay(now, workOrder.startMinute + workOrder.durationMinutes);
@@ -397,13 +427,11 @@ function createWorkOrderStages(
now,
workOrder.startMinute + workOrder.durationMinutes + workOrder.replyWindowMinutes
);
const executionEndMinute = workOrder.startMinute + workOrder.durationMinutes;
return [
{
id: "dispatch" as const,
title: "派发",
status: currentMinutesOfDay >= workOrder.startMinute ? ("done" as const) : ("current" as const),
status: phase === "dispatch" ? ("current" as const) : ("done" as const),
owner: workOrder.dispatcher,
timeLabel: formatClock(dispatchAt),
description: `确认${workOrder.location}任务范围、优先级和到场窗口,派发给${workOrder.assignee}。`
@@ -412,22 +440,19 @@ function createWorkOrderStages(
id: "execution" as const,
title: "执行",
status:
currentMinutesOfDay >= executionEndMinute
? ("done" as const)
: currentMinutesOfDay >= workOrder.startMinute
phase === "dispatch"
? ("pending" as const)
: phase === "execution"
? ("current" as const)
: ("pending" as const),
: ("done" as const),
owner: workOrder.assignee,
timeLabel: formatClockRange(scheduledAtDate, workOrder.durationMinutes),
description: workOrder.summary
},
{
id: "reply" as const,
title: "复令",
status:
currentMinutesOfDay >= executionEndMinute
? ("current" as const)
: ("pending" as const),
title: "待复令",
status: phase === "reply" ? ("current" as const) : ("pending" as const),
owner: `${workOrder.assignee} → 调度中心`,
timeLabel: formatClockRange(executionEnd, workOrder.replyWindowMinutes),
description: `提交处置结果、现场照片和影响复核,最迟 ${formatClock(replyEnd)} 前完成复令。`