同步6/16
This commit is contained in:
@@ -67,7 +67,7 @@ export function validator(value: string | number, regType: RegType): boolean {
|
||||
|
||||
/**
|
||||
* 车牌验证工具类
|
||||
* 支持传统燃油、新能源、军警、武警、使馆、临时、港澳等全量车牌
|
||||
* 支持传统燃油、新能源、军警、武警、使馆、临时、港澳、挂车等全量车牌
|
||||
*/
|
||||
export class LicensePlateValidator {
|
||||
/**
|
||||
@@ -75,49 +75,37 @@ export class LicensePlateValidator {
|
||||
*/
|
||||
private static readonly PROVINCE = '[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼]';
|
||||
|
||||
/**
|
||||
* 使领馆前缀
|
||||
*/
|
||||
private static readonly EMBASSY_PREFIX = '[使领]';
|
||||
|
||||
/**
|
||||
* 验证传统燃油车牌 (蓝牌/黄牌)
|
||||
* 格式: 省份 + 字母 + 5位字符
|
||||
* 格式: 省份 + 字母 + 5位字符 (数字或字母,排除I,O)
|
||||
* 示例: 京A·12345, 粤B·88888
|
||||
* 总长7位
|
||||
*/
|
||||
static isTraditionalPlate(plate: string): boolean {
|
||||
// 包含普通民用以及使领馆非新能源部分(如果使领馆归为此类,通常使领馆有单独规则,这里仅指普通民用)
|
||||
// 注意:使领馆车牌通常格式特殊,见 isEmbassyPlate
|
||||
const reg = new RegExp(`^${this.PROVINCE}[A-HJ-NP-Z][A-HJ-NP-Z0-9]{5}$`);
|
||||
return reg.test(plate.toUpperCase());
|
||||
if (!reg.test(plate.toUpperCase())) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证新能源车牌 (绿牌)
|
||||
* 小型: 省份 + 字母 + D/F + 4位数字/字母 或 省份 + 字母 + 5位数字/字母 + D/F
|
||||
* 大型: 省份 + 字母 + 5位数字/字母 + D/F (通常最后一位是D/F)
|
||||
* 示例: 京AD12345, 京A12345D, 沪AF12345
|
||||
* 规则:除了标识位 D/F 外,其余序号位必须为数字 (0-9)
|
||||
* 小型: 省份 + 字母 + D/F + 5位数字 或 省份 + 字母 + 5位数字 + D/F
|
||||
* 大型: 省份 + 字母 + 5位数字 + D/F
|
||||
* 总长8位
|
||||
*/
|
||||
static isNewEnergyPlate(plate: string): boolean {
|
||||
// 小型新能源:第2位或第7位是D/F
|
||||
// 大型新能源:最后一位是D/F (且总长8位)
|
||||
// 综合正则:
|
||||
// 1. [省份][A-HJ-NP-Z][D-F][0-9A-HJ-NP-Z]{4} (小型,D/F在第2位)
|
||||
// 2. [省份][A-HJ-NP-Z][0-9A-HJ-NP-Z]{4}[D-F] (小型/大型,D/F在最后)
|
||||
// 3. [省份][A-HJ-NP-Z][0-9A-HJ-NP-Z][D-F][0-9A-HJ-NP-Z]{3} (较少见,但某些早期试点或特殊编排可能存在,标准通常只认1和2)
|
||||
|
||||
// 更严谨的标准新能源正则 (GA 804-2018):
|
||||
// 小型: [省份][A-HJ-NP-Z][D-F][0-9A-HJ-NP-Z]{4} | [省份][A-HJ-NP-Z][0-9A-HJ-NP-Z]{4}[D-F]
|
||||
// 大型: [省份][A-HJ-NP-Z][0-9A-HJ-NP-Z]{5}[D-F] (其实包含在上面第二种情况的子集里,只要保证总长8位)
|
||||
|
||||
const reg = new RegExp(`^${this.PROVINCE}[A-HJ-NP-Z](?:[D-F][0-9A-HJ-NP-Z]{4}|[0-9A-HJ-NP-Z]{5}[D-F])$`);
|
||||
// 修正:非D/F位仅限数字
|
||||
// 1. [省份][A-HJ-NP-Z][D-F][0-9]{5} (D/F在序号第1位,后跟5位数字)
|
||||
// 2. [省份][A-HJ-NP-Z][0-9]{5}[D-F] (D/F在序号最后1位,前跟5位数字)
|
||||
const reg = new RegExp(`^${this.PROVINCE}[A-HJ-NP-Z](?:[D-F][0-9]{5}|[0-9]{5}[D-F])$`);
|
||||
return reg.test(plate.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证警车车牌
|
||||
* 格式: 省份 + 字母 + 4位数字 + 警
|
||||
* 示例: 京A·1234警
|
||||
* 总长7位
|
||||
*/
|
||||
static isPolicePlate(plate: string): boolean {
|
||||
const reg = new RegExp(`^${this.PROVINCE}[A-HJ-NP-Z][0-9]{4}警$`);
|
||||
@@ -127,45 +115,47 @@ export class LicensePlateValidator {
|
||||
/**
|
||||
* 验证教练车牌
|
||||
* 格式: 省份 + 字母 + 4位数字 + 学
|
||||
* 示例: 京A·1234学
|
||||
* 总长7位
|
||||
*/
|
||||
static isCoachPlate(plate: string): boolean {
|
||||
const reg = new RegExp(`^${this.PROVINCE}[A-HJ-NP-Z][0-9]{4}学$`);
|
||||
return reg.test(plate.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证挂车车牌
|
||||
* 格式: 省份 + 字母 + 4位数字 + 挂
|
||||
* 总长7位
|
||||
*/
|
||||
static isTrailerPlate(plate: string): boolean {
|
||||
const reg = new RegExp(`^${this.PROVINCE}[A-HJ-NP-Z][0-9]{4}挂$`);
|
||||
return reg.test(plate.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证武警车牌 (2013式)
|
||||
* 格式: WJ + 省份/部门简称 + 5位字符
|
||||
* 示例: WJ·京12345, WJ·12345X, WJ·B12345
|
||||
* 注意:WJ后紧跟的可能是省份简称或部门字母
|
||||
* 总长8位 (WJ+1+5)
|
||||
*/
|
||||
static isArmedPolicePlate(plate: string): boolean {
|
||||
// WJ + (省份简称 | 部门字母) + 5位字符
|
||||
// 部门字母包括: 内边消水电林通海等,这里简化处理,允许字母或省份
|
||||
const reg = /^WJ(?:[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼]|[A-Z])[0-9A-HJ-NP-Z]{5}$/;
|
||||
const reg = /^WJ(?:[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼]|[A-HJ-NP-Z])[0-9A-HJ-NP-Z]{5}$/;
|
||||
return reg.test(plate.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证军队车牌 (2012式)
|
||||
* 格式: 军种字母 + · + 5位字符 (实际输入常不带点)
|
||||
* 军种: V(军委), K(空军), H(海军), B(北京军区), S(沈阳), L(兰州), J(济南), N(南京), G(广州), C(成都) 等
|
||||
* 示例: V·12345, K·A1234
|
||||
* 格式: 军种字母 + 字母/数字 + 5位字符
|
||||
* 总长7位
|
||||
*/
|
||||
static isMilitaryPlate(plate: string): boolean {
|
||||
// 简化版:首字母为大写(排除I,O),后跟5位字符
|
||||
// 更严谨应限制首字母为特定军种代号,但考虑到军改变化,此处做通用校验
|
||||
// 2012式军牌格式:XY·12345 (X为军种/大区,Y为单位)
|
||||
// 常见前缀: V, K, H, B, S, L, J, N, G, C, M, P, O, A, E 等
|
||||
const reg = /^[VKBHSLJNGCMPEOA][A-HJ-NP-Z0-9][0-9A-HJ-NP-Z]{4}$/;
|
||||
return reg.test(plate.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证使馆/领馆车牌
|
||||
* 格式: 使/领 + 3位数字 + 3位数字 (共6位数字,或 使·123456)
|
||||
* 示例: 使·123456, 领·123456
|
||||
* 格式: 使/领 + 6位数字
|
||||
* 总长7位
|
||||
*/
|
||||
static isEmbassyPlate(plate: string): boolean {
|
||||
const reg = /^[使领][0-9]{6}$/;
|
||||
@@ -175,7 +165,7 @@ export class LicensePlateValidator {
|
||||
/**
|
||||
* 验证港澳入出境车 (粤Z牌)
|
||||
* 格式: 粤Z + 4位字符 + 港/澳
|
||||
* 示例: 粤Z·1234港, 粤Z·1234澳
|
||||
* 总长7位
|
||||
*/
|
||||
static isHKMacauPlate(plate: string): boolean {
|
||||
const reg = /^粤Z[A-HJ-NP-Z0-9]{4}[港澳]$/;
|
||||
@@ -185,7 +175,7 @@ export class LicensePlateValidator {
|
||||
/**
|
||||
* 验证临时车牌
|
||||
* 格式: 省份 + 字母 + 5位字符 + 临 / 超
|
||||
* 示例: 京A·12345临, 沪B·12345超
|
||||
* 总长8位
|
||||
*/
|
||||
static isTemporaryPlate(plate: string): boolean {
|
||||
const reg = new RegExp(`^${this.PROVINCE}[A-HJ-NP-Z][0-9A-HJ-NP-Z]{5}[临超]$`);
|
||||
@@ -201,11 +191,17 @@ export class LicensePlateValidator {
|
||||
|
||||
const upperPlate = plate.toUpperCase().replace(/[·\s-]/g, ''); // 去除分隔符和空格
|
||||
|
||||
// 长度预检查:车牌只能是 7 位或 8 位
|
||||
if (upperPlate.length !== 7 && upperPlate.length !== 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
this.isTraditionalPlate(upperPlate) ||
|
||||
this.isNewEnergyPlate(upperPlate) ||
|
||||
this.isPolicePlate(upperPlate) ||
|
||||
this.isCoachPlate(upperPlate) ||
|
||||
this.isTrailerPlate(upperPlate) ||
|
||||
this.isArmedPolicePlate(upperPlate) ||
|
||||
this.isMilitaryPlate(upperPlate) ||
|
||||
this.isEmbassyPlate(upperPlate) ||
|
||||
|
||||
Reference in New Issue
Block a user