Replace single-dimension Pareto dropdown with 6 simultaneous Pareto charts (不良原因, PACKAGE, TYPE, WORKFLOW, 站點, 機台) in a responsive 3-column grid. Clicking items in one Pareto cross-filters the other 5 (exclude-self logic), and the detail table applies all dimension selections with AND logic. Backend: - Add batch-pareto endpoint (cache-only, no Oracle queries) - Add _apply_cross_filter() with exclude-self pattern - Extend view/export endpoints for multi-dimension sel_* params Frontend: - New ParetoGrid.vue wrapping 6 ParetoSection instances - Simplify ParetoSection: remove dimension dropdown, keep TOP20 toggle - Replace single-dimension state with paretoSelections reactive object - Adaptive x-axis labels (font size, rotation, hideOverlap) for compact grid - Responsive grid: 3-col desktop, 2-col tablet, 1-col mobile Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.6 KiB
4.6 KiB
1. Backend — Batch Pareto with Cross-Filter
- 1.1 Add
_apply_cross_filter(df, selections, exclude_dim)helper inreject_dataset_cache.py— applies all dimension selections exceptexclude_dimusing_DIM_TO_DF_COLUMNmapping - 1.2 Add
compute_batch_pareto()function inreject_dataset_cache.py— iterates all 6 dimensions from cached DataFrame (no Oracle query), applies policy → supplementary → trend-date → cross-filter, supportspareto_display_scope=top20truncation for applicable dimensions, returns{"dimensions": {...}} - 1.3 Add
_parse_multi_pareto_selections()helper inreject_history_routes.py— parsessel_reason,sel_package,sel_type,sel_workflow,sel_workcenter,sel_equipmentfrom query params - 1.4 Add
GET /api/reject-history/batch-paretoendpoint inreject_history_routes.py— cache-only (no Oracle fallback), acceptspareto_display_scopeparam, callscompute_batch_pareto()
2. Backend — Multi-Dimension Detail/Export Filter
- 2.1 Extend
_apply_pareto_selection_filter()inreject_dataset_cache.pyto acceptpareto_selections: dict(multi-dimension AND logic), keeping backward compat with singlepareto_dimension/pareto_values - 2.2 Update
apply_view()andexport_csv_from_cache()inreject_dataset_cache.pyto pass multi-dimension selections - 2.3 Update
viewandexport-cachedendpoints inreject_history_routes.pyto parse and forwardsel_*params
3. Frontend — State Refactor (App.vue)
- 3.1 Replace single-dimension state (
paretoDimension,selectedParetoValues,dimensionParetoItems,dimensionParetoLoading) withparetoSelectionsreactive object andparetoDatareactive object; keepparetoDisplayScoperef for global TOP20/ALL toggle - 3.2 Add
fetchBatchPareto()function — callsGET /api/reject-history/batch-paretowithsel_*params, updates all 6paretoDataentries - 3.3 Rewrite
onParetoItemToggle(dimension, value)— toggle inparetoSelections[dimension], callfetchBatchPareto()+refreshView(), reset page - 3.4 Remove dead code:
allParetoItems,filteredParetoItems,activeParetoItemscomputed,fetchDimensionPareto(),refreshDimensionParetoIfActive(),onDimensionChange(),PARETO_DIMENSION_LABELS; keepPARETO_TOP20_DIMENSIONSandparetoDisplayScopefor global TOP20/ALL toggle - 3.5 Update
activeFilterChipscomputed — loop all 6 dimensions, generate chip per selected value with dimension label - 3.6 Update chip removal handler to call
onParetoItemToggle(dim, value)
4. Frontend — URL State
- 4.1 Update
updateUrlState()— replacepareto_dimension/pareto_valueswithsel_reason,sel_package, etc. array params; keeppareto_display_scopefor TOP20/ALL - 4.2 Update
restoreFromUrl()— parsesel_*params intoparetoSelectionsobject - 4.3 Update
buildViewParams()inreject-history-filters.js— replaceparetoDimension/paretoValueswithparetoSelectionsdict, emitsel_*params
5. Frontend — Components
- 5.1 Simplify
ParetoSection.vue— remove dimension selector dropdown andDIMENSION_OPTIONS; keep per-chart TOP20 truncation logic (controlled by parent viadisplayScopeprop); add dimension label map; emititem-togglewith value only (parent handles dimension routing) - 5.2 Create
ParetoGrid.vue— 3-column grid container rendering 6ParetoSectioninstances, props:paretoData,paretoSelections,loading,metricLabel,selectedDates; emititem-toggle(dimension, value) - 5.3 Update
App.vuetemplate — replace single<ParetoSection>with<ParetoGrid>
6. Frontend — Styling
- 6.1 Add
.pareto-gridCSS class instyle.css— 3-column grid with responsive breakpoints (2-col at ≤1200px, 1-col at ≤768px) - 6.2 Adjust
.pareto-chart-wrapheight from 340px to ~240px for compact multi-chart display - 6.3 Adjust
.pareto-layoutfor vertical stack (chart above table) in grid context
7. Integration & Wire-Up
- 7.1 Wire
fetchBatchPareto()intoloadAllData()flow — call after primary query completes - 7.2 Wire supplementary filter changes and trend-date changes to trigger
fetchBatchPareto() - 7.3 Wire export button to include all 6 dimension selections in export request
8. Testing
- 8.1 Add unit tests for
compute_batch_pareto()cross-filter logic intests/test_reject_dataset_cache.py - 8.2 Add route tests for
GET /api/reject-history/batch-paretoendpoint intests/test_reject_history_routes.py - 8.3 Add tests for multi-dimension
_apply_pareto_selection_filter()intests/test_reject_dataset_cache.py