🐛 补充提交遗漏的 region-address 与 route-change 工具文件

This commit is contained in:
2026-10-14 13:06:09 +08:00
parent 74780b8777
commit 749b314ceb
2 changed files with 118 additions and 0 deletions
+89
View File
@@ -0,0 +1,89 @@
/**
* 行政区划展示格式化(仅展示层,不改动后端存储值)。
*
* 需求:省 / 市 / 区县之间要有空格隔开,避免「上海市浦东新区」「广西壮族自治区南宁市邕宁区」挤成一坨。
* 与全站既有规则保持一致(公路地址按「市 区县」展示,省/自治区不重复展示):
* 上海市浦东新区 -> 上海市 浦东新区
* 广西壮族自治区南宁市邕宁区 -> 南宁市 邕宁区
* 梅州市梅县区 -> 梅州市 梅县区
*
* 非纯行政区划串(站点名「南宁站」「广州南站」、含街道门牌的详细地址等)原样返回,不做任何改动。
*/
// 行政区划后缀:长后缀在前,避免「自治区」被截成「区」、「自治州」被截成「州」
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;
+29
View File
@@ -0,0 +1,29 @@
/**
* 路线变更记录内容格式化
*
* 存储格式(单行):
* YD-20260904-0022:发货地 A → B;到货地 C → D;YD-20260904-0025:发货地 E → F;到货地 G → H
*
* 展示格式(变更前 / 变更后分行):
* YD-20260904-0022:发货地 A →
* B
* 到货地 C →
* D
*
* 说明:仅用于展示层,不改变已存储的 content 文本(历史数据同样适用)。
*/
export const formatRouteChangeContent = (content, emptyText = '-') => {
if (content === undefined || content === null) return emptyText;
const text = String(content).trim();
if (!text) return emptyText;
return text
.replace(/\r\n?/g, '\n')
// 多条记录之间换行
.replace(/[ \t]*[;;][ \t]*/g, '\n')
// 变更前地址 / 变更后地址分行(箭头保留在上一行行尾)
.replace(/[ \t]*[-—]+>[ \t]*|[ \t]*→[ \t]*/g, ' →\n')
.replace(/\n{2,}/g, '\n')
.replace(/[ \t]+\n/g, '\n')
.trim();
};