From e2b28b4b692a6d3585aef897c3ee28f31b4bdb56 Mon Sep 17 00:00:00 2001 From: ogt Date: Thu, 25 Jun 2026 18:58:23 +0800 Subject: [PATCH] feat: sanitize system import prompts --- config.py | 2 +- docs/AI_INTELLIGENCE_MODULE_SOT.md | 1 + templates/system_settings.html | 47 +++++++++++++++------ tests/test_pchome_revenue_growth_service.py | 13 +++++- 4 files changed, 47 insertions(+), 16 deletions(-) diff --git a/config.py b/config.py index 3621871..10f0bcc 100644 --- a/config.py +++ b/config.py @@ -402,7 +402,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '') # ========================================== # 系統版本與路徑 # ========================================== -SYSTEM_VERSION = "V10.695" +SYSTEM_VERSION = "V10.696" LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log') public_url = PUBLIC_URL # 用於模板顯示 diff --git a/docs/AI_INTELLIGENCE_MODULE_SOT.md b/docs/AI_INTELLIGENCE_MODULE_SOT.md index 810cc57..214f2ea 100644 --- a/docs/AI_INTELLIGENCE_MODULE_SOT.md +++ b/docs/AI_INTELLIGENCE_MODULE_SOT.md @@ -772,3 +772,4 @@ POSTGRES_HOST=momo-db | 2026-06-25 | 成長報表不得把比價內部指標整排丟給使用者 | V10.693 起 `/growth_analysis` 的比價品質區改為「PChome 價格作戰可用度」:只呈現可直接決策、同款覆蓋、價格需刷新、待補/待確認四個訊號,並依資料狀態給下一步建議與今日作戰入口;測試禁止回到「比價資料品質、高信心門檻、未知新鮮度、人工否決」這類工程化列表。 | | 2026-06-25 | 比價頁每筆結果也必須能雙開賣場 | V10.694 起 `/price_comparison` 的結果列在 PChome/MOMO 連結都存在時提供「雙開賣場」操作,Excel 與手動輸入提示改成白話作戰語言,不再顯示「格式說明、欄位、商品名稱,價格」這類工程化提示;`tests/test_frontend_v2_assets.py` 鎖定此行為。 | | 2026-06-25 | 匯入任務列表只顯示處置提醒 | V10.695 起 `/auto_import` 任務列表不再把 `error_message` 原文當主要欄位顯示,而是由 `buildImportActionHint()` 轉成 Google Drive 授權、當日業績明細檔、重新匯入或通知維護人員等下一步,避免重啟後瀏覽器/授權/同步技術錯誤直接暴露給營運使用者。 | +| 2026-06-25 | 系統設定匯入提示不得顯示資料表或日誌口徑 | V10.696 起 `/system_settings` 不再用 `realtime_sales_monthly` 判斷前端提示,也不再顯示「資料落點、檢查日誌、發生系統錯誤」等內部口徑;所有匯入與備份失敗提示統一走 `toImportActionMessage()`,轉成重新授權、改用正確業績報表、重新匯入或通知維護人員。 | diff --git a/templates/system_settings.html b/templates/system_settings.html index 5b868a6..b6a82fb 100644 --- a/templates/system_settings.html +++ b/templates/system_settings.html @@ -189,16 +189,39 @@ function triggerBackup() { window.location.href = data.download_url; } } else { - alert('錯誤: ' + data.message); + alert('備份沒有完成:' + toImportActionMessage(data.message)); } }) .catch(error => { console.error('Error:', error); - alert('備份請求失敗,請檢查日誌。'); + alert('備份連線失敗,請稍後重試;若重複失敗請通知維護人員。'); }); } } +function toImportActionMessage(message) { + const raw = String(message || '').trim(); + const text = raw.toLowerCase(); + if (!raw) return '請稍後重試;若重複失敗請通知維護人員。'; + if (text.includes('google drive') || raw.includes('雲端') || raw.includes('授權')) { + return '請重新確認 Google Drive 授權或雲端檔案權限後再匯入。'; + } + if (raw.includes('欄位') || raw.includes('格式') || raw.includes('日期') || text.includes('excel')) { + return '請改用正確的業績報表,確認包含日期、商品與業績金額後重新匯入。'; + } + if ( + text.includes('database') || + text.includes('sql') || + text.includes('table') || + text.includes('snapshot') || + text.includes('monthly') || + raw.includes('資料庫') + ) { + return '業績資料處理未完整完成,請重新匯入最新檔案;若重複失敗請通知維護人員。'; + } + return raw; +} + function uploadSalesReport() { const fileInput = document.getElementById('salesReportFile'); const file = fileInput.files[0]; @@ -209,7 +232,7 @@ function uploadSalesReport() { } if (!file.name.includes('即時業績') || !file.name.includes('全月')) { - if (!confirm('檔案名稱似乎不符合「即時業績(全月)」的格式,確定要繼續匯入嗎?\n系統會嘗試辨識檔案內容並更新業績資料。')) { + if (!confirm('檔名不像「即時業績(全月)」報表,確定要繼續匯入嗎?\n系統會嘗試辨識內容並更新業績資料。')) { return; } } else if (!confirm('確定要匯入此份業績報表嗎?\n匯入後會更新月度業績判斷,供成長分析與報表使用。')) { @@ -234,19 +257,15 @@ function uploadSalesReport() { .then(response => response.json()) .then(data => { if (data.status === 'success') { - if (data.table === 'realtime_sales_monthly') { - alert('業績報表匯入成功!\n共 ' + data.rows + ' 筆資料已更新,可回到分析頁確認結果。'); - } else { - alert('匯入操作完成。\n系統偵測到資料落點與預期不同,請確認月度分析是否已更新。\n共寫入 ' + data.rows + ' 筆資料。'); - } + alert('業績報表匯入成功!\n共 ' + Number(data.rows || 0).toLocaleString() + ' 筆資料已更新,可回到成長分析確認結果。'); fileInput.value = ''; } else { - alert('匯入失敗: ' + data.message); + alert('匯入沒有完成:' + toImportActionMessage(data.message)); } }) .catch(error => { console.error('Error:', error); - alert('發生系統錯誤,請檢查日誌'); + alert('匯入連線逾時,請稍後查看分析頁是否更新;若沒有更新請重新匯入。'); }) .finally(() => { btn.innerHTML = originalText; @@ -285,15 +304,15 @@ function uploadExcel() { .then(response => response.json()) .then(data => { if (data.status === 'success') { - alert('匯入成功!\n共寫入 ' + data.rows + ' 筆資料,可回到分析頁確認結果。'); + alert('匯入成功!\n共更新 ' + Number(data.rows || 0).toLocaleString() + ' 筆資料,可回到分析頁確認結果。'); fileInput.value = ''; } else { - alert('匯入失敗: ' + data.message); + alert('匯入沒有完成:' + toImportActionMessage(data.message)); } }) .catch(error => { console.error('Error:', error); - alert('發生系統錯誤,請檢查日誌'); + alert('匯入連線逾時,請稍後查看分析頁是否更新;若沒有更新請重新匯入。'); }) .finally(() => { btn.innerHTML = originalText; @@ -337,7 +356,7 @@ function uploadMonthlySummary() { alert('匯入完成:' + data.message); fileInput.value = ''; } else { - alert('匯入失敗: ' + data.message); + alert('匯入沒有完成:' + toImportActionMessage(data.message)); } }) .catch(error => { diff --git a/tests/test_pchome_revenue_growth_service.py b/tests/test_pchome_revenue_growth_service.py index 0df185a..8bada2d 100644 --- a/tests/test_pchome_revenue_growth_service.py +++ b/tests/test_pchome_revenue_growth_service.py @@ -856,7 +856,13 @@ def test_governance_and_low_frequency_pages_avoid_engineering_status_copy(): "重新匯入最新檔案", ], "templates/settings.html": ["比價來源同步", "補齊 MOMO 參考來源"], - "templates/system_settings.html": ["營運資料備份", "可回復的業績與設定狀態"], + "templates/system_settings.html": [ + "營運資料備份", + "可回復的業績與設定狀態", + "toImportActionMessage", + "匯入沒有完成", + "業績資料處理未完整完成", + ], "templates/ai_recommend.html": ["值得主推、調價或補比價", "回到 PChome 銷售動作"], "templates/notification_templates.html": ["商品、風險與下一步"], "templates/vendor_stockout_index_v2.html": ["處理缺貨", "主推商品供貨風險"], @@ -904,6 +910,11 @@ def test_governance_and_low_frequency_pages_avoid_engineering_status_copy(): "AI 程式碼審查", "Google Drive →", "匯入資料庫", + "realtime_sales_monthly", + "daily_sales_snapshot", + "資料落點", + "檢查日誌", + "發生系統錯誤", "刪除雲端原檔", "資料表:", "資料表:",