// 使用示例: // import IDCardParser from '@/utils/IDCardParser'; // const handleCheck = (idStr) => { // const parser = new IDCardParser(idStr); // const result = parser.getInfo(); // if(result.valid) { // // 填充表单 // console.log(result.age, result.gender); // } else { // alert(result.message); // } // } class IDCardParser { constructor(idNumber) { this.idNumber = idNumber ? idNumber.trim().toUpperCase() : ""; this.provinceMap = { 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: "澳门特别行政区" }; // 初始化验证结果 const validation = this._validate(); this.isValid = validation.isValid; this.errorMsg = validation.msg; // 如果合法,预先解析数据 if (this.isValid) { this._parseData(); } } /** * 核心校验逻辑 */ _validate() { // 1. 基础正则 (18位,末位数字或X) if (!/^\d{17}[\d|X]$/.test(this.idNumber)) { return { isValid: false, msg: "格式错误:必须是18位,末位为数字或X" }; } // 2. 省份校验 const provinceCode = parseInt(this.idNumber.substring(0, 2)); if (!this.provinceMap[provinceCode]) { return { isValid: false, msg: "省份代码错误" }; } // 3. 日期合法性严格校验 const year = parseInt(this.idNumber.substring(6, 10)); const month = parseInt(this.idNumber.substring(10, 12)); const day = parseInt(this.idNumber.substring(12, 14)); const date = new Date(year, month - 1, day); // JS Date会自动纠错(例如2月30会变成3月),所以必须反向比对 if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) { return { isValid: false, msg: "出生日期无效" }; } // 检查年份范围(可选,例如限制在1900年以后) if (year < 1900 || date > new Date()) { return { isValid: false, msg: "出生日期不在合理范围内" }; } // 4. 校验码计算 (ISO 7064:1983.MOD 11-2) if (!this._checkSum()) { return { isValid: false, msg: "校验码错误(身份证可能无效)" }; } return { isValid: true, msg: "验证通过" }; } /** * 校验码算法 */ _checkSum() { const factors = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; const checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']; let sum = 0; for (let i = 0; i < 17; i++) { sum += parseInt(this.idNumber[i]) * factors[i]; } const mod = sum % 11; return checkCodes[mod] === this.idNumber[17]; } /** * 解析内部数据 */ _parseData() { const year = parseInt(this.idNumber.substring(6, 10)); const month = parseInt(this.idNumber.substring(10, 12)); const day = parseInt(this.idNumber.substring(12, 14)); this.birthDate = new Date(year, month - 1, day); this.province = this.provinceMap[parseInt(this.idNumber.substring(0, 2))]; // 性别:第17位,奇数男,偶数女 const genderCode = parseInt(this.idNumber.substring(16, 17)); this.gender = genderCode % 2 !== 0 ? "男" : "女"; } /** * 获取所有信息 */ getInfo() { if (!this.isValid) { return { valid: false, message: this.errorMsg }; } return { valid: true, idNumber: this.idNumber, province: this.province, birthday: this._formatDate(this.birthDate), gender: this.gender, age: this._calculateAge(), zodiac: this._getZodiac(), // 生肖 constellation: this._getConstellation() // 星座 }; } _formatDate(date) { const y = date.getFullYear(); const m = String(date.getMonth() + 1).padStart(2, '0'); const d = String(date.getDate()).padStart(2, '0'); return `${y}-${m}-${d}`; } _calculateAge() { const today = new Date(); let age = today.getFullYear() - this.birthDate.getFullYear(); const m = today.getMonth() - this.birthDate.getMonth(); // 如果没过生日,年龄减1 if (m < 0 || (m === 0 && today.getDate() < this.birthDate.getDate())) { age--; } return age; } _getZodiac() { // 猴鸡狗猪鼠牛虎兔龙蛇马羊 (对应余数 0-11) const zodiacs = "猴鸡狗猪鼠牛虎兔龙蛇马羊"; return zodiacs.charAt(this.birthDate.getFullYear() % 12); } _getConstellation() { const month = this.birthDate.getMonth() + 1; const day = this.birthDate.getDate(); // 星座分割日 const dates = [20, 19, 21, 20, 21, 22, 23, 23, 23, 24, 23, 22]; const constellations = [ "摩羯座", "水瓶座", "双鱼座", "白羊座", "金牛座", "双子座", "巨蟹座", "狮子座", "处女座", "天秤座", "天蝎座", "射手座", "摩羯座" ]; if (day < dates[month - 1]) { return constellations[month - 1]; } else { return constellations[month]; } } } export default IDCardParser;