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