is/idcard.js

/**
 * @description 返回是否是有效身份证
 * @author grantguo <https://github.com/ForeverGuo>
 * @category is
 * @alias is_idcard
 * @param { string } card
 * @return 返回是否是有效身份证
 * @summary 返回是否是有效身份证
 * @example
 * is_card(card)
 * => true or false
 */

export default (card) => {
  let cardNo = card;
  const len = cardNo.length;

  if (len === 15) {
    cardNo = convert15To18(cardNo);
  }
  return validate18IdCard(cardNo);
};

function convert15To18 (idCard) {
  if (idCard.length !== 15) {
    return null; // 如果不是15位身份证号码,返回null
  }

  const id17 = idCard.substring(0, 6) + '19' + idCard.substring(6); // 在出生年份前加上"19"
  const power = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; // 加权因子
  const checkCode = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']; // 校验码对应值
  let sum = 0;

  for (let i = 0; i < 17; i++) {
    sum += Number(id17.charAt(i)) * power[i];
  }

  const mod = sum % 11;
  const checkBit = checkCode[mod];

  return id17 + checkBit; // 返回18位身份证号码
}

function validate18IdCard (idNumber) {
  // 正则表达式匹配身份证号码的规则
  const pattern = /^\d{17}[\dXx]$/;

  if (!pattern.test(idNumber)) {
    return false;
  }

  // 加权因子
  const weightFactor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
  // 校验位
  const checkCodeList = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];

  // 计算校验位
  let sum = 0;
  for (let i = 0; i < 17; i++) {
    sum += Number(idNumber[i]) * weightFactor[i];
  }
  const mod = sum % 11;
  const checkCode = checkCodeList[mod];

  // 校验校验位
  if (idNumber[17].toUpperCase() === checkCode) {
    return true;
  } else {
    return false;
  }
}