小程序优化,商铺定位等
This commit is contained in:
@@ -17,8 +17,15 @@ import {
|
||||
type RegionSelection,
|
||||
} from '../../lib/region-data';
|
||||
import UserTabBar, { shouldRenderPageTabBar, syncTabBarSelected } from '../../components/UserTabBar';
|
||||
import { getCityCodeForCatalog, resolveUserCity } from '../../lib/user-location';
|
||||
import {
|
||||
getCityCodeForCatalog,
|
||||
readCachedUserCoords,
|
||||
resolveUserCity,
|
||||
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';
|
||||
|
||||
type Store = {
|
||||
@@ -37,10 +44,11 @@ type Store = {
|
||||
status?: string;
|
||||
categoryId?: string | null;
|
||||
category?: { id?: string; name?: string; parentId?: string | null } | null;
|
||||
latitude?: number | string | null;
|
||||
longitude?: number | string | null;
|
||||
distanceMeters?: number | null;
|
||||
};
|
||||
|
||||
const MOCK_DISTANCES = ['800m', '1.2km', '3.5km', '1.5km', '2.0km'];
|
||||
|
||||
export default function StoresPage() {
|
||||
const [stores, setStores] = useState<Store[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
@@ -52,6 +60,7 @@ export default function StoresPage() {
|
||||
const [categoryOpen, setCategoryOpen] = useState(false);
|
||||
const [categoryTree, setCategoryTree] = useState<StoreCategoryNode[]>([]);
|
||||
const [cityCode, setCityCode] = useState<string>(FALLBACK_CITY_CODE);
|
||||
const [userCoords, setUserCoords] = useState<UserCoords | null>(() => readCachedUserCoords());
|
||||
const regionLabel = formatRegionLabel(region);
|
||||
const categoryLabel = formatCategoryLabel(category);
|
||||
|
||||
@@ -69,8 +78,9 @@ export default function StoresPage() {
|
||||
useDidShow(() => {
|
||||
syncTabBarSelected(1);
|
||||
void resolveUserCity().then((resolved) => {
|
||||
setRegion(resolved.region);
|
||||
setRegion(toCityWideRegion(resolved.region));
|
||||
setCityCode(getCityCodeForCatalog(resolved));
|
||||
setUserCoords(readCachedUserCoords());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -82,12 +92,19 @@ export default function StoresPage() {
|
||||
|
||||
const loadStores = useCallback(() => {
|
||||
setLoading(true);
|
||||
const path = cityCode ? `/stores?cityCode=${encodeURIComponent(cityCode)}` : '/stores';
|
||||
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<Store[]>(path)
|
||||
.then((list) => setStores(Array.isArray(list) ? list : []))
|
||||
.catch((e) => toast(e instanceof Error ? e.message : '加载失败'))
|
||||
.finally(() => setLoading(false));
|
||||
}, [cityCode]);
|
||||
}, [cityCode, userCoords]);
|
||||
|
||||
useEffect(() => {
|
||||
void loadStores();
|
||||
@@ -96,12 +113,20 @@ export default function StoresPage() {
|
||||
usePullDownRefresh(() => {
|
||||
void (async () => {
|
||||
try {
|
||||
const resolved = await resolveUserCity();
|
||||
setRegion(resolved.region);
|
||||
const resolved = await resolveUserCity(true);
|
||||
setRegion(toCityWideRegion(resolved.region));
|
||||
const nextCode = getCityCodeForCatalog(resolved);
|
||||
setCityCode(nextCode);
|
||||
const coords = readCachedUserCoords();
|
||||
setUserCoords(coords);
|
||||
setLoading(true);
|
||||
const path = nextCode ? `/stores?cityCode=${encodeURIComponent(nextCode)}` : '/stores';
|
||||
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<Store[]>(path);
|
||||
setStores(Array.isArray(list) ? list : []);
|
||||
} catch (e) {
|
||||
@@ -189,7 +214,7 @@ export default function StoresPage() {
|
||||
{loading ? <View className="u-empty">加载中…</View> : null}
|
||||
{!loading && filtered.length === 0 ? <View className="u-empty">暂无营业中门店</View> : null}
|
||||
{!loading &&
|
||||
filtered.map((s, index) => (
|
||||
filtered.map((s) => (
|
||||
<View
|
||||
key={s.id}
|
||||
className="store-card"
|
||||
@@ -211,7 +236,9 @@ export default function StoresPage() {
|
||||
<Text className="store-card-meta">人均¥{Number(s.avgPrice).toFixed(0)}</Text>
|
||||
) : null}
|
||||
<View className="store-card-footer">
|
||||
<Text className="store-card-distance">{MOCK_DISTANCES[index % MOCK_DISTANCES.length]}</Text>
|
||||
<Text className="store-card-distance">
|
||||
{formatDistanceMeters(s.distanceMeters)}
|
||||
</Text>
|
||||
<Text
|
||||
className="store-card-cta"
|
||||
onClick={(e) => {
|
||||
|
||||
Reference in New Issue
Block a user