Replace the monolithic useQueryToolData composable and nested Vue component tree with a modular architecture: useLotResolve, useLotLineage, useLotDetail, and useEquipmentQuery. Introduce ECharts TreeChart (LR orthogonal layout) for lot lineage visualization with multi-select support, subtree expansion, zoom/pan, and serial number normalization. Add unified LineageEngine backend with split descendant traversal and leaf serial number queries. Archive the query-tool-rewrite openspec change and sync delta specs to main. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
8.0 KiB
ADDED Requirements
Requirement: Query-tool page SHALL use tab-based layout separating LOT tracing from equipment queries
The query-tool page SHALL present two top-level tabs: "LOT 追蹤" and "設備查詢", each with independent state and UI.
Scenario: Tab switching preserves state
- WHEN the user switches from LOT tab to Equipment tab and back
- THEN the LOT tab SHALL retain its resolved lots, lineage tree state, and selected lot detail
- THEN the Equipment tab SHALL retain its query results independently
Scenario: URL state reflects active tab
- WHEN the user is on a specific tab
- THEN the URL SHALL include a
tabparameter (e.g.,?tab=lotor?tab=equipment) - THEN reloading the page SHALL restore the active tab
Requirement: QueryBar SHALL resolve LOT/Serial/WorkOrder inputs
The query bar SHALL accept multi-value input (newline or comma-separated) with input type selection and resolve via POST /api/query-tool/resolve.
Scenario: Successful LOT resolution
- WHEN the user enters lot IDs and clicks resolve
- THEN the system SHALL call
POST /api/query-tool/resolvewithinput_typeandvalues - THEN resolved lots SHALL appear as root nodes in the lineage tree
- THEN not-found values SHALL be displayed as warnings below the tree
Scenario: Work order expansion
- WHEN the user enters work order IDs (max 10)
- THEN each work order MAY expand to 100+ lots
- THEN all expanded lots SHALL appear as root nodes in the lineage tree
Scenario: Input validation
- WHEN the user submits empty input or exceeds limits (50 lot IDs, 50 serial numbers, 10 work orders)
- THEN the system SHALL display a validation error without making an API call
Requirement: LineageTree SHALL display as a decomposition tree with progressive growth animation
After resolve completes, the lineage tree SHALL auto-fire lineage API calls for each resolved lot with concurrency control, rendering an animated tree that grows as results arrive.
Scenario: Auto-fire lineage after resolve
- WHEN lot resolution completes with N resolved lots
- THEN the system SHALL automatically call
POST /api/trace/lineagefor each lot - THEN concurrent lineage requests SHALL be limited to 3 at a time
- THEN the lineage tree SHALL render root nodes immediately (resolved lots)
Scenario: Progressive tree growth animation
- WHEN a lineage API response returns for a lot
- THEN ancestor nodes SHALL animate into the tree (slide-in + fade, staggered 30-50ms per sibling)
- THEN the animation SHALL give the visual impression of a tree "growing" its branches
Scenario: Tree node expand/collapse
- WHEN the user clicks a tree node with children (ancestors)
- THEN children SHALL toggle between expanded and collapsed state
- THEN expand/collapse SHALL be a client-side operation (no additional API call)
Scenario: Expand-all and collapse-all
- WHEN the user clicks "全部展開"
- THEN all tree nodes at all levels SHALL expand with staggered animation
- WHEN the user clicks "收合"
- THEN all tree nodes SHALL collapse to show only root nodes
Scenario: Merge relationships visually distinct
- WHEN the lineage data includes merge relationships
- THEN merge nodes SHALL display a distinct icon and/or color to differentiate from direct ancestor relationships
Scenario: Leaf nodes without expand affordance
- WHEN a tree node has no ancestors (leaf/terminal node)
- THEN it SHALL NOT display an expand button or clickable expand area
Scenario: Lineage cache prevents duplicate fetches
- WHEN lineage data has already been fetched for a lot
- THEN subsequent interactions SHALL use cached data without re-fetching
- WHEN a new resolve query is executed
- THEN the lineage cache SHALL be cleared
Requirement: Left-right master-detail layout SHALL show tree and LOT detail side by side
The LOT tracing tab SHALL use a left-right split layout with the lineage tree on the left and LOT detail on the right.
Scenario: LOT selection from tree
- WHEN the user clicks any node in the lineage tree (root lot or ancestor)
- THEN the right panel SHALL load detail for that node's container ID
- THEN the selected node SHALL be visually highlighted in the tree
Scenario: Right panel sub-tabs
- WHEN a LOT is selected
- THEN the right panel SHALL display sub-tabs: 歷程 (History), 物料 (Materials), 退貨 (Rejects), Hold, Split, Job
- THEN each sub-tab SHALL load data on-demand when activated (not pre-fetched)
Scenario: Responsive behavior
- WHEN the viewport width is below 1024px
- THEN the layout SHALL stack vertically (tree above, detail below)
Requirement: LOT History sub-tab SHALL display production history with workcenter filter
The History sub-tab SHALL show production history data from GET /api/query-tool/lot-history with workcenter group filtering.
Scenario: History table display
- WHEN the user selects the History sub-tab for a LOT
- THEN the system SHALL call
GET /api/query-tool/lot-history?container_id=X - THEN results SHALL display in a table with sticky headers and horizontal scroll
Scenario: Workcenter group filter
- WHEN the user selects workcenter groups from the filter dropdown
- THEN the history query SHALL include the selected groups as filter parameters
- THEN the history table SHALL refresh with filtered results
Requirement: LOT Production Timeline SHALL visualize station progression over time
The History sub-tab SHALL include a timeline visualization showing the lot's journey through production stations.
Scenario: Timeline rendering
- WHEN lot history data is loaded
- THEN a horizontal Gantt-style timeline SHALL render with time on the X-axis
- THEN each workcenter/station SHALL appear as a track with a colored bar from track-in to track-out time
Scenario: Workcenter filter affects timeline
- WHEN the user filters by workcenter groups
- THEN the timeline SHALL show only stations matching the selected groups
- THEN filtered-out stations SHALL be hidden (not grayed out)
Scenario: Timeline event markers
- WHEN hold events or material consumption events exist within the timeline range
- THEN they SHALL be displayed as markers on the timeline with tooltip details on hover
Requirement: LOT Association sub-tabs SHALL load data on-demand
Each association sub-tab (Materials, Rejects, Holds, Splits, Jobs) SHALL fetch data independently when activated.
Scenario: Association data loading
- WHEN the user activates a sub-tab (e.g., Materials)
- THEN the system SHALL call
GET /api/query-tool/lot-associations?container_id=X&type=materials - THEN results SHALL display in a table with dynamic columns
Scenario: Sub-tab data caching within session
- WHEN the user switches between sub-tabs for the same LOT
- THEN previously loaded sub-tab data SHALL be preserved (not re-fetched)
- WHEN the user selects a different LOT
- THEN all sub-tab caches SHALL be cleared
Requirement: Each sub-tab SHALL support independent CSV export
Every detail sub-tab SHALL have its own export button.
Scenario: Per-tab export
- WHEN the user clicks export on the Materials sub-tab
- THEN the system SHALL call
POST /api/query-tool/export-csvwithexport_type: "lot_materials"and the current container_id - THEN a CSV file SHALL download with the appropriate filename
Scenario: Export disabled when no data
- WHEN a sub-tab has no data loaded or the data is empty
- THEN the export button SHALL be disabled
Requirement: Legacy dead code SHALL be removed
The legacy frontend/src/query-tool/main.js (448L vanilla JS) and frontend/src/query-tool/style.css SHALL be deleted.
Scenario: Dead code removal
- WHEN the rewrite is complete
- THEN
frontend/src/query-tool/main.jsSHALL contain only the Vite entry point (createApp + mount) - THEN
frontend/src/query-tool/style.cssSHALL be deleted (all styling via Tailwind)