feat: sanitize system import prompts
This commit is contained in:
@@ -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 # 用於模板顯示
|
||||
|
||||
|
||||
@@ -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()`,轉成重新授權、改用正確業績報表、重新匯入或通知維護人員。 |
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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",
|
||||
"資料落點",
|
||||
"檢查日誌",
|
||||
"發生系統錯誤",
|
||||
"刪除雲端原檔",
|
||||
"資料表:",
|
||||
"資料表:",
|
||||
|
||||
Reference in New Issue
Block a user