拦截伪区县写入与下单;推单失败挂 fulfillmentHold,HQ 可见超区/推单失败。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -6,8 +6,10 @@ import {
|
||||
getCitiesForPicker,
|
||||
getDistricts,
|
||||
getDistrictsForPicker,
|
||||
getDistrictsForShippingPicker,
|
||||
getProvincesForPicker,
|
||||
normalizeRegionSelection,
|
||||
normalizeShippingRegionSelection,
|
||||
toCityLevelRegion,
|
||||
type RegionSelection,
|
||||
} from '../lib/region-data';
|
||||
@@ -18,6 +20,8 @@ type RegionPickerProps = {
|
||||
onClose: () => void;
|
||||
onConfirm: (region: RegionSelection) => void;
|
||||
levels?: 2 | 3;
|
||||
/** filter:门店筛选可「全市」;shipping:收货地址禁止伪区县 */
|
||||
mode?: 'filter' | 'shipping';
|
||||
};
|
||||
|
||||
type PickerLevel = 'province' | 'city' | 'district';
|
||||
@@ -28,8 +32,13 @@ const ALL_TABS: Array<{ key: PickerLevel; label: string }> = [
|
||||
{ key: 'district', label: '区县' },
|
||||
];
|
||||
|
||||
function initialTab(value: RegionSelection, levels: 2 | 3): PickerLevel {
|
||||
const normalized = levels === 2 ? toCityLevelRegion(value) : normalizeRegionSelection(value);
|
||||
function initialTab(value: RegionSelection, levels: 2 | 3, mode: 'filter' | 'shipping'): PickerLevel {
|
||||
const normalized =
|
||||
levels === 2
|
||||
? toCityLevelRegion(value)
|
||||
: mode === 'shipping'
|
||||
? normalizeShippingRegionSelection(value)
|
||||
: normalizeRegionSelection(value);
|
||||
if (levels === 2) {
|
||||
return normalized.province && normalized.province !== REGION_ALL ? 'city' : 'province';
|
||||
}
|
||||
@@ -54,24 +63,35 @@ export default function RegionPicker({
|
||||
onClose,
|
||||
onConfirm,
|
||||
levels = 3,
|
||||
mode = 'filter',
|
||||
}: RegionPickerProps) {
|
||||
const [draft, setDraft] = useState<RegionSelection>(value);
|
||||
const [activeTab, setActiveTab] = useState<PickerLevel>('province');
|
||||
|
||||
const tabs = levels === 2 ? ALL_TABS.slice(0, 2) : ALL_TABS;
|
||||
const shipping = mode === 'shipping';
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
const normalized = levels === 2 ? toCityLevelRegion(value) : normalizeRegionSelection(value);
|
||||
const normalized =
|
||||
levels === 2
|
||||
? toCityLevelRegion(value)
|
||||
: shipping
|
||||
? normalizeShippingRegionSelection(value)
|
||||
: normalizeRegionSelection(value);
|
||||
setDraft(normalized);
|
||||
setActiveTab(initialTab(value, levels));
|
||||
}, [open, value, levels]);
|
||||
setActiveTab(initialTab(value, levels, mode));
|
||||
}, [open, value, levels, mode, shipping]);
|
||||
|
||||
const listItems = useMemo(() => {
|
||||
if (activeTab === 'province') return getProvincesForPicker();
|
||||
if (activeTab === 'city') return getCitiesForPicker(draft.province);
|
||||
if (activeTab === 'city') {
|
||||
if (shipping) return getCities(draft.province);
|
||||
return getCitiesForPicker(draft.province);
|
||||
}
|
||||
if (shipping) return getDistrictsForShippingPicker(draft.province, draft.city);
|
||||
return getDistrictsForPicker(draft.province, draft.city);
|
||||
}, [activeTab, draft.province, draft.city]);
|
||||
}, [activeTab, draft.province, draft.city, shipping]);
|
||||
|
||||
const selectedValue =
|
||||
activeTab === 'province' ? draft.province : activeTab === 'city' ? draft.city : draft.district;
|
||||
@@ -79,12 +99,19 @@ export default function RegionPicker({
|
||||
const canConfirm =
|
||||
levels === 2
|
||||
? Boolean(draft.province && draft.city)
|
||||
: Boolean(draft.province && draft.city && draft.district);
|
||||
: shipping
|
||||
? Boolean(
|
||||
draft.province &&
|
||||
draft.city &&
|
||||
draft.district &&
|
||||
draft.district !== REGION_ALL,
|
||||
)
|
||||
: Boolean(draft.province && draft.city && draft.district);
|
||||
|
||||
if (!open) return null;
|
||||
|
||||
function selectProvince(province: string) {
|
||||
if (province === REGION_ALL) {
|
||||
if (!shipping && province === REGION_ALL) {
|
||||
setDraft({ province: REGION_ALL, city: REGION_ALL, district: REGION_ALL });
|
||||
setActiveTab('city');
|
||||
return;
|
||||
@@ -97,12 +124,16 @@ export default function RegionPicker({
|
||||
return;
|
||||
}
|
||||
const nextDistricts = getDistricts(province, city);
|
||||
setDraft({ province, city, district: nextDistricts[0] ?? '' });
|
||||
setDraft({
|
||||
province,
|
||||
city,
|
||||
district: shipping ? '' : (nextDistricts[0] ?? ''),
|
||||
});
|
||||
setActiveTab('city');
|
||||
}
|
||||
|
||||
function selectCity(city: string) {
|
||||
if (city === REGION_ALL) {
|
||||
if (!shipping && city === REGION_ALL) {
|
||||
setDraft({ ...draft, city: REGION_ALL, district: REGION_ALL });
|
||||
if (levels === 3) setActiveTab('district');
|
||||
return;
|
||||
@@ -112,11 +143,16 @@ export default function RegionPicker({
|
||||
return;
|
||||
}
|
||||
const nextDistricts = getDistricts(draft.province, city);
|
||||
setDraft({ ...draft, city, district: nextDistricts[0] ?? '' });
|
||||
setDraft({
|
||||
...draft,
|
||||
city,
|
||||
district: shipping ? '' : (nextDistricts[0] ?? ''),
|
||||
});
|
||||
setActiveTab('district');
|
||||
}
|
||||
|
||||
function selectDistrict(district: string) {
|
||||
if (shipping && district === REGION_ALL) return;
|
||||
setDraft({ ...draft, district });
|
||||
}
|
||||
|
||||
@@ -134,7 +170,13 @@ export default function RegionPicker({
|
||||
|
||||
function handleConfirm() {
|
||||
if (!canConfirm) return;
|
||||
const next = levels === 2 ? toCityLevelRegion(draft) : normalizeRegionSelection(draft);
|
||||
const next =
|
||||
levels === 2
|
||||
? toCityLevelRegion(draft)
|
||||
: shipping
|
||||
? normalizeShippingRegionSelection(draft)
|
||||
: normalizeRegionSelection(draft);
|
||||
if (shipping && (!next.district || next.district === REGION_ALL)) return;
|
||||
onConfirm(next);
|
||||
onClose();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user