90 lines
3.0 KiB
JavaScript
90 lines
3.0 KiB
JavaScript
/**
|
|
* 行政区划展示格式化(仅展示层,不改动后端存储值)。
|
|
*
|
|
* 需求:省 / 市 / 区县之间要有空格隔开,避免「上海市浦东新区」「广西壮族自治区南宁市邕宁区」挤成一坨。
|
|
* 与全站既有规则保持一致(公路地址按「市 区县」展示,省/自治区不重复展示):
|
|
* 上海市浦东新区 -> 上海市 浦东新区
|
|
* 广西壮族自治区南宁市邕宁区 -> 南宁市 邕宁区
|
|
* 梅州市梅县区 -> 梅州市 梅县区
|
|
*
|
|
* 非纯行政区划串(站点名「南宁站」「广州南站」、含街道门牌的详细地址等)原样返回,不做任何改动。
|
|
*/
|
|
|
|
// 行政区划后缀:长后缀在前,避免「自治区」被截成「区」、「自治州」被截成「州」
|
|
const REGION_SUFFIXES = [
|
|
'特别行政区',
|
|
'自治区',
|
|
'自治州',
|
|
'自治县',
|
|
'自治旗',
|
|
'开发区',
|
|
'新区',
|
|
'林区',
|
|
'矿区',
|
|
'地区',
|
|
'省',
|
|
'市',
|
|
'州',
|
|
'盟',
|
|
'区',
|
|
'县',
|
|
'旗',
|
|
];
|
|
|
|
// 省级区划:展示时不在区划链首重复(「广西壮族自治区南宁市邕宁区」-> 「南宁市 邕宁区」)
|
|
const PROVINCE_SUFFIX = /(?:省|自治区|特别行政区)$/;
|
|
|
|
/**
|
|
* 从文本头部匹配第一个行政区划片段。
|
|
* 特例:「梅州市」州后紧跟市,并入同一片段;「梅县区」县/旗后紧跟区,并入同一片段。
|
|
* @param {string} text 已去除空白的文本
|
|
* @returns {string} 片段,未匹配到返回 ''
|
|
*/
|
|
function matchRegionToken(text) {
|
|
for (let end = 0; end < text.length; end += 1) {
|
|
const prefix = text.slice(0, end + 1);
|
|
const suffix = REGION_SUFFIXES.find(item => prefix.endsWith(item));
|
|
if (!suffix) continue;
|
|
const next = text[end + 1] || '';
|
|
if ((suffix === '州' || suffix === '盟') && next === '市') continue;
|
|
if ((suffix === '县' || suffix === '旗') && next === '区') return text.slice(0, end + 2);
|
|
return prefix;
|
|
}
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* 按行政区划后缀把文本切成区划片段。
|
|
* @param {string} value 原值
|
|
* @returns {string[]|null} 整串都是行政区划时返回片段数组,否则返回 null
|
|
*/
|
|
export function splitRegionTokens(value) {
|
|
const text = String(value ?? '').replace(/\s+/g, '');
|
|
if (!text) return null;
|
|
const tokens = [];
|
|
let rest = text;
|
|
while (rest) {
|
|
const token = matchRegionToken(rest);
|
|
if (!token) return null;
|
|
tokens.push(token);
|
|
rest = rest.slice(token.length);
|
|
}
|
|
return tokens;
|
|
}
|
|
|
|
/**
|
|
* 行政区划串按「市 区县」展示,省/自治区不重复展示。
|
|
* @param {string} value 原值
|
|
* @returns {string} 含空格的展示值;非纯行政区划串原样返回
|
|
*/
|
|
export function formatRegionAddress(value) {
|
|
const text = String(value ?? '').trim();
|
|
if (!text) return '';
|
|
const tokens = splitRegionTokens(text);
|
|
if (!tokens || !tokens.length) return text;
|
|
const display = PROVINCE_SUFFIX.test(tokens[0]) ? tokens.slice(1) : tokens;
|
|
return (display.length ? display : tokens).join(' ');
|
|
}
|
|
|
|
export default formatRegionAddress;
|