Migrate /wip-overview, /wip-detail, and /hold-detail (1,941 lines vanilla JS) to Vue 3 SFC architecture. Extract shared CSS/constants/components to wip-shared/. Switch Pareto charts to vue-echarts with autoresize. Replace Jinja2 template injection with frontend URL params + constant classification for Hold Detail. Add 10-min auto-refresh + AbortController to Hold Detail. Remove three Jinja2 templates, update Flask routes to send_from_directory. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
5.4 KiB
5.4 KiB
Purpose
Define stable requirements for hold-detail-page.
Requirements
Requirement: Hold Detail page SHALL display hold reason analysis
The page SHALL show summary statistics for a specific hold reason.
Scenario: Summary cards rendering
- WHEN the page loads with
?reason={reason}in the URL - THEN the page SHALL call
GET /api/wip/hold-detail/summarywith the reason - THEN five cards SHALL display: Total Lots, Total QTY, 平均當站滯留, 最久當站滯留, 影響站群
- THEN age values SHALL display with "天" suffix
Scenario: Hold type classification
- WHEN the page loads
- THEN the header gradient color SHALL be red (#ef4444) for quality holds or orange (#f97316) for non-quality holds
- THEN a badge SHALL display "品質異常" or "非品質異常" accordingly
- THEN classification SHALL use a frontend
NON_QUALITY_HOLD_REASONSconstant set (11 values matching backendsql/filters.py)
Scenario: Missing reason parameter
- WHEN the page loads without a
reasonURL parameter - THEN the page SHALL redirect to
/wip-overview
Requirement: Hold Detail page SHALL display age distribution
The page SHALL show the distribution of hold lots by age at current station.
Scenario: Age distribution cards
- WHEN distribution data is loaded from
GET /api/wip/hold-detail/distribution - THEN four clickable cards SHALL display: 0-1天, 1-3天, 3-7天, 7+天
- THEN each card SHALL show Lots, QTY, and percentage
Scenario: Age card click filters lots
- WHEN user clicks an age card
- THEN the lot table SHALL reload filtered to that age range
- THEN the clicked card SHALL show a blue active border
- THEN clicking the same card again SHALL remove the filter
Requirement: Hold Detail page SHALL display workcenter and package distribution
The page SHALL show distribution tables for workcenter and package breakdowns.
Scenario: Distribution tables rendering
- WHEN distribution data is loaded
- THEN two side-by-side tables SHALL display: By Workcenter and By Package
- THEN each table SHALL show Name, Lots, QTY, and percentage columns
- THEN tables SHALL be scrollable with max-height 300px
Scenario: Distribution row click filters lots
- WHEN user clicks a row in the workcenter or package table
- THEN the lot table SHALL reload filtered by that workcenter or package
- THEN the clicked row SHALL show an active highlight
- THEN clicking the same row again SHALL remove the filter
Requirement: Hold Detail page SHALL display paginated lot details
The page SHALL display detailed lot information with server-side pagination.
Scenario: Lot table rendering
- WHEN lot data is loaded from
GET /api/wip/hold-detail/lots - THEN a table SHALL display with 10 columns: LOTID, WORKORDER, QTY, Package, Workcenter, Spec, Age, Hold By, Dept, Hold Comment
- THEN age values SHALL display with "天" suffix
Scenario: Filter indicator
- WHEN any filter is active (workcenter, package, or age range)
- THEN a blue filter indicator bar SHALL display showing active filters (e.g., "篩選: Workcenter=WC-A, Age=3-7天")
- THEN clicking the "×" on the indicator SHALL clear all filters
Scenario: Pagination
- WHEN total pages exceeds 1
- THEN Prev/Next buttons and page info SHALL display
- THEN page info SHALL show "顯示 {start} - {end} / {total}"
Scenario: Filter changes reset pagination
- WHEN any filter is toggled
- THEN pagination SHALL reset to page 1
Requirement: Hold Detail page SHALL have back navigation to Overview
The page SHALL provide a way to return to the WIP Overview page.
Scenario: Back button
- WHEN user clicks the "← WIP Overview" button in the header
- THEN the page SHALL navigate to
/wip-overview
Requirement: Hold Detail page SHALL auto-refresh and handle request cancellation
The page SHALL automatically refresh data and prevent stale request pile-up.
Scenario: Auto-refresh interval
- WHEN the page is loaded
- THEN data SHALL auto-refresh every 10 minutes
- THEN auto-refresh SHALL be skipped when the tab is hidden
Scenario: Visibility change refresh
- WHEN the tab becomes visible after being hidden
- THEN data SHALL refresh immediately
Scenario: Request cancellation
- WHEN a new data load is triggered while a previous request is in-flight
- THEN the previous request SHALL be cancelled via AbortController
- THEN the cancelled request SHALL NOT update the UI
Scenario: Manual refresh
- WHEN user clicks the "重新整理" button
- THEN data SHALL reload and the auto-refresh timer SHALL reset
Requirement: Hold Detail page SHALL handle loading and error states
The page SHALL display appropriate feedback during API calls and on errors.
Scenario: Initial loading overlay
- WHEN the page first loads
- THEN a full-page loading overlay SHALL display until all data is loaded
Scenario: API error handling
- WHEN an API call fails
- THEN the affected section SHALL display an error message
- THEN the page SHALL NOT crash or become unresponsive
Scenario: Empty lot result
- WHEN a query returns zero lots
- THEN the lot table SHALL display a "No data" placeholder