feat(store): 门店可见白名单(对齐商品)
HQ 可配置 visibilityWhitelistEnabled + 手机号;C 端公开门店列表/详情按登录手机号过滤;登录态变化后小程序重新拉门店列表。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -22,6 +22,8 @@ export type StoresSessionCategory = {
|
||||
export type StoresListCache = {
|
||||
cityKey: string;
|
||||
cityCode: string;
|
||||
/** 登录态指纹:token 变化时需重新拉取(白名单) */
|
||||
authKey: string;
|
||||
listRegion: StoresSessionRegion;
|
||||
items: unknown[];
|
||||
filterRegion: StoresSessionRegion;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { View, Text, Image } from '@tarojs/components';
|
||||
import Taro, { usePageScroll, useRouter, useShareAppMessage, useShareTimeline } from '@tarojs/taro';
|
||||
import Taro, { useDidShow, usePageScroll, useRouter, useShareAppMessage, useShareTimeline } from '@tarojs/taro';
|
||||
import PageShell from '../../components/PageShell';
|
||||
import PageNavBar from '../../components/PageNavBar';
|
||||
import ProductCarousel from '../../components/ProductCarousel';
|
||||
@@ -78,20 +78,15 @@ export default function StoreDetailPage() {
|
||||
setHeaderSolid(scrollTop > 100);
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
useDidShow(() => {
|
||||
if (!storeId) return;
|
||||
request<Store>(`/stores/${storeId}`)
|
||||
.then(setStore)
|
||||
.catch(() => {
|
||||
request<Store[]>('/stores')
|
||||
.then((list) => {
|
||||
const found = (Array.isArray(list) ? list : []).find((s) => s.id === storeId);
|
||||
if (found) setStore(found);
|
||||
else toast('门店不存在');
|
||||
})
|
||||
.catch((e) => toast(e instanceof Error ? e.message : '加载失败'));
|
||||
setStore(null);
|
||||
toast('门店不存在或暂不可见');
|
||||
});
|
||||
}, [storeId]);
|
||||
});
|
||||
|
||||
const sharePayload = useMemo(
|
||||
() => {
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
} from '../../lib/user-location';
|
||||
import { FALLBACK_CITY_CODE } from '../../lib/product-images';
|
||||
import { formatDistanceMeters } from '../../lib/geo';
|
||||
import { request, toast } from '../../lib/api';
|
||||
import { getToken, request, toast } from '../../lib/api';
|
||||
import {
|
||||
getStoresListCache,
|
||||
isStoresSessionBootstrapped,
|
||||
@@ -143,6 +143,7 @@ export default function StoresPage() {
|
||||
setStoresListCache({
|
||||
cityKey,
|
||||
cityCode: nextCode,
|
||||
authKey: getToken() || '',
|
||||
listRegion: toCityWideRegion(listRegion),
|
||||
items,
|
||||
filterRegion,
|
||||
@@ -160,12 +161,38 @@ export default function StoresPage() {
|
||||
|
||||
/**
|
||||
* 首次进入:弹窗 + 定位 + 拉列表。
|
||||
* 同次再切回:只同步 tab 选中态,不改筛选、不拉接口、不 setState。
|
||||
* 同次再切回:只同步 tab 选中态(登录态未变)。
|
||||
* 登录/退出后 token 变化:按缓存失效重新拉列表(白名单)。
|
||||
*/
|
||||
useDidShow(() => {
|
||||
syncTabBarSelected(1);
|
||||
|
||||
const authKey = getToken() || '';
|
||||
const cache = getStoresListCache();
|
||||
if (isStoresSessionBootstrapped()) {
|
||||
if (cache && (cache.authKey ?? '') === authKey) {
|
||||
return;
|
||||
}
|
||||
// 登录态变了:保留筛选,重新拉列表
|
||||
void (async () => {
|
||||
setLoading(true);
|
||||
const nextCode = cache?.cityCode || FALLBACK_CITY_CODE;
|
||||
const listRegion = cache?.listRegion
|
||||
? {
|
||||
province: cache.listRegion.province,
|
||||
city: cache.listRegion.city,
|
||||
district: cache.listRegion.district || '全部',
|
||||
}
|
||||
: regionRef.current;
|
||||
const nextCityKey = cache?.cityKey || makeCityKey(listRegion);
|
||||
await fetchStores(
|
||||
nextCode,
|
||||
readCachedUserCoords(),
|
||||
nextCityKey,
|
||||
listRegion,
|
||||
regionRef.current,
|
||||
);
|
||||
})();
|
||||
return;
|
||||
}
|
||||
markStoresSessionBootstrapped();
|
||||
|
||||
Reference in New Issue
Block a user