首页商品:对齐门店「当次会话」——首次进入 / 城市变化 / 登录态变化 / 下拉刷新才拉列表,切 Tab 不再重复请求;退出登录会清缓存。

核销成功时间:按 Asia/Shanghai 格式化为「2026年8月3日 13点45分」。
核销码编号:单行省略显示,双击复制(有「双击复制」提示)。
This commit is contained in:
2026-08-03 13:51:29 +08:00
parent ebd8c07147
commit 06cbcdeb9c
6 changed files with 185 additions and 30 deletions
+56 -24
View File
@@ -1,4 +1,4 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useCallback, useMemo, useRef, useState } from 'react';
import { View, Text, Image, Swiper, SwiperItem } from '@tarojs/components';
import Taro, {
useDidShow,
@@ -13,7 +13,12 @@ import CouponBadge from '../../components/CouponBadge';
import WechatShareReady from '../../components/WechatShareReady';
import UserTabBar, { shouldRenderPageTabBar, syncTabBarSelected } from '../../components/UserTabBar';
import { goLogin } from '../../lib/auth-nav';
import { isLoggedIn, request, toast } from '../../lib/api';
import { getToken, isLoggedIn, request, toast } from '../../lib/api';
import {
getHomeCatalogCache,
isHomeCatalogBootstrapped,
setHomeCatalogCache,
} from '../../lib/home-catalog-session';
import { ensurePayReady } from '../../lib/pay-ready';
import { capturePromoSceneAndTouchScan } from '../../lib/promo';
import { getProductMainImage } from '../../lib/product-images';
@@ -29,7 +34,6 @@ import {
DEFAULT_SHARE_TITLE,
toWeappShareMessage,
} from '../../lib/wechat-share';
type Product = {
id: string;
name: string;
@@ -110,35 +114,60 @@ export default function HomePage() {
});
}, []);
const loadProducts = useCallback(() => {
setLoading(true);
return request<Product[]>(`/catalog/products?cityCode=${encodeURIComponent(cityCode)}`)
.then((list) =>
setProducts(Array.isArray(list) ? list.map((p) => normalizeFulfillmentFlags(p)) : []),
)
.catch((e) => toast(e instanceof Error ? e.message : '加载失败'))
.finally(() => setLoading(false));
}, [cityCode]);
const applyProductList = useCallback((list: Product[], nextCode: string, authKey: string) => {
const normalized = Array.isArray(list) ? list.map((p) => normalizeFulfillmentFlags(p)) : [];
setProducts(normalized);
setHomeCatalogCache({ cityCode: nextCode, authKey, products: normalized });
}, []);
const fetchProducts = useCallback(
(nextCode: string, authKey: string) => {
setLoading(true);
return request<Product[]>(`/catalog/products?cityCode=${encodeURIComponent(nextCode)}`)
.then((list) => applyProductList(list, nextCode, authKey))
.catch((e) => toast(e instanceof Error ? e.message : '加载失败'))
.finally(() => setLoading(false));
},
[applyProductList],
);
/**
* 首次进入 / 城市或登录态变化:拉商品。
* 同次再切 tab:只同步选中态,不重复请求(对齐门店页)。
*/
useDidShow(() => {
syncTabBarSelected(0);
void capturePromoSceneAndTouchScan();
void loadMiniHome();
// 白名单商品按登录手机号过滤;登录后 switchTab 回首页不会卸载页面,须重新拉列表
void loadProducts();
void resolveUserCity().then((resolved) => {
setDisplayCity(resolved.displayCity);
setCityCode(getCityCodeForCatalog(resolved));
});
});
useEffect(() => {
void loadProducts();
}, [loadProducts]);
const authKey = getToken() || '';
void (async () => {
const resolved = await resolveUserCity();
const nextCode = getCityCodeForCatalog(resolved);
setDisplayCity(resolved.displayCity);
setCityCode(nextCode);
const cache = getHomeCatalogCache();
if (
isHomeCatalogBootstrapped() &&
cache &&
cache.cityCode === nextCode &&
cache.authKey === authKey &&
Array.isArray(cache.products)
) {
setProducts(cache.products as Product[]);
setLoading(false);
return;
}
await fetchProducts(nextCode, authKey);
})();
});
usePullDownRefresh(() => {
void (async () => {
try {
const authKey = getToken() || '';
const resolved = await resolveUserCity();
setDisplayCity(resolved.displayCity);
const nextCode = getCityCodeForCatalog(resolved);
@@ -148,7 +177,11 @@ export default function HomePage() {
request<Product[]>(`/catalog/products?cityCode=${encodeURIComponent(nextCode)}`),
loadMiniHome(),
]);
setProducts(Array.isArray(list) ? list.map((p) => normalizeFulfillmentFlags(p)) : []);
applyProductList(
Array.isArray(list) ? list : [],
nextCode,
authKey,
);
} catch (e) {
toast(e instanceof Error ? e.message : '加载失败');
} finally {
@@ -157,7 +190,6 @@ export default function HomePage() {
}
})();
});
function openProductDetail(id: string) {
Taro.navigateTo({ url: `/pages/product-detail/index?id=${id}` });
}