diff --git a/config.py b/config.py index fe42366..a0bbb39 100644 --- a/config.py +++ b/config.py @@ -414,7 +414,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '') # ========================================== # 系統版本與路徑 # ========================================== -SYSTEM_VERSION = "V10.804" +SYSTEM_VERSION = "V10.805" LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log') public_url = PUBLIC_URL # 用於模板顯示 diff --git a/tests/test_analysis_period_linkage.py b/tests/test_analysis_period_linkage.py index ee98a56..777ba24 100644 --- a/tests/test_analysis_period_linkage.py +++ b/tests/test_analysis_period_linkage.py @@ -280,3 +280,14 @@ def test_monthly_frontend_has_replayable_period_and_no_fixed_years(): assert "data-analysis-target" in tabs assert "renderChartEmpty" in script assert "未以其他月份回填" in script + + +def test_sales_frontend_uses_live_period_linked_api_routes(): + script = (ROOT / "web/static/js/page-sales-analysis.js").read_text(encoding="utf-8") + + assert "buildPeriodApiUrl" in script + assert "new URLSearchParams(window.location.search)" in script + assert "/api/sales_analysis/yoy_comparison" in script + assert "/api/sales_analysis/table_data" in script + assert "fetch(`/api/yoy?" not in script + assert "'/api/sales_table?'" not in script diff --git a/web/static/js/page-sales-analysis.js b/web/static/js/page-sales-analysis.js index d220a78..72054ff 100644 --- a/web/static/js/page-sales-analysis.js +++ b/web/static/js/page-sales-analysis.js @@ -30,6 +30,17 @@ // mix helper – browser already supports color-mix; fallback to manual rgba const mix = (c, pct) => `color-mix(in srgb, ${c} ${pct}%, transparent)`; + const buildPeriodApiUrl = (path, overrides = {}) => { + const url = new URL(path, window.location.origin); + new URLSearchParams(window.location.search).forEach((value, key) => { + url.searchParams.append(key, value); + }); + Object.entries(overrides).forEach(([key, value]) => { + url.searchParams.set(key, value); + }); + return url.toString(); + }; + // ─── Loading overlay ──────────────────────────────────── const overlay = document.getElementById('loadingOverlay'); const showLoading = (text) => { @@ -466,8 +477,16 @@ const y1 = document.getElementById('yoy-year1').value; const y2 = document.getElementById('yoy-year2').value; const m = document.getElementById('yoy-metric').value; - fetch(`/api/yoy?year1=${y1}&year2=${y2}&metric=${m}&${window.location.search.slice(1)}`) - .then(r => r.json()) + const url = buildPeriodApiUrl('/api/sales_analysis/yoy_comparison', { + year1: y1, + year2: y2, + metric: m + }); + fetch(url) + .then((response) => { + if (!response.ok) throw new Error(`HTTP ${response.status}`); + return response.json(); + }) .then(d => { document.getElementById('yoy-year1-label').textContent = `${y1}年`; document.getElementById('yoy-year2-label').textContent = `${y2}年`; @@ -510,7 +529,7 @@ const initDataTable = () => { const $tbl = window.jQuery && jQuery('#dataTable'); if (!$tbl || !$tbl.length || !jQuery.fn.DataTable) return; - const url = '/api/sales_table?' + window.location.search.slice(1); + const url = buildPeriodApiUrl('/api/sales_analysis/table_data'); $tbl.DataTable({ ajax: { url, dataSrc: 'data' }, processing: true, serverSide: false,