Files
dvcp_v2_webapp/ui/lib/js/identity.js
2022-12-01 09:13:53 +08:00

239 lines
5.6 KiB
JavaScript

import dayjs from "./moment";
const PARAMS = {
/* 省,直辖市代码表 */
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: '国外'
},
/* 每位加权因子 */
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'],
/* 性别 */
genders: {1: '男', 0: '女'},
}
const Check = {
/* 校验地址码 */
checkAddressCode(addressCode) {
const check = /^[1-9]\d{5}$/.test(addressCode)
if (!check) return false
return !!PARAMS.provinceAndCitys[parseInt(addressCode.substring(0, 2))]
},
/* 校验日期码 */
checkBirthDayCode(birDayCode) {
const check = /^[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))$/.test(
birDayCode
)
if (!check) return false
const yyyy = parseInt(birDayCode.substring(0, 4), 10)
const mm = parseInt(birDayCode.substring(4, 6), 10)
const dd = parseInt(birDayCode.substring(6), 10)
const xdata = new Date(yyyy, mm - 1, dd)
if (xdata > new Date()) {
return false // 生日不能大于当前日期
} else {
return (
xdata.getFullYear() == yyyy &&
xdata.getMonth() == mm - 1 &&
xdata.getDate() == dd
)
}
},
/* 验证校检码 */
checkParityBit(idCardNo) {
const parityBit = idCardNo.charAt(17).toUpperCase()
return this.getParityBit(idCardNo) == parityBit
},
// 校验15位的身份证号码
check15IdCardNo(idCardNo) {
// 15位身份证号码的基本校验
let check = /^[1-9]\d{7}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}$/.test(
idCardNo
)
if (!check) return false
// 校验地址码
const addressCode = idCardNo.substring(0, 6)
check = this.checkAddressCode(addressCode)
if (!check) return false
const birDayCode = '19' + idCardNo.substring(6, 12)
// 校验日期码
return this.checkBirthDayCode(birDayCode)
},
// 校验18位的身份证号码
check18IdCardNo(idCardNo) {
// 18位身份证号码的基本格式校验
let check = /^[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
)
if (!check) return false
// 校验地址码
const addressCode = idCardNo.substring(0, 6)
check = this.checkAddressCode(addressCode)
if (!check) return false
// 校验日期码
const birDayCode = idCardNo.substring(6, 14)
check = this.checkBirthDayCode(birDayCode)
if (!check) return false
// 验证校检码
return this.checkParityBit(idCardNo)
},
/* 计算校检码 */
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(PARAMS.powers[i])
}
/* 取模 */
const mod = power % 11
return PARAMS.parityBit[mod]
}
}
export default class Identity {
constructor(code) {
this.code = this.getId18(code)
this.init()
}
init() {
const {code} = this
if (!!code) {
this.hideCode = Identity.hideId(code)
this.getIdCardInfo(code)
}
}
static hideId(code) {
return code?.replace(/^(\d{10})\d{4}(.{4}$)/g, `$1${Array(5).join('*')}$2`)
}
getId18(code) {
if (code.length == 15) {
const id17 = code.substring(0, 6) + '19' + code.substring(6)
const parityBit = Check.getParityBit(id17)
return id17 + parityBit
} else if (code.length == 18) {
return code
} else {
return null
}
}
getIdCardInfo(idCardNo) {
this.birthday = Identity.getBirthday(idCardNo)
this.sex = Identity.getSex(idCardNo)
this.gender = PARAMS.genders[this.sex]
this.age = Identity.getAge(idCardNo)
this.areaId = Identity.getArea(idCardNo)
}
/**
* 获取性别
* @param code
* @returns {string}
*/
static getSex(code) {
return (Number(code.substring(16, 17)) % 2).toString()
}
/**
* 获取年龄
* @param code
* @returns {number}
*/
static getAge(code) {
const birthday = dayjs(code.substring(6, 14), 'YYYYMMDD')
return Math.ceil(dayjs.duration(dayjs().unix() - dayjs(birthday).unix(), 's').asYears())
}
/**
* 获取地区编码
* @param code
*/
static getArea(code) {
return code.substring(0, 6) + new Array(7).join(0)
}
/**
* 获取生日
*/
static getBirthday(code) {
return dayjs(code.substring(6, 14), 'YYYYMMDD').format("YYYY-MM-DD").replace('Invalid Date', '')
}
/* 校验15位或18位的身份证号码 */
static check(idCardNo) {
// 15位和18位身份证号码的基本校验
const check = /^\d{15}|(\d{17}(\d|x|X))$/.test(idCardNo)
if (!check) return false
// 判断长度为15位或18位
if (idCardNo.length == 15) {
return Check.check15IdCardNo(idCardNo)
} else if (idCardNo.length == 18) {
return Check.check18IdCardNo(idCardNo)
} else {
return false
}
}
}