From 27bf1f170e4ef6a9305eb957207cda861be0e38c Mon Sep 17 00:00:00 2001 From: "z.zhang" Date: Fri, 9 Oct 2026 22:46:26 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E6=B6=88=E9=99=A4=E6=9C=AC?= =?UTF-8?q?=E6=AC=A1=E7=89=B9=E6=80=A7=E5=BC=95=E5=85=A5=E7=9A=84=E5=AD=97?= =?UTF-8?q?=E9=9D=A2=E9=87=8F=E7=A1=AC=E7=BC=96=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - orders.py 注释去掉具体单号示例,只描述规则 - flex.py 阻断原因行数上限提为 MAX_BLOCKED_ORDER_REASONS - VirtualLineReplay 日志条数/订单泳道上限提为 MAX_REPLAY_LOG_ROWS / MAX_ORDER_LANES 前端 tsc+vite 构建通过,flex/intake/order golden 192 项全过。 --- apps/web/src/viewport/VirtualLineReplay.tsx | 6 ++++-- server/aps_domain/flex.py | 5 ++++- server/aps_domain/orders.py | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/web/src/viewport/VirtualLineReplay.tsx b/apps/web/src/viewport/VirtualLineReplay.tsx index 1a44b7a..13d30d8 100644 --- a/apps/web/src/viewport/VirtualLineReplay.tsx +++ b/apps/web/src/viewport/VirtualLineReplay.tsx @@ -5,6 +5,8 @@ import './VirtualLineReplay.css'; const COLORS = ['#2563eb', '#f59e0b', '#0ea5e9', '#8b5cf6', '#ef4444', '#10b981', '#ec4899']; const DEFAULT_OPERATION_ORDER = ['激光下料', '下料', '折弯', '焊接', '喷涂', '组装', '装配']; const TARGET_REPLAY_MS = 45_000; +const MAX_REPLAY_LOG_ROWS = 8; // 推演日志面板最多展示条数,更早的由滚动承接 +const MAX_ORDER_LANES = 8; // 订单泳道最多展示条数,避免窄屏溢出 type ReplayStatus = 'loading' | 'running' | 'warning' | 'passed' | 'blocked'; @@ -187,7 +189,7 @@ export default function VirtualLineReplay({ data }: { data: FlexGanttData }) { kind: late || risk ? 'risk' : 'finish', }); } - return rows.filter(row => row.time <= virtualTime).sort((a, b) => b.time - a.time).slice(0, 8); + return rows.filter(row => row.time <= virtualTime).sort((a, b) => b.time - a.time).slice(0, MAX_REPLAY_LOG_ROWS); }, [virtualTime, workOrders]); const orderPosition = (order: OrderTrack) => { @@ -283,7 +285,7 @@ export default function VirtualLineReplay({ data }: { data: FlexGanttData }) { )}
订单入口 - {orders.slice(0, 8).map(order => { + {orders.slice(0, MAX_ORDER_LANES).map(order => { const pos = orderPosition(order); const left = stations.length <= 1 ? 50 : ((pos.stationIndex + 0.5) / stations.length) * 100; const risk = pos.focus.conflict || pos.focus.overdue; diff --git a/server/aps_domain/flex.py b/server/aps_domain/flex.py index 7a37c01..1d40508 100644 --- a/server/aps_domain/flex.py +++ b/server/aps_domain/flex.py @@ -230,6 +230,9 @@ def flex_gantt_view(world: World) -> dict: } +MAX_BLOCKED_ORDER_REASONS = 8 # 单张阻断订单展示的缺料原因行数上限,超出由冲突中心承接 + + def _blocked_orders_view(world: World, wos_out: list[dict], orders_by_no: dict, products: dict, latest_id) -> list[dict]: """阻断订单投影:本版本有冲突但没有任何工单的订单(如缺料急单)。 @@ -264,7 +267,7 @@ def _blocked_orders_view(world: World, wos_out: list[dict], orders_by_no: dict, "priority": o.get("priority"), "isRush": bool(o.get("isRush")), "severity": severity_by_order.get(ono) or "", - "reasons": reasons[:8], + "reasons": reasons[:MAX_BLOCKED_ORDER_REASONS], }) blocked.sort(key=lambda b: (b.get("dueDate") or "", b["orderNo"])) return blocked diff --git a/server/aps_domain/orders.py b/server/aps_domain/orders.py index fa83188..dc0ecf2 100644 --- a/server/aps_domain/orders.py +++ b/server/aps_domain/orders.py @@ -713,7 +713,7 @@ def apply_order_action(world: World, next_id, action: str, payload: dict[str, An product = _product(world, p["productId"]) order_no = p.get("orderNo") or "" if order_no: - # 计划员指定单号(如急单 RUSH-0007):保留并查重,失败即拒绝 + # 计划员指定单号:保留原号并全池查重,冲突即拒绝 folded = order_no.casefold() clash = any( str(o.get("orderNo") or "").casefold() == folded