上次比价
@@ -8997,7 +8997,9 @@ function goAuthLocation() {
openLocSysPopup();
}
// 回前台(定位授权窗 / 设置返回)重核授权态并刷新 feed 区(纯 H5,不依赖原生事件)。
-document.addEventListener('visibilitychange', function(){ if (document.visibilityState === 'visible') { try { applyLocationState(); } catch(e){} } });
+document.addEventListener('visibilitychange', function(){ if (document.visibilityState === 'visible') { try { applyLocationState(); } catch(e){} try { renderLastCompareBanner(); } catch(e){} } });
+// 「上次比价」横幅:进页拉一次 + 回前台(上面 visibilitychange)再拉(4 分钟窗口随时间过期;在外卖 App 比完价回来即出)
+document.addEventListener('DOMContentLoaded', function(){ try { renderLastCompareBanner(); } catch(e){} });
function isHomeNearbyEmpty(feed) {
try {
var params = new URLSearchParams(location.search);
@@ -9089,13 +9091,7 @@ function renderTriClaim() {
if (entry) entry.classList.toggle('coupon-claimed', homeCouponClaimed);
}
-const LAST_COMPARE_RECORD_KEY = 'proto_last_compare_record';
-const DEFAULT_LAST_COMPARE_RECORD = {
- shop: '窑鸡王(康营店)',
- items: ['招牌窑鸡整只-原味', '窑鸡饭套餐'],
- bestPlatform: '淘宝',
- bestPrice: 57.9
-};
+// 「上次比价」数据改由后端 /api/v1/compare/records 实拉(见 renderLastCompareBanner);原写死 mock 已移除。
const LAST_COMPARE_VARIANTS = ['reference', 'tagright', 'topbar', 'pricebadge', 'mutedright'];
const LAST_COMPARE_PLATFORM_LOGOS = {
'淘宝': 'assets/shared/logos/taobao.png',
@@ -9112,20 +9108,50 @@ function getLastCompareVariant() {
return LAST_COMPARE_VARIANTS.includes(value) ? value : 'reference';
}
-function readLastCompareRecord() {
- try {
- const raw = localStorage.getItem(LAST_COMPARE_RECORD_KEY);
- return raw ? JSON.parse(raw) : null;
- } catch(e) {
- return null;
- }
-}
-
function renderLastCompareBanner() {
const banner = document.getElementById('lastCompareBanner');
if (!banner) return;
+ const token = (window.SGBridge && SGBridge.getToken && SGBridge.getToken()) || '';
+ if (!token) { banner.style.display = 'none'; return; } // 未登录 → 隐藏
+ fetch('/api/v1/compare/records?limit=5', { headers: { 'Authorization': 'Bearer ' + token } })
+ .then(function (r) { return r.ok ? r.json() : null; })
+ .then(function (d) {
+ const rec = pickFreshLastCompare(d && d.items);
+ if (!rec) { banner.style.display = 'none'; return; } // 无成功 / 超 4 分钟窗口 / 401 → 隐藏
+ banner.style.display = '';
+ fillLastCompareBanner(lastCompareToSummary(rec));
+ })
+ .catch(function () { banner.style.display = 'none'; });
+}
- const record = readLastCompareRecord() || DEFAULT_LAST_COMPARE_RECORD;
+// 取最近一条成功比价并卡 4 分钟新鲜窗口(records 按 created_at 倒序,首条成功即最新成功)。
+function pickFreshLastCompare(items) {
+ if (!Array.isArray(items)) return null;
+ for (let i = 0; i < items.length; i++) {
+ const it = items[i];
+ if (it && it.status === 'success') {
+ const t = Date.parse(it.created_at);
+ if (isNaN(t)) return null;
+ const age = Date.now() - t; // 容 1 分钟时钟偏差(同原生 toFreshSummary)
+ return (age >= -60000 && age <= 4 * 60 * 1000) ? it : null;
+ }
+ }
+ return null;
+}
+
+// 后端 ComparisonRecordOut → 横幅摘要(对齐原生 LastCompareSummary)。
+function lastCompareToSummary(rec) {
+ return {
+ shop: rec.store_name || '',
+ items: (rec.items || []).map(function (it) { return it && it.name; }).filter(Boolean),
+ bestPlatform: rec.best_platform_name || '',
+ bestPrice: rec.best_price_cents != null ? rec.best_price_cents / 100 : 0,
+ };
+}
+
+function fillLastCompareBanner(record) {
+ const banner = document.getElementById('lastCompareBanner');
+ if (!banner) return;
const shopEl = document.getElementById('lastCompareShop');
const dishEl = document.getElementById('lastCompareDish');
const ageEl = document.getElementById('lastCompareAge');
diff --git a/tests/test_h5_hosting.py b/tests/test_h5_hosting.py
index 4300299..b5e30c4 100644
--- a/tests/test_h5_hosting.py
+++ b/tests/test_h5_hosting.py
@@ -70,3 +70,19 @@ def test_h5_home_feed_wired(client) -> None:
assert "茶百道" not in body # 写死的 mock 卡(店名)已移除
assert "chabaidao.png" not in body # 写死的 mock 头图已移除
assert "比团购省 5.5 元" not in body # 随原生:mock 卡的「比团购省」标签已删(渲染只用 price_label/rank_label)
+
+
+def test_h5_home_last_compare_wired(client) -> None:
+ # 「上次比价」横幅改接真实 /api/v1/compare/records + 4 分钟新鲜窗口;原写死 mock 默认值已移除
+ resp = client.get("/h5/home/index.html")
+ assert resp.status_code == 200
+ body = resp.text
+ assert "/api/v1/compare/records" in body # 接真实比价记录端点
+ assert "pickFreshLastCompare" in body # 4 分钟新鲜窗口逻辑
+ assert "DEFAULT_LAST_COMPARE_RECORD" not in body # 写死 mock 默认已移除
+
+
+def test_compare_records_requires_auth(client) -> None:
+ # 横幅靠 Bearer token 才拿得到数据;无鉴权必须 401(无桥/未登录时横幅隐藏)
+ resp = client.get("/api/v1/compare/records?limit=5")
+ assert resp.status_code == 401