217 lines
6.6 KiB
TypeScript
217 lines
6.6 KiB
TypeScript
/**
|
||
* 验证身份证号码(18位,支持尾号x/X)
|
||
* @param idCard 身份证号
|
||
* @return {boolean} true 符合 false 不符合
|
||
*/
|
||
export function validateIdCard(idCard: string): boolean {
|
||
// 18位身份证正则
|
||
const reg = /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;
|
||
return reg.test(idCard.trim());
|
||
}
|
||
/**
|
||
* 验证车牌号
|
||
* @param val 兼容新能源 + 普通车牌
|
||
* @return {boolean} true 符合 false 不符合
|
||
*/
|
||
export function isPlateNumber(val: string): boolean {
|
||
const reg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼][A-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/;
|
||
return reg.test(val);
|
||
}
|
||
/**
|
||
* 验证金钱
|
||
* @return {boolean} true 符合 false 不符合
|
||
* @param value
|
||
*/
|
||
export function isMoney(value: number): boolean {
|
||
const reg = /^(0|[1-9]\d*)(\.\d{1,2})?$/;
|
||
return reg.test(String(value).trim());
|
||
}
|
||
/**
|
||
* 验证姓名
|
||
* @param {string} val
|
||
* @return {boolean} true 符合 false 不符合
|
||
*/
|
||
export function isChineseName(val: string): boolean {
|
||
return /^[\u4e00-\u9fa5·]{2,16}$/.test(String(val).trim());
|
||
}
|
||
|
||
const reg = {
|
||
/** 金钱 */
|
||
money: /^(0|[1-9]\d*)(\.\d{1,2})?$/,
|
||
/** 身份证 */
|
||
idCard: /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/,
|
||
/** 车牌 */
|
||
PlateNumber: /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼][A-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/,
|
||
/** 姓名 */
|
||
ChineseName: /^[\u4e00-\u9fa5·]{2,16}$/,
|
||
/** 手机号 */
|
||
phone: /^1[3-9]\d{9}$/,
|
||
/** 邮箱 */
|
||
email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
|
||
/** QQ */
|
||
qq: /^[1-9]\d{4,11}$/,
|
||
/** 微信 */
|
||
wechat: /^[a-zA-Z][a-zA-Z0-9_-]{5,19}$/,
|
||
/** 护照 */
|
||
passport: /^[EG]\d{8}$/,
|
||
/** 港澳通行证 */
|
||
hongkongPassport: /^[CHMW]\d{8}$/
|
||
};
|
||
// 自动推导 TS 类型(最标准)
|
||
export type RegType = keyof typeof reg;
|
||
/**
|
||
* 验证姓名
|
||
* @param {string|number} value
|
||
* @param {string} regType
|
||
* @return {boolean} true 符合 false 不符合
|
||
*/
|
||
export function validator(value: string | number, regType: RegType): boolean {
|
||
return reg[regType].test(String(value));
|
||
}
|
||
|
||
/**
|
||
* 车牌验证工具类
|
||
* 支持传统燃油、新能源、军警、武警、使馆、临时、港澳、挂车等全量车牌
|
||
*/
|
||
export class LicensePlateValidator {
|
||
/**
|
||
* 省份简称正则片段
|
||
*/
|
||
private static readonly PROVINCE = '[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼]';
|
||
|
||
/**
|
||
* 验证传统燃油车牌 (蓝牌/黄牌)
|
||
* 格式: 省份 + 字母 + 5位字符 (数字或字母,排除I,O)
|
||
* 示例: 京A·12345, 粤B·88888
|
||
* 总长7位
|
||
*/
|
||
static isTraditionalPlate(plate: string): boolean {
|
||
const reg = new RegExp(`^${this.PROVINCE}[A-HJ-NP-Z][A-HJ-NP-Z0-9]{5}$`);
|
||
if (!reg.test(plate.toUpperCase())) return false;
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 验证新能源车牌 (绿牌)
|
||
* 规则:除了标识位 D/F 外,其余序号位必须为数字 (0-9)
|
||
* 小型: 省份 + 字母 + D/F + 5位数字 或 省份 + 字母 + 5位数字 + D/F
|
||
* 大型: 省份 + 字母 + 5位数字 + D/F
|
||
* 总长8位
|
||
*/
|
||
static isNewEnergyPlate(plate: string): boolean {
|
||
// 修正:非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位数字 + 警
|
||
* 总长7位
|
||
*/
|
||
static isPolicePlate(plate: string): boolean {
|
||
const reg = new RegExp(`^${this.PROVINCE}[A-HJ-NP-Z][0-9]{4}警$`);
|
||
return reg.test(plate.toUpperCase());
|
||
}
|
||
|
||
/**
|
||
* 验证教练车牌
|
||
* 格式: 省份 + 字母 + 4位数字 + 学
|
||
* 总长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位字符
|
||
* 总长8位 (WJ+1+5)
|
||
*/
|
||
static isArmedPolicePlate(plate: string): boolean {
|
||
const reg = /^WJ(?:[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼]|[A-HJ-NP-Z])[0-9A-HJ-NP-Z]{5}$/;
|
||
return reg.test(plate.toUpperCase());
|
||
}
|
||
|
||
/**
|
||
* 验证军队车牌 (2012式)
|
||
* 格式: 军种字母 + 字母/数字 + 5位字符
|
||
* 总长7位
|
||
*/
|
||
static isMilitaryPlate(plate: string): boolean {
|
||
const reg = /^[VKBHSLJNGCMPEOA][A-HJ-NP-Z0-9][0-9A-HJ-NP-Z]{4}$/;
|
||
return reg.test(plate.toUpperCase());
|
||
}
|
||
|
||
/**
|
||
* 验证使馆/领馆车牌
|
||
* 格式: 使/领 + 6位数字
|
||
* 总长7位
|
||
*/
|
||
static isEmbassyPlate(plate: string): boolean {
|
||
const reg = /^[使领][0-9]{6}$/;
|
||
return reg.test(plate);
|
||
}
|
||
|
||
/**
|
||
* 验证港澳入出境车 (粤Z牌)
|
||
* 格式: 粤Z + 4位字符 + 港/澳
|
||
* 总长7位
|
||
*/
|
||
static isHKMacauPlate(plate: string): boolean {
|
||
const reg = /^粤Z[A-HJ-NP-Z0-9]{4}[港澳]$/;
|
||
return reg.test(plate.toUpperCase());
|
||
}
|
||
|
||
/**
|
||
* 验证临时车牌
|
||
* 格式: 省份 + 字母 + 5位字符 + 临 / 超
|
||
* 总长8位
|
||
*/
|
||
static isTemporaryPlate(plate: string): boolean {
|
||
const reg = new RegExp(`^${this.PROVINCE}[A-HJ-NP-Z][0-9A-HJ-NP-Z]{5}[临超]$`);
|
||
return reg.test(plate.toUpperCase());
|
||
}
|
||
|
||
/**
|
||
* 验证所有合法车牌(全量)
|
||
* @param plate 车牌号码
|
||
*/
|
||
static isValidPlate(plate: string): boolean {
|
||
if (!plate || typeof plate !== 'string') return false;
|
||
|
||
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) ||
|
||
this.isHKMacauPlate(upperPlate) ||
|
||
this.isTemporaryPlate(upperPlate)
|
||
);
|
||
}
|
||
}
|