V10.611 補強作戰入口操作提示
All checks were successful
CD Pipeline / deploy (push) Successful in 1m4s

This commit is contained in:
OoO
2026-06-16 09:36:57 +08:00
parent b7cb807683
commit cac9752aac
5 changed files with 231 additions and 9 deletions

View File

@@ -402,7 +402,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '')
# ==========================================
# 系統版本與路徑
# ==========================================
SYSTEM_VERSION = "V10.610"
SYSTEM_VERSION = "V10.611"
LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log')
public_url = PUBLIC_URL # 用於模板顯示

View File

@@ -1,8 +1,8 @@
# PChome 業績成長自動化作戰系統 — AI 競價情報模組 Single Source of Truth
> **最後更新**: 2026-06-15 (台北時間)
> **狀態**: 🟢 四 AI Agent 自動化閉環已落地LLM 路由紅線升級為 Ollama-first 三主機級聯PChome 後台業績匯入韌性已補強產品定位正名為「PChome 業績成長自動化作戰系統」;外部市場來源正規化層、自動同步、作戰清單優先讀取CSV 備援預檢已建立
> **適用版本**: V10.610
> **最後更新**: 2026-06-16 (台北時間)
> **狀態**: 🟢 四 AI Agent 自動化閉環已落地LLM 路由紅線升級為 Ollama-first 三主機級聯PChome 後台業績匯入韌性已補強產品定位正名為「PChome 業績成長自動化作戰系統」;外部市場來源正規化層、自動同步、作戰清單優先讀取CSV 備援預檢與前台操作入口已建立
> **適用版本**: V10.611
---
@@ -57,6 +57,7 @@
- V10.608 新增 `/api/ai/pchome-growth/external-offers/csv-dry-run` 與 AI 情報頁「外部報價預檢」。CSV 預檢只讀、不寫 DB逐列回報「可使用」「需人工確認」「不能使用」並支援中文表頭避免格式小錯造成整批匯入失敗。
- V10.609 明確把外部報價主路徑改為自動化:`run_external_offer_sync_task` 每 4 小時將已確認同款的既有比價快取同步進 `external_offers`。CSV 只保留為 API / crawler / provider 失敗時的備援預檢入口,不是日常營運主流程。
- V10.610 起 `/api/ai/pchome-growth/opportunities` 優先讀取 `external_offers` 的自動同步資料;只有新資料層缺資料時才 fallback 舊 `competitor_prices`。API stats 會回傳資料來源計數,方便確認作戰清單是否已走新資料層。
- V10.611 起 `/ai_intelligence` 是營運使用者主入口:頁首提供「今日作戰入口」,依序連到 PChome 成長作戰、補商品對應、MOMO 外部價格參考與外部報價預檢;作戰清單左側會直接顯示今日優先動作與資料來源摘要。
## 零之一、12 Agent 決策信封2026-05-24

View File

@@ -212,3 +212,10 @@
- `external_offers.raw_payload_json` 會保留舊比價快取中的 PChome 公開價,讓新資料層仍可算出 MOMO / PChome 價差。
- API stats 新增 `external_data_source_counts`,可看到「自動同步資料層」與「舊比價快取」各有多少筆。
- 下一步:把其他比價報表與 AI 告警逐步改讀 `external_offers`,讓 `competitor_prices` 降為 bridge/cache。
## 14. 2026-06-16 V10.611 作戰入口與資料來源可見化
- `/ai_intelligence` 是 PChome 業績成長自動化作戰系統的營運主入口,頁首新增「今日作戰入口」:看作戰清單、補商品對應、看可比價商品、預檢備援資料。
- PChome 成長作戰區塊會依 API stats 顯示今日優先動作,例如先補商品對應、先處理可直接比價商品,避免使用者只看到數字不知道下一步。
- 同區塊新增資料來源摘要,直接顯示「自動同步資料層」或「舊比價快取」各有多少筆,方便確認 V10.610 新資料層是否真的被作戰清單採用。
- CSV 預檢在 UI 文案上維持備援定位;日常主流程仍是自動同步外部報價。

View File

@@ -239,6 +239,92 @@
gap: 14px;
}
.ops-flow {
border: 1px solid var(--momo-border-subtle);
border-radius: 8px;
background: rgba(255, 255, 255, 0.82);
box-shadow: var(--momo-shadow-soft);
padding: 14px;
}
.ops-flow-head {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: 8px;
align-items: center;
margin-bottom: 10px;
}
.ops-flow-note {
color: var(--momo-text-muted);
font-size: 0.78rem;
font-weight: 800;
}
.ops-flow-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 10px;
}
.ops-flow-item {
display: grid;
grid-template-columns: auto minmax(0, 1fr);
gap: 10px;
align-items: start;
width: 100%;
border: 1px solid rgba(42, 37, 32, 0.1);
border-radius: 8px;
background: rgba(250, 247, 240, 0.52);
color: var(--momo-text-strong);
padding: 11px;
text-align: left;
transition: transform 0.16s ease, border-color 0.16s ease, background-color 0.16s ease;
}
.ops-flow-item:hover,
.ops-flow-item:focus {
border-color: rgba(172, 92, 58, 0.34);
background: rgba(255, 255, 255, 0.86);
transform: translateY(-1px);
}
.ops-flow-step {
display: inline-flex;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
border-radius: 999px;
background: rgba(172, 92, 58, 0.12);
color: var(--momo-warm-rust);
font-family: var(--momo-font-mono);
font-size: 0.76rem;
font-weight: 900;
}
.ops-flow-title {
margin: 0;
color: var(--momo-text-strong);
font-size: 0.86rem;
font-weight: 900;
line-height: 1.25;
}
.ops-flow-copy,
.ops-flow-target {
margin: 4px 0 0;
color: var(--momo-text-muted);
font-size: 0.74rem;
line-height: 1.4;
}
.ops-flow-target {
color: var(--momo-warm-rust);
font-weight: 900;
}
.growth-metric-row {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
@@ -273,6 +359,29 @@
line-height: 1.55;
}
.growth-action-hint {
margin: 10px 0 0;
border: 1px solid rgba(172, 92, 58, 0.16);
border-radius: 8px;
background: rgba(242, 178, 90, 0.14);
color: var(--momo-text-strong);
font-size: 0.82rem;
font-weight: 800;
line-height: 1.5;
padding: 9px 10px;
}
.growth-data-summary {
margin: 8px 0 0;
border: 1px solid rgba(42, 37, 32, 0.08);
border-radius: 8px;
background: rgba(255, 255, 255, 0.68);
color: var(--momo-text-muted);
font-size: 0.78rem;
line-height: 1.45;
padding: 8px 10px;
}
.growth-source-list {
display: grid;
gap: 8px;
@@ -574,7 +683,8 @@
.growth-ops-grid,
.offer-dryrun-grid,
.growth-metric-row {
.growth-metric-row,
.ops-flow-grid {
grid-template-columns: 1fr;
}
@@ -606,18 +716,62 @@
<button class="btn btn-outline-danger btn-sm ai-action-btn" id="btnTrigger" onclick="triggerAnalysis()">
<i class="fas fa-bolt me-1"></i>整理建議
</button>
<button class="btn btn-outline-primary btn-sm ai-action-btn" id="btnPickList" onclick="generatePickList()">
<button class="btn btn-outline-primary btn-sm ai-action-btn" id="btnPickList" onclick="generatePickList()" title="依目前業績與比價資料整理商品處理清單">
<i class="fas fa-wand-magic-sparkles me-1"></i>產生作戰商品
</button>
<button class="btn btn-outline-warning btn-sm ai-action-btn" id="btnBackfill" onclick="backfillPchomeMatches()">
<button class="btn btn-outline-warning btn-sm ai-action-btn" id="btnBackfill" onclick="backfillPchomeMatches()" title="替還不能比價的 PChome 商品尋找 MOMO 參考">
<i class="fas fa-magnifying-glass-chart me-1"></i>補商品對應
</button>
<button class="btn btn-outline-secondary btn-sm ai-action-btn" onclick="loadDashboard()">
<button class="btn btn-outline-secondary btn-sm ai-action-btn" onclick="loadDashboard()" title="重新載入畫面資料">
<i class="fas fa-redo me-1"></i>重新整理
</button>
</div>
</section>
<!-- ── 今日作戰入口 ── -->
<section class="ops-flow" aria-label="今日作戰入口">
<div class="ops-flow-head">
<span class="ai-panel-title">
<i class="fas fa-route"></i>今日作戰入口
</span>
<span class="ops-flow-note">依清單、對應、比價、備援資料的順序處理</span>
</div>
<div class="ops-flow-grid">
<button type="button" class="ops-flow-item" onclick="scrollToPanel('growthOpsPanel')">
<span class="ops-flow-step">1</span>
<span>
<span class="ops-flow-title">看作戰清單</span>
<span class="ops-flow-copy d-block">先看高業績商品與建議動作。</span>
<span class="ops-flow-target d-block">PChome 成長作戰</span>
</span>
</button>
<button type="button" class="ops-flow-item" onclick="backfillPchomeMatches()">
<span class="ops-flow-step">2</span>
<span>
<span class="ops-flow-title">補商品對應</span>
<span class="ops-flow-copy d-block">待補對應太多時,先接上外部參考價。</span>
<span class="ops-flow-target d-block">啟動補商品對應</span>
</span>
</button>
<button type="button" class="ops-flow-item" onclick="scrollToPanel('externalPricePanel')">
<span class="ops-flow-step">3</span>
<span>
<span class="ops-flow-title">看可比價商品</span>
<span class="ops-flow-copy d-block">只看已確認同款的 MOMO 價格參考。</span>
<span class="ops-flow-target d-block">MOMO 外部價格參考</span>
</span>
</button>
<button type="button" class="ops-flow-item" onclick="scrollToPanel('externalOfferDryRunPanel')">
<span class="ops-flow-step">4</span>
<span>
<span class="ops-flow-title">預檢備援資料</span>
<span class="ops-flow-copy d-block">自動來源缺資料時,再檢查 CSV 可不可用。</span>
<span class="ops-flow-target d-block">外部報價預檢</span>
</span>
</button>
</div>
</section>
<!-- ── PChome 成長作戰清單 ── -->
<section class="card shadow-sm ai-panel" id="growthOpsPanel">
<div class="card-header d-flex justify-content-between align-items-center py-2 bg-white border-bottom">
@@ -646,6 +800,8 @@
<span>待補對應</span>
</div>
</div>
<p class="growth-action-hint" id="growthActionHint">正在判斷今天優先處理順序...</p>
<p class="growth-data-summary" id="growthDataSourceSummary">資料來源整理中...</p>
<p class="growth-source-note" id="growthSourceNote">來源整理中...</p>
<div class="growth-source-list" id="growthSourceReadiness">
<div class="growth-source-chip">
@@ -764,7 +920,7 @@
<!-- ── 左:外部價格參考 ── -->
<div class="col-xl-7">
<div class="card shadow-sm h-100 ai-panel">
<div class="card shadow-sm h-100 ai-panel" id="externalPricePanel">
<div class="card-header d-flex justify-content-between align-items-center py-2 bg-white border-bottom">
<span class="ai-panel-title">
<i class="fas fa-balance-scale text-warning me-2"></i>MOMO 外部價格參考
@@ -915,6 +1071,12 @@ function escapeHtml(value) {
}[ch]));
}
function scrollToPanel(panelId) {
const panel = document.getElementById(panelId);
if (!panel) return;
panel.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
async function loadGrowthOps(forceRefresh = false) {
const list = document.getElementById('growthOpsList');
if (forceRefresh) {
@@ -933,6 +1095,8 @@ async function loadGrowthOps(forceRefresh = false) {
document.getElementById('growthCandidateCount').textContent = (stats.candidate_count || 0).toLocaleString();
document.getElementById('growthMappedCount').textContent = (stats.mapped_count || 0).toLocaleString();
document.getElementById('growthNeedsMapping').textContent = (stats.needs_mapping_count || 0).toLocaleString();
renderGrowthActionHint(stats);
renderGrowthDataSourceSummary(stats);
const scope = data.source_scope || {};
const active = (scope.active_external_sources || []).join('、') || '尚未接入';
@@ -944,6 +1108,8 @@ async function loadGrowthOps(forceRefresh = false) {
renderGrowthOps(data.opportunities || []);
} catch (error) {
console.error(error);
renderGrowthActionHint({ candidate_count: 0, mapped_count: 0, needs_mapping_count: 0 });
renderGrowthDataSourceSummary({});
list.innerHTML = `<div class="text-center py-4 text-muted">
<i class="fas fa-circle-exclamation d-block mb-2"></i>
PChome 成長作戰清單暫時無法讀取,請稍後再試。
@@ -951,6 +1117,49 @@ async function loadGrowthOps(forceRefresh = false) {
}
}
function renderGrowthActionHint(stats) {
const hint = document.getElementById('growthActionHint');
if (!hint) return;
const candidateCount = Number(stats.candidate_count || 0);
const mappedCount = Number(stats.mapped_count || 0);
const needsMapping = Number(stats.needs_mapping_count || 0);
if (!candidateCount) {
hint.textContent = '目前沒有可處理的作戰商品,請先確認 PChome 業績資料已更新。';
return;
}
if (needsMapping > 0 && mappedCount === 0) {
hint.textContent = `今天先補商品對應:目前 ${needsMapping.toLocaleString()} 件高業績商品還不能直接比價。`;
return;
}
if (needsMapping > 0) {
hint.textContent = `先處理 ${mappedCount.toLocaleString()} 件可直接比價商品,再補 ${needsMapping.toLocaleString()} 件商品對應。`;
return;
}
hint.textContent = '目前商品都可直接比價,先檢查售價偏高或可以放大價格優勢的項目。';
}
function renderGrowthDataSourceSummary(stats) {
const summary = document.getElementById('growthDataSourceSummary');
if (!summary) return;
const counts = stats.external_data_source_counts || {};
const entries = Object.entries(counts)
.filter(([, count]) => Number(count || 0) > 0)
.map(([label, count]) => `${label} ${Number(count).toLocaleString()}`);
if (!entries.length) {
summary.textContent = '資料來源:目前作戰清單尚未接到外部參考價,請先補商品對應。';
return;
}
summary.textContent = `資料來源:${entries.join('、')}`;
}
function renderGrowthSourceReadiness(sources) {
const box = document.getElementById('growthSourceReadiness');
if (!box) return;

View File

@@ -155,5 +155,10 @@ def test_ai_intelligence_template_uses_pchome_growth_name_and_endpoint():
assert "/api/ai/pchome-growth/opportunities" in template
assert "/api/ai/pchome-growth/external-offers/csv-dry-run" in template
assert "growthSourceReadiness" in template
assert "今日作戰入口" in template
assert "growthActionHint" in template
assert "growthDataSourceSummary" in template
assert "external_data_source_counts" in template
assert "scrollToPanel('externalPricePanel')" in template
assert "外部報價預檢" in template
assert "待補對應" in template