diff --git a/TODO_NEXT_STEPS.txt b/TODO_NEXT_STEPS.txt index af8b159..e32502f 100644 --- a/TODO_NEXT_STEPS.txt +++ b/TODO_NEXT_STEPS.txt @@ -4,6 +4,7 @@ ================================================================================ 【已完成】 + - V10.197 強化 `/observability/ppt_audit_history` Action Queue:新增「異常優先」lane,將產出失敗、PPTX 檔案異常、視覺 QA 失敗拉到最前面,並顯示錯誤訊息與可預覽入口。 - V10.196 補 `/observability/ppt_audit_history` Action Queue:把待補齊、可預覽、視覺 QA、DB 寫入集中成工作隊列,讓使用者不用在多張卡與表格間找下一個處理點。 - V10.194 重整 `/observability/ppt_audit_history` 產線資訊階層:新增 Pipeline Health、五段式流程階段、排程/覆蓋/DB/預覽/視覺 QA 狀態摘要,讓「已產生」改為可判斷的目標產生、其他版本、待排程補齊等狀態。 - V10.192 補 `/observability/ppt_audit_history` 最近可預覽簡報 workbench:最新 4 份 PPT 直接在控制台下方提供線上預覽與下載,降低使用者找檔案的操作成本;完整檔案清單仍保留在下方表格。 diff --git a/routes/admin_observability_routes.py b/routes/admin_observability_routes.py index 8932db5..332b010 100644 --- a/routes/admin_observability_routes.py +++ b/routes/admin_observability_routes.py @@ -2358,8 +2358,49 @@ def _build_ppt_pipeline_view(files, auto_generation, audit_stats, generation_run item for item in audit_records if item.get('audit_status') in ('failed', 'error') ] + run_failures = [ + item for item in generation_runs + if item.get('status') == 'error' + ] + broken_files = [ + item for item in files + if item.get('file_exists') and not item.get('is_valid_ppt') + ] + triage_entries = [] + for item in run_failures[:3]: + triage_entries.append({ + 'title': item.get('report_label') or item.get('report_type') or '未知簡報', + 'meta': item.get('started_at') or '時間未知', + 'detail': item.get('error_msg') or f"{item.get('schedule_label') or '手動'} · {item.get('target_label') or '最新資料'}", + 'status_label': '產出失敗', + 'filename': item.get('file_name') or '', + }) + for item in broken_files[:3]: + triage_entries.append({ + 'title': item.get('name') or '未命名檔案', + 'meta': item.get('mtime') or '時間未知', + 'detail': item.get('file_error') or 'PPTX 檔案不可預覽,建議重新產生。', + 'status_label': '檔案異常', + 'filename': item.get('name') or '', + }) + for item in audit_attention[:3]: + triage_entries.append({ + 'title': item.get('pptx_filename') or '未命名檔案', + 'meta': item.get('audited_at') or '時間未知', + 'detail': item.get('error_msg') or f"問題 {item.get('issues_count', 0)} 個", + 'status_label': '視覺 QA', + 'filename': item.get('pptx_filename') or '', + }) action_lanes = [ + { + 'key': 'triage', + 'label': '異常優先', + 'status': 'error' if triage_entries else 'ready', + 'count': len(triage_entries), + 'empty_text': '目前沒有產出失敗、檔案異常或視覺 QA 失敗。', + 'entries': triage_entries[:4], + }, { 'key': 'missing', 'label': '待補齊', diff --git a/templates/admin/ppt_audit_history.html b/templates/admin/ppt_audit_history.html index 1f4befa..7eecb1b 100644 --- a/templates/admin/ppt_audit_history.html +++ b/templates/admin/ppt_audit_history.html @@ -178,7 +178,7 @@
{{ item.status_label }} - {% if item.filename and lane.key in ['preview', 'database'] %} + {% if item.filename and lane.key in ['preview', 'database', 'triage'] %} 預覽 diff --git a/tests/test_admin_observability_routes.py b/tests/test_admin_observability_routes.py index 399ce63..be41ce1 100644 --- a/tests/test_admin_observability_routes.py +++ b/tests/test_admin_observability_routes.py @@ -201,20 +201,36 @@ def test_ppt_audit_history_shows_ppt_schedule_and_db_runs(client, monkeypatch): 'cadences': cadences, 'cadence_summary': '、'.join(c['schedule_text'] for c in cadences), }) - monkeypatch.setattr(svc, 'get_generation_run_history', lambda **_kw: [{ - 'schedule_kind': 'daily', - 'schedule_label': '每日', - 'report_type': 'daily', - 'report_label': '每日日報', - 'target_label': '2026/05/17', - 'status': 'ready', - 'status_label': '已產生', - 'file_name': 'ocbot_daily_20260517.pptx', - 'file_size_kb': 1024, - 'error_msg': '', - 'started_at': '2026-05-17 20:30', - 'finished_at': '2026-05-17 20:31', - }]) + monkeypatch.setattr(svc, 'get_generation_run_history', lambda **_kw: [ + { + 'schedule_kind': 'daily', + 'schedule_label': '每日', + 'report_type': 'daily', + 'report_label': '每日日報', + 'target_label': '2026/05/17', + 'status': 'error', + 'status_label': '失敗', + 'file_name': '', + 'file_size_kb': None, + 'error_msg': '產線錯誤:缺少資料來源', + 'started_at': '2026-05-17 20:29', + 'finished_at': '2026-05-17 20:30', + }, + { + 'schedule_kind': 'daily', + 'schedule_label': '每日', + 'report_type': 'daily', + 'report_label': '每日日報', + 'target_label': '2026/05/17', + 'status': 'ready', + 'status_label': '已產生', + 'file_name': 'ocbot_daily_20260517.pptx', + 'file_size_kb': 1024, + 'error_msg': '', + 'started_at': '2026-05-17 20:30', + 'finished_at': '2026-05-17 20:31', + }, + ]) r = client.get('/observability/ppt_audit_history') html = r.data.decode('utf-8') @@ -229,6 +245,8 @@ def test_ppt_audit_history_shows_ppt_schedule_and_db_runs(client, monkeypatch): assert '線上預覽' in html assert 'Action Queue' in html assert '接下來要處理的事' in html + assert '異常優先' in html + assert '產線錯誤:缺少資料來源' in html assert '待排程補齊' in html diff --git a/web/static/css/page-ppt-audit-history.css b/web/static/css/page-ppt-audit-history.css index 0feec39..639611c 100644 --- a/web/static/css/page-ppt-audit-history.css +++ b/web/static/css/page-ppt-audit-history.css @@ -332,7 +332,7 @@ .ppt-action-grid { display: grid; - grid-template-columns: repeat(4, minmax(0, 1fr)); + grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--momo-space-3, 12px); }