15 changed files with 342 additions and 2042 deletions
File diff suppressed because it is too large
@ -1,138 +0,0 @@ |
|||||
[ |
|
||||
{ |
|
||||
"name": "北京市", |
|
||||
"id": "110000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "天津市", |
|
||||
"id": "120000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "河北省", |
|
||||
"id": "130000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "山西省", |
|
||||
"id": "140000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "内蒙古自治区", |
|
||||
"id": "150000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "辽宁省", |
|
||||
"id": "210000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "吉林省", |
|
||||
"id": "220000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "黑龙江省", |
|
||||
"id": "230000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "上海市", |
|
||||
"id": "310000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "江苏省", |
|
||||
"id": "320000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "浙江省", |
|
||||
"id": "330000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "安徽省", |
|
||||
"id": "340000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "福建省", |
|
||||
"id": "350000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "江西省", |
|
||||
"id": "360000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "山东省", |
|
||||
"id": "370000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "河南省", |
|
||||
"id": "410000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "湖北省", |
|
||||
"id": "420000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "湖南省", |
|
||||
"id": "430000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "广东省", |
|
||||
"id": "440000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "广西壮族自治区", |
|
||||
"id": "450000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "海南省", |
|
||||
"id": "460000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "重庆市", |
|
||||
"id": "500000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "四川省", |
|
||||
"id": "510000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "贵州省", |
|
||||
"id": "520000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "云南省", |
|
||||
"id": "530000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "西藏自治区", |
|
||||
"id": "540000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "陕西省", |
|
||||
"id": "610000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "甘肃省", |
|
||||
"id": "620000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "青海省", |
|
||||
"id": "630000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "宁夏回族自治区", |
|
||||
"id": "640000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "新疆维吾尔自治区", |
|
||||
"id": "650000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "台湾省", |
|
||||
"id": "710000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "香港特别行政区", |
|
||||
"id": "810000" |
|
||||
}, |
|
||||
{ |
|
||||
"name": "澳门特别行政区", |
|
||||
"id": "820000" |
|
||||
} |
|
||||
] |
|
||||
@ -0,0 +1,22 @@ |
|||||
|
import { request } from '@umijs/max'; |
||||
|
import { beforeEach, describe, expect, it, vi } from 'vitest'; |
||||
|
import { queryCity } from './service'; |
||||
|
|
||||
|
vi.mock('@umijs/max', () => ({ |
||||
|
request: vi.fn(), |
||||
|
})); |
||||
|
|
||||
|
describe('account settings service', () => { |
||||
|
beforeEach(() => { |
||||
|
vi.clearAllMocks(); |
||||
|
vi.mocked(request).mockResolvedValue({ data: [] }); |
||||
|
}); |
||||
|
|
||||
|
it('encodes province when requesting city options', async () => { |
||||
|
await queryCity('33/000?x=1'); |
||||
|
|
||||
|
expect(request).toHaveBeenCalledWith( |
||||
|
'/api/geographic/city/33%2F000%3Fx%3D1', |
||||
|
); |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,52 @@ |
|||||
|
import { describe, expect, it } from 'vitest'; |
||||
|
import { getCityOptions, provinceOptions } from './chinaDivision'; |
||||
|
|
||||
|
describe('chinaDivision geographic options', () => { |
||||
|
it('keeps province values compatible with existing six-digit province ids', () => { |
||||
|
expect(provinceOptions).toContainEqual({ |
||||
|
label: '浙江省', |
||||
|
key: '330000', |
||||
|
}); |
||||
|
expect(provinceOptions).toContainEqual({ |
||||
|
label: '台湾省', |
||||
|
key: '710000', |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
it('returns city options for ordinary provinces', () => { |
||||
|
expect(getCityOptions('130000')).toContainEqual({ |
||||
|
label: '石家庄市', |
||||
|
key: '130100', |
||||
|
}); |
||||
|
expect(getCityOptions('320000')).toContainEqual({ |
||||
|
label: '南京市', |
||||
|
key: '320100', |
||||
|
}); |
||||
|
expect(getCityOptions('32')).toContainEqual({ |
||||
|
label: '南京市', |
||||
|
key: '320100', |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
it('returns district options for municipalities', () => { |
||||
|
expect(getCityOptions('110000')).toContainEqual({ |
||||
|
label: '东城区', |
||||
|
key: '110101', |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
it('returns city options for Hong Kong, Macao and Taiwan', () => { |
||||
|
expect(getCityOptions('710000')).toContainEqual({ |
||||
|
label: '台北市', |
||||
|
key: '710100', |
||||
|
}); |
||||
|
expect(getCityOptions('810000')).toContainEqual({ |
||||
|
label: '香港岛', |
||||
|
key: '810100', |
||||
|
}); |
||||
|
expect(getCityOptions('820000')).toContainEqual({ |
||||
|
label: '澳门半岛', |
||||
|
key: '820100', |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,69 @@ |
|||||
|
import hkMoTwSource from 'china-division/dist/HK-MO-TW.json'; |
||||
|
import pcaSource from 'china-division/dist/pca-code.json'; |
||||
|
|
||||
|
export type GeographicOption = { |
||||
|
label: string; |
||||
|
key: string; |
||||
|
}; |
||||
|
|
||||
|
type DivisionNode = { |
||||
|
code: string; |
||||
|
name: string; |
||||
|
children?: DivisionNode[]; |
||||
|
}; |
||||
|
|
||||
|
const directAdminCodes = new Set(['11', '12', '31', '50']); |
||||
|
|
||||
|
const specialRegions: GeographicOption[] = [ |
||||
|
{ label: '台湾省', key: '710000' }, |
||||
|
{ label: '香港特别行政区', key: '810000' }, |
||||
|
{ label: '澳门特别行政区', key: '820000' }, |
||||
|
]; |
||||
|
|
||||
|
const toProvinceKey = (code: string) => `${code}0000`; |
||||
|
|
||||
|
const toCityKey = (code: string) => (code.length === 4 ? `${code}00` : code); |
||||
|
|
||||
|
const toOption = (item: DivisionNode): GeographicOption => ({ |
||||
|
label: item.name, |
||||
|
key: toCityKey(item.code), |
||||
|
}); |
||||
|
|
||||
|
export const provinceOptions: GeographicOption[] = [ |
||||
|
...(pcaSource as DivisionNode[]).map((item) => ({ |
||||
|
label: item.name, |
||||
|
key: toProvinceKey(item.code), |
||||
|
})), |
||||
|
...specialRegions, |
||||
|
]; |
||||
|
|
||||
|
export const getCityOptions = (provinceKey: string): GeographicOption[] => { |
||||
|
const provinceCode = |
||||
|
provinceKey.length === 2 ? provinceKey : provinceKey.slice(0, 2); |
||||
|
const province = (pcaSource as DivisionNode[]).find( |
||||
|
(item) => item.code === provinceCode, |
||||
|
); |
||||
|
|
||||
|
if (province) { |
||||
|
const children = province.children ?? []; |
||||
|
const cityNodes = directAdminCodes.has(provinceCode) |
||||
|
? children.flatMap((item) => item.children ?? [item]) |
||||
|
: children; |
||||
|
|
||||
|
return cityNodes.map(toOption); |
||||
|
} |
||||
|
|
||||
|
const specialRegion = specialRegions.find((item) => item.key === provinceKey); |
||||
|
if (!specialRegion) { |
||||
|
return []; |
||||
|
} |
||||
|
|
||||
|
return Object.keys( |
||||
|
(hkMoTwSource as Record<string, Record<string, string[]>>)[ |
||||
|
specialRegion.label |
||||
|
] ?? {}, |
||||
|
).map((name, index) => ({ |
||||
|
label: name, |
||||
|
key: `${provinceCode}${String(index + 1).padStart(2, '0')}00`, |
||||
|
})); |
||||
|
}; |
||||
Loading…
Reference in new issue