flat: 暂存
This commit is contained in:
@@ -542,6 +542,335 @@ function isInWechatMiniProgramWebview() {
|
||||
function isEmptyObject(obj) {
|
||||
return obj && typeof obj === 'object' && !Array.isArray(obj) && Object.keys(obj).length === 0;
|
||||
}
|
||||
/**
|
||||
* 身份证号码校验工具
|
||||
* 支持15位和18位身份证号码校验
|
||||
* 提供详细的校验结果和错误信息
|
||||
*/
|
||||
export const IdCardValidator = {
|
||||
// 每位加权因子
|
||||
powers: ['7', '9', '10', '5', '8', '4', '2', '1', '6', '3', '7', '9', '10', '5', '8', '4', '2'],
|
||||
|
||||
// 第18位校检码
|
||||
parityBit: ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'],
|
||||
|
||||
// 省市地区码映射
|
||||
provinceAndCitys: {
|
||||
11: '北京',
|
||||
12: '天津',
|
||||
13: '河北',
|
||||
14: '山西',
|
||||
15: '内蒙古',
|
||||
21: '辽宁',
|
||||
22: '吉林',
|
||||
23: '黑龙江',
|
||||
31: '上海',
|
||||
32: '江苏',
|
||||
33: '浙江',
|
||||
34: '安徽',
|
||||
35: '福建',
|
||||
36: '江西',
|
||||
37: '山东',
|
||||
41: '河南',
|
||||
42: '湖北',
|
||||
43: '湖南',
|
||||
44: '广东',
|
||||
45: '广西',
|
||||
46: '海南',
|
||||
50: '重庆',
|
||||
51: '四川',
|
||||
52: '贵州',
|
||||
53: '云南',
|
||||
54: '西藏',
|
||||
61: '陕西',
|
||||
62: '甘肃',
|
||||
63: '青海',
|
||||
64: '宁夏',
|
||||
65: '新疆',
|
||||
71: '台湾',
|
||||
81: '香港',
|
||||
82: '澳门',
|
||||
91: '国外'
|
||||
},
|
||||
|
||||
/**
|
||||
* 验证身份证号码
|
||||
* @param {string} idCardNo - 身份证号码
|
||||
* @returns {Object} 校验结果 { valid: boolean, message: string, info: Object }
|
||||
*/
|
||||
validate(idCardNo) {
|
||||
// 检查是否为空
|
||||
if (this._isEmpty(idCardNo)) {
|
||||
return this._createResult(false, '身份证号码不能为空');
|
||||
}
|
||||
|
||||
// 去除空格
|
||||
idCardNo = idCardNo.trim();
|
||||
|
||||
// 检查长度,支持15位和18位
|
||||
if (idCardNo.length === 15) {
|
||||
return this._validate15IdCardNo(idCardNo);
|
||||
} else if (idCardNo.length === 18) {
|
||||
return this._validate18IdCardNo(idCardNo);
|
||||
} else {
|
||||
return this._createResult(false, '身份证号码长度必须是15位或18位');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 验证18位身份证号码
|
||||
* @param {string} idCardNo - 18位身份证号码
|
||||
* @returns {Object} 校验结果
|
||||
*/
|
||||
_validate18IdCardNo(idCardNo) {
|
||||
// 18位身份证号码的基本格式校验
|
||||
if (!/^[1-9]\d{5}[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}(\d|x|X)$/.test(
|
||||
idCardNo)) {
|
||||
return this._createResult(false, '身份证号码格式不正确');
|
||||
}
|
||||
|
||||
// 校验地址码
|
||||
const addressCode = idCardNo.substring(0, 6);
|
||||
const addressResult = this._checkAddressCode(addressCode);
|
||||
if (!addressResult.valid) {
|
||||
return addressResult;
|
||||
}
|
||||
|
||||
// 校验日期码
|
||||
const birDayCode = idCardNo.substring(6, 14);
|
||||
const birthResult = this._checkBirthDayCode(birDayCode);
|
||||
if (!birthResult.valid) {
|
||||
return birthResult;
|
||||
}
|
||||
|
||||
// 验证校检码
|
||||
if (!this._checkParityBit(idCardNo)) {
|
||||
return this._createResult(false, '身份证号码校验码错误');
|
||||
}
|
||||
|
||||
// 提取身份证信息
|
||||
const info = this._extractInfo(idCardNo, 18);
|
||||
|
||||
return this._createResult(true, '身份证号码校验通过', info);
|
||||
},
|
||||
|
||||
/**
|
||||
* 验证15位身份证号码
|
||||
* @param {string} idCardNo - 15位身份证号码
|
||||
* @returns {Object} 校验结果
|
||||
*/
|
||||
_validate15IdCardNo(idCardNo) {
|
||||
// 15位身份证号码的基本格式校验
|
||||
if (!/^[1-9]\d{5}\d{2}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}$/.test(idCardNo)) {
|
||||
return this._createResult(false, '身份证号码格式不正确');
|
||||
}
|
||||
|
||||
// 校验地址码
|
||||
const addressCode = idCardNo.substring(0, 6);
|
||||
const addressResult = this._checkAddressCode(addressCode);
|
||||
if (!addressResult.valid) {
|
||||
return addressResult;
|
||||
}
|
||||
|
||||
// 校验日期码(15位身份证年份是两位,这里转换为四位)
|
||||
const year = `19${idCardNo.substring(6, 8)}`; // 15位身份证一般是1900年以后出生
|
||||
const month = idCardNo.substring(8, 10);
|
||||
const day = idCardNo.substring(10, 12);
|
||||
const birDayCode = `${year}${month}${day}`;
|
||||
|
||||
const birthResult = this._checkBirthDayCode(birDayCode);
|
||||
if (!birthResult.valid) {
|
||||
return birthResult;
|
||||
}
|
||||
|
||||
// 提取身份证信息
|
||||
const info = this._extractInfo(idCardNo, 15);
|
||||
|
||||
return this._createResult(true, '身份证号码校验通过', info);
|
||||
},
|
||||
|
||||
/**
|
||||
* 校验地址码
|
||||
* @param {string} addressCode - 地址码
|
||||
* @returns {Object} 校验结果
|
||||
*/
|
||||
_checkAddressCode(addressCode) {
|
||||
if (!/^[1-9]\d{5}$/.test(addressCode)) {
|
||||
return this._createResult(false, '地址码格式不正确');
|
||||
}
|
||||
|
||||
const provinceCode = parseInt(addressCode.substring(0, 2));
|
||||
if (!this.provinceAndCitys[provinceCode]) {
|
||||
return this._createResult(false, '地址码对应的地区不存在');
|
||||
}
|
||||
|
||||
return this._createResult(true);
|
||||
},
|
||||
|
||||
/**
|
||||
* 校验日期码
|
||||
* @param {string} birDayCode - 日期码 (格式:YYYYMMDD)
|
||||
* @returns {Object} 校验结果
|
||||
*/
|
||||
_checkBirthDayCode(birDayCode) {
|
||||
if (!/^[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))$/.test(birDayCode)) {
|
||||
return this._createResult(false, '出生日期格式不正确');
|
||||
}
|
||||
|
||||
const year = parseInt(birDayCode.substring(0, 4), 10);
|
||||
const month = parseInt(birDayCode.substring(4, 6), 10);
|
||||
const day = parseInt(birDayCode.substring(6), 10);
|
||||
|
||||
// 检查年份范围(合理的出生年份范围)
|
||||
const currentYear = new Date().getFullYear();
|
||||
if (year < 1900 || year > currentYear) {
|
||||
return this._createResult(false, '出生年份超出合理范围');
|
||||
}
|
||||
|
||||
// 检查日期有效性
|
||||
const date = new Date(year, month - 1, day);
|
||||
if (
|
||||
date.getFullYear() !== year ||
|
||||
date.getMonth() !== month - 1 ||
|
||||
date.getDate() !== day
|
||||
) {
|
||||
return this._createResult(false, '出生日期无效');
|
||||
}
|
||||
|
||||
// 检查是否为未来日期
|
||||
if (date > new Date()) {
|
||||
return this._createResult(false, '出生日期不能是未来日期');
|
||||
}
|
||||
|
||||
return this._createResult(true);
|
||||
},
|
||||
|
||||
/**
|
||||
* 验证校检码
|
||||
* @param {string} idCardNo - 18位身份证号码
|
||||
* @returns {boolean} 校验结果
|
||||
*/
|
||||
_checkParityBit(idCardNo) {
|
||||
const parityBit = idCardNo.charAt(17).toUpperCase();
|
||||
return this._getParityBit(idCardNo) === parityBit;
|
||||
},
|
||||
|
||||
/**
|
||||
* 计算校检码
|
||||
* @param {string} idCardNo - 18位身份证号码
|
||||
* @returns {string} 校检码
|
||||
*/
|
||||
_getParityBit(idCardNo) {
|
||||
const id17 = idCardNo.substring(0, 17);
|
||||
let power = 0;
|
||||
|
||||
for (let i = 0; i < 17; i++) {
|
||||
power += parseInt(id17.charAt(i), 10) * parseInt(this.powers[i], 10);
|
||||
}
|
||||
|
||||
const mod = power % 11;
|
||||
return this.parityBit[mod];
|
||||
},
|
||||
|
||||
/**
|
||||
* 提取身份证信息
|
||||
* @param {string} idCardNo - 身份证号码
|
||||
* @param {number} type - 类型 15或18
|
||||
* @returns {Object} 身份证信息
|
||||
*/
|
||||
_extractInfo(idCardNo, type) {
|
||||
let addressCode, birthYear, birthMonth, birthDay, genderCode, gender;
|
||||
|
||||
// 地址码
|
||||
addressCode = idCardNo.substring(0, 6);
|
||||
const provinceCode = parseInt(addressCode.substring(0, 2));
|
||||
const province = this.provinceAndCitys[provinceCode] || '';
|
||||
|
||||
// 出生日期
|
||||
if (type === 18) {
|
||||
birthYear = idCardNo.substring(6, 10);
|
||||
birthMonth = idCardNo.substring(10, 12);
|
||||
birthDay = idCardNo.substring(12, 14);
|
||||
genderCode = idCardNo.substring(14, 17);
|
||||
} else {
|
||||
birthYear = `19${idCardNo.substring(6, 8)}`;
|
||||
birthMonth = idCardNo.substring(8, 10);
|
||||
birthDay = idCardNo.substring(10, 12);
|
||||
genderCode = idCardNo.substring(12, 15);
|
||||
}
|
||||
|
||||
// 性别
|
||||
gender = parseInt(genderCode, 10) % 2 === 1 ? '男' : '女';
|
||||
|
||||
return {
|
||||
addressCode,
|
||||
province,
|
||||
birthday: `${birthYear}-${birthMonth}-${birthDay}`,
|
||||
gender,
|
||||
length: type
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* 检查是否为空
|
||||
* @param {*} value - 要检查的值
|
||||
* @returns {boolean} 是否为空
|
||||
*/
|
||||
_isEmpty(value) {
|
||||
return value === null || value === undefined || value === '';
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建校验结果对象
|
||||
* @param {boolean} valid - 是否有效
|
||||
* @param {string} message - 消息
|
||||
* @param {Object} info - 附加信息
|
||||
* @returns {Object} 校验结果
|
||||
*/
|
||||
_createResult(valid, message = '', info = {}) {
|
||||
return {
|
||||
valid,
|
||||
message,
|
||||
info
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* 将15位身份证升级为18位
|
||||
* @param {string} idCardNo - 15位身份证号码
|
||||
* @returns {string|boolean} 18位身份证号码或false(无效的15位身份证)
|
||||
*/
|
||||
upgrade15To18(idCardNo) {
|
||||
if (idCardNo.length !== 15) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 先验证15位身份证是否有效
|
||||
const validateResult = this._validate15IdCardNo(idCardNo);
|
||||
if (!validateResult.valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 转换出生年份为4位
|
||||
const year = `19${idCardNo.substring(6, 8)}`;
|
||||
const rest = idCardNo.substring(8);
|
||||
|
||||
// 拼接17位
|
||||
const id17 = `${idCardNo.substring(0, 6)}${year}${rest}`;
|
||||
|
||||
// 计算校验码
|
||||
let power = 0;
|
||||
for (let i = 0; i < 17; i++) {
|
||||
power += parseInt(id17.charAt(i), 10) * parseInt(this.powers[i], 10);
|
||||
}
|
||||
const mod = power % 11;
|
||||
const parityBit = this.parityBit[mod];
|
||||
|
||||
// 拼接18位身份证
|
||||
return `${id17}${parityBit}`;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
export const $api = {
|
||||
@@ -567,6 +896,7 @@ export default {
|
||||
navBack,
|
||||
cloneDeep,
|
||||
formatDate,
|
||||
IdCardValidator,
|
||||
getdeviceInfo,
|
||||
checkingPhoneRegExp,
|
||||
checkingEmailRegExp,
|
||||
|
Reference in New Issue
Block a user