feat(trade): v4.0.13 收货禁全市与小飞侠拒单可感知
CI / verify (push) Has been cancelled

拦截伪区县写入与下单;推单失败挂 fulfillmentHold,HQ 可见超区/推单失败。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-02 17:20:40 +08:00
parent 63fcf33416
commit c6b01def4c
18 changed files with 613 additions and 76 deletions
+55 -13
View File
@@ -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();
}