SQLAlchemy text() parses :param patterns in SQL comments as bind parameters. When EventFetcher replaces the WHERE clause via string substitution, orphaned :container_id in comments causes "A value is required for bind parameter 'container_id'" errors. Changes: - Remove colon prefix from parameter names in SQL comments for lot_history, lot_rejects, lot_holds, lot_materials - Archive trace-progressive-ui change (22/22 tasks complete) - Sync delta specs to main: add trace-staged-api, progressive-trace-ux, merge api-safety-hygiene (+2 requirements) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3.8 KiB
3.8 KiB
Phase 1: 後端 trace_routes.py Blueprint
- 1.1 建立
src/mes_dashboard/routes/trace_routes.py:trace_bpBlueprint(url_prefix='/api/trace') - 1.2 實作
POST /api/trace/seed-resolvehandler:request body 驗證、profile dispatch(_seed_resolve_query_tool/_seed_resolve_msd)、response format - 1.3 實作
POST /api/trace/lineagehandler:呼叫LineageEngine.resolve_full_genealogy()、response format、504 timeout 處理 - 1.4 實作
POST /api/trace/eventshandler:呼叫EventFetcher.fetch_events()、mid_section_defect profile 自動 aggregation、EVENTS_PARTIAL_FAILURE處理 - 1.5 為三個 endpoint 加入
configured_rate_limit()(seed: 10/60s, lineage: 10/60s, events: 15/60s) - 1.6 為三個 endpoint 加入 L2 Redis cache(seed:
trace:seed:{profile}:{params_hash}, lineage:trace:lineage:{sorted_cids_hash}, events:trace:evt:{profile}:{domains_hash}:{sorted_cids_hash},TTL=300s) - 1.7 在
src/mes_dashboard/routes/__init__.py匯入並註冊trace_bpBlueprint(維持專案統一的 route 註冊入口) - 1.8 API contract 測試:驗證 200/400/429/504 status code、
Retry-Afterheader、error code 格式、snake_case field names
Phase 2: 前端共用元件
- 2.1 建立
frontend/src/shared-composables/useTraceProgress.js:reactive state(current_stage,completed_stages,stage_results,stage_errors,is_running)+execute()/reset()/abort()methods - 2.2 實作 sequential fetch 邏輯:seed-resolve → lineage → events,每段完成後立即更新 reactive state,錯誤記錄到 stage_errors 不拋出
- 2.3 建立
frontend/src/shared-composables/TraceProgressBar.vue:三段式進度指示器(props:current_stage,completed_stages,stage_errors),完成=green、進行中=blue pulse、待處理=gray、錯誤=red
Phase 3: mid-section-defect 漸進渲染
- 3.1 在
frontend/src/mid-section-defect/App.vue中引入useTraceProgress({ profile: 'mid_section_defect' }) - 3.2 改造
loadAnalysis()流程:從apiGet('/analysis')單次呼叫改為trace.execute(params)分段 fetch - 3.3 加入 skeleton placeholders:KpiCards(6 cards, min-height 100px)、ParetoChart(6 charts, min-height 300px)、TrendChart(min-height 300px),灰色脈動動畫
- 3.4 加入 fade-in transition:stage_results.events 完成後 KPI/charts 以
opacity 0→1, 300ms ease-in填入 - 3.5 用
TraceProgressBar取代 filter bar 下方的 loading spinner - 3.6 整合
useAutoRefresh:onRefresh→trace.abort()+trace.execute(committedFilters) - 3.7 驗證 detail 分頁不受影響(仍使用
/api/mid-section-defect/analysis/detailGET endpoint) - 3.8 Golden test:
/api/mid-section-defect/analysisGET endpoint 回傳結果與重構前完全一致(浮點 tolerance ±0.01%)
Phase 4: query-tool on-demand lineage
- 4.1 在
useQueryToolData.js新增lineageCachereactive object +loadLotLineage(containerId)函數 - 4.2
loadLotLineage呼叫POST /api/trace/lineage(profile: 'query_tool',container_ids: [containerId]),結果存入lineageCache - 4.3 在 lot 列表 UI 新增 lineage 展開按鈕(accordion pattern),點擊觸發
loadLotLineage,已快取的不重新 fetch - 4.4
resolveLots()時清空lineageCache(新一輪查詢) - 4.5 驗證既有 resolve → lot-history → lot-associations 流程不受影響
Phase 5: Legacy cleanup
- 5.1 刪除
src/mes_dashboard/static/js/query-tool.js(3056L, 126KB pre-Vite dead code) - 5.2
grep -r "static/js/query-tool.js" src/ frontend/ templates/確認 0 結果 - 5.3 確認
frontend_asset('query-tool.js')正確解析到 Vite manifest 中的 hashed filename