前言
好记性不如烂笔头,虽然做的项目也不少了,但是用到复杂表单校验的情况却也不多,但是每到用到的时候却又一时半会弄不出来,索性都给封装好记下来,下次直接化身CV工程师即可。(其他的用到再加)
正文
数字校验
/**
* 输入框数字校验
* @param {string} message 必填时的提示内容
* @param {number} float 小数位精确位数,默认 0 不判断
* @param {boolean} required 是否必填
* @param {string|number} min 最小值
* @param {string|number} max 最大值
* @returns {[{required, validator: fun, trigger: string[]}]}
*/
export function numberValidator(message = '', required = false, float = 0, min = '', max = '') {
let fun = (rule, value, callback) => {
if (required && !value) {
callback(new Error(message || '必填项'));
} else if (value && !/^[-+]?\d+(\.\d+)?$/.test(value)) {
callback(new Error('数字格式不正确'));
} else if (value && Number(value) !== 0 && float > 0 && countDecimalPlaces(value) !== float) {
callback(new Error(`小数位数需精确到${float}位`));
} else if (value && /^[-+]?\d+(\.\d+)?$/.test(min) && Number(value) < Number(min)) {
callback(new Error(`不小于${min}`));
} else if (value && /^[-+]?\d+(\.\d+)?$/.test(max) && Number(value) > Number(max)) {
callback(new Error(`不大于${max}`));
} else {
callback();
}
};
return [{
required: required,
validator: fun,
trigger: ['blur', 'change']
}];
}
// 计算小数字符串的小数位数
function countDecimalPlaces(numStr) {
// 匹配小数点后的数字部分
let reg = /^[-+]?\d*(\.\d+)?([eE][-+]?\d+)?$/;
let matchResult = numStr.match(reg);
if (matchResult) {
let decimalPart = matchResult[1];
if (decimalPart) {
return decimalPart.substring(1).length;
} else {
return 0;
}
} else {
return 0;
}
}
手机号校验
/**
* 手机号校验
* @param {string} message 必填时的提示信息
* @param {boolean} required 是否必填,默认非必填
* @returns {[{required: boolean, validator: fun, trigger: string[]}]}
*/
export function phoneValidator(message = '', required = false) {
let fun = (rule, value, callback) => {
if (required && !value) {
callback(new Error(message || '必填项'));
} else if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error('手机号格式不正确'));
} else {
callback();
}
};
return [{
required: required,
validator: fun,
trigger: ['blur', 'change']
}];
}
统一社会信用代码校验
/**
* 统一社会信用代码校验
* @param {string} message 必填时的提示信息
* @param {boolean} required 是否必填,默认非必填
* @returns {[{required: boolean, validator: fun, trigger: string[]}]}
*/
export function unifiedSocialCreditCodeValidator(message = '', required = false) {
// 定义合法的登记管理部门代码范围
const validRegDepartmentCodes = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'N', 'Y'];
let fun = (rule, value, callback) => {
if (required && !value) {
callback(new Error(message || '必填项'));
} else if (value && value.length !== 18) {
// 1. 长度校验,必须为18位
callback(new Error('统一社会信用代码必须满足18位'));
} else if (value && !validRegDepartmentCodes.includes(value.charAt(0))) {
// 2. 第1位登记管理部门代码校验
callback(new Error('第1位登记管理部门代码校验不通过'));
} else if (value && !/^[0-9A-HJ-NP-RTUW-Y]{17}$/.test(value.slice(0, 17))) {
// 3. 除第18位外,前17位字符范围校验(只允许数字和大写字母且避开特定字母 IOSZV)
callback(new Error('前17位代码校验不通过'));
} else if (value && actualCheckCode(value) !== value.charAt(17)) {
// 5. 校验码比对校验
callback(new Error('校验码比对校验失败'));
} else {
callback();
}
};
return [{
required: required,
validator: fun,
trigger: ['blur', 'change']
}];
}
// 4. 主体标识码加权校验计算
function actualCheckCode(code) {
let sum = 0;
// 加权因子,用于主体标识码校验计算
const weightFactors = [1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28];
// 校验码映射表
let str = '0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,J,K,L,M,N,P,Q,R,T,U,W,X,Y';
let checkCodeMap = str.split(',');
for (let i = 0; i < code.length - 1; i++) {
const char = code.charAt(i);
let num = checkCodeMap.indexOf(char);
sum = sum + num * weightFactors[i];
//权重与加权因子相乘之和
}
let remainder = 31 - sum % 31;
if (remainder === 31) {
remainder = 0;
}
return checkCodeMap[remainder];
}
身份证号码校验
/**
* 身份证号码校验
* @param {string} message 必填时的提示信息
* @param {boolean} required 是否必填,默认非必填
* @returns {[{required, validator: fun, trigger: string[]}]}
*/
export function iDCardValidator(message, required) {
let fun = (rule, value, callback) => {
if (required && !value) {
callback(new Error(message || '必填项'));
} else if (value && value.length !== 18) {
// 长度校验,必须为18位
callback(new Error('身份证号码必须满足18位!'));
} else if (value && !birthDateCode(value)) {
// 出生日期码校验
callback(new Error('出生日期码不合法!'));
} else if (value && checkCode(value) !== value.charAt(17)) {
// 校验码比对校验
callback(new Error('校验码校验不通过!'));
} else {
callback();
}
};
return [{
required: required,
validator: fun,
trigger: ['blur', 'change']
}];
}
// 出生日期码合法性校验
function birthDateCode(idCard) {
const birthDateCode = idCard.slice(6, 14);
const year = birthDateCode.slice(0, 4);
const month = birthDateCode.slice(4, 6);
const day = birthDateCode.slice(6, 8);
const date = new Date(year, month - 1, day);
if (date.getFullYear() !== parseInt(year) || date.getMonth() + 1 !== parseInt(month) || date.getDate() !== parseInt(day)) {
return false;
}
return true;
}
// 校验码计算
function checkCode(idCard) {
const weightFactors = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
const checkCodeMap = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
let sum = 0;
for (let i = 0; i < 17; i++) {
sum += parseInt(idCard.charAt(i)) * weightFactors[i];
}
const remainder = sum % 11;
return checkCodeMap[remainder];
}