Files
u-desktop/scripts/gen-cities.ps1
T
lxy efe54d6a41 新增: 天气城市扩展至全国地级市附生成脚本
- 城市列表由18个常用扩至386个地级市(和风LocationList地市级)
- 附 gen-cities.ps1 从源数据一键再生成, 支持双源下载
- 前端城市选择器由后端 citiesByProv 驱动, 无需改动
2026-10-03 10:19:33 +08:00

104 lines
4.7 KiB
PowerShell

$ErrorActionPreference = "Stop"
$csvPath = Join-Path $PSScriptRoot "china-cities.csv"
if (-not (Test-Path $csvPath)) {
Write-Host "下载城市数据 CSV..."
$urls = @(
"https://raw.githubusercontent.com/qwd/LocationList/master/China-City-List-latest.csv",
"https://cdn.jsdelivr.net/gh/qwd/LocationList@master/China-City-List-latest.csv"
)
$ok = $false
foreach ($u in $urls) {
try { Invoke-WebRequest -Uri $u -OutFile $csvPath -UseBasicParsing; Write-Host "OK: $u"; $ok = $true; break }
catch { Write-Host "失败: $($_.Exception.Message)" }
}
if (-not $ok) { Write-Host "CSV 下载失败"; exit 1 }
}
$provMap = @{
"北京市"="北京"; "天津市"="天津"; "上海市"="上海"; "重庆市"="重庆";
"河北省"="河北"; "山西省"="山西"; "辽宁省"="辽宁"; "吉林省"="吉林"; "黑龙江省"="黑龙江";
"江苏省"="江苏"; "浙江省"="浙江"; "安徽省"="安徽"; "福建省"="福建"; "江西省"="江西";
"山东省"="山东"; "河南省"="河南"; "湖北省"="湖北"; "湖南省"="湖南"; "广东省"="广东";
"海南省"="海南"; "四川省"="四川"; "贵州省"="贵州"; "云南省"="云南"; "陕西省"="陕西";
"甘肃省"="甘肃"; "青海省"="青海";
"内蒙古自治区"="内蒙古"; "广西壮族自治区"="广西"; "西藏自治区"="西藏"; "宁夏回族自治区"="宁夏"; "新疆维吾尔自治区"="新疆";
"香港特别行政区"="香港"; "澳门特别行政区"="澳门"; "台湾省"="台湾";
}
$fullMap = @{}
foreach ($k in $provMap.Keys) { $fullMap[$provMap[$k]] = $k }
$provOrder = @(
"北京","天津","上海","重庆",
"河北","山西","辽宁","吉林","黑龙江",
"江苏","浙江","安徽","福建","江西","山东",
"河南","湖北","湖南","广东","海南",
"四川","贵州","云南","陕西","甘肃","青海",
"内蒙古","广西","西藏","宁夏","新疆",
"香港","澳门","台湾"
)
# 解析 CSV(跳过第1行版本号)
$lines = Get-Content $csvPath -Encoding UTF8
$tempCsv = Join-Path $PSScriptRoot "_cities_temp.csv"
$lines[1..($lines.Length-1)] | Set-Content $tempCsv -Encoding UTF8
$csv = Import-Csv $tempCsv -Encoding UTF8
Remove-Item $tempCsv -Force
Write-Host "CSV 记录: $($csv.Count)"
# 按 Adm1 一次性分桶
$byAdm1 = @{}
foreach ($r in $csv) {
$a = $r.'Adm1_Name_ZH'
if (-not $byAdm1.ContainsKey($a)) { $byAdm1[$a] = New-Object System.Collections.ArrayList }
[void]$byAdm1[$a].Add($r)
}
$result = New-Object System.Collections.ArrayList
$weird = New-Object System.Collections.ArrayList
foreach ($provShort in $provOrder) {
$provFull = $fullMap[$provShort]
$rows = @()
if ($byAdm1.ContainsKey($provFull)) { $rows = @($byAdm1[$provFull]) }
if ($rows.Count -eq 0) {
foreach ($k in $byAdm1.Keys) { if ($k -like "*$provShort*") { $rows += @($byAdm1[$k]) } }
}
if ($rows.Count -eq 0) { Write-Host "省份未找到: $provShort"; continue }
# 按 Adm2 分组,每 Adm2 取 Location_ID 最小(地级市中心)
$adm2Groups = $rows | Group-Object 'Adm2_Name_ZH'
$cnt = 0
foreach ($g in $adm2Groups) {
if ($g.Name -match "省直辖|直辖县|县级行政区") {
[void]$weird.Add("$provShort/$($g.Name)"); continue
}
$center = $g.Group | Sort-Object Location_ID | Select-Object -First 1
# 过滤非数字 ID(台湾乡镇异常十六进制 ID,非和风标准 9 位)
if ($center.Location_ID -notmatch '^\d+$') {
[void]$weird.Add("$provShort/$($g.Name)/$($center.Location_ID)"); continue
}
# name 用 Adm2 名去末尾"市"/"特别行政区"(避免区名如"双桥",简化港澳)
$name = $g.Name -replace '市$','' -replace '特别行政区$',''
[void]$result.Add([pscustomobject]@{ id=$center.Location_ID; name=$name; adm1=$provShort })
$cnt++
}
Write-Host (" {0,-8} : {1} 城" -f $provShort, $cnt)
}
Write-Host ""
Write-Host "总计: $($result.Count) 城"
if ($weird.Count -gt 0) { Write-Host "已过滤 ($($weird.Count)): $($weird -join '; ')" }
# 输出
$utf8 = [System.Text.UTF8Encoding]::new($false)
[System.IO.File]::WriteAllText((Join-Path $PSScriptRoot "cities.json"), ($result | ConvertTo-Json -Depth 2), $utf8)
$goLines = $result | ForEach-Object { ' {"' + $_.id + '", "' + $_.name + '", "' + $_.name + '", "' + $_.adm1 + '"},' }
$goBlock = "var cities = []City{`n" + ($goLines -join "`n") + "`n}"
[System.IO.File]::WriteAllText((Join-Path $PSScriptRoot "cities.go.txt"), $goBlock, $utf8)
$vueLines = $result | ForEach-Object { " { id: '" + $_.id + "', name: '" + $_.name + "', province: '" + $_.adm1 + "' }," }
$vueBlock = "const allCities = [`n" + ($vueLines -join "`n") + "`n].map((c, i) => ({ ...c, _idx: i }))"
[System.IO.File]::WriteAllText((Join-Path $PSScriptRoot "cities.vue.txt"), $vueBlock, $utf8)
Write-Host "已生成: cities.json / cities.go.txt / cities.vue.txt"