定位获取城市功能,需要微信地图的key?
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import AppImage from '@dukang/shared-ui/AppImage';
|
||||
import { request } from '../lib/api';
|
||||
@@ -7,10 +7,12 @@ import TabMainHeader from '../components/TabMainHeader';
|
||||
import RegionPicker from '../components/RegionPicker';
|
||||
import {
|
||||
DEFAULT_REGION,
|
||||
FALLBACK_CITY_REGION,
|
||||
formatRegion,
|
||||
REGION_ALL,
|
||||
type RegionSelection,
|
||||
} from '../lib/region-data';
|
||||
import { FALLBACK_CITY_CODE, resolveUserCity } from '../lib/wechat-location';
|
||||
|
||||
type OpenCity = {
|
||||
code: string;
|
||||
@@ -62,6 +64,9 @@ export default function StoreListPage() {
|
||||
const [keyword, setKeyword] = useState('');
|
||||
const [region, setRegion] = useState<RegionSelection>(DEFAULT_REGION);
|
||||
const [regionPickerOpen, setRegionPickerOpen] = useState(false);
|
||||
const [filterMode, setFilterMode] = useState<'auto' | 'manual'>('auto');
|
||||
const [usedFallback, setUsedFallback] = useState(false);
|
||||
const [geoReady, setGeoReady] = useState(false);
|
||||
|
||||
const cityCode = useMemo(() => resolveCityCode(region, cities), [region, cities]);
|
||||
|
||||
@@ -74,15 +79,45 @@ export default function StoreListPage() {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (filterMode !== 'auto' || geoReady) return;
|
||||
resolveUserCity().then((resolved) => {
|
||||
if (resolved) {
|
||||
setRegion(resolved.region);
|
||||
}
|
||||
setGeoReady(true);
|
||||
});
|
||||
}, [filterMode, geoReady]);
|
||||
|
||||
const fetchStores = useCallback(
|
||||
async (targetRegion: RegionSelection, allowFallback: boolean) => {
|
||||
const code = resolveCityCode(targetRegion, cities);
|
||||
const qs = code ? `?cityCode=${encodeURIComponent(code)}` : '';
|
||||
const data = await request<StoreItem[]>('USER_H5', `/stores${qs}`).catch(() => [] as StoreItem[]);
|
||||
|
||||
if (
|
||||
allowFallback &&
|
||||
filterMode === 'auto' &&
|
||||
data.length === 0 &&
|
||||
!usedFallback &&
|
||||
code &&
|
||||
code !== FALLBACK_CITY_CODE
|
||||
) {
|
||||
setUsedFallback(true);
|
||||
setRegion(FALLBACK_CITY_REGION);
|
||||
return null;
|
||||
}
|
||||
return data;
|
||||
},
|
||||
[cities, filterMode, usedFallback],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (filterMode === 'auto' && !geoReady) return;
|
||||
let cancelled = false;
|
||||
setLoading(true);
|
||||
const qs = cityCode ? `?cityCode=${encodeURIComponent(cityCode)}` : '';
|
||||
request<StoreItem[]>('USER_H5', `/stores${qs}`)
|
||||
fetchStores(region, true)
|
||||
.then((data) => {
|
||||
if (!cancelled) setStores(data);
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) setStores([]);
|
||||
if (!cancelled && data) setStores(data);
|
||||
})
|
||||
.finally(() => {
|
||||
if (!cancelled) setLoading(false);
|
||||
@@ -90,7 +125,7 @@ export default function StoreListPage() {
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [cityCode]);
|
||||
}, [region, cities, filterMode, geoReady, fetchStores, usedFallback]);
|
||||
|
||||
const filtered = useMemo(() => {
|
||||
let list = stores;
|
||||
@@ -122,6 +157,10 @@ export default function StoreListPage() {
|
||||
}, [stores, categoryTab, keyword, region, cityCode]);
|
||||
|
||||
const regionLabel = formatRegion(region.province, region.city, region.district);
|
||||
const emptyMessage =
|
||||
filterMode === 'manual' && filtered.length === 0
|
||||
? '未找到匹配门店'
|
||||
: '暂无门店';
|
||||
|
||||
return (
|
||||
<div className="page store-page">
|
||||
@@ -144,7 +183,10 @@ export default function StoreListPage() {
|
||||
type="search"
|
||||
placeholder="搜索门店名称或地址"
|
||||
value={keyword}
|
||||
onChange={(e) => setKeyword(e.target.value)}
|
||||
onChange={(e) => {
|
||||
setFilterMode('manual');
|
||||
setKeyword(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -156,7 +198,10 @@ export default function StoreListPage() {
|
||||
key={tab}
|
||||
type="button"
|
||||
className={`store-category-tab${categoryTab === tab ? ' active' : ''}`}
|
||||
onClick={() => setCategoryTab(tab)}
|
||||
onClick={() => {
|
||||
setFilterMode('manual');
|
||||
setCategoryTab(tab);
|
||||
}}
|
||||
>
|
||||
{tab}
|
||||
</button>
|
||||
@@ -215,7 +260,7 @@ export default function StoreListPage() {
|
||||
))}
|
||||
|
||||
{!loading && filtered.length === 0 && (
|
||||
<div className="store-empty">{stores.length === 0 ? '暂无门店' : '未找到匹配门店'}</div>
|
||||
<div className="store-empty">{emptyMessage}</div>
|
||||
)}
|
||||
|
||||
{!loading && filtered.length > 0 && (
|
||||
@@ -228,6 +273,7 @@ export default function StoreListPage() {
|
||||
value={region}
|
||||
onClose={() => setRegionPickerOpen(false)}
|
||||
onConfirm={(next) => {
|
||||
setFilterMode('manual');
|
||||
setRegion(next);
|
||||
setRegionPickerOpen(false);
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user