diff --git a/config.py b/config.py
index 92666d0..a43057c 100644
--- a/config.py
+++ b/config.py
@@ -402,7 +402,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '')
# ==========================================
# 系統版本與路徑
# ==========================================
-SYSTEM_VERSION = "V10.693"
+SYSTEM_VERSION = "V10.694"
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 d711507..6b6839b 100644
--- a/docs/AI_INTELLIGENCE_MODULE_SOT.md
+++ b/docs/AI_INTELLIGENCE_MODULE_SOT.md
@@ -770,3 +770,4 @@ POSTGRES_HOST=momo-db
| 2026-06-25 | 全頁價格方向統一為 PChome 成長視角 | V10.691 起 AI Intelligence、Daily Sales、Growth Analysis、Dashboard、Telegram 與 AI 報告 prompt 不再使用「PChome 價格壓力 / MOMO 價格優勢 / MOMO 更便宜 / PChome 有優勢」等易混淆詞;統一為「PChome 價格優勢」與「MOMO 低價壓力」。 |
| 2026-06-25 | 候選比較卡與價格語意必須有測試防線 | V10.692 起 `tests/test_pchome_revenue_growth_service.py` 鎖定 `/ai_intelligence` 模板必須提供 PChome/MOMO 雙賣場連結、雙開賣場操作與白話候選理由,且不得再出現 `variant_selection_review`、`focused_exact_identity`、`source_code`、`momo_reference` 或反向價格詞。 |
| 2026-06-25 | 成長報表不得把比價內部指標整排丟給使用者 | V10.693 起 `/growth_analysis` 的比價品質區改為「PChome 價格作戰可用度」:只呈現可直接決策、同款覆蓋、價格需刷新、待補/待確認四個訊號,並依資料狀態給下一步建議與今日作戰入口;測試禁止回到「比價資料品質、高信心門檻、未知新鮮度、人工否決」這類工程化列表。 |
+| 2026-06-25 | 比價頁每筆結果也必須能雙開賣場 | V10.694 起 `/price_comparison` 的結果列在 PChome/MOMO 連結都存在時提供「雙開賣場」操作,Excel 與手動輸入提示改成白話作戰語言,不再顯示「格式說明、欄位、商品名稱,價格」這類工程化提示;`tests/test_frontend_v2_assets.py` 鎖定此行為。 |
diff --git a/templates/price_comparison.html b/templates/price_comparison.html
index d0f9bec..4a76786 100644
--- a/templates/price_comparison.html
+++ b/templates/price_comparison.html
@@ -956,7 +956,7 @@
-
- 格式說明: 每行一筆商品,用逗號或 Tab 分隔
- 商品名稱,價格 或 商品名稱,價格,商品連結(選填)
+
+ 貼上 MOMO 商品、售價與賣場連結;系統會整理成可比價清單。
@@ -1314,7 +1313,7 @@ La Roche-Posay 安得利防曬液 50ml,920
parts = line.split('\t');
}
if (parts.length < 2) {
- showToast(`第 ${i + 1} 行格式錯誤,請使用「商品名稱,價格」,例如:理膚寶水 B5修復霜,680。`, 'warning');
+ showToast(`第 ${i + 1} 行缺商品名稱或售價,請補齊後再加入比價清單。`, 'warning');
return;
}
@@ -1699,10 +1698,20 @@ La Roche-Posay 安得利防曬液 50ml,920
// 處理 URL (可能是 url 或 product_url)
const pchomeUrl = toSafeUrl(m.pchome?.url || m.pchome?.product_url || '');
const momoUrl = toSafeUrl(m.momo?.url || m.momo?.product_url || '');
+ const dualOpenButton = pchomeUrl && momoUrl
+ ? `
`
+ : '';
row.innerHTML = `
${actionBadge}
+ ${dualOpenButton}
|
@@ -1757,6 +1766,22 @@ La Roche-Posay 安得利防曬液 50ml,920
document.getElementById('resultSection').style.display = 'block';
}
+ function openComparisonStores(button) {
+ const pchomeUrl = toSafeUrl(button?.dataset?.pchomeUrl || '');
+ const momoUrl = toSafeUrl(button?.dataset?.momoUrl || '');
+ const opened = [];
+ if (pchomeUrl) opened.push(window.open(pchomeUrl, `pchome_compare_${Date.now()}`));
+ if (momoUrl) opened.push(window.open(momoUrl, `momo_compare_${Date.now()}`));
+ for (const win of opened) {
+ if (win) {
+ try { win.opener = null; } catch (_) {}
+ }
+ }
+ if (opened.some((win) => !win)) {
+ showToast('瀏覽器擋住了其中一個視窗;請用商品旁的 PChome / MOMO 按鈕分別開啟。', 'warning');
+ }
+ }
+
function getResultActionBadge(match) {
if (match.cheaper_at === 'momo') {
return '檢查售價';
diff --git a/tests/test_frontend_v2_assets.py b/tests/test_frontend_v2_assets.py
index bb7272d..590cff7 100644
--- a/tests/test_frontend_v2_assets.py
+++ b/tests/test_frontend_v2_assets.py
@@ -572,10 +572,19 @@ def test_price_comparison_page_is_action_oriented_and_plain_chinese():
assert "主推曝光" in template
assert "PChome 貴" in template
assert "PChome 便宜" in template
+ assert "雙開賣場" in template
+ assert "openComparisonStores" in template
+ assert "data-pchome-url" in template
+ assert "data-momo-url" in template
+ assert "Excel 至少要有商品名稱與售價" in template
+ assert "貼上 MOMO 商品、售價與賣場連結" in template
assert "resetComparisonResult" in template
assert "showToast" in template
assert "text.textContent = message" in template
assert "toast.innerHTML" not in template
+ assert "格式說明" not in template
+ assert "商品名稱,價格" not in template
+ assert "欄位" not in template
assert "Step 1" not in template
assert "Step 2" not in template
assert "Step 3" not in template
|