<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">身份证校验脚本 (国家标准 GB/T 2260-2007)</title>
<style>
* {
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Roboto, system-ui, sans-serif;
background: linear-gradient(145deg, #f5f7fc 0%, #e9ecf3 100%);
min-height: 100vh;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.card {
background: rgba(255, 255, 255, 0.75);
backdrop-filter: blur(8px);
border-radius: 36px;
box-shadow: 0 20px 40px rgba(0, 10, 30, 0.12), 0 6px 12px rgba(0, 0, 0, 0.02);
padding: 32px 28px;
width: 100%;
max-width: 560px;
transition: all 0.2s ease;
border: 1px solid rgba(255, 255, 255, 0.5);
}
h2 {
font-weight: 600;
font-size: 1.8rem;
margin-top: 0.1rem;
margin-bottom: 0.25rem;
color: #1a2639;
letter-spacing: -0.02em;
display: flex;
align-items: center;
gap: 8px;
}
.subhead {
color: #4a5a72;
margin-top: -4px;
margin-bottom: 28px;
font-weight: 400;
font-size: 0.95rem;
border-left: 3px solid #2b7be4;
padding-left: 14px;
background: rgba(43, 123, 228, 0.04);
border-radius: 0 8px 8px 0;
}
.input-group {
display: flex;
gap: 12px;
flex-wrap: wrap;
margin-bottom: 20px;
}
.input-wrapper {
flex: 1;
min-width: 200px;
}
.input-wrapper input {
width: 100%;
padding: 14px 18px;
border-radius: 60px;
border: 1px solid #d0d9e6;
background: white;
font-size: 1rem;
transition: 0.2s;
box-shadow: inset 0 1px 4px rgba(0,0,0,0.02);
font-weight: 500;
letter-spacing: 1px;
}
.input-wrapper input:focus {
outline: none;
border-color: #2b7be4;
box-shadow: 0 0 0 4px rgba(43, 123, 228, 0.2);
}
.input-wrapper input::placeholder {
color: #a6b3c9;
font-weight: 400;
letter-spacing: 0;
}
button {
background: #1a2639;
border: none;
color: white;
font-weight: 600;
padding: 14px 28px;
border-radius: 60px;
font-size: 1rem;
cursor: pointer;
transition: 0.2s;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
white-space: nowrap;
box-shadow: 0 6px 12px rgba(26, 38, 57, 0.15);
border: 1px solid rgba(255,255,255,0.1);
letter-spacing: 0.3px;
flex-shrink: 0;
}
button:hover {
background: #2b3b55;
transform: scale(0.98);
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
button:active {
background: #0f1827;
transform: scale(0.96);
}
.result-area {
background: white;
border-radius: 24px;
padding: 18px 22px;
margin: 20px 0 14px;
min-height: 80px;
border: 1px solid #eef2f8;
box-shadow: inset 0 2px 6px rgba(0,0,0,0.02);
word-break: break-word;
font-size: 0.95rem;
}
.result-area .label {
color: #5a6f8c;
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 8px;
display: flex;
gap: 12px;
align-items: baseline;
}
.result-area .label span {
background: #eef2f8;
padding: 2px 12px;
border-radius: 40px;
font-size: 0.7rem;
color: #2b3b55;
}
.result-content {
font-size: 1.1rem;
color: #1a2639;
line-height: 1.5;
}
.result-content .valid {
color: #1e7e34;
font-weight: 600;
}
.result-content .invalid {
color: #b13e3e;
font-weight: 600;
}
.detail-stack {
margin-top: 6px;
font-size: 0.9rem;
color: #345;
display: flex;
flex-direction: column;
gap: 4px;
}
.detail-stack span {
background: #f2f5fa;
padding: 2px 12px 2px 8px;
border-radius: 30px;
display: inline-block;
width: fit-content;
}
.example-area {
margin-top: 18px;
display: flex;
flex-wrap: wrap;
gap: 10px 16px;
font-size: 0.8rem;
color: #5a6f8c;
border-top: 1px solid #dce2ed;
padding-top: 16px;
}
.example-area span {
cursor: pointer;
background: #ecf0f7;
padding: 4px 14px;
border-radius: 40px;
transition: 0.1s;
font-family: 'SF Mono', 'Fira Code', monospace;
letter-spacing: 0.2px;
font-weight: 500;
}
.example-area span:hover {
background: #d3dcec;
color: #0f1827;
}
.example-area .ex-label {
background: transparent;
padding: 4px 0;
cursor: default;
font-weight: 400;
color: #4a5a72;
}
.footer-note {
margin-top: 12px;
font-size: 0.7rem;
color: #6b7d99;
text-align: right;
opacity: 0.7;
}
@media (max-width: 480px) {
.card { padding: 24px 18px; }
button { width: 100%; }
.input-group { flex-direction: column; }
}
</style>
</head>
<body>
<div class="card">
<h2>🆔 身份证校验</h2>
<div class="subhead">依据 GB/T 2260-2007 · 18位校验码</div>
<div class="input-group">
<div class="input-wrapper">
<input type="text" id="idInput" placeholder="输入 18 位身份证号" maxlength="18" autocomplete="off" value="11010519491231002X">
</div>
<button id="checkBtn">🔍 校验</button>
</div>
<div class="result-area" id="resultBox">
<div class="label">
📋 校验结果
<span id="statusBadge">就绪</span>
</div>
<div class="result-content" id="resultContent">
点击「校验」或按回车
</div>
<div class="detail-stack" id="detailStack"></div>
</div>
<div class="example-area">
<span class="ex-label">⚡ 快速填入</span>
<span data-example="11010519491231002X">11010519491231002X</span>
<span data-example="440308199901104076">440308199901104076</span>
<span data-example="123456789012345678">123456789012345678</span>
</div>
<div class="footer-note">支持大小写X · 实时校验</div>
</div>
<script>
(function() {
// ----- 核心校验函数 (严格遵循国家标准) -----
function validateIdCard(id) {
// 统一转为大写
const raw = id.trim().toUpperCase();
const result = {
valid: false,
raw: raw,
reason: '',
// 额外信息
areaCode: '',
birthDate: '',
gender: '',
checkDigit: '',
expectedCheck: ''
};
// 1. 基本长度与格式 (18位, 前17位数字, 第18位数字或X)
if (raw.length !== 18) {
result.reason = '长度必须为18位';
return result;
}
const regex = /^[0-9]{17}[0-9X]$/;
if (!regex.test(raw)) {
result.reason = '格式错误:前17位需为数字,第18位为数字或X';
return result;
}
// 2. 加权因子与校验码表
const weights = [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++) {
const digit = parseInt(raw[i], 10);
if (isNaN(digit)) {
result.reason = '前17位包含非数字字符';
return result;
}
sum += digit * weights[i];
}
const remainder = sum % 11;
const expectedCheck = checkCodes[remainder];
const actualCheck = raw[17];
result.checkDigit = actualCheck;
result.expectedCheck = expectedCheck;
// 校验码不匹配
if (actualCheck !== expectedCheck) {
result.reason = `校验码错误:期望 ${expectedCheck},实际 ${actualCheck}`;
return result;
}
// 3. 校验出生日期 (第7-14位)
const birthStr = raw.substring(6, 14);
const year = parseInt(birthStr.substring(0, 4), 10);
const month = parseInt(birthStr.substring(4, 6), 10);
const day = parseInt(birthStr.substring(6, 8), 10);
const date = new Date(year, month - 1, day);
const isValidDate = (
date.getFullYear() === year &&
date.getMonth() === month - 1 &&
date.getDate() === day &&
year >= 1800 && year <= 2100 // 合理范围
);
if (!isValidDate) {
result.reason = `出生日期无效:${birthStr.substring(0,4)}-${birthStr.substring(4,6)}-${birthStr.substring(6,8)}`;
return result;
}
// 额外:地区代码简单检查 (前6位为数字,不深入校验)
const areaCode = raw.substring(0, 6);
result.areaCode = areaCode;
// 出生日期占位
result.birthDate = `${year}-${String(month).padStart(2,'0')}-${String(day).padStart(2,'0')}`;
// 性别 (第17位, 索引16)
const genderDigit = parseInt(raw[16], 10);
result.gender = (genderDigit % 2 === 0) ? '女' : '男';
// 所有校验通过
result.valid = true;
result.reason = '✅ 合法的身份证号码';
return result;
}
// ----- DOM 元素 -----
const inputEl = document.getElementById('idInput');
const checkBtn = document.getElementById('checkBtn');
const resultContent = document.getElementById('resultContent');
const detailStack = document.getElementById('detailStack');
const statusBadge = document.getElementById('statusBadge');
// 快速填入示例
document.querySelectorAll('[data-example]').forEach(el => {
el.addEventListener('click', function() {
inputEl.value = this.dataset.example;
// 自动触发校验
performValidation();
});
});
// 执行校验 & 渲染
function performValidation() {
const id = inputEl.value;
const res = validateIdCard(id);
// 更新 badge
statusBadge.textContent = res.valid ? '有效' : '无效';
statusBadge.style.background = res.valid ? '#d4edda' : '#f8d7da';
statusBadge.style.color = res.valid ? '#155724' : '#721c24';
statusBadge.style.padding = '2px 14px';
statusBadge.style.borderRadius = '40px';
// 更新主结果
if (res.raw === '') {
resultContent.innerHTML = '⚠️ 请输入身份证号码';
detailStack.innerHTML = '';
return;
}
if (res.valid) {
resultContent.innerHTML = `<span class="valid">✔ 校验通过</span> · ${res.raw}`;
// 详细信息
detailStack.innerHTML = `
<span>📍 地区码: ${res.areaCode}</span>
<span>🎂 出生日期: ${res.birthDate}</span>
<span>⚥ 性别: ${res.gender}</span>
<span>🔢 校验位: ${res.checkDigit} (正确)</span>
`;
} else {
resultContent.innerHTML = `<span class="invalid">✘ 校验失败</span> · ${res.raw}`;
let extra = '';
if (res.expectedCheck && res.checkDigit) {
extra = `<span>期望校验位: ${res.expectedCheck} · 实际: ${res.checkDigit}</span>`;
}
detailStack.innerHTML = `
<span style="background:#fbecec; color:#a94442;">❗ ${res.reason}</span>
${extra}
`;
// 如果没有任何额外信息但错误原因存在
if (!extra && res.reason) {
detailStack.innerHTML = `<span style="background:#fbecec; color:#a94442;">❗ ${res.reason}</span>`;
}
// 显示地区 / 出生日期片段 (若解析部分)
if (res.areaCode && /^\d{6}$/.test(res.areaCode)) {
detailStack.innerHTML += `<span>📍 地区码: ${res.areaCode}</span>`;
}
if (res.birthDate) {
detailStack.innerHTML += `<span>🎂 出生日期: ${res.birthDate}</span>`;
}
}
}
// 绑定事件
checkBtn.addEventListener('click', performValidation);
inputEl.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
e.preventDefault();
performValidation();
}
});
// 初始化: 校验默认值 (11010519491231002X)
window.addEventListener('DOMContentLoaded', function() {
performValidation();
});
// 自动trim防误触
inputEl.addEventListener('blur', function() {
this.value = this.value.trim();
});
})();
</script>
</body>
</html>
校验逻辑与交互说明
您只需输入18位身份证号,脚本便会自动完成多项校验并清晰反馈结果。

- 核心校验流程:脚本会依次检查号码的长度、格式、校验码以及出生日期的有效性,校验码的计算严格遵循国家标准中的加权因子和校验码表。
- 交互与反馈:您可以直接在输入框中输入号码,点击“校验”按钮或按回车键即可触发验证,结果区域会清晰显示“有效”或“无效”,并附带地区码、出生日期、性别等详细信息,如果校验失败,还会明确指出具体原因,校验码错误”或“出生日期无效”。
- 便捷功能:页面提供了几个示例号码,点击即可快速填入并自动校验,方便您测试脚本的运行效果。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播