Files
ewoooc/templates/dashboard_v2.html
ogt 3894bd0afb
All checks were successful
CD Pipeline / deploy (push) Successful in 1m3s
fix: correct dashboard price semantics
2026-06-25 15:43:15 +08:00

1157 lines
88 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends 'ewoooc_base.html' %}
{% block title %}EwoooC 商品看板{% endblock %}
{% block extra_css %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/page-dashboard-v2.css') }}">
{% endblock %}
{% block ewooo_content %}
<div class="dashboard-v2-stack">
{% set overview = competitor_overview | default({}) %}
{% set growth = pchome_growth_command_center | default({}) %}
<section class="growth-command-center" aria-label="PChome 業績成長作戰台">
<div class="growth-command-head">
<div>
<div class="dashboard-section-label">
<span class="num momo-mono">00</span>
<span class="title">PChome 業績成長作戰台</span>
<span class="meta momo-mono">業績日 {{ growth.latest_sales_date or '待匯入' }}</span>
</div>
<h1 class="growth-command-title">先看業績,再決定調價、曝光與組合</h1>
</div>
<div class="growth-command-status is-{{ growth.sales_delta_tone | default('neutral') }}">
<span>近 7 天</span>
<strong>{{ growth.sales_delta_label | default('待匯入') }}</strong>
</div>
</div>
<div class="growth-command-kpis">
<div class="growth-command-kpi is-sales">
<span class="growth-kpi-label">PChome 近 7 天業績</span>
<strong class="growth-kpi-value momo-mono">NT$ {{ growth.sales_7d | default(0) | int | number_format }}</strong>
<div class="growth-bar-stack" aria-label="近 7 天與前 7 天業績比較">
<div class="growth-bar-row">
<span>近 7 天</span>
<i><b style="width: {{ growth.sales_current_width | default(0) }}%"></b></i>
</div>
<div class="growth-bar-row is-muted">
<span>前 7 天</span>
<i><b style="width: {{ growth.sales_prev_width | default(0) }}%"></b></i>
</div>
</div>
</div>
<div class="growth-command-kpi">
<span class="growth-kpi-label">下滑商品</span>
<strong class="growth-kpi-value momo-mono">{{ growth.declining_product_count | default(0) | number_format }}</strong>
<em>{{ growth.active_product_count | default(0) | number_format }} 個有銷售商品</em>
</div>
<div class="growth-command-kpi">
<span class="growth-kpi-label">比價可用率</span>
<strong class="growth-kpi-value momo-mono">{{ growth.mapping_rate | default(0) }}%</strong>
<div class="growth-progress"><span style="width: {{ growth.mapping_rate_width | default(0) }}%"></span></div>
<em>{{ growth.mapped_count | default(0) }} / {{ growth.candidate_count | default(0) }} 個高業績商品已對應</em>
</div>
<div class="growth-command-kpi">
<span class="growth-kpi-label">最大業績分類</span>
<strong class="growth-kpi-value is-text">{{ growth.top_category or '待分類' }}</strong>
<em>NT$ {{ growth.top_category_sales_7d | default(0) | int | number_format }}</em>
</div>
</div>
<div class="growth-command-grid">
<div class="growth-priority-panel">
<div class="growth-panel-head">
<strong>今天先做</strong>
<span>照順序處理</span>
</div>
<div class="growth-task-list">
{% for task in growth.priority_tasks | default([]) %}
{% if task.action == 'backfill' %}
<button class="growth-task is-{{ task.tone | default('neutral') }}" type="button" data-pchome-growth-backfill-trigger data-limit="16">
<span class="momo-mono">{{ '%02d'|format(task.rank) }}</span>
<strong>{{ task.title }}</strong>
<em>{{ task.metric }}</em>
<b>{{ task.button }}</b>
</button>
{% elif task.action == 'price_review' %}
<a class="growth-task is-{{ task.tone | default('neutral') }}" href="{{ url_for('dashboard.index', filter='pchome_review', category=current_category, q=search_query, sort_by='pchome_review', order='desc') }}">
<span class="momo-mono">{{ '%02d'|format(task.rank) }}</span>
<strong>{{ task.title }}</strong>
<em>{{ task.metric }}</em>
<b>{{ task.button }}</b>
</a>
{% elif task.action == 'ai_picks' %}
<a class="growth-task is-{{ task.tone | default('neutral') }}" href="{{ url_for('dashboard.index', filter='ai_picks', category=current_category, q=search_query, sort_by='timestamp', order='desc') }}">
<span class="momo-mono">{{ '%02d'|format(task.rank) }}</span>
<strong>{{ task.title }}</strong>
<em>{{ task.metric }}</em>
<b>{{ task.button }}</b>
</a>
{% else %}
<a class="growth-task is-{{ task.tone | default('neutral') }}" href="{{ url_for('daily_sales.daily_sales') }}">
<span class="momo-mono">{{ '%02d'|format(task.rank) }}</span>
<strong>{{ task.title }}</strong>
<em>{{ task.metric }}</em>
<b>{{ task.button }}</b>
</a>
{% endif %}
{% endfor %}
</div>
<div class="growth-backfill-status momo-mono" data-pchome-growth-backfill-status>
每日 10:45 自動補對應;按下可立即補高業績商品的 MOMO 對應
</div>
</div>
<div class="growth-strategy-panel">
<div class="growth-panel-head">
<strong>MOMO 比價後怎麼做</strong>
<span>直接轉成銷售策略</span>
</div>
<div class="growth-strategy-grid">
{% for lane in growth.strategy_lanes | default([]) %}
<div class="growth-strategy-lane is-{{ lane.tone | default('neutral') }}">
<span>{{ lane.label }}</span>
<strong class="momo-mono">{{ lane.value | default(0) | number_format }}</strong>
<small>{{ lane.decision }}</small>
<em>{{ lane.action }}</em>
</div>
{% endfor %}
</div>
</div>
</div>
<div class="growth-opportunity-panel">
<div class="growth-panel-head">
<strong>高業績商品作戰清單</strong>
<span>業績 × MOMO 價格 × 下一步</span>
</div>
<div class="growth-opportunity-table-wrap">
<table class="growth-opportunity-table">
<thead>
<tr>
<th>商品</th>
<th class="text-end">近 7 天業績</th>
<th>趨勢</th>
<th>MOMO 比價</th>
<th>下一步</th>
</tr>
</thead>
<tbody>
{% for item in growth.top_opportunities | default([]) %}
{% set external = item.external_price or {} %}
<tr>
<td>
<a class="growth-product-name" href="https://24h.pchome.com.tw/prod/{{ item.pchome_product_id }}" target="_blank" rel="noopener noreferrer">{{ item.product_name }}</a>
<span class="growth-product-id momo-mono">{{ item.pchome_product_id }}</span>
</td>
<td class="text-end momo-mono">NT$ {{ item.sales_7d | default(0) | int | number_format }}</td>
<td>
{% if item.sales_delta_pct is not none %}
<span class="growth-delta {% if item.sales_delta_pct < 0 %}is-down{% else %}is-up{% endif %}">
{{ '%+.1f'|format(item.sales_delta_pct) }}%
</span>
{% else %}
<span class="growth-delta is-flat">新基準</span>
{% endif %}
</td>
<td>
{% if external %}
<span class="growth-compare-pill {% if external.gap_pct is not none and external.gap_pct < -5 %}is-risk{% elif external.gap_pct is not none and external.gap_pct > 5 %}is-win{% else %}is-even{% endif %}">
{{ external.price_basis_label or '商品總價' }}
{% if external.gap_pct is not none %} {{ '%+.1f'|format(external.gap_pct) }}%{% endif %}
</span>
{% else %}
<span class="growth-compare-pill is-missing">未配對</span>
{% endif %}
</td>
<td><span class="growth-action-chip">{{ item.recommended_action.label }}</span></td>
</tr>
{% else %}
<tr>
<td colspan="5" class="growth-empty">尚未產生成長作戰清單,請先完成 PChome 業績匯入。</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</section>
<section>
<div class="dashboard-section-label">
<span class="num momo-mono">01</span>
<span class="title">比價監控總覽</span>
<span class="meta momo-mono">指標 · 最新有效價格 {{ overview.last_pchome_crawled or '待刷新' }}</span>
</div>
<div class="dashboard-kpi-grid">
<div class="dashboard-kpi dashboard-kpi--coverage">
<div class="dashboard-kpi-label momo-mono">決策支援覆蓋率</div>
<div class="dashboard-kpi-value momo-mono">{{ overview.decision_support_rate | default(overview.decision_ready_rate | default(0)) }}%</div>
<div class="dashboard-kpi-sub">可直接支援調價、挑品、簡報的有效比價資料</div>
<div class="dashboard-kpi-metrics momo-mono" aria-label="決策支援組成">
<span><em>支援</em><strong>{{ overview.decision_support_count | default(overview.decision_ready_count | default(0)) | number_format }}</strong></span>
<span><em>有效商品</em><strong>{{ overview.total_active | default(total_products) | number_format }}</strong></span>
<span><em>身份</em><strong>{{ overview.identity_coverage_rate | default(overview.match_rate | default(0)) }}%</strong></span>
<span><em>型錄</em><strong>{{ overview.catalog_comparable_count | default(0) | number_format }}</strong></span>
</div>
</div>
<div class="dashboard-kpi is-accent">
<div class="dashboard-kpi-label momo-mono">PChome 價格優勢</div>
<div class="dashboard-kpi-value momo-mono">{{ overview.pchome_advantage_count | default(0) | number_format }}</div>
<div class="dashboard-kpi-sub momo-mono">PChome 較低 · 平均價差 +{{ overview.avg_advantage_gap | default(0) }}%</div>
</div>
<div class="dashboard-kpi">
<div class="dashboard-kpi-label momo-mono">MOMO 低價壓力</div>
<div class="dashboard-kpi-value momo-mono is-success">{{ overview.momo_threat_count | default(0) | number_format }}</div>
<div class="dashboard-kpi-sub momo-mono">MOMO 價格低於 PChome</div>
</div>
<div class="dashboard-kpi">
<div class="dashboard-kpi-label momo-mono">AI 挑品</div>
<div class="dashboard-kpi-value momo-mono is-success">{{ overview.ai_pick_count | default(0) | number_format }}</div>
<div class="dashboard-kpi-sub momo-mono">
<a class="dashboard-kpi-sub-link" href="{{ url_for('dashboard.index', filter='ai_picks', category=current_category, q=search_query, sort_by='timestamp', order='desc') }}">查看 {{ ai_pick_list_limit }} 品清單</a>
</div>
</div>
<div class="dashboard-kpi dashboard-kpi--ops">
<div class="dashboard-kpi-label momo-mono">比價覆核</div>
<div class="dashboard-kpi-value momo-mono is-warning">{{ overview.review_queue_count | default(0) | number_format }}</div>
<div class="dashboard-kpi-metrics momo-mono" aria-label="比價覆核組成">
<a href="{{ url_for('dashboard.index', filter='pchome_review', category=current_category, q=search_query, review_status='rescore_accepted', sort_by='pchome_review', order='desc') }}" title="重算待覆核 {{ overview.rescore_accepted_count | default(0) | number_format }}"><em>重算待覆核</em><strong>{{ overview.rescore_accepted_count | default(0) | number_format }}</strong></a>
<a href="{{ url_for('dashboard.index', filter='pchome_review', category=current_category, q=search_query, review_status='catalog_identity_review', sort_by='pchome_review', order='desc') }}" title="身份採用待核 {{ overview.catalog_identity_review_count | default(0) | number_format }}"><em>身份採用</em><strong>{{ overview.catalog_identity_review_count | default(0) | number_format }}</strong></a>
<a href="{{ url_for('dashboard.index', filter='pchome_review', category=current_category, q=search_query, review_status='unit_comparable', sort_by='pchome_review', order='desc') }}" title="需單位價 {{ overview.unit_comparable_count | default(0) | number_format }}"><em>需單位價</em><strong>{{ overview.unit_comparable_count | default(0) | number_format }}</strong></a>
<span><em>待補抓</em><strong>{{ overview.pending_match_count | default(0) | number_format }}</strong></span>
</div>
</div>
</div>
<div class="dashboard-backfill-card"
data-pchome-backfill-card
data-backfill-endpoint="/api/ai/pchome-match/backfill"
data-refresh-stale-endpoint="/api/ai/pchome-match/refresh-stale"
data-status-endpoint="/api/ai/pchome-match/backfill/status"
data-pchome-backfill-action="backfillPchomeMatches">
<div class="dashboard-backfill-main">
<div class="dashboard-backfill-label momo-mono">PChome 比價補強</div>
<div class="dashboard-backfill-title">PChome 比價補強產線</div>
<div class="dashboard-backfill-meta">刷新過期、補抓未配對、清理近門檻候選,目標是提高可決策覆蓋率。</div>
<div class="dashboard-backfill-pills momo-mono" aria-label="補強產線隊列">
<span title="待刷新 {{ overview.stale_match_count | default(0) | number_format }}">待刷新 <strong>{{ overview.stale_match_count | default(0) | number_format }}</strong></span>
<span>未設到期 <strong>{{ overview.unknown_freshness_count | default(0) | number_format }}</strong></span>
<span>待補抓 <strong>{{ overview.pending_match_count | default(0) | number_format }}</strong></span>
<span>覆核 <strong>{{ overview.review_queue_count | default(0) | number_format }}</strong></span>
<span>單位價 <strong>{{ overview.unit_comparable_count | default(0) | number_format }}</strong></span>
</div>
</div>
<div class="dashboard-backfill-progress" aria-hidden="true">
<span data-pchome-backfill-progress></span>
</div>
<div class="dashboard-backfill-status momo-mono">
<span data-pchome-backfill-status>讀取狀態中</span>
<span data-pchome-backfill-result>--</span>
</div>
<div class="dashboard-backfill-actions">
<button class="dashboard-action-button"
type="button"
data-pchome-refresh-stale-trigger
data-limit="120">
<i class="fas fa-rotate"></i> 刷新過期 120 筆
</button>
<button class="dashboard-action-button is-primary"
type="button"
data-pchome-backfill-trigger
data-limit="60">
<i class="fas fa-magnifying-glass-chart"></i> 補強 60 筆
</button>
</div>
</div>
<div class="dashboard-decision-workbench" aria-label="提升決策支援覆蓋率工作流">
<div class="dashboard-decision-workbench__head">
<span class="dashboard-backfill-label momo-mono">覆蓋率流程</span>
<strong>提升決策支援覆蓋率</strong>
<em>先處理最能轉成可決策資料的隊列,避免盲目降低門檻。</em>
</div>
<div class="dashboard-decision-lanes">
<button class="dashboard-decision-lane"
type="button"
data-pchome-refresh-stale-trigger
data-limit="120">
<span class="momo-mono">01</span>
<strong>刷新過期</strong>
<em>{{ overview.stale_match_count | default(0) | number_format }} 筆價格需要重新確認</em>
</button>
<button class="dashboard-decision-lane"
type="button"
data-pchome-backfill-trigger
data-limit="60">
<span class="momo-mono">02</span>
<strong>補抓未配對</strong>
<em>{{ overview.pending_match_count | default(0) | number_format }} 筆尚未形成有效身份配對</em>
</button>
<a class="dashboard-decision-lane" href="{{ url_for('dashboard.index', filter='pchome_review', category=current_category, q=search_query, review_status='unit_comparable', sort_by='pchome_review', order='desc') }}">
<span class="momo-mono">03</span>
<strong>單位價覆核</strong>
<em>{{ overview.unit_comparable_count | default(0) | number_format }} 筆需判斷容量、入數、組合價</em>
</a>
<a class="dashboard-decision-lane" href="{{ url_for('dashboard.index', filter='pchome_review', category=current_category, q=search_query, review_status='catalog_identity_review', sort_by='pchome_review', order='desc') }}">
<span class="momo-mono">04</span>
<strong>身份採用待核</strong>
<em>{{ overview.catalog_identity_review_count | default(0) | number_format }} 筆高信心同款,確認後可寫入正式比價</em>
</a>
<a class="dashboard-decision-lane" href="{{ url_for('dashboard.index', filter='pchome_review', category=current_category, q=search_query, review_status='rescore_accepted', sort_by='pchome_review', order='desc') }}">
<span class="momo-mono">05</span>
<strong>採用/否決候選</strong>
<em>{{ overview.rescore_accepted_count | default(0) | number_format }} 筆近門檻候選等待確認</em>
</a>
</div>
</div>
</section>
<section>
<div class="dashboard-section-label">
<span class="num momo-mono">02</span>
<span class="title">比價決策焦點</span>
<span class="meta momo-mono">{{ today_date }}</span>
</div>
<div class="dashboard-focus-grid">
<div class="dashboard-focus-card">
<div class="dashboard-focus-label momo-mono">今日優先銷售</div>
{% if overview.top_picks %}
<div class="dashboard-focus-list">
{% for pick in overview.top_picks %}
<div class="dashboard-focus-row">
<a class="dashboard-focus-row-title momo-tracked-link" href="{{ pick.momo_url or '#' }}" data-momo-original-url="{{ pick.momo_url or '#' }}" target="_blank" rel="noopener noreferrer"
data-track-platform="momo"
data-track-source="dashboard-v2-overview-top-picks"
data-track-product-id="{{ pick.sku }}"
data-track-icode="{{ pick.sku }}"
data-track-product-name="{{ pick.name|e }}">{{ pick.name }}</a>
<div class="dashboard-focus-row-meta momo-mono">
<span class="dashboard-focus-chip is-win">AI {{ (pick.confidence * 100) | round(0) | int if pick.confidence else 0 }}%</span>
<span>證據 {{ pick.evidence_quality | round(0) | int }}%</span>
<span>機會 {{ pick.opportunity_score | round(0) | int }}</span>
<span>MOMO ${{ pick.momo_price | int | number_format }}</span>
<span>PChome ${{ pick.pchome_price | int | number_format }}</span>
<span>+{{ pick.gap_pct | round(1) }}%</span>
</div>
{% if pick.missing_evidence %}
<div class="dashboard-ai-evidence-line">
{% for evidence in pick.missing_evidence[:2] %}
<span class="dashboard-ai-evidence-chip">{{ evidence }}</span>
{% endfor %}
</div>
{% endif %}
<div class="dashboard-focus-row-links">
<a class="dashboard-platform-link is-momo momo-tracked-link" href="{{ pick.momo_url or '#' }}" data-momo-original-url="{{ pick.momo_url or '#' }}" target="_blank" rel="noopener noreferrer"
data-track-platform="momo"
data-track-source="dashboard-v2-overview-top-picks"
data-track-product-id="{{ pick.sku }}"
data-track-icode="{{ pick.sku }}"
data-track-product-name="{{ pick.name|e }}">MOMO {{ pick.sku }}</a>
{% if pick.pchome_url %}
<a class="dashboard-platform-link is-pchome" href="{{ pick.pchome_url }}" target="_blank" rel="noopener noreferrer">PChome {{ pick.pchome_id }}</a>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="dashboard-focus-title">尚無挑品建議</div>
<div class="dashboard-focus-sub momo-mono">先累積 PChome 比價與挑品資料</div>
{% endif %}
</div>
<div class="dashboard-focus-card">
<div class="dashboard-focus-label momo-mono">價格威脅</div>
{% if overview.top_momo_threats %}
<div class="dashboard-focus-list">
{% for item in overview.top_momo_threats %}
<div class="dashboard-focus-row">
<a class="dashboard-focus-row-title momo-tracked-link" href="{{ item.momo_url or '#' }}" data-momo-original-url="{{ item.momo_url or '#' }}" target="_blank" rel="noopener noreferrer"
data-track-platform="momo"
data-track-source="dashboard-v2-overview-top-momo-threats"
data-track-product-id="{{ item.sku }}"
data-track-icode="{{ item.sku }}"
data-track-product-name="{{ item.name|e }}">{{ item.name }}</a>
<div class="dashboard-focus-row-meta momo-mono">
<span class="dashboard-focus-chip is-risk">{{ item.gap_pct | round(1) }}%</span>
<span>MOMO ${{ item.momo_price | int | number_format }}</span>
<span>PChome ${{ item.pchome_price | int | number_format }}</span>
</div>
<div class="dashboard-focus-row-links">
<a class="dashboard-platform-link is-momo momo-tracked-link" href="{{ item.momo_url or '#' }}" data-momo-original-url="{{ item.momo_url or '#' }}" target="_blank" rel="noopener noreferrer"
data-track-platform="momo"
data-track-source="dashboard-v2-overview-top-momo-threats"
data-track-product-id="{{ item.sku }}"
data-track-icode="{{ item.sku }}"
data-track-product-name="{{ item.name|e }}">MOMO {{ item.sku }}</a>
{% if item.pchome_url %}
<a class="dashboard-platform-link is-pchome" href="{{ item.pchome_url }}" target="_blank" rel="noopener noreferrer">PChome {{ item.pchome_id }}</a>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="dashboard-focus-title">尚無明顯威脅</div>
<div class="dashboard-focus-sub momo-mono">目前沒有 MOMO 低於 PChome 5% 以上的配對商品</div>
{% endif %}
</div>
<div class="dashboard-focus-card">
<div class="dashboard-focus-label momo-mono">覆核與補資料</div>
{% if overview.review_queue %}
<div class="dashboard-focus-list">
{% for item in overview.review_queue %}
<div class="dashboard-focus-row">
<a class="dashboard-focus-row-title" href="{{ url_for('dashboard.index', filter='pchome_review', q=item.sku, sort_by='pchome_review', order='desc') }}">{{ item.name }}</a>
<div class="dashboard-focus-row-meta momo-mono">
<span class="dashboard-focus-chip is-review">{{ item.status_label }}</span>
<span>MOMO ${{ item.momo_price | int | number_format }}</span>
{% if item.candidate_pc_price %}
<span>候選 PChome ${{ item.candidate_pc_price | int | number_format }}</span>
{% endif %}
{% if item.best_match_score %}
<span>信心 {{ (item.best_match_score * 100) | round(0) | int }}%</span>
{% endif %}
</div>
<div class="dashboard-focus-sub">{{ item.action_label }}</div>
{% if item.decision_envelope %}
{% set envelope = item.decision_envelope %}
{% set guardrails = envelope.guardrails or {} %}
{% set data_quality = guardrails.data_quality | default('partial', true) | lower %}
<div class="dashboard-review-envelope" aria-label="決策信封摘要">
<span>優先 {{ envelope.severity or 'P4' }}</span>
<span>{{ {'complete': '證據完整', 'partial': '部分證據', 'missing': '證據不足'}.get(data_quality, '部分證據') }}</span>
{% if guardrails.can_auto_execute == false %}
<span>需人工</span>
{% endif %}
</div>
{% endif %}
{% if item.diagnostic_reasons %}
<div class="dashboard-review-reasons" aria-label="比對診斷原因">
{% for reason in item.diagnostic_reasons[:4] %}
<span>{{ reason.label }}</span>
{% endfor %}
</div>
{% endif %}
{% if item.unit_comparison and item.unit_comparison.summary %}
<div class="dashboard-review-note momo-mono">{{ item.unit_comparison.summary }}</div>
{% endif %}
{% if item.unit_price_insight and item.unit_price_insight.summary %}
<div class="dashboard-review-note">{{ item.unit_price_insight.summary }}</div>
{% endif %}
<div class="dashboard-focus-row-links">
<a class="dashboard-platform-link is-momo momo-tracked-link" href="{{ build_momo_product_url(item.sku) if build_momo_product_url is defined else '#' }}" data-momo-original-url="{{ build_momo_product_url(item.sku) if build_momo_product_url is defined else '#' }}" target="_blank" rel="noopener noreferrer"
data-track-platform="momo"
data-track-source="dashboard-v2-overview-review-queue"
data-track-product-id="{{ item.sku }}"
data-track-icode="{{ item.sku }}"
data-track-product-name="{{ item.name|e }}">MOMO {{ item.sku }}</a>
{% if item.candidate_pc_id %}
<a class="dashboard-platform-link is-pchome" href="https://24h.pchome.com.tw/prod/{{ item.candidate_pc_id }}" target="_blank" rel="noopener noreferrer">PChome {{ item.candidate_pc_id }}</a>
{% endif %}
</div>
</div>
{% endfor %}
</div>
<a class="dashboard-focus-action" href="{{ url_for('dashboard.index', filter='pchome_review', category=current_category, q=search_query, sort_by='pchome_review', order='desc') }}">查看高優先覆核隊列</a>
{% elif overview.pending_priority %}
<div class="dashboard-focus-list">
{% for item in overview.pending_priority %}
<div class="dashboard-focus-row">
<a class="dashboard-focus-row-title momo-tracked-link" href="{{ item.momo_url or '#' }}" data-momo-original-url="{{ item.momo_url or '#' }}" target="_blank" rel="noopener noreferrer"
data-track-platform="momo"
data-track-source="dashboard-v2-overview-pending-priority"
data-track-product-id="{{ item.sku }}"
data-track-icode="{{ item.sku }}"
data-track-product-name="{{ item.name|e }}">{{ item.name }}</a>
<div class="dashboard-focus-row-meta momo-mono">
<span class="dashboard-focus-chip is-neutral">尚未搜尋</span>
<span>MOMO ${{ item.momo_price | int | number_format }}</span>
<span>{{ item.category or '未分類' }}</span>
</div>
<div class="dashboard-focus-row-links">
<a class="dashboard-platform-link is-momo momo-tracked-link" href="{{ item.momo_url or '#' }}" data-momo-original-url="{{ item.momo_url or '#' }}" target="_blank" rel="noopener noreferrer"
data-track-platform="momo"
data-track-source="dashboard-v2-overview-pending-priority"
data-track-product-id="{{ item.sku }}"
data-track-icode="{{ item.sku }}"
data-track-product-name="{{ item.name|e }}">MOMO {{ item.sku }}</a>
<span class="dashboard-platform-muted">尚未進入 PChome 補抓</span>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="dashboard-focus-title">覆核隊列已清空</div>
<div class="dashboard-focus-sub momo-mono">目前有效商品沒有高優先 PChome 覆核項目</div>
{% endif %}
</div>
</div>
</section>
<section>
<div class="dashboard-section-label">
<span class="num momo-mono">03</span>
<span class="title">篩選</span>
</div>
<div class="dashboard-filter-card">
<form class="dashboard-filter-form" method="GET" action="/">
<input class="dashboard-search" type="text" name="q" value="{{ search_query }}" placeholder="搜尋商品名稱或品號...">
<select class="dashboard-select" name="category" data-dashboard-auto-submit>
<option value="all">所有分類</option>
{% for cat in categories %}
<option value="{{ cat }}" {% if current_category == cat %}selected{% endif %}>{{ cat }}</option>
{% endfor %}
</select>
<input type="hidden" name="filter" value="{{ current_filter }}">
<input type="hidden" name="review_status" value="{{ current_review_status }}">
<input type="hidden" name="sort_by" value="{{ current_sort }}">
<input type="hidden" name="order" value="{{ current_order }}">
<button class="dashboard-action-button" type="submit">
<i class="fas fa-search"></i> 搜尋
</button>
<div class="dashboard-segmented">
<a class="{% if current_filter == 'all' %}is-active{% endif %}" href="{{ url_for('dashboard.index', filter='all', category=current_category, q=search_query, sort_by=current_sort, order=current_order) }}">全部</a>
<a class="{% if current_filter == 'ai_picks' %}is-active{% endif %}" href="{{ url_for('dashboard.index', filter='ai_picks', category=current_category, q=search_query, sort_by='timestamp', order='desc') }}">AI挑品</a>
<a class="{% if current_filter == 'pchome_review' %}is-active{% endif %}" href="{{ url_for('dashboard.index', filter='pchome_review', review_status='all', category=current_category, q=search_query, sort_by='pchome_review', order='desc') }}">比價覆核</a>
<a class="{% if current_filter == 'new' %}is-active{% endif %}" href="{{ url_for('dashboard.index', filter='new', category=current_category, q=search_query, sort_by=current_sort, order=current_order) }}">新上架</a>
<a class="{% if current_filter == 'increase' %}is-active{% endif %}" href="{{ url_for('dashboard.index', filter='increase', category=current_category, q=search_query, sort_by=current_sort, order=current_order) }}">漲價</a>
<a class="{% if current_filter == 'decrease' %}is-active{% endif %}" href="{{ url_for('dashboard.index', filter='decrease', category=current_category, q=search_query, sort_by=current_sort, order=current_order) }}">降價</a>
<a class="{% if current_filter == 'delisted' %}is-active{% endif %}" href="{{ url_for('dashboard.index', filter='delisted', category=current_category, q=search_query, sort_by=current_sort, order=current_order) }}">下架</a>
</div>
<button class="dashboard-action-button" type="button" data-dashboard-task="crawler">
<i class="fas fa-rotate"></i> 更新
</button>
<button class="dashboard-action-button is-primary" type="button" data-dashboard-task="notification">
<i class="fas fa-bell"></i> 發送通知
</button>
</form>
</div>
</section>
<section>
<div class="dashboard-table-card">
<div class="dashboard-table-head">
<span class="dashboard-section-index momo-mono">04</span>
<span class="dashboard-table-title">{{ 'AI 挑品清單' if current_filter == 'ai_picks' else ('比價覆核隊列' if current_filter == 'pchome_review' else '商品列表') }}</span>
<span class="dashboard-table-meta momo-mono">
{% if current_filter == 'ai_picks' %}
{{ total_items | number_format }} / {{ ai_pick_list_limit }} 品
{% elif current_filter == 'pchome_review' %}
{% if review_total_is_estimated %}約 {% endif %}{{ total_items | number_format }} / {{ overview.review_queue_count | default(0) | number_format }} 待處理
{% else %}
{{ total_items | number_format }} 筆
{% endif %}
</span>
<div class="momo-topbar-spacer"></div>
<a class="dashboard-action-link" href="/api/export/excel/all">
<i class="fas fa-download"></i> 匯出全部
</a>
<a class="dashboard-action-link" href="/api/export/excel/changes">
<i class="fas fa-arrow-trend-up"></i> 匯出漲跌
</a>
{% if current_filter == 'ai_picks' %}
<a class="dashboard-action-link" href="/api/export/excel/ai-picks">
<i class="fas fa-file-excel"></i> 匯出 AI 挑品
</a>
{% elif current_filter == 'pchome_review' %}
<a class="dashboard-action-link" href="{{ url_for('export.export_excel_pchome_review', review_status=current_review_status, category=current_category, q=search_query) }}">
<i class="fas fa-file-excel"></i> 匯出覆核
</a>
{% endif %}
</div>
{% if current_filter == 'ai_picks' and ai_pick_summary %}
<div class="dashboard-ai-summary-grid">
<div class="dashboard-ai-summary-item">
<div class="dashboard-ai-summary-label">挑品數</div>
<div class="dashboard-ai-summary-value momo-mono">{{ ai_pick_summary.count | number_format }}</div>
<div class="dashboard-ai-summary-sub">目前清單上限 {{ ai_pick_list_limit }} 品</div>
</div>
<div class="dashboard-ai-summary-item">
<div class="dashboard-ai-summary-label">平均信心</div>
<div class="dashboard-ai-summary-value momo-mono">{{ (ai_pick_summary.avg_confidence * 100) | round(0) | int }}%</div>
<div class="dashboard-ai-summary-sub">高信心 {{ ai_pick_summary.high_confidence_count | number_format }} 品</div>
</div>
<div class="dashboard-ai-summary-item">
<div class="dashboard-ai-summary-label">證據完整度</div>
<div class="dashboard-ai-summary-value momo-mono">{{ ai_pick_summary.avg_evidence_quality | round(0) | int }}%</div>
<div class="dashboard-ai-summary-sub">需補證據 {{ ai_pick_summary.needs_evidence_count | number_format }} 品</div>
</div>
<div class="dashboard-ai-summary-item">
<div class="dashboard-ai-summary-label">平均價差</div>
<div class="dashboard-ai-summary-value momo-mono">+{{ ai_pick_summary.avg_gap_pct | round(1) }}%</div>
<div class="dashboard-ai-summary-sub">PChome 相對 MOMO 價差</div>
</div>
<div class="dashboard-ai-summary-item">
<div class="dashboard-ai-summary-label">最大價差</div>
<div class="dashboard-ai-summary-value momo-mono">+{{ ai_pick_summary.max_gap_pct | round(1) }}%</div>
<div class="dashboard-ai-summary-sub">清單內最大價格優勢</div>
</div>
<div class="dashboard-ai-summary-item">
<div class="dashboard-ai-summary-label">待補證據</div>
<div class="dashboard-ai-summary-value momo-mono">
{% if ai_pick_summary.top_missing_evidence %}
{{ ai_pick_summary.top_missing_evidence[0].count | number_format }}
{% else %}
0
{% endif %}
</div>
<div class="dashboard-ai-summary-sub">
{% if ai_pick_summary.top_missing_evidence %}
{{ ai_pick_summary.top_missing_evidence[0].label }}
{% else %}
暫無待補證據
{% endif %}
</div>
</div>
</div>
{% endif %}
{% if current_filter == 'pchome_review' %}
<div class="dashboard-review-segments">
{% for option in review_status_options %}
<a class="{% if current_review_status == option.key %}is-active{% endif %}" href="{{ url_for('dashboard.index', page=1, filter='pchome_review', review_status=option.key, category=current_category, q=search_query, sort_by='pchome_review', order='desc') }}">
<span>{{ option.label }}</span>
<span class="momo-mono">{{ option.count | number_format }}</span>
</a>
{% endfor %}
</div>
{% endif %}
<div class="dashboard-table-wrap {% if current_filter == 'pchome_review' %}is-review-wrap{% endif %}">
<table class="dashboard-table {% if current_filter == 'ai_picks' %}is-ai-picks{% elif current_filter == 'pchome_review' %}is-review{% endif %}">
<thead>
{% if current_filter == 'pchome_review' %}
<tr>
<th>分類</th>
<th>商品 / MOMO</th>
<th>PChome 候選</th>
<th>覆核判讀</th>
<th>下一步</th>
<th class="text-end">紀錄</th>
</tr>
{% else %}
<tr>
<th>分類</th>
<th>商品名稱</th>
<th class="text-end">
<a href="{{ url_for('dashboard.index', page=1, sort_by='price', order='asc' if current_sort == 'price' and current_order == 'desc' else 'desc', category=current_category, filter=current_filter, q=search_query) }}">MOMO 價格</a>
</th>
<th class="text-end">PChome 價格</th>
<th>競價判讀</th>
{% if current_filter == 'ai_picks' %}
<th>AI 建議</th>
{% endif %}
<th class="text-end">
<a href="{{ url_for('dashboard.index', page=1, sort_by='yesterday_change', order='asc' if current_sort == 'yesterday_change' and current_order == 'desc' else 'desc', category=current_category, filter=current_filter, q=search_query) }}">昨日漲跌</a>
</th>
<th class="text-end">
<a href="{{ url_for('dashboard.index', page=1, sort_by='week_change', order='asc' if current_sort == 'week_change' and current_order == 'desc' else 'desc', category=current_category, filter=current_filter, q=search_query) }}">週漲跌</a>
</th>
<th class="text-end">
<a href="{{ url_for('dashboard.index', page=1, sort_by='timestamp', order='asc' if current_sort == 'timestamp' and current_order == 'desc' else 'desc', category=current_category, filter=current_filter, q=search_query) }}">更新時間</a>
</th>
<th class="text-end">上架時間</th>
</tr>
{% endif %}
</thead>
<tbody>
{% for item in items %}
{% set product = item.record.product %}
{% set competitor = item.pchome_competitor %}
{% set decision = item.competitor_decision %}
{% set match_status = item.pchome_match_status %}
{% set image_url = product.image_url or ('https://m.momoshop.com.tw/moscdn/goods/' ~ product.i_code ~ '_m.webp') %}
{% set safe_product_url = item.safe_momo_url or '#' %}
{% if current_filter == 'pchome_review' %}
{% set review = item.pchome_review %}
{% set envelope = review.decision_envelope if review else {} %}
{% set guardrails = envelope.guardrails if envelope else {} %}
<tr class="dashboard-review-workbench-row" data-product-id="{{ product.id }}" data-product-name="{{ product.name|e }}">
<td><span class="dashboard-category">{{ product.category or '未分類' }}</span></td>
<td>
<div class="dashboard-review-product-stack">
<div class="dashboard-product-cell">
<img class="dashboard-product-thumb" src="{{ image_url }}" alt="{{ product.name }}" loading="lazy" referrerpolicy="no-referrer">
<div>
<a class="dashboard-product-name momo-tracked-link" href="{{ safe_product_url or '#' }}" target="_blank" rel="noopener noreferrer"
data-momo-original-url="{{ safe_product_url or '#' }}"
data-track-platform="momo"
data-track-source="dashboard-v2-pchome-review"
data-track-product-id="{{ product.id }}"
data-track-icode="{{ product.i_code }}"
data-track-product-name="{{ product.name|e }}">{{ product.name }}</a>
<div class="dashboard-review-product-meta">
<span>MOMO {{ product.i_code }}</span>
<span>${{ item.record.price | int | number_format }}</span>
</div>
</div>
</div>
</div>
</td>
<td>
<div class="dashboard-review-candidate">
{% if review and review.candidate_pc_id %}
<a class="dashboard-review-candidate-title" href="https://24h.pchome.com.tw/prod/{{ review.candidate_pc_id }}" target="_blank" rel="noopener noreferrer">
{{ review.candidate_pc_name or ('PChome ' ~ review.candidate_pc_id) }}
</a>
<div class="dashboard-review-candidate-meta">
{% if review.candidate_pc_price %}
<span>${{ review.candidate_pc_price | int | number_format }}</span>
{% endif %}
<span>PChome {{ review.candidate_pc_id }}</span>
{% if review.candidate_count %}
<span>{{ review.candidate_count }} 筆候選</span>
{% endif %}
</div>
{% elif competitor and competitor.product_id %}
<a class="dashboard-review-candidate-title" href="{{ competitor.product_url or ('https://24h.pchome.com.tw/prod/' ~ competitor.product_id) }}" target="_blank" rel="noopener noreferrer">
{{ competitor.product_name or ('PChome ' ~ competitor.product_id) }}
</a>
<div class="dashboard-review-candidate-meta">
{% if competitor.price %}
<span>${{ competitor.price | int | number_format }}</span>
{% endif %}
<span>PChome {{ competitor.product_id }}</span>
</div>
{% else %}
<span class="dashboard-match-state is-{{ match_status.tone | default('neutral') }}">{{ match_status.label | default('尚未搜尋') }}</span>
<div class="dashboard-review-note">{{ match_status.summary | default('尚未進入 PChome 補抓佇列') }}</div>
{% endif %}
</div>
</td>
<td>
<div class="dashboard-review-decision">
<div class="dashboard-review-decision-head">
<span class="dashboard-ai-pick-rank">{{ review.status_label if review else match_status.label }}</span>
{% if review and review.best_match_score %}
<span class="dashboard-ai-pick-confidence is-medium">信心 {{ (review.best_match_score * 100) | round(0) | int }}%</span>
{% endif %}
</div>
<div class="dashboard-ai-pick-reason">{{ review.action_label if review else match_status.summary }}</div>
{% if review and review.identity_evidence_summary %}
<div class="dashboard-review-note">證據:{{ review.identity_evidence_summary }}</div>
{% endif %}
{% if review and review.diagnostic_reasons %}
<div class="dashboard-review-reasons" aria-label="比對差異與證據">
{% for reason in review.diagnostic_reasons[:4] %}
<span>{{ reason.label }}</span>
{% endfor %}
</div>
{% endif %}
{% if review and review.unit_comparison and review.unit_comparison.summary %}
<div class="dashboard-review-note momo-mono">{{ review.unit_comparison.summary }}</div>
{% endif %}
{% if review and review.unit_price_insight and review.unit_price_insight.summary %}
<div class="dashboard-review-note">{{ review.unit_price_insight.summary }}</div>
{% endif %}
{% if envelope %}
{% set data_quality = guardrails.data_quality | default('partial', true) | lower %}
<div class="dashboard-review-envelope" aria-label="決策信封摘要">
<span>優先 {{ envelope.severity or 'P4' }}</span>
<span>{{ {'complete': '證據完整', 'partial': '部分證據', 'missing': '證據不足'}.get(data_quality, '部分證據') }}</span>
{% if guardrails.can_auto_execute == false %}
<span>需人工</span>
{% endif %}
{% if envelope.decision_id %}
<span title="決策追蹤">追蹤</span>
{% endif %}
</div>
{% endif %}
</div>
</td>
<td>
<div class="dashboard-review-next-step">
{% if review and review.catalog_review_guidance %}
<div class="dashboard-review-next-title">{{ review.catalog_review_guidance.lane_label }}</div>
<div class="dashboard-review-note">{{ review.catalog_review_guidance.action_hint }}</div>
{% else %}
<div class="dashboard-review-next-title">人工覆核</div>
<div class="dashboard-review-note">{{ match_status.summary | default('確認候選是否同款,再決定是否採用。') }}</div>
{% endif %}
{% if review %}
<div class="dashboard-review-actions" aria-label="人工覆核決策">
{% if review.candidate_pc_id and review.candidate_pc_price %}
<button class="dashboard-review-action is-accept" type="button"
data-pchome-review-action
data-review-action="accept_identity"
data-review-sku="{{ review.sku }}"
data-review-confirm="確認採用這筆 PChome 候選為正式同款配對?">
採用同款
</button>
{% endif %}
<button class="dashboard-review-action" type="button"
data-pchome-review-action
data-review-action="reject_identity"
data-review-sku="{{ review.sku }}"
data-review-confirm="確認否決這筆 PChome 候選?">
否決候選
</button>
<button class="dashboard-review-action" type="button"
data-pchome-review-action
data-review-action="unit_price_required"
data-review-sku="{{ review.sku }}"
data-review-confirm="確認標記為需單位價比較?">
標記單位價
</button>
<button class="dashboard-review-action is-research" type="button"
data-pchome-review-action
data-review-action="needs_research"
data-review-sku="{{ review.sku }}"
data-review-confirm="確認要求補搜尋詞或重新抓取?">
補搜尋
</button>
</div>
{% endif %}
</div>
</td>
<td class="dashboard-review-record text-end">
{% if review and review.attempted_at %}
<div class="momo-mono">{{ review.attempted_at }}</div>
{% else %}
<div class="momo-mono">{{ item.record.timestamp.strftime('%m-%d %H:%M') if item.record.timestamp else '--' }}</div>
{% endif %}
<div class="dashboard-review-record-tags">
{% if review %}
<span>覆核紀錄</span>
{% endif %}
{% if guardrails and guardrails.can_auto_execute == false %}
<span>需人工</span>
{% endif %}
</div>
</td>
</tr>
{% else %}
<tr class="is-history-enabled" data-product-id="{{ product.id }}" data-product-name="{{ product.name|e }}" title="點擊查看歷史價格圖表">
<td><span class="dashboard-category">{{ product.category or '未分類' }}</span></td>
<td>
<div class="dashboard-product-cell">
<img class="dashboard-product-thumb" src="{{ image_url }}" alt="{{ product.name }}" loading="lazy" referrerpolicy="no-referrer">
{% set safe_product_url = item.safe_momo_url or '#' %}
<a class="dashboard-product-name momo-tracked-link" href="{{ safe_product_url or '#' }}" target="_blank" rel="noopener noreferrer"
data-momo-original-url="{{ safe_product_url or '#' }}"
data-track-platform="momo"
data-track-source="dashboard-v2-table-main"
data-track-product-id="{{ product.id }}"
data-track-icode="{{ product.i_code }}"
data-track-product-name="{{ product.name|e }}">{{ product.name }}</a>
<div>
<div class="dashboard-platform-links">
<a class="dashboard-platform-link is-momo momo-tracked-link" href="{{ safe_product_url or '#' }}" target="_blank" rel="noopener noreferrer"
data-momo-original-url="{{ safe_product_url or '#' }}"
data-track-platform="momo"
data-track-source="dashboard-v2-table-main"
data-track-product-id="{{ product.id }}"
data-track-icode="{{ product.i_code }}"
data-track-product-name="{{ product.name|e }}">
MOMO {{ product.i_code }}
</a>
{% if competitor and competitor.product_url %}
<a class="dashboard-platform-link is-pchome" href="{{ competitor.product_url }}" target="_blank" rel="noopener noreferrer">
PChome {{ competitor.product_id }}
</a>
{% elif competitor and competitor.product_id %}
<span class="dashboard-platform-muted">PChome {{ competitor.product_id }}</span>
{% else %}
<span class="dashboard-platform-status is-{{ match_status.tone | default('neutral') }}" title="{{ match_status.summary | default('尚未搜尋 PChome 同款') }}">
PChome {{ match_status.label | default('尚未搜尋') }}
</span>
{% endif %}
</div>
{% if competitor and competitor.product_name %}
<div class="dashboard-product-id momo-mono" title="{{ competitor.product_name }}">PChome{{ competitor.product_name }}</div>
{% elif item.pchome_match_attempt and item.pchome_match_attempt.best_competitor_product_name %}
<div class="dashboard-product-id momo-mono" title="{{ item.pchome_match_attempt.best_competitor_product_name }}">候選:{{ item.pchome_match_attempt.best_competitor_product_name }}</div>
{% if item.pchome_match_attempt.competitor_product_url %}
<a class="dashboard-product-id dashboard-candidate-link momo-mono" href="{{ item.pchome_match_attempt.competitor_product_url }}" target="_blank" rel="noopener noreferrer">
PChome 候選 {{ item.pchome_match_attempt.best_competitor_product_id }}
</a>
{% endif %}
{% if item.pchome_match_attempt.diagnostic_reasons %}
<div class="dashboard-review-reasons" aria-label="比對診斷原因">
{% for reason in item.pchome_match_attempt.diagnostic_reasons[:3] %}
<span>{{ reason.label }}</span>
{% endfor %}
</div>
{% endif %}
{% endif %}
{% if item.ai_pick %}
<div class="dashboard-product-id momo-mono" title="{{ item.ai_pick.reason }}">
AI挑品 #{{ item.ai_pick.rank }} · 信心 {{ (item.ai_pick.confidence * 100) | round(0) | int }}% · 證據 {{ item.ai_pick.evidence_quality | round(0) | int }}% · 價差 {{ item.ai_pick.gap_pct | round(1) }}%
</div>
{% endif %}
</div>
</div>
</td>
<td class="text-end">
<button
class="dashboard-history-button"
type="button"
data-history-trigger
data-product-id="{{ product.id }}"
data-product-name="{{ product.name|e }}"
aria-label="查看歷史價格圖表"
>
<span class="dashboard-price momo-mono">${{ item.record.price | int | number_format }}</span>
<i class="fas fa-chart-line" aria-hidden="true"></i>
</button>
</td>
<td class="text-end momo-mono">
{% if competitor and competitor.price %}
<div class="dashboard-pchome-price">${{ competitor.price | int | number_format }}</div>
{% if competitor.match_score %}
<div class="dashboard-price-sub">信心 {{ (competitor.match_score * 100) | round(0) | int }}%</div>
{% endif %}
{% elif item.pchome_match_attempt and item.pchome_match_attempt.best_competitor_price and match_status.label == '需單位價比較' %}
<div class="dashboard-pchome-price">${{ item.pchome_match_attempt.best_competitor_price | int | number_format }}</div>
<div class="dashboard-price-sub">候選價,需單位換算</div>
{% else %}
<span class="dashboard-match-state is-{{ match_status.tone | default('neutral') }}" title="{{ match_status.summary | default('尚未搜尋 PChome 同款') }}">
{{ match_status.label | default('尚未搜尋') }}
</span>
{% if match_status.detail %}
<div class="dashboard-price-sub">{{ match_status.detail }}</div>
{% endif %}
{% if match_status.summary %}
<div class="dashboard-price-sub">{{ match_status.summary }}</div>
{% endif %}
{% endif %}
</td>
<td>
<div class="dashboard-competition-card">
<span class="dashboard-competition-badge is-{{ decision.tone }}">{{ decision.label }}</span>
{% if decision.gap_pct is not none %}
<span class="dashboard-competition-meta momo-mono">
MOMO - PChome
{% if decision.gap_amount > 0 %}+{% endif %}${{ decision.gap_amount | round(0) | int | number_format }}
/ {% if decision.gap_pct > 0 %}+{% endif %}{{ decision.gap_pct | round(1) }}%
</span>
{% endif %}
<span class="dashboard-competition-meta">{{ decision.summary }}</span>
</div>
</td>
{% if current_filter == 'ai_picks' %}
<td>
{% if item.ai_pick %}
<div class="dashboard-ai-pick-card">
<div class="dashboard-ai-pick-head">
<span class="dashboard-ai-pick-rank">#{{ item.ai_pick.rank }}</span>
<span class="dashboard-ai-pick-confidence is-{{ item.ai_pick.confidence_band | replace('_', '-') }}">信心 {{ (item.ai_pick.confidence * 100) | round(0) | int }}%</span>
</div>
<div class="dashboard-ai-evidence-line">
<span>機會 {{ item.ai_pick.opportunity_score | round(0) | int }}</span>
<span>證據 {{ item.ai_pick.evidence_quality | round(0) | int }}%</span>
{% if item.ai_pick.margin_rate is not none %}
<span>毛利 {{ item.ai_pick.margin_rate | round(1) }}%</span>
{% endif %}
</div>
<div class="dashboard-ai-pick-reason">{{ item.ai_pick.reason }}</div>
{% if item.ai_pick.missing_evidence %}
<div class="dashboard-ai-evidence-line" title="{{ item.ai_pick.missing_evidence_text }}">
{% for evidence in item.ai_pick.missing_evidence[:3] %}
<span class="dashboard-ai-evidence-chip">{{ evidence }}</span>
{% endfor %}
</div>
{% endif %}
</div>
{% else %}
<span class="dashboard-muted">尚無建議理由</span>
{% endif %}
</td>
{% elif current_filter == 'pchome_review' %}
<td>
{% set review = item.pchome_review %}
{% set envelope = review.decision_envelope if review else {} %}
{% set guardrails = envelope.guardrails if envelope else {} %}
<div class="dashboard-review-card">
<div class="dashboard-ai-pick-head">
<span class="dashboard-ai-pick-rank">{{ review.status_label if review else match_status.label }}</span>
{% if review and review.best_match_score %}
<span class="dashboard-ai-pick-confidence is-medium">信心 {{ (review.best_match_score * 100) | round(0) | int }}%</span>
{% endif %}
</div>
<div class="dashboard-ai-pick-reason">{{ review.action_label if review else decision.summary }}</div>
{% if envelope %}
{% set data_quality = guardrails.data_quality | default('partial', true) | lower %}
<div class="dashboard-review-envelope" aria-label="決策信封摘要">
<span>優先 {{ envelope.severity or 'P4' }}</span>
<span>{{ {'complete': '證據完整', 'partial': '部分證據', 'missing': '證據不足'}.get(data_quality, '部分證據') }}</span>
{% if guardrails.can_auto_execute == false %}
<span>需人工</span>
{% endif %}
{% if envelope.decision_id %}
<span title="決策追蹤">追蹤</span>
{% endif %}
</div>
{% endif %}
{% if review %}
{% if review.candidate_pc_name or review.candidate_pc_price %}
<div class="dashboard-review-note">
{% if review.candidate_pc_name %}
{{ review.candidate_pc_name[:42] }}
{% endif %}
{% if review.candidate_pc_price %}
<span class="momo-mono">候選 ${{ review.candidate_pc_price | number_format }}</span>
{% endif %}
</div>
{% endif %}
{% if review.diagnostic_reasons %}
<div class="dashboard-review-reasons" aria-label="比對診斷原因">
{% for reason in review.diagnostic_reasons[:4] %}
<span>{{ reason.label }}</span>
{% endfor %}
</div>
{% endif %}
{% if review.catalog_review_guidance %}
<div class="dashboard-review-note">
覆核建議:{{ review.catalog_review_guidance.lane_label }} · {{ review.catalog_review_guidance.action_hint }}
</div>
{% endif %}
<div class="dashboard-ai-evidence-line">
{% if review.candidate_count %}
<span>{{ review.candidate_count }} 筆候選</span>
{% endif %}
{% if review.candidate_pc_id %}
<span>PChome {{ review.candidate_pc_id }}</span>
{% endif %}
{% if review.attempted_at %}
<span>{{ review.attempted_at }}</span>
{% endif %}
</div>
{% if review.unit_comparison and review.unit_comparison.summary %}
<div class="dashboard-review-note momo-mono">{{ review.unit_comparison.summary }}</div>
{% endif %}
{% if review.unit_price_insight and review.unit_price_insight.summary %}
<div class="dashboard-review-note">{{ review.unit_price_insight.summary }}</div>
{% endif %}
<div class="dashboard-review-actions" aria-label="人工覆核決策">
{% if review.candidate_pc_id and review.candidate_pc_price %}
<button class="dashboard-review-action is-accept" type="button"
data-pchome-review-action
data-review-action="accept_identity"
data-review-sku="{{ review.sku }}"
data-review-confirm="確認採用這筆 PChome 候選為正式同款配對?">
採用同款
</button>
{% endif %}
<button class="dashboard-review-action" type="button"
data-pchome-review-action
data-review-action="reject_identity"
data-review-sku="{{ review.sku }}"
data-review-confirm="確認否決這筆 PChome 候選?">
否決候選
</button>
<button class="dashboard-review-action" type="button"
data-pchome-review-action
data-review-action="unit_price_required"
data-review-sku="{{ review.sku }}"
data-review-confirm="確認標記為需單位價比較?">
標記單位價
</button>
<button class="dashboard-review-action is-research" type="button"
data-pchome-review-action
data-review-action="needs_research"
data-review-sku="{{ review.sku }}"
data-review-confirm="確認要求補搜尋詞或重新抓取?">
補搜尋
</button>
</div>
{% endif %}
</div>
</td>
{% endif %}
<td class="text-end momo-mono">
{% if item.yesterday_diff > 0 %}
<span class="dashboard-change-up">▲ +{{ item.yesterday_diff | abs | int | number_format }}</span>
{% elif item.yesterday_diff < 0 %}
<span class="dashboard-change-down">▼ -{{ item.yesterday_diff | abs | int | number_format }}</span>
{% else %}
<span class="dashboard-muted">--</span>
{% endif %}
</td>
<td class="text-end momo-mono">
{% set week_diff = item.stats.get('7d_diff', 0) %}
{% if week_diff > 0 %}
<span class="dashboard-change-up">+{{ week_diff | int | number_format }}</span>
{% elif week_diff < 0 %}
<span class="dashboard-change-down">-{{ week_diff | abs | int | number_format }}</span>
{% else %}
<span class="dashboard-muted">--</span>
{% endif %}
</td>
<td class="dashboard-table-time text-end momo-mono">
{{ item.record.timestamp.strftime('%m-%d %H:%M') if item.record.timestamp else '--' }}
</td>
<td class="dashboard-table-time text-end momo-mono">
{{ item.safe_created_at.strftime('%m-%d %H:%M') if item.safe_created_at else '--' }}
</td>
</tr>
{% endif %}
{% else %}
<tr>
<td colspan="{{ 6 if current_filter == 'pchome_review' else (10 if current_filter == 'ai_picks' else 9) }}">
<div class="dashboard-empty">
{% if search_query %}
找不到與「{{ search_query }}」相關的商品
{% else %}
目前沒有符合條件的商品
{% endif %}
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if total_pages > 1 %}
<div class="dashboard-pagination">
{% if current_page > 1 %}
<a class="dashboard-action-link" href="{{ url_for('dashboard.index', page=current_page - 1, category=current_category, filter=current_filter, review_status=current_review_status, q=search_query, sort_by=current_sort, order=current_order) }}">上一頁</a>
{% endif %}
<span class="dashboard-table-meta momo-mono">第 {{ current_page }} / {{ total_pages }} 頁</span>
{% if current_page < total_pages %}
<a class="dashboard-action-link" href="{{ url_for('dashboard.index', page=current_page + 1, category=current_category, filter=current_filter, review_status=current_review_status, q=search_query, sort_by=current_sort, order=current_order) }}">下一頁</a>
{% endif %}
</div>
{% endif %}
</div>
</section>
</div>
<div class="modal fade dashboard-history-modal" id="historyModal" tabindex="-1" aria-labelledby="historyModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<div>
<h5 class="modal-title" id="historyModalLabel">歷史價格走勢</h5>
<div class="dashboard-history-subtitle momo-mono" id="historyModalSubtitle">真實價格紀錄</div>
<div class="dashboard-history-range" aria-label="價格歷史區間">
<button type="button" data-history-range="week"></button>
<button class="is-active" type="button" data-history-range="month"></button>
<button type="button" data-history-range="quarter"></button>
<button type="button" data-history-range="year"></button>
</div>
</div>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="關閉"></button>
</div>
<div class="modal-body">
<div class="dashboard-chart-shell">
<div class="dashboard-chart-state" id="historyChartState">載入價格歷史中...</div>
<canvas class="dashboard-chart-canvas is-hidden" id="priceChart"></canvas>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script src="{{ url_for('static', filename='js/analysis-chart-theme.js') }}"></script>
<script src="{{ url_for('static', filename='js/page-dashboard-v2.js') }}"></script>
{% endblock %}