Files
ewoooc/templates/growth_analysis.html
ogt d668c3873c
All checks were successful
CD Pipeline / deploy (push) Successful in 1m6s
fix: make help and empty states action oriented
2026-06-25 11:32:44 +08:00

189 lines
9.1 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-growth.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/page-growth-bem.css') }}">
{% endblock %}
{% macro ga_chart_snapshot(labels, values, mode='currency') %}
<div class="ga-chart-snapshot">
{% for label in labels %}
{% set val = values[loop.index0]|default(0) %}
<span class="ga-chart-snapshot__item">
<b>{{ label }}</b>
<strong>
{% if mode == 'pct' %}{{ "{:+.1f}%".format(val) }}
{% else %}${{ "{:,.0f}".format(val) }}{% endif %}
</strong>
</span>
{% endfor %}
</div>
{% endmacro %}
{% block ewooo_content %}
<div class="growth-analysis-page" data-page-group="analytics">
{% include 'components/_analysis_report_tabs.html' %}
{# ── Page head ──────────────────────────────────── #}
<header class="ga-page-head">
<div class="ga-page-head__title">
<i class="fas fa-rocket ga-page-head__icon"></i>
<div>
<h1 class="ga-page-head__h1">營運成長策略報表</h1>
<p class="ga-page-head__brief">用月趨勢評估成長缺口、價差壓力與毛利品質。</p>
</div>
</div>
<span class="ga-page-head__meta">
數據更新至 <strong>{{ chart_data.labels[-1] if chart_data.labels else '-' }}</strong>
</span>
</header>
{% if is_empty_state|default(false) %}
<section class="ga-empty-state">
<i class="fas fa-chart-line" aria-hidden="true"></i>
<h2>尚未匯入可分析的業績資料</h2>
<p>{{ empty_message|default('先匯入月度業績資料再評估成長、AOV 與毛利缺口。') }}</p>
</section>
{% endif %}
{# ── KPI Row (3 cards) ──────────────────────────── #}
<section class="ga-kpi-row">
<article class="ga-kpi ga-kpi--revenue">
<div class="ga-kpi__label">YTD 本年度累計業績 ({{ kpi.current_year }})</div>
<div class="ga-kpi__value">${{ "{:,.0f}".format(kpi.ytd_revenue) }}</div>
<div class="ga-kpi__delta">
<span class="ga-kpi__chip">YoY Growth</span>
<span class="ga-kpi__yoy {{ 'is-up' if kpi.ytd_growth >= 0 else 'is-down' }}">
<i class="fas fa-{{ 'arrow-up' if kpi.ytd_growth >= 0 else 'arrow-down' }}"></i>
{{ "{:+.1f}%".format(kpi.ytd_growth) }}
</span>
<span class="ga-kpi__hint">vs 去年同期</span>
</div>
<i class="fas fa-chart-line ga-kpi__icon-bg"></i>
</article>
<article class="ga-kpi ga-kpi--aov">
<div class="ga-kpi__label">最新月平均單價</div>
<div class="ga-kpi__value">${{ "{:,.0f}".format(kpi.recent_aov) }}</div>
<div class="ga-kpi__hint">月結銷售額 ÷ 銷量</div>
<i class="fas fa-shopping-cart ga-kpi__icon-bg"></i>
</article>
<article class="ga-kpi ga-kpi--orders">
<div class="ga-kpi__label">總銷量</div>
<div class="ga-kpi__value">{{ "{:,.0f}".format(kpi.total_orders) }}</div>
<div class="ga-kpi__hint">全時期累計件數</div>
<i class="fas fa-receipt ga-kpi__icon-bg"></i>
</article>
</section>
{# ── Charts Row 1 ──────────────────────────────── #}
<section class="ga-chart-row ga-chart-row--8-4">
<article class="ga-chart-card">
<header class="ga-chart-card__head">
<span class="ga-chart-card__title"><i class="fas fa-chart-bar"></i> 月營收與年增率 (Revenue & YoY)</span>
</header>
<div class="ga-chart-card__body ga-chart-card__body--lg has-html-chart">
<canvas id="revenueChart"></canvas>
{{ ga_chart_snapshot(chart_data.labels, chart_data.revenue, 'currency') }}
</div>
</article>
<article class="ga-chart-card">
<header class="ga-chart-card__head">
<span class="ga-chart-card__title"><i class="fas fa-percentage"></i> 月增率分析 (MoM)</span>
</header>
<div class="ga-chart-card__body ga-chart-card__body--lg has-html-chart">
<canvas id="momChart"></canvas>
{{ ga_chart_snapshot(chart_data.labels, chart_data.mom, 'pct') }}
</div>
</article>
</section>
{# ── Charts Row 2 ──────────────────────────────── #}
<section class="ga-chart-row ga-chart-row--6-6">
<article class="ga-chart-card">
<header class="ga-chart-card__head">
<span class="ga-chart-card__title"><i class="fas fa-wallet"></i> 平均單價趨勢</span>
</header>
<div class="ga-chart-card__body ga-chart-card__body--md has-html-chart">
<canvas id="aovChart"></canvas>
{{ ga_chart_snapshot(chart_data.labels, chart_data.aov, 'currency') }}
</div>
</article>
<article class="ga-chart-card">
<header class="ga-chart-card__head">
<span class="ga-chart-card__title"><i class="fas fa-hand-holding-usd"></i> 獲利能力分析 (Gross Margin %)</span>
</header>
<div class="ga-chart-card__body ga-chart-card__body--md has-html-chart">
<canvas id="marginChart"></canvas>
{{ ga_chart_snapshot(chart_data.labels, chart_data.margin_rate, 'pct') }}
</div>
</article>
</section>
<section class="ga-chart-row ga-chart-row--8-4">
<article class="ga-chart-card">
<header class="ga-chart-card__head">
<span class="ga-chart-card__title"><i class="fas fa-scale-balanced"></i> PChome 價格壓力趨勢</span>
</header>
<div class="ga-chart-card__body ga-chart-card__body--md has-html-chart">
<canvas id="competitorPressureChart"></canvas>
{{ ga_chart_snapshot(chart_data.labels, chart_data.competitor_gap_pct, 'pct') }}
</div>
</article>
<article class="ga-chart-card">
<header class="ga-chart-card__head">
<span class="ga-chart-card__title"><i class="fas fa-bullseye"></i> 比價資料品質</span>
</header>
<div class="ga-chart-card__body ga-chart-card__body--md">
{% set coverage = chart_data.competitor_coverage | default({}) %}
<div class="ga-competitor-quality">
<span>高信心門檻</span>
<strong class="momo-mono">{{ coverage.match_score_floor | default(0.76) }}</strong>
<span>決策支援覆蓋率</span>
<strong class="momo-mono">{{ coverage.decision_support_rate | default(coverage.decision_ready_rate | default(0)) }}%</strong>
<span>精準可告警覆蓋</span>
<strong class="momo-mono">{{ coverage.decision_ready_rate | default(0) }}%</strong>
<span>身份配對</span>
<strong class="momo-mono">{{ coverage.valid_matches | default(0) | number_format }}</strong>
<span>身份覆蓋率</span>
<strong class="momo-mono">{{ coverage.match_rate | default(0) }}%</strong>
<span>價格新鮮</span>
<strong class="momo-mono">{{ coverage.fresh_matches | default(0) | number_format }}</strong>
<span>新鮮率</span>
<strong class="momo-mono">{{ coverage.fresh_match_rate | default(0) }}%</strong>
<span>價格過期</span>
<strong class="momo-mono">{{ coverage.stale_matches | default(0) | number_format }}</strong>
<span>未知新鮮度</span>
<strong class="momo-mono">{{ coverage.unknown_freshness_matches | default(0) | number_format }}</strong>
<span>未形成有效身份配對</span>
<strong class="momo-mono">{{ coverage.pending | default(0) | number_format }}</strong>
<span>需單位價覆核</span>
<strong class="momo-mono">{{ coverage.unit_comparable_count | default(0) | number_format }}</strong>
<span>型錄/任選可比</span>
<strong class="momo-mono">{{ coverage.catalog_comparable_count | default(0) | number_format }}</strong>
<span>重算待人工覆核</span>
<strong class="momo-mono">{{ coverage.rescore_accepted_count | default(0) | number_format }}</strong>
<span>人工採用</span>
<strong class="momo-mono">{{ coverage.manual_accept_count | default(0) | number_format }}</strong>
<span>人工否決</span>
<strong class="momo-mono">{{ coverage.manual_reject_count | default(0) | number_format }}</strong>
<span>人工單位價</span>
<strong class="momo-mono">{{ coverage.manual_unit_price_count | default(0) | number_format }}</strong>
</div>
</div>
</article>
</section>
</div>
{% endblock %}
{% block extra_js %}
<template id="chart-data">{{ chart_data | tojson }}</template>
<script src="{{ url_for('static', filename='js/analysis-chart-theme.js') }}"></script>
<script src="{{ url_for('static', filename='js/page-growth.js') }}"></script>
{% endblock %}