import { codeToText, regionData } from 'element-china-area-data'; export { regionData as CHINA_REGION_OPTIONS }; export type ProvinceCityOption = { value: string; label: string; children?: Array<{ value: string; label: string }>; }; /** 省 / 市二级(不含区县) */ export const PROVINCE_CITY_OPTIONS: ProvinceCityOption[] = regionData.map((province) => ({ value: province.value, label: province.label, children: province.children?.map((city) => ({ value: city.value, label: city.label, })), })); export type OpenCityRef = { id: string; name: string; code: string; partnerBindings?: Array<{ partnerAccountId: string }>; boundPartnerIds?: string[]; }; function cityBoundPartnerIds(city: OpenCityRef): string[] { if (city.boundPartnerIds?.length) return city.boundPartnerIds.map(String); return (city.partnerBindings ?? []).map((b) => String(b.partnerAccountId)); } export type ParsedChinaRegion = { province: string; city: string; district: string; provinceCode: string; cityCode: string; districtCode: string; }; export type ParsedProvinceCity = { province: string; city: string; provinceCode: string; cityCode: string; }; /** element-china-area-data 市级码(如 4101)→ 国标 6 位 adcode(410100) */ export function normalizeCityAdcode(code: string): string { const raw = code.trim(); if (/^\d{6}$/.test(raw)) return raw; if (/^\d{4}$/.test(raw)) return `${raw}00`; if (/^\d{2}$/.test(raw)) return `${raw}0100`; return raw.padEnd(6, '0').slice(0, 6); } export function parseProvinceCityCodes(codes?: string[]): ParsedProvinceCity | null { if (!codes || codes.length < 2) return null; const [provinceCode, cityCode] = codes; const province = codeToText[provinceCode]; let city = codeToText[cityCode]; if (!province || !city) return null; if (city === '市辖区' || city === '县' || city === '省直辖县级行政区划') { city = province.endsWith('市') ? province : city; } return { province, city, provinceCode, cityCode: normalizeCityAdcode(cityCode), }; } /** 区县 adcode → 地级市 adcode(如 410105 → 410100) */ export function districtCodeToCityCode(districtCode: string): string { if (districtCode.length < 6) return districtCode; return `${districtCode.slice(0, 4)}00`; } export type DistrictOption = { value: string; label: string }; /** 按开城城市 code(4 位或 6 位)取该市下区县列表 */ export function getDistrictOptionsByCityCode(cityCode?: string | null): DistrictOption[] { if (!cityCode?.trim()) return []; const normalized = normalizeCityAdcode(cityCode.trim()); const prefix4 = normalized.slice(0, 4); for (const province of regionData) { for (const city of province.children ?? []) { const cityValue = String(city.value); const cityNorm = normalizeCityAdcode(cityValue); if (cityNorm === normalized || cityValue === prefix4 || cityValue === cityCode.trim()) { return (city.children ?? []).map((d) => ({ value: String(d.value), label: String(d.label), })); } } } return []; } export function districtCodeLabel(code: string): string { return codeToText[code] || code; } /** 列表展示:区县码 → 中文名,顿号拼接 */ export function formatDistrictLabels(codes?: string[] | null): string { if (!codes?.length) return '—'; return codes.map((c) => districtCodeLabel(String(c))).join('、'); } 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, partnerAccountId?: string, ): string | undefined { const cityCode = districtCodeToCityCode(districtCode); const scoped = partnerAccountId ? cities.filter((c) => cityBoundPartnerIds(c).includes(String(partnerAccountId))) : 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[], partnerAccountId?: string, ) { const region = parseRegionCodes(codes); if (!region) return null; const cityId = matchOpenCityId(cities, region.districtCode, partnerAccountId); const matchedCity = cityId ? cities.find((c) => c.id === cityId) : undefined; return { region, cityId, matchedCity, cityCode: districtCodeToCityCode(region.districtCode), }; }