feat(workbench): integrate runtime data and map tooling

This commit is contained in:
2026-09-22 10:45:46 +08:00
parent bf44cc0f25
commit bebcf2a06c
163 changed files with 15642 additions and 1312 deletions
@@ -0,0 +1,547 @@
import { expect, test } from "@playwright/test";
import { mockAgentApi } from "./support/mock-agent-api";
test.describe("外围样板管理", () => {
test.beforeEach(async ({ page }) => {
await mockAgentApi(page);
await page.route("**/runtime-config.js", (route) =>
route.fulfill({
contentType: "text/javascript",
body: `globalThis.__TJWATER_CONFIG__ = ${JSON.stringify({
TJWATER_AUTH_MODE: "disabled",
TJWATER_SERVER_API_BASE_URL: "http://server.test",
TJWATER_MAP_URL: "http://map.test/geoserver",
TJWATER_GEOSERVER_WORKSPACE: "tjwater_next"
})};`
})
);
await page.route("http://server.test/api/v1/projects**", (route) =>
route.fulfill({
json: {
items: [
{
project_id: "324ff7ee-c2d4-5184-a84b-48fb14a2933e",
gs_workspace: "tjwater_next",
status: "active"
}
],
total: 1,
limit: 1000,
offset: 0
}
})
);
await page.route("http://server.test/api/v1/scada-devices**", (route) =>
route.fulfill({ json: { items: [], total: 0, limit: 1000, offset: 0 } })
);
await page.route("http://map.test/**", (route) => route.fulfill({ status: 204 }));
});
test("展示已配置的历史回放与合成样本", async ({ page }, testInfo) => {
const observationQueries: Record<string, string>[] = [];
const writeRequests: string[] = [];
await page.route("**/runtime-config.js", (route) =>
route.fulfill({
contentType: "text/javascript",
body: `globalThis.__TJWATER_CONFIG__ = ${JSON.stringify({
TJWATER_AUTH_MODE: "disabled",
TJWATER_SERVER_API_BASE_URL: "http://server.test",
TJWATER_PERIPHERAL_SAMPLE_API_BASE_URL: "http://peripheral.test",
TJWATER_PERIPHERAL_SAMPLE_TIME_MODE: "demo",
TJWATER_PERIPHERAL_SAMPLE_DEMO_START: "2026-04-30T08:00:00Z",
TJWATER_PERIPHERAL_SAMPLE_DEMO_END: "2026-04-30T16:00:00Z"
})};`
})
);
await page.route("http://server.test/api/v1/projects**", (route) =>
route.fulfill({
json: {
items: [
{
project_id: "324ff7ee-c2d4-5184-a84b-48fb14a2933e",
gs_workspace: "tjwater_next",
status: "active"
}
],
total: 1,
limit: 1000,
offset: 0
}
})
);
const feedback = {
feedback_id: "40000000-0000-4000-8000-000000000001",
task_id: "10000000-0000-4000-8000-000000000001",
recorded_by: "operator",
recorded_at: "2026-04-30T09:10:00Z",
occurred_at: "2026-04-30T09:00:00Z",
applicable_time: { start: "2026-04-30T08:00:00Z", end: "2026-04-30T16:00:00Z" },
asset_ids: ["DEMO-P001"],
finding: "instrument_fault",
notes: "压力变送器零点漂移",
attachment_refs: [],
origin: "synthetic"
};
const task = {
task_id: feedback.task_id,
project_id: "324ff7ee-c2d4-5184-a84b-48fb14a2933e",
revision: 3,
title: "DEMO-P001 测点偏差核查",
summary: "校验记录外围核查",
source: {
system: "next",
task_id: "20000000-0000-4000-8000-000000000001",
object_type: "validation",
object_id: "30000000-0000-4000-8000-000000000001",
revision: 2
},
asset_ids: ["DEMO-P001"],
analysis_window: { start: "2026-04-30T08:00:00Z", end: "2026-04-30T16:00:00Z" },
evidence_refs: [],
requested_check: "核查仪表状态",
status: "pending_review",
origin: "synthetic",
created_at: "2026-04-30T08:05:00Z",
updated_at: "2026-04-30T09:10:00Z",
created_by: "operator",
history: [
{
sequence: 1,
from_status: null,
to_status: "pending",
actor: "operator",
at: "2026-04-30T08:05:00Z",
reason: "提交样板核查"
},
{
sequence: 2,
from_status: "processing",
to_status: "pending_review",
actor: "operator",
at: "2026-04-30T09:10:00Z",
reason: "等待审核"
}
],
feedback: [feedback]
};
await page.route("http://peripheral.test/api/sample/v1/**", async (route) => {
const url = new URL(route.request().url());
if (route.request().method() !== "GET") writeRequests.push(route.request().url());
if (url.pathname.endsWith("/monitoring/observations"))
observationQueries.push(Object.fromEntries(url.searchParams));
if (url.pathname.endsWith("/context"))
return route.fulfill({
json: {
protocol_version: "tjwater-peripheral-sample@1",
origin: "synthetic",
project_id: task.project_id,
user_id: "50000000-0000-4000-8000-000000000001",
can_write: true,
scenarios: ["normal"],
managed_resources: { work_orders: "available", test_data: "available" },
state_transitions: {
pending: ["processing"],
processing: ["pending_review"],
pending_review: ["processing", "completed"],
completed: []
}
}
});
if (url.pathname.endsWith("/scenario"))
return route.fulfill({ json: { scenario: "normal", revision: 1 } });
if (url.pathname.endsWith("/tasks"))
return route.fulfill({ json: { items: [task], next_cursor: null } });
if (url.pathname.endsWith("/work-orders"))
return route.fulfill({ json: { items: createSourceWorkOrders(task.project_id), next_cursor: null } });
if (url.pathname.endsWith("/test-data"))
return route.fulfill({ json: { items: [], next_cursor: null } });
if (url.pathname.endsWith("/monitoring/points"))
return route.fulfill({
json: {
items: Array.from({ length: 118 }, (_, index) => ({
point_id: `SCADA-${index + 1}`,
label: `压力测点 ${index + 1}`,
unit: "m",
status: "active",
origin: "historical_replay"
})),
next_cursor: null,
origin: "historical_replay",
source_id: "tjwater_v2"
}
});
if (url.pathname.endsWith("/monitoring/alerts"))
return route.fulfill({
json: {
availability: "not_configured",
items: [],
origin: "historical_replay",
reason: "来源未配置",
source_id: "tjwater_v2"
}
});
if (url.pathname.endsWith("/monitoring/observations"))
return route.fulfill({
json: {
origin: "historical_replay",
source_id: "tjwater_v2",
source_revision: "2026-04-30",
truncated: false,
items: [
{
record_id: "reading-1",
point_id: "SCADA-1",
observed_at: "2026-04-30T08:15:00Z",
value: 31.42,
quality: "valid",
unit: "m"
},
{
record_id: "reading-2",
point_id: "SCADA-1",
observed_at: "2026-04-30T08:30:00Z",
value: null,
quality: "missing",
unit: "m"
}
]
}
});
if (url.pathname.endsWith("/demo-data"))
return route.fulfill({ json: createDemoDataset(task.project_id) });
return route.fulfill({
status: 404,
json: { code: "NOT_FOUND", message: "not found", effect: "none", request_id: null }
});
});
await page.goto("/");
await page.getByRole("button", { name: "外围样板管理" }).click();
await expect(page.getByText(/118 个测点 · 告警来源未配置 · 真实项目样本回放/)).toBeVisible();
const hierarchy = page.getByLabel("任务层级");
await expect(hierarchy).toContainText("外围合成数据核查");
await expect(hierarchy).toContainText("3 个子任务");
await expect(page.getByLabel("子任务阶段 合成通信核查")).toContainText(/派发.*当前阶段.*执行.*待开始.*复令.*待开始/);
await expect(page.getByLabel("子任务阶段 合成压力偏差复核")).toContainText(/派发.*已完成.*执行.*当前阶段.*复令.*待开始/);
await expect(page.getByLabel("子任务阶段 合成零流量样本确认")).toContainText(/派发.*已完成.*执行.*已完成.*复令.*已完成/);
const scenarioSelect = page.getByRole("combobox", { name: "场景" });
await scenarioSelect.focus();
await page.keyboard.press("Enter");
await expect(page.getByRole("listbox")).toBeVisible();
await page.keyboard.press("Escape");
await expect(page.getByRole("listbox")).toBeHidden();
await expect(scenarioSelect).toBeFocused();
const pointSelect = page.getByRole("combobox", { name: "测点", exact: true });
await pointSelect.click();
await page.getByRole("option", { name: "压力测点 2 · m" }).click();
await expect(pointSelect).toContainText("压力测点 2 · m");
const historyMode = page.getByRole("combobox", { name: "时间模式", exact: true });
const historyStart = page.getByRole("button", { name: "开始(UTC)", exact: true });
const historyEnd = page.getByRole("button", { name: "结束(UTC)", exact: true });
await expect(historyStart).toContainText("2026-04-30 08:00");
await historyMode.click();
await page.getByRole("option", { name: "最近 8 小时", exact: true }).click();
await expect(page.getByText(/UTC 历史窗口 · 最近 8 小时/)).toBeVisible();
await expect(historyStart).not.toContainText("2026-04-30 08:00");
await historyMode.click();
await page.getByRole("option", { name: "演示历史窗口", exact: true }).click();
await expect(historyStart).toContainText("2026-04-30 08:00");
await expect(historyEnd).toContainText("2026-04-30 16:00");
await historyStart.click();
const startDialog = page.getByRole("dialog", { name: "选择开始(UTC)" });
await startDialog.getByRole("gridcell", { name: "2026年4月29日", exact: true }).click();
await startDialog.getByRole("combobox", { name: "分钟" }).click();
await page.getByRole("option", { name: "15", exact: true }).click();
await startDialog.getByRole("button", { name: "确认", exact: true }).click();
await expect(historyStart).toContainText("2026-04-29 08:15");
await historyEnd.click();
const endDialog = page.getByRole("dialog", { name: "选择结束(UTC)" });
await endDialog.getByRole("combobox", { name: "分钟" }).click();
await page.getByRole("option", { name: "45", exact: true }).click();
await endDialog.getByRole("button", { name: "确认", exact: true }).click();
await expect(historyEnd).toContainText("2026-04-30 16:45");
expect(observationQueries).toEqual([]);
await page.getByRole("button", { name: "读取历史读数" }).click();
await expect(page.getByText("31.42 m")).toBeVisible();
await expect(page.getByText("缺失")).toBeVisible();
expect(observationQueries).toEqual([
{ point_id: "SCADA-2", start: "2026-04-29T08:15:00Z", end: "2026-04-30T16:45:00Z" }
]);
await page.getByText("合成演示样本", { exact: true }).click();
await page.getByRole("button", { name: "手动读取合成样本" }).click();
await expect(
page.getByText(/5 个虚拟测点,240 条读数,9 条状态,2 条告警,4 条运行事件/)
).toBeVisible();
await expect(page.getByText("0 m", { exact: true }).first()).toBeVisible();
await expect(page.getByText("缺失", { exact: true }).first()).toBeVisible();
for (const width of [320, 375, 1280]) {
await page.setViewportSize({ width, height: 720 });
await pointSelect.scrollIntoViewIfNeeded();
await pointSelect.click();
await expect(page.getByRole("listbox")).toBeVisible();
expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBeLessThanOrEqual(
width
);
await testInfo.attach(`peripheral-select-${width}px`, {
body: await page.screenshot(),
contentType: "image/png"
});
await page.keyboard.press("Escape");
await historyStart.click();
await expect(startDialog).toBeVisible();
await expect(
startDialog.locator(
'input[type="datetime-local"], input[type="date"], input[type="time"], select'
)
).toHaveCount(0);
await startDialog.getByRole("gridcell", { name: "2026年4月28日", exact: true }).click();
const calendarBox = await startDialog.boundingBox();
expect(calendarBox!.x).toBeGreaterThanOrEqual(0);
expect(calendarBox!.x + calendarBox!.width).toBeLessThanOrEqual(width);
expect(
await startDialog.evaluate((element) => element.scrollWidth <= element.clientWidth)
).toBe(true);
await page.screenshot({ path: `test-results/peripheral-datetime/${width}-calendar.png` });
await page.keyboard.press("Escape");
await expect(startDialog).toBeHidden();
await expect(historyStart).toBeFocused();
await expect(historyStart).toContainText("2026-04-29 08:15");
}
expect(observationQueries).toHaveLength(1);
expect(writeRequests).toEqual([]);
});
test("未配置时从顶栏进入且不暗连外围服务", async ({ page }) => {
const peripheralRequests: string[] = [];
page.on("request", (request) => {
if (request.url().includes("/api/sample/v1")) peripheralRequests.push(request.url());
});
await page.goto("/");
await page.getByRole("button", { name: "外围样板管理" }).click();
await expect(page.getByRole("complementary", { name: "外围样板管理" })).toBeVisible();
await expect(
page
.getByRole("complementary", { name: "外围样板管理" })
.getByText("外围系统模拟接入,不是正式工单/现场结果", { exact: true })
.last()
).toBeVisible();
await expect(page.getByText(/当前不会连接任何外围服务/)).toBeVisible();
expect(peripheralRequests).toEqual([]);
});
test("增量存储未供给时保留原有外围能力且不请求缺表资源", async ({ page }) => {
const projectId = "324ff7ee-c2d4-5184-a84b-48fb14a2933e";
const managedRequests: string[] = [];
await page.route("**/runtime-config.js", (route) => route.fulfill({
contentType: "text/javascript",
body: `globalThis.__TJWATER_CONFIG__=${JSON.stringify({
TJWATER_AUTH_MODE: "disabled",
TJWATER_SERVER_API_BASE_URL: "http://server.test",
TJWATER_PERIPHERAL_SAMPLE_API_BASE_URL: "http://peripheral.test"
})}`
}));
await page.route("http://peripheral.test/api/sample/v1/**", (route) => {
const path = new URL(route.request().url()).pathname;
if (path.includes("/work-orders") || path.includes("/test-data")) {
managedRequests.push(path);
return route.fulfill({ status: 503, json: {} });
}
if (path.endsWith("/context")) return route.fulfill({ json: {
protocol_version: "tjwater-peripheral-sample@1", origin: "synthetic", project_id: projectId,
user_id: "50000000-0000-4000-8000-000000000001", can_write: true,
scenarios: ["normal"], managed_resources: {
work_orders: "not_configured", test_data: "not_configured"
}, state_transitions: { pending: [], processing: [], pending_review: [], completed: [] }
} });
if (path.endsWith("/scenario")) return route.fulfill({ json: { scenario: "normal", revision: 1 } });
if (path.endsWith("/tasks")) return route.fulfill({ json: { items: [], next_cursor: null } });
if (path.endsWith("/monitoring/points")) return route.fulfill({ json: {
items: [], next_cursor: null, origin: "historical_replay", source_id: "tjwater_v2"
} });
if (path.endsWith("/monitoring/alerts")) return route.fulfill({ json: {
items: [], availability: "not_configured", reason: "告警源未配置",
origin: "historical_replay", source_id: "tjwater_v2"
} });
return route.fulfill({ status: 404, json: {} });
});
await page.goto("/");
await page.getByRole("button", { name: "外围样板管理" }).click();
const panel = page.getByRole("complementary", { name: "外围样板管理" });
await expect(panel.getByText("测试工单存储待供给", { exact: true })).toBeVisible();
await expect(panel.getByText("测试数据存储待供给", { exact: true })).toBeVisible();
await expect(panel.getByText("连接与演练场景", { exact: true })).toBeVisible();
expect(managedRequests).toEqual([]);
});
test("创建、修改并软删除测试工单和测试数据", async ({ page }) => {
const projectId = "324ff7ee-c2d4-5184-a84b-48fb14a2933e";
let workOrders: Record<string, unknown>[] = [];
let testData: Record<string, unknown>[] = [];
await page.route("**/runtime-config.js", (route) => route.fulfill({
contentType: "text/javascript",
body: `globalThis.__TJWATER_CONFIG__=${JSON.stringify({ TJWATER_AUTH_MODE: "disabled", TJWATER_SERVER_API_BASE_URL: "http://server.test", TJWATER_PERIPHERAL_SAMPLE_API_BASE_URL: "http://peripheral.test" })}`
}));
await page.route("http://peripheral.test/api/sample/v1/**", async (route) => {
const request = route.request();
const url = new URL(request.url());
const path = url.pathname;
const now = "2026-09-18T00:00:00Z";
if (path.endsWith("/context")) return route.fulfill({ json: { protocol_version: "tjwater-peripheral-sample@1", origin: "synthetic", project_id: projectId, user_id: "50000000-0000-4000-8000-000000000001", can_write: true, scenarios: ["normal"], managed_resources: { work_orders: "available", test_data: "available" }, state_transitions: { pending: ["processing"], processing: ["pending_review"], pending_review: ["processing", "completed"], completed: [] } } });
if (path.endsWith("/scenario")) return route.fulfill({ json: { scenario: "normal", revision: 1 } });
if (path.endsWith("/tasks")) return route.fulfill({ json: { items: [], next_cursor: null } });
if (path.endsWith("/monitoring/points")) return route.fulfill({ json: { items: [], next_cursor: null, origin: "historical_replay", source_id: "test" } });
if (path.endsWith("/monitoring/alerts")) return route.fulfill({ json: { items: [], availability: "not_configured", reason: "未配置", origin: "historical_replay", source_id: "test" } });
if (path.endsWith("/demo-data")) return route.fulfill({ json: createDemoDataset(projectId) });
if (path.endsWith("/work-orders") && request.method() === "GET") return route.fulfill({ json: { items: workOrders, next_cursor: null } });
if (path.endsWith("/work-orders") && request.method() === "POST") {
const body = request.postDataJSON();
const item = { ...body, work_order_id: "50000000-0000-4000-8000-000000000001", project_id: projectId, revision: 1, origin: "synthetic", created_at: now, updated_at: now, created_by: "tester", updated_by: "tester" };
delete item.request_id; workOrders = [item]; return route.fulfill({ status: 201, json: item });
}
if (path.includes("/work-orders/") && request.method() === "PATCH") {
const body = request.postDataJSON(); workOrders = [{ ...workOrders[0], ...body, revision: 2 }]; delete workOrders[0].request_id; delete workOrders[0].expected_revision;
return route.fulfill({ json: workOrders[0] });
}
if (path.includes("/work-orders/") && request.method() === "DELETE") { workOrders = []; return route.fulfill({ json: { resource_type: "work_order", resource_id: path.split("/").at(-1), revision: 3, deleted: true } }); }
if (path.endsWith("/test-data") && request.method() === "GET") return route.fulfill({ json: { items: testData, next_cursor: null } });
if (path.endsWith("/test-data") && request.method() === "POST") {
const body = request.postDataJSON(); const item = { ...body, record_id: "60000000-0000-4000-8000-000000000001", project_id: projectId, revision: 1, origin: "synthetic", created_at: now, updated_at: now, created_by: "tester", updated_by: "tester" };
delete item.request_id; testData = [item]; return route.fulfill({ status: 201, json: item });
}
if (path.includes("/test-data/") && request.method() === "PATCH") { const body = request.postDataJSON(); testData = [{ ...testData[0], ...body, revision: 2 }]; delete testData[0].request_id; delete testData[0].expected_revision; return route.fulfill({ json: testData[0] }); }
if (path.includes("/test-data/") && request.method() === "DELETE") { testData = []; return route.fulfill({ json: { resource_type: "test_data_record", resource_id: path.split("/").at(-1), revision: 3, deleted: true } }); }
return route.fulfill({ status: 404, json: { code: "NOT_FOUND", message: "not found", effect: "none", request_id: null } });
});
await page.goto("/");
await page.getByRole("button", { name: "外围样板管理" }).click();
const panel = page.getByRole("complementary", { name: "外围样板管理" });
await expect(panel.getByText("外围任务编排", { exact: true })).toBeVisible();
await expect(panel.getByLabel("任务层级")).toContainText("外围合成数据核查");
await expect(panel.getByRole("textbox", { name: "标题" })).toBeHidden();
await panel.getByRole("button", { name: "新增子任务" }).click();
await panel.getByRole("textbox", { name: "标题" }).fill("演示 测试工单");
await panel.getByRole("textbox", { name: "说明" }).fill("外围 CRUD 联调");
await panel.getByRole("button", { name: "创建子任务" }).click();
await expect(panel.getByText("演示 测试工单", { exact: true })).toBeVisible();
await panel.getByRole("button", { name: "编辑子任务 演示 测试工单" }).click();
await panel.getByRole("textbox", { name: "标题" }).fill("演示 测试工单(已改)");
await panel.getByRole("button", { name: "保存修改" }).click();
await expect(panel.getByText("演示 测试工单(已改)", { exact: true })).toBeVisible();
await panel.getByRole("button", { name: "删除子任务 演示 测试工单(已改)" }).click();
await expect(panel.getByText("演示 测试工单(已改)", { exact: true })).toBeHidden();
await panel.getByRole("group", { name: "外围样板资源类型" }).getByRole("button", { name: /测试数据/ }).click();
await panel.getByRole("button", { name: "新增测试数据" }).click();
await panel.getByRole("textbox", { name: "名称" }).fill("演示 压力样本");
await panel.getByRole("textbox", { name: "数值" }).fill("31.2");
await panel.getByRole("button", { name: "创建数据" }).click();
await expect(panel.getByText("演示 压力样本", { exact: true })).toBeVisible();
await panel.getByRole("button", { name: "编辑数据 演示 压力样本" }).click();
await panel.getByRole("textbox", { name: "数值" }).fill("30.8");
await panel.getByRole("button", { name: "保存修改" }).click();
await expect(panel.getByText(/30.8 m/)).toBeVisible();
await panel.getByRole("button", { name: "删除数据 演示 压力样本" }).click();
await expect(panel.getByText("演示 压力样本", { exact: true })).toBeHidden();
});
test("在 375px 视口内完整呈现面板", async ({ page }) => {
await page.setViewportSize({ width: 375, height: 720 });
await page.goto("/");
const launcher = page.getByRole("button", { name: "外围样板管理" });
await launcher.focus();
await page.keyboard.press("Enter");
const panel = page.getByRole("complementary", { name: "外围样板管理" });
await expect(panel).toBeVisible();
const box = await panel.boundingBox();
expect(box).not.toBeNull();
expect(box!.x).toBeGreaterThanOrEqual(0);
expect(box!.x + box!.width).toBeLessThanOrEqual(375);
});
});
function createDemoDataset(projectId: string) {
const points = Array.from({ length: 5 }, (_, index) => ({
point_id: `DEMO-${index + 1}`,
label: `虚拟压力测点 ${index + 1}`,
unit: "m",
status: "active",
origin: "synthetic"
}));
return {
generator_version: "water-demo@1",
seed: "water-demo-seed-20260917",
origin: "synthetic",
window: { start: "2026-09-17T00:00:00Z", end: "2026-09-17T12:00:00Z" },
project_id: projectId,
source_id: "peripheral-demo",
source_revision: "demo-r1",
points,
observations: Array.from({ length: 240 }, (_, index) => ({
record_id: `demo-reading-${index}`,
point_id: `DEMO-${(index % 5) + 1}`,
observed_at: `2026-09-17T${String(Math.floor(index / 20)).padStart(2, "0")}:${String((index % 4) * 15).padStart(2, "0")}:00Z`,
value: index === 0 ? 0 : index === 5 ? null : 31 + index / 100,
quality: index === 5 ? "missing" : "valid",
unit: "m"
})),
device_states: Array.from({ length: 9 }, (_, index) => ({
record_id: `60000000-0000-4000-8000-${String(index).padStart(12, "0")}`,
asset_id: `VIRTUAL-${index + 1}`,
asset_type: "pressure_sensor",
observed_at: "2026-09-17T01:00:00Z",
state: index === 1 ? "offline" : "online"
})),
alerts: [
{
alert_id: "70000000-0000-4000-8000-000000000001",
asset_id: "VIRTUAL-2",
code: "communication_lost",
message: "演示通信中断",
occurred_at: "2026-09-17T02:00:00Z",
cleared_at: "2026-09-17T02:15:00Z"
},
{
alert_id: "70000000-0000-4000-8000-000000000002",
asset_id: "VIRTUAL-3",
code: "low_level",
message: "演示低水位",
occurred_at: "2026-09-17T05:00:00Z",
cleared_at: null
}
],
operations: Array.from({ length: 4 }, (_, index) => ({
record_id: `80000000-0000-4000-8000-${String(index).padStart(12, "0")}`,
actor: "synthetic-generator",
asset_id: `VIRTUAL-${index + 1}`,
operation: ["pump_start", "pump_stop", "valve_open", "valve_close"][index],
note: "演示事件,不是控制指令",
occurred_at: `2026-09-17T0${index + 1}:30:00Z`
}))
};
}
function createSourceWorkOrders(projectId: string) {
return [
["合成通信核查", "核查监测点通信和数据上送状态", "open", "high"],
["合成压力偏差复核", "复核压力偏差与历史回放证据", "in_progress", "urgent"],
["合成零流量样本确认", "确认零流量样本及质量标记", "completed", "normal"]
].map(([title, summary, status, priority], index) => ({
work_order_id: `50000000-0000-4000-8000-${String(index + 1).padStart(12, "0")}`,
project_id: projectId,
revision: 1,
title,
summary,
status,
priority,
assignee: null,
scheduled_at: "2026-09-17T08:00:00Z",
origin: "synthetic",
created_at: "2026-09-17T00:00:00Z",
updated_at: "2026-09-17T00:00:00Z",
created_by: "synthetic-generator",
updated_by: "synthetic-generator"
}));
}