From e742f1e88b7bfe9d0c51ff1529f655f1e399502b Mon Sep 17 00:00:00 2001 From: jacy <18049821889@163.com> Date: Wed, 29 Jul 2026 11:56:40 +0800 Subject: [PATCH] fix(mini-user): locate before store list fetch; prefer masked phone on mine Resolve city once then fetch stores once; skip refetch when city unchanged. Show masked phone under nickname when available. Co-authored-by: Cursor --- apps/mini-user/src/pages/mine/index.tsx | 13 +-- apps/mini-user/src/pages/stores/index.tsx | 99 +++++++++++++---------- 2 files changed, 64 insertions(+), 48 deletions(-) diff --git a/apps/mini-user/src/pages/mine/index.tsx b/apps/mini-user/src/pages/mine/index.tsx index 9cbe707..c689b3e 100644 --- a/apps/mini-user/src/pages/mine/index.tsx +++ b/apps/mini-user/src/pages/mine/index.tsx @@ -351,11 +351,14 @@ export default function MinePage() { const needProfileFill = isWeapp && needsWxProfileFill(display); const avatarProfileReady = isWeapp ? !needProfileFill : hasWechat; const maskedPhone = profile?.phone ? maskPhone(String(profile.phone)) : ''; - const memberLabel = needProfileFill - ? '点击头像完善资料' - : !isWeapp && !hasWechat && canWxAuth - ? '点击头像授权' - : maskedPhone || '未绑定手机'; + // 昵称下优先展示脱敏手机号;无手机号时再提示完善资料/授权 + const memberLabel = + maskedPhone || + (needProfileFill + ? '点击头像完善资料' + : !isWeapp && !hasWechat && canWxAuth + ? '点击头像授权' + : '未绑定手机'); const avatarClickable = isWeapp || (!hasWechat && canWxAuth); const previewAvatar = draftAvatarUrl || display.avatarUrl; diff --git a/apps/mini-user/src/pages/stores/index.tsx b/apps/mini-user/src/pages/stores/index.tsx index 883aecd..c77d443 100644 --- a/apps/mini-user/src/pages/stores/index.tsx +++ b/apps/mini-user/src/pages/stores/index.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useEffect, useMemo, useRef, useState } from 'react'; import { View, Text, Image, Input } from '@tarojs/components'; import Taro, { useDidShow, usePullDownRefresh, useShareAppMessage, useShareTimeline } from '@tarojs/taro'; import PageShell from '../../components/PageShell'; @@ -25,7 +25,6 @@ import { toCityWideRegion, type UserCoords, } from '../../lib/user-location'; -import { FALLBACK_CITY_CODE } from '../../lib/product-images'; import { formatDistanceMeters } from '../../lib/geo'; import { request, toast } from '../../lib/api'; import { @@ -55,6 +54,10 @@ type Store = { distanceMeters?: number | null; }; +function regionEqual(a: RegionSelection, b: RegionSelection): boolean { + return a.province === b.province && a.city === b.city && a.district === b.district; +} + export default function StoresPage() { const [stores, setStores] = useState([]); const [loading, setLoading] = useState(true); @@ -65,8 +68,9 @@ export default function StoresPage() { const [category, setCategory] = useState(EMPTY_CATEGORY); const [categoryOpen, setCategoryOpen] = useState(false); const [categoryTree, setCategoryTree] = useState([]); - const [cityCode, setCityCode] = useState(FALLBACK_CITY_CODE); - const [userCoords, setUserCoords] = useState(() => readCachedUserCoords()); + /** 上次已用于请求的城市编码;仅换城才再拉列表 */ + const cityCodeRef = useRef(null); + const fetchSeqRef = useRef(0); const regionLabel = formatRegionLabel(region); const categoryLabel = formatCategoryLabel(category); @@ -81,13 +85,51 @@ export default function StoresPage() { return map; }, [categoryTree]); + /** 按城市拉门店;coords 仅用于排序距离,不单独触发二次请求 */ + async function fetchStores(nextCode: string, coords: UserCoords | null) { + const seq = ++fetchSeqRef.current; + setLoading(true); + const qs = new URLSearchParams(); + if (nextCode) qs.set('cityCode', nextCode); + if (coords) { + qs.set('lat', String(coords.latitude)); + qs.set('lng', String(coords.longitude)); + } + const path = qs.toString() ? `/stores?${qs}` : '/stores'; + try { + const list = await request(path); + if (seq !== fetchSeqRef.current) return; + setStores(Array.isArray(list) ? list : []); + } catch (e) { + if (seq !== fetchSeqRef.current) return; + toast(e instanceof Error ? e.message : '加载失败'); + } finally { + if (seq === fetchSeqRef.current) setLoading(false); + } + } + + /** + * 流程:先定位 → 再请求一次列表(成功用定位城市,失败用默认城市)。 + * 再次进入页且城市未变:不重复请求,避免列表闪烁。 + */ useDidShow(() => { syncTabBarSelected(1); - void resolveUserCity().then((resolved) => { - setRegion(toCityWideRegion(resolved.region)); - setCityCode(getCityCodeForCatalog(resolved)); - setUserCoords(readCachedUserCoords()); - }); + void (async () => { + const resolved = await resolveUserCity(); + const nextCode = getCityCodeForCatalog(resolved); + const nextCoords = readCachedUserCoords(); + const nextRegion = toCityWideRegion(resolved.region); + const cityChanged = cityCodeRef.current !== nextCode; + + setRegion((prev) => (regionEqual(prev, nextRegion) ? prev : nextRegion)); + + if (cityCodeRef.current == null || cityChanged) { + cityCodeRef.current = nextCode; + await fetchStores(nextCode, nextCoords); + return; + } + setLoading(false); + })(); }); useEffect(() => { @@ -96,49 +138,20 @@ export default function StoresPage() { .catch(() => setCategoryTree([])); }, []); - const loadStores = useCallback(() => { - setLoading(true); - const qs = new URLSearchParams(); - if (cityCode) qs.set('cityCode', cityCode); - const coords = userCoords ?? readCachedUserCoords(); - if (coords) { - qs.set('lat', String(coords.latitude)); - qs.set('lng', String(coords.longitude)); - } - const path = qs.toString() ? `/stores?${qs}` : '/stores'; - return request(path) - .then((list) => setStores(Array.isArray(list) ? list : [])) - .catch((e) => toast(e instanceof Error ? e.message : '加载失败')) - .finally(() => setLoading(false)); - }, [cityCode, userCoords]); - - useEffect(() => { - void loadStores(); - }, [loadStores]); - usePullDownRefresh(() => { void (async () => { try { const resolved = await resolveUserCity(true); - setRegion(toCityWideRegion(resolved.region)); const nextCode = getCityCodeForCatalog(resolved); - setCityCode(nextCode); + const nextRegion = toCityWideRegion(resolved.region); const coords = readCachedUserCoords(); - setUserCoords(coords); - setLoading(true); - const qs = new URLSearchParams(); - if (nextCode) qs.set('cityCode', nextCode); - if (coords) { - qs.set('lat', String(coords.latitude)); - qs.set('lng', String(coords.longitude)); - } - const path = qs.toString() ? `/stores?${qs}` : '/stores'; - const list = await request(path); - setStores(Array.isArray(list) ? list : []); + cityCodeRef.current = nextCode; + setRegion(nextRegion); + await fetchStores(nextCode, coords); } catch (e) { toast(e instanceof Error ? e.message : '加载失败'); - } finally { setLoading(false); + } finally { Taro.stopPullDownRefresh(); } })();