修复匹配详情中“用户自填未经核验”等来源说明,清理未参与项的橙色注意提示,修正贷款统计口径文案;补充公积金完整可选路径提取逻辑,确保明确无额外时长要求的公积金分支可正确识别并通过。
74 lines
3.7 KiB
Python
74 lines
3.7 KiB
Python
"""从版本化选择字典生成前后端城市数据;不下载、不修改生产配置。"""
|
|
import argparse
|
|
import json
|
|
import re
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--backend', type=Path, required=True)
|
|
parser.add_argument('--check', action='store_true')
|
|
args = parser.parse_args()
|
|
data = json.loads((ROOT / 'docs/data/city-options.json').read_text(encoding='utf-8'))
|
|
regions = data['regions']
|
|
names = [city['name'] for region in regions for city in region['cities']]
|
|
codes = {city['code']: city['name'] for region in regions for city in region['cities'] if city['code']}
|
|
assert len(names) == len(set(names)), '城市名称不能歧义'
|
|
assert len(codes) == sum(bool(city['code']) for region in regions for city in region['cities']), '代码重复'
|
|
assert all(re.fullmatch(r'\d{6}', code) for code in codes)
|
|
uts = "// 由 scripts/generate-city-options.py 生成;来源和覆盖口径见 docs/data/city-options.json。\n"
|
|
uts += "export type CityOption = { name: string, code: string }\nexport type CityRegion = { name: string, cities: CityOption[] }\n"
|
|
uts += "export const cityRegions: CityRegion[] = [\n"
|
|
uts += ',\n'.join(' ' + json.dumps(region, ensure_ascii=False) for region in regions) + '\n]\n'
|
|
provinces = {str(index['code']) + '0000': index['name'] for index in data['provinces']}
|
|
uts += 'export const provinceOptions: CityOption[] = ' + json.dumps([{'name':name,'code':code} for code,name in provinces.items()],ensure_ascii=False) + '\n'
|
|
uts += '''
|
|
export const citySelection = (name: string): number[] => {
|
|
for (let province = 0; province < cityRegions.length; province++) {
|
|
const cities = cityRegions[province].cities
|
|
for (let city = 0; city < cities.length; city++) {
|
|
if (cities[city].name == name) return [province, city]
|
|
}
|
|
}
|
|
return [-1, -1]
|
|
}
|
|
|
|
export const cityCodeForName = (name: string): string | null => {
|
|
const selected = citySelection(name)
|
|
if (selected[0] < 0) return null
|
|
const code = cityRegions[selected[0]].cities[selected[1]].code
|
|
return code.length > 0 ? code : null
|
|
}
|
|
|
|
export const cityDisplayName = (name: string): string => {
|
|
const selected = citySelection(name)
|
|
if (selected[0] < 0) return name
|
|
const province = cityRegions[selected[0]].name
|
|
return province == name ? name : province + ' / ' + name
|
|
}
|
|
|
|
export const provinceCodeForName = (name: string): string | null => {
|
|
const index = provinceOptions.findIndex((item: CityOption): boolean => item.name == name)
|
|
return index < 0 ? null : provinceOptions[index].code
|
|
}
|
|
|
|
// 仅供历史城市资料回填为省份;未知名称不猜测。
|
|
export const provinceForCity = (name: string): string => {
|
|
if (provinceCodeForName(name) != null) return name
|
|
const selected = citySelection(name)
|
|
return selected[0] < 0 ? '' : cityRegions[selected[0]].name
|
|
}
|
|
'''
|
|
constant = ' const PROVINCES = [\n' + '\n'.join(" '%s' => '%s'," % (code, name) for code,name in provinces.items()) + '\n ];\n'
|
|
backend = args.backend / 'application/common/library/AssessmentRecords.php'
|
|
original = backend.read_text(encoding='utf-8')
|
|
php, replacements = re.subn(r' const PROVINCES = .*?;\n', lambda _: constant, original, count=1, flags=re.S)
|
|
if not replacements:
|
|
php = original.replace(' private static function only(', constant + '\n private static function only(',1)
|
|
for path, content in [(ROOT / 'services/cities.uts', uts), (backend, php)]:
|
|
if args.check:
|
|
assert path.read_text(encoding='utf-8') == content, f'生成文件不同步:{path}'
|
|
else:
|
|
path.write_text(content, encoding='utf-8', newline='\n')
|
|
print(f'{len(provinces)} province choices; legacy city lookup retained; ' + ('consistent' if args.check else 'generated'))
|