分销问题修复,订单问题修复

This commit is contained in:
2025-10-30 17:11:18 +08:00
parent 6283d168e9
commit 09fc28de06
29 changed files with 2652 additions and 533 deletions

143
utils/util.js Normal file
View File

@@ -0,0 +1,143 @@
/**
* 手机号脱敏隐藏中间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
}
};
}