You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
2.6 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!-- components/IDCardInput.vue -->
<template>
<view class="idcard-input-wrapper">
<input v-model="inputValue" class="idcard-input" placeholder="请输入18位身份证号码" type="text" maxlength="18"
@input="handleInput" @blur="handleBlur" />
<text v-if="showClear && inputValue" class="clear-btn" @click="clearInput">×</text>
</view>
</template>
<script setup>
import {
ref,
watch
} from 'vue';
const props = defineProps({
modelValue: String,
showClear: {
type: Boolean,
default: true
}
});
const emit = defineEmits(['update:modelValue', 'change']);
const inputValue = ref(props.modelValue || '');
// 处理输入
const handleInput = (e) => {
const value = e.detail.value.toUpperCase();
inputValue.value = value;
emit('update:modelValue', value);
// 验证身份证格式
const isValid = validateIDCard(value);
emit('change', value, isValid);
};
// 失焦验证
const handleBlur = () => {
const isValid = validateIDCard(inputValue.value);
emit('change', inputValue.value, isValid);
};
// 清空输入
const clearInput = () => {
inputValue.value = '';
emit('update:modelValue', '');
emit('change', '', false);
};
// 身份证验证函数
const validateIDCard = (idCard) => {
if (!idCard) return false;
// 基本格式验证
const reg = /^[1-9]\d{5}(19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
if (!reg.test(idCard)) return false;
// 校验码验证
const idCardArray = idCard.split('');
const factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
const parity = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
let sum = 0;
for (let i = 0; i < 17; i++) {
sum += parseInt(idCardArray[i]) * factor[i];
}
const mod = sum % 11;
return parity[mod] === idCardArray[17].toUpperCase();
};
// 监听外部值变化
watch(() => props.modelValue, (newVal) => {
if (newVal !== inputValue.value) {
inputValue.value = newVal || '';
}
});
</script>
<style scoped>
.idcard-input-wrapper {
position: relative;
}
.idcard-input {
width: 100%;
height: 88rpx;
border: 2rpx solid #e0e0e0;
border-radius: 12rpx;
padding: 0 60rpx 0 24rpx;
font-size: 28rpx;
background: #fafafa;
box-sizing: border-box;
font-family: monospace;
}
.idcard-input:focus {
border-color: #007AFF;
background: white;
}
.clear-btn {
position: absolute;
right: 24rpx;
top: 50%;
transform: translateY(-50%);
font-size: 36rpx;
color: #999;
width: 40rpx;
height: 40rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background: rgba(0, 0, 0, 0.1);
}
</style>