import cityCodeJson from '@/utils/json/cityCode.json' /** 与平台 ruoyi-ui `utils/region.js` 逻辑一致 */ export function normalizeRegionTree(nodes) { if (!nodes || !nodes.length) { return [] } return nodes.map((node) => { const hasChildren = node.children && node.children.length > 0 const children = hasChildren ? normalizeRegionTree(node.children) : undefined const isDistrict = node.type === 3 const item = { code: node.code, name: node.name, type: node.type } if (children && children.length) { item.children = children } return item }) } export function findRegionPath(nodes, targetCode, path) { if (!nodes || !nodes.length || targetCode == null || targetCode === '') { return null } const target = String(targetCode) for (let i = 0; i < nodes.length; i++) { const node = nodes[i] const nextPath = (path || []).concat(node.code) if (String(node.code) === target) { return nextPath } if (node.children && node.children.length) { const found = findRegionPath(node.children, target, nextPath) if (found) { return found } } } return null } export function getRegionNamesByCodes(regionTree, codes) { const names = [] let nodes = regionTree for (let i = 0; i < codes.length; i++) { const code = codes[i] const node = (nodes || []).find((item) => String(item.code) === String(code)) if (!node) { break } names.push(node.name) nodes = node.children || [] } return names } export function findRegionNodeByCodes(regionTree, codes) { let nodes = regionTree let node = null for (let i = 0; i < codes.length; i++) { node = (nodes || []).find((item) => String(item.code) === String(codes[i])) if (!node) { return null } nodes = node.children || [] } return node } /** * 解析级联选择结果(须选至区县 type=3) * @returns {{ valid: boolean, code?: string, name?: string }} */ export function parseRegionSelection(regionTree, codes) { if (!codes || !codes.length) { return { valid: false } } const lastNode = findRegionNodeByCodes(regionTree, codes) if (!lastNode || lastNode.type !== 3) { return { valid: false } } const names = getRegionNamesByCodes(regionTree, codes) return { valid: true, code: String(codes[codes.length - 1]), name: names.join('/') } } /** 展示用:省/市/区 → 空格分隔 */ export function formatRegionDisplay(regionName) { return (regionName || '').replace(/\//g, ' ') } /** * 将 cityCode.json 转为三级树(与后端 RegionTreeVO 结构一致) */ export function convertCityCodeToRegionTree(cityCodeList) { return (cityCodeList || []).map((province) => { const provinceCode = String(province.code) const cities = (province.cityList || []).map((city) => { const cityCode = String(city.code) const areas = (city.areaList || []).map((area) => ({ code: String(area.code), name: area.name, type: 3 })) const cityNode = { code: cityCode, name: city.name, type: 2 } if (areas.length) { cityNode.children = areas } return cityNode }) const provinceNode = { code: provinceCode, name: province.name, type: 1 } if (cities.length) { provinceNode.children = cities } return provinceNode }) } let cachedRawTree = null let cachedCascaderTree = null function getRegionTreeFromCityCode() { if (!cachedRawTree) { cachedRawTree = convertCityCodeToRegionTree(cityCodeJson) } return cachedRawTree } /** 加载并缓存级联树(本地 cityCode.json,normalize 后供 up-cascader) */ export function loadRegionCascaderTree(force = false) { if (!force && cachedCascaderTree) { return Promise.resolve({ raw: cachedRawTree, cascader: cachedCascaderTree }) } cachedRawTree = getRegionTreeFromCityCode() cachedCascaderTree = normalizeRegionTree(cachedRawTree) return Promise.resolve({ raw: cachedRawTree, cascader: cachedCascaderTree }) }