| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- /**
- * 身份证号验证工具
- *
- * 提供严格的18位身份证号校验:
- * - 格式校验
- * - 出生日期校验
- * - 校验码验证(ISO 7064:1983.MOD 11-2)
- */
- // 加权因子
- const WEIGHT_FACTORS = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
- // 校验码对应值
- const CHECK_CODES = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
- /**
- * 验证身份证号格式
- */
- function validateFormat(idCard: string): { valid: boolean; error: string } {
- // 必须是18位
- if (idCard.length !== 18) {
- return { valid: false, error: '身份证号必须为18位' };
- }
- // 前17位必须是数字,最后一位是数字或X
- if (!/^\d{17}[\dXx]$/.test(idCard)) {
- return { valid: false, error: '身份证号格式不正确' };
- }
- return { valid: true, error: '' };
- }
- /**
- * 验证出生日期
- */
- function validateBirthDate(idCard: string): { valid: boolean; error: string } {
- // 提取出生日期(第7-14位)
- const year = idCard.substring(6, 10);
- const month = idCard.substring(10, 12);
- const day = idCard.substring(12, 14);
- // 验证年份(1900-当前年份)
- const yearInt = parseInt(year, 10);
- const currentYear = new Date().getFullYear();
- if (yearInt < 1900 || yearInt > currentYear) {
- return { valid: false, error: `出生年份不合法(应在1900-${currentYear}之间)` };
- }
- // 验证月份(01-12)
- const monthInt = parseInt(month, 10);
- if (monthInt < 1 || monthInt > 12) {
- return { valid: false, error: '出生月份不合法(应在01-12之间)' };
- }
- // 验证日期
- const dayInt = parseInt(day, 10);
- const birthDate = new Date(yearInt, monthInt - 1, dayInt);
- // 检查日期是否有效
- if (
- birthDate.getFullYear() !== yearInt ||
- birthDate.getMonth() !== monthInt - 1 ||
- birthDate.getDate() !== dayInt
- ) {
- return { valid: false, error: '出生日期不合法' };
- }
- // 不能是未来日期
- if (birthDate > new Date()) {
- return { valid: false, error: '出生日期不能是未来日期' };
- }
- return { valid: true, error: '' };
- }
- /**
- * 验证校验码(ISO 7064:1983.MOD 11-2)
- */
- function validateCheckCode(idCard: string): { valid: boolean; error: string } {
- // 计算校验码
- let sum = 0;
- for (let i = 0; i < 17; i++) {
- sum += parseInt(idCard[i], 10) * WEIGHT_FACTORS[i];
- }
- // 取模得到校验码索引
- const checkIndex = sum % 11;
- const expectedCheckCode = CHECK_CODES[checkIndex];
- // 比较校验码(不区分大小写)
- const actualCheckCode = idCard[17].toUpperCase();
- if (actualCheckCode !== expectedCheckCode) {
- return { valid: false, error: '身份证号校验码错误' };
- }
- return { valid: true, error: '' };
- }
- /**
- * 完整验证身份证号
- */
- export function validateIDCard(idCard: string): { valid: boolean; error: string } {
- // 转大写并去除空格
- const cleanedIDCard = idCard.toUpperCase().trim();
- // 格式验证
- let result = validateFormat(cleanedIDCard);
- if (!result.valid) return result;
- // 出生日期验证
- result = validateBirthDate(cleanedIDCard);
- if (!result.valid) return result;
- // 校验码验证
- result = validateCheckCode(cleanedIDCard);
- if (!result.valid) return result;
- return { valid: true, error: '' };
- }
- /**
- * 验证真实姓名
- *
- * 规则:
- * - 纯汉字
- * - 无特殊符号、无空格
- * - 长度2-20位
- */
- export function validateRealName(name: string): { valid: boolean; error: string } {
- // 去除首尾空格
- const trimmedName = name.trim();
- // 长度验证(2-20位)
- if (trimmedName.length < 2 || trimmedName.length > 20) {
- return { valid: false, error: '姓名长度应为2-20个字符' };
- }
- // 纯汉字验证(不允许特殊符号、空格)
- if (!/^[\u4e00-\u9fa5]+$/.test(trimmedName)) {
- return { valid: false, error: '姓名只能包含汉字,不能有空格或特殊符号' };
- }
- return { valid: true, error: '' };
- }
|