feat(wip): preserve filters between Overview and Detail with thundering-herd fix

URL is now single source of truth for filter state (workorder, lotid,
package, type, status) across WIP Overview and Detail pages. Drill-down
carries all filters + status; back button dynamically reflects Detail
changes. Backend Detail API now supports pj_type filter parameter.

Harden concurrency: add pagehide abort for MPA navigation, double-check
locking on Redis JSON parse and snapshot build to prevent thread pool
saturation during rapid page switching. Fix watchdog setsid and PID
discovery. Fix test_realtime_equipment_cache RUNCARDLOTID field mismatch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
egg
2026-02-11 07:22:48 +08:00
parent 3a15b0abaf
commit be22571421
24 changed files with 1522 additions and 266 deletions

View File

@@ -17,6 +17,11 @@ The page SHALL read URL query parameters to initialize its state from the Overvi
- **THEN** filter inputs SHALL be pre-filled with those values
- **THEN** data SHALL be loaded with those filters applied
#### Scenario: Status passthrough from Overview
- **WHEN** the URL contains a `status` parameter (e.g., `?workcenter=焊接_DW&status=RUN`)
- **THEN** the status card corresponding to the `status` value SHALL be activated
- **THEN** data SHALL be loaded with the status filter applied
#### Scenario: Missing workcenter fallback
- **WHEN** the page loads without a `workcenter` parameter
- **THEN** the page SHALL fetch available workcenters from `GET /api/wip/meta/workcenters`
@@ -35,6 +40,7 @@ The page SHALL display five summary cards with status counts for the current wor
- **THEN** the active card SHALL show a visual active state
- **THEN** non-active status cards SHALL dim
- **THEN** clicking the same card again SHALL remove the filter
- **THEN** the URL SHALL be updated to reflect the active status filter
### Requirement: Detail page SHALL display lot details table with sticky columns
The page SHALL display a scrollable table with fixed left columns and dynamic spec columns.
@@ -107,12 +113,18 @@ The page SHALL paginate lot data with server-side support.
- **WHEN** user clicks Next or Prev
- **THEN** data SHALL reload with the updated page number
### Requirement: Detail page SHALL have back navigation to Overview
The page SHALL provide a way to return to the Overview page.
### Requirement: Detail page SHALL have back navigation to Overview with filter preservation
The page SHALL provide a way to return to the Overview page while preserving all current filter state.
#### Scenario: Back button
#### Scenario: Back button with filter state
- **WHEN** user clicks the "← Overview" button in the header
- **THEN** the page SHALL navigate to `/wip-overview`
- **THEN** the page SHALL navigate to `/wip-overview` with current filter values (workorder, lotid, package, type) and status as URL parameters
- **THEN** only non-empty filter values SHALL appear as URL parameters
#### Scenario: Back button reflects Detail changes
- **WHEN** the user modifies filters or status in Detail (e.g., changes status from RUN to QUEUE)
- **THEN** the back button URL SHALL dynamically update to reflect the current Detail filter state
- **THEN** navigating back SHALL cause Overview to load with the updated filter state
### Requirement: Detail page SHALL auto-refresh and handle request cancellation
The page SHALL auto-refresh and cancel stale requests identically to Overview.
@@ -122,3 +134,12 @@ The page SHALL auto-refresh and cancel stale requests identically to Overview.
- **THEN** data SHALL auto-refresh every 10 minutes, skipping when tab is hidden
- **THEN** visibility change SHALL trigger immediate refresh
- **THEN** new requests SHALL cancel in-flight requests via AbortController
### Requirement: Detail page SHALL synchronize status filter to URL
The page SHALL include the active status filter in URL state management.
#### Scenario: Status included in URL state
- **WHEN** the status filter is active
- **THEN** `updateUrlState()` SHALL include `status={value}` in the URL parameters
- **WHEN** the status filter is cleared
- **THEN** the `status` parameter SHALL be removed from the URL

View File

@@ -31,6 +31,7 @@ The page SHALL display four clickable status cards (RUN, QUEUE, 品質異常,
- **THEN** the clicked card SHALL show an active visual state
- **THEN** non-active cards SHALL dim to 50% opacity
- **THEN** clicking the same card again SHALL deactivate the filter and restore all cards
- **THEN** the URL SHALL be updated to reflect the active status filter
### Requirement: Overview page SHALL display Workcenter × Package matrix
The page SHALL display a cross-tabulation table of workcenters vs packages.
@@ -45,6 +46,7 @@ The page SHALL display a cross-tabulation table of workcenters vs packages.
- **WHEN** user clicks a workcenter name in the matrix
- **THEN** the page SHALL navigate to `/wip-detail?workcenter={name}`
- **THEN** active filter values (workorder, lotid, package, type) SHALL be passed as URL parameters
- **THEN** the active status filter SHALL be passed as the `status` URL parameter if set
### Requirement: Overview page SHALL display Hold Pareto analysis
The page SHALL display Pareto charts and tables for quality and non-quality hold reasons.
@@ -81,13 +83,15 @@ The page SHALL provide autocomplete-enabled filter inputs for WORKORDER, LOT ID,
#### Scenario: Apply and clear filters
- **WHEN** user clicks "套用篩選" or presses Enter in a filter input
- **THEN** all three API calls (summary, matrix, hold) SHALL reload with the filter values
- **THEN** the URL SHALL be updated to reflect the applied filter values
- **WHEN** user clicks "清除篩選"
- **THEN** all filter inputs SHALL be cleared and data SHALL reload without filters
- **THEN** the URL SHALL be cleared of all filter and status parameters
#### Scenario: Active filter display
- **WHEN** filters are applied
- **THEN** active filters SHALL be displayed as removable tags (e.g., "WO: {value} ×")
- **THEN** clicking a tag's remove button SHALL clear that filter and reload data
- **THEN** clicking a tag's remove button SHALL clear that filter, reload data, and update the URL
### Requirement: Overview page SHALL auto-refresh and handle request cancellation
The page SHALL automatically refresh data and prevent stale request pile-up.
@@ -109,3 +113,26 @@ The page SHALL automatically refresh data and prevent stale request pile-up.
#### Scenario: Manual refresh
- **WHEN** user clicks the "重新整理" button
- **THEN** data SHALL reload and the auto-refresh timer SHALL reset
### Requirement: Overview page SHALL persist filter state in URL
The page SHALL synchronize all filter state (workorder, lotid, package, type, status) to URL query parameters as the single source of truth.
#### Scenario: URL state initialization on page load
- **WHEN** the page loads with filter query parameters in the URL (e.g., `?package=SOD-323&status=RUN`)
- **THEN** the filter inputs SHALL be pre-filled with the URL parameter values
- **THEN** the status card corresponding to the `status` parameter SHALL be activated
- **THEN** data SHALL be loaded with all restored filters and status applied
#### Scenario: URL state initialization without parameters
- **WHEN** the page loads without any filter query parameters
- **THEN** all filters SHALL be empty and no status card SHALL be active
- **THEN** data SHALL load without filters (current default behavior)
#### Scenario: URL update on filter change
- **WHEN** filters are applied, cleared, or a single filter is removed
- **THEN** the URL SHALL be updated via `history.replaceState` to reflect the current filter state
- **THEN** only non-empty filter values SHALL appear as URL parameters
#### Scenario: URL update on status toggle
- **WHEN** a status card is clicked to activate or deactivate
- **THEN** the URL SHALL be updated via `history.replaceState` to include or remove the `status` parameter