77 lines
2.2 KiB
TypeScript
77 lines
2.2 KiB
TypeScript
import { codeToText, regionData } from 'element-china-area-data';
|
||
|
||
export { regionData as CHINA_REGION_OPTIONS };
|
||
|
||
export type OpenCityRef = {
|
||
id: string;
|
||
name: string;
|
||
code: string;
|
||
partnerId?: string | null;
|
||
partner?: { id: string };
|
||
};
|
||
|
||
export type ParsedChinaRegion = {
|
||
province: string;
|
||
city: string;
|
||
district: string;
|
||
provinceCode: string;
|
||
cityCode: string;
|
||
districtCode: string;
|
||
};
|
||
|
||
/** 区县 adcode → 地级市 adcode(如 410105 → 410100) */
|
||
export function districtCodeToCityCode(districtCode: string): string {
|
||
if (districtCode.length < 6) return districtCode;
|
||
return `${districtCode.slice(0, 4)}00`;
|
||
}
|
||
|
||
export function parseRegionCodes(codes?: string[]): ParsedChinaRegion | null {
|
||
if (!codes || codes.length < 3) return null;
|
||
const [provinceCode, cityCode, districtCode] = codes;
|
||
const province = codeToText[provinceCode];
|
||
const city = codeToText[cityCode];
|
||
const district = codeToText[districtCode];
|
||
if (!province || !city || !district) return null;
|
||
return { province, city, district, provinceCode, cityCode, districtCode };
|
||
}
|
||
|
||
export function formatRegionLabel(region: ParsedChinaRegion): string {
|
||
return `${region.province} / ${region.city} / ${region.district}`;
|
||
}
|
||
|
||
export function matchOpenCityId(
|
||
cities: OpenCityRef[],
|
||
districtCode: string,
|
||
partnerId?: string,
|
||
): string | undefined {
|
||
const cityCode = districtCodeToCityCode(districtCode);
|
||
const scoped = partnerId
|
||
? cities.filter((c) => {
|
||
const pid = c.partnerId ?? c.partner?.id;
|
||
return !pid || String(pid) === partnerId;
|
||
})
|
||
: cities;
|
||
return (
|
||
scoped.find((c) => c.code === cityCode)?.id
|
||
?? scoped.find((c) => c.code === districtCode)?.id
|
||
?? scoped.find((c) => districtCode.startsWith(c.code.slice(0, 4)))?.id
|
||
);
|
||
}
|
||
|
||
export function resolveRegionBinding(
|
||
codes: string[],
|
||
cities: OpenCityRef[],
|
||
partnerId?: string,
|
||
) {
|
||
const region = parseRegionCodes(codes);
|
||
if (!region) return null;
|
||
const cityId = matchOpenCityId(cities, region.districtCode, partnerId);
|
||
const matchedCity = cityId ? cities.find((c) => c.id === cityId) : undefined;
|
||
return {
|
||
region,
|
||
cityId,
|
||
matchedCity,
|
||
cityCode: districtCodeToCityCode(region.districtCode),
|
||
};
|
||
}
|