Files
cashier_wx/utils/util.js

143 lines
5.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 手机号脱敏隐藏中间4位11位手机号通用
* @param {string} phone - 原始手机号可带非数字字符如138-1234-5678
* @returns {string} 脱敏后手机号
*/
export function desensitizePhone(phone) {
// 1. 提取纯数字(过滤非数字字符)
const purePhone = (phone || "").replace(/[^\d]/g, "");
// 2. 边界判断非11位手机号返回原字符串或自定义提示
if (purePhone.length !== 11) {
console.warn("手机号格式不正确需11位纯数字");
return phone; // 或返回 ''、'手机号格式错误' 等
}
// 3. 脱敏前3位 + **** + 后4位
return purePhone.replace(/(\d{3})(\d{4})(\d{4})/, "$1****$3");
}
/**
* 姓名合法性校验
* @param {string} name - 待校验的姓名
* @returns {Object} 校验结果:{ valid: boolean, msg: string }
*/
export function validateName(name) {
// 1. 空值校验
if (!name || name.trim() === '') {
return { valid: false, msg: '姓名不能为空' };
}
const pureName = name.trim();
// 2. 长度校验2-6位含少数民族中间点
if (pureName.length < 2 || pureName.length > 6) {
return { valid: false, msg: '姓名长度应为2-6位' };
}
// 3. 正则校验:仅允许中文、少数民族中间点(·),且中间点不能在开头/结尾
// 中文范围:[\u4e00-\u9fa5],中间点:[\u00b7]Unicode 标准中间点,非小数点)
const nameReg = /^[\u4e00-\u9fa5]+([\u00b7][\u4e00-\u9fa5]+)*$/;
if (!nameReg.test(pureName)) {
return {
valid: false,
msg: '姓名仅支持中文和少数民族中间点(·),且不能包含数字、字母或特殊符号'
};
}
// 4. 额外限制:中间点不能连续(如“李··四”)
if (/[\u00b7]{2,}/.test(pureName)) {
return { valid: false, msg: '姓名中的中间点(·)不能连续' };
}
// 校验通过
return { valid: true, msg: '姓名格式合法' };
}
/**
* 身份证号码合法性校验支持18位/15位
* @param {string} idCard - 待校验的身份证号
* @returns {Object} 校验结果:{ valid: boolean, msg: string, info?: Object }
* info 可选返回:{ birthDate: string, gender: string }(出生日期、性别)
*/
export function validateIdCard(idCard) {
// 1. 空值校验
if (!idCard || idCard.trim() === '') {
return { valid: false, msg: '身份证号码不能为空' };
}
const pureIdCard = idCard.trim().toUpperCase(); // 统一转为大写处理X
// 2. 格式校验18位或15位
const id18Reg = /^[1-9]\d{5}(19|20)\d{2}((0[1-9])|(1[0-2]))((0[1-9])|([12]\d)|(3[01]))\d{3}([0-9]|X)$/;
const id15Reg = /^[1-9]\d{5}\d{2}((0[1-9])|(1[0-2]))((0[1-9])|([12]\d)|(3[01]))\d{3}$/;
if (!id18Reg.test(pureIdCard) && !id15Reg.test(pureIdCard)) {
return {
valid: false,
msg: '身份证号码格式错误需18位最后一位可含X或15位纯数字'
};
}
// 3. 提取出生日期并校验合法性
let birthDateStr, birthDate;
if (pureIdCard.length === 18) {
// 18位第7-14位为出生日期YYYYMMDD
birthDateStr = pureIdCard.slice(6, 14);
birthDate = new Date(`${birthDateStr.slice(0,4)}-${birthDateStr.slice(4,6)}-${birthDateStr.slice(6,8)}`);
} else {
// 15位第7-12位为出生日期YYMMDD补全为YYYYMMDD19xx或20xx默认19xx
const year = `19${pureIdCard.slice(6, 8)}`;
const month = pureIdCard.slice(8, 10);
const day = pureIdCard.slice(10, 12);
birthDateStr = `${year}${month}${day}`;
birthDate = new Date(`${year}-${month}-${day}`);
}
// 校验出生日期有效性如20230230 → 日期对象会是Invalid Date
if (
isNaN(birthDate.getTime()) ||
birthDateStr.slice(0,4) !== birthDate.getFullYear().toString() ||
birthDateStr.slice(4,6) !== (birthDate.getMonth() + 1).toString().padStart(2, '0') ||
birthDateStr.slice(6,8) !== birthDate.getDate().toString().padStart(2, '0')
) {
return { valid: false, msg: '身份证中的出生日期无效' };
}
// 4. 18位身份证额外校验校验码合法性加权算法
if (pureIdCard.length === 18) {
// 加权因子
const weightFactors = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
// 校验码对应值0-10 → 10对应X
const checkCodeMap = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
// 计算前17位与加权因子的乘积和
let sum = 0;
for (let i = 0; i < 17; i++) {
sum += parseInt(pureIdCard[i]) * weightFactors[i];
}
// 计算预期校验码
const expectedCheckCode = checkCodeMap[sum % 11];
// 对比实际校验码(最后一位)
if (pureIdCard[17] !== expectedCheckCode) {
return { valid: false, msg: '身份证校验码错误,可能是无效身份证' };
}
}
// 5. 可选提取性别18位第17位15位第15位奇数=男,偶数=女)
let gender = '';
if (pureIdCard.length === 18) {
const genderCode = parseInt(pureIdCard[16]);
gender = genderCode % 2 === 1 ? '男' : '女';
} else {
const genderCode = parseInt(pureIdCard[14]);
gender = genderCode % 2 === 1 ? '男' : '女';
}
// 校验通过,返回额外信息(出生日期、性别)
return {
valid: true,
msg: '身份证号码合法',
info: {
birthDate: `${birthDate.getFullYear()}-${(birthDate.getMonth() + 1).toString().padStart(2, '0')}-${birthDate.getDate().toString().padStart(2, '0')}`,
gender: gender
}
};
}