hookehuyr

feat(证件类型): 添加证件类型选择功能并优化证件号码验证

- 在搜索和添加参观者页面增加证件类型选择器
- 根据证件类型动态调整证件号码输入长度限制
- 优化证件号码验证逻辑,支持不同类型证件
- 重构二维码查询组件,支持按证件类型查询
......@@ -35,34 +35,22 @@
</template>
<script setup>
import { ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { Cookies, axios, storeToRefs, mainStore, Toast, useTitle } from '@/utils/generatePackage.js'
//import { } from '@/utils/generateModules.js'
//import { } from '@/utils/generateIcons.js'
//import { } from '@/composables'
import { formatDatetime } from '@/utils/tools';
import { qrcodeListAPI, qrcodeStatusAPI, billPersonAPI, queryQrCodeAPI } from '@/api/index'
const $route = useRoute();
const $router = useRouter();
useTitle($route.meta.title);
import { qrcodeStatusAPI, queryQrCodeAPI } from '@/api/index'
const props = defineProps({
id: {
type: String,
default: ''
},
id_type: {
type: Number,
default: 1,
}
});
const userinfo = ref({});
watch(
() => props.id,
async (id) => {
console.warn(id);
}
)
/**
* 生成15位身份证号中间8位替换为*号
* @param {*} inputString
......@@ -101,44 +89,54 @@ const STATUS_CODE = {
USED: '7',
};
const formatStatus = (status) => {
switch (status) {
case 'success':
return {
key: 'success',
value: '预约成功'
}
case 'cancel':
return {
key: 'cancel',
value: '已取消'
const resetState = () => {
userinfo.value = {}
useStatus.value = '0'
}
const loadQrCodeInfo = async () => {
const id_number = String(props.id || '').trim()
if (!id_number) {
resetState()
return
}
case 'used':
return {
key: 'used',
value: '已使用'
const params = { id_number }
if (props.id_type) params.id_type = props.id_type
const { code, data } = await queryQrCodeAPI(params);
if (!code || !data) {
resetState()
return
}
const raw = Array.isArray(data) ? data?.[0] : data
if (!raw?.qr_code) {
resetState()
return
}
}
onMounted(async () => {
if (props.id) {
const { code, data } = await queryQrCodeAPI({ id_number: props.id });
if (code) {
userinfo.value = {
id: formatId(props.id),
name: data?.name,
datetime: formatDatetime({ begin_time: data?.begin_time, end_time: data?.end_time }),
qr_code: data?.qr_code,
qr_code_url: '/admin?m=srv&a=get_qrcode&key=' + data?.qr_code,
id: formatId(id_number),
name: raw?.name,
datetime: formatDatetime({ begin_time: raw?.begin_time, end_time: raw?.end_time }),
qr_code: raw?.qr_code,
qr_code_url: '/admin?m=srv&a=get_qrcode&key=' + encodeURIComponent(String(raw?.qr_code)),
}
const { code: status_code, data: status_data } = await qrcodeStatusAPI({ qr_code: data?.qr_code });
const { code: status_code, data: status_data } = await qrcodeStatusAPI({ qr_code: raw?.qr_code });
if (status_code) {
useStatus.value = status_data.status;
useStatus.value = String(status_data.status);
}
}
}
});
}
watch(
() => [props.id, props.id_type],
() => {
loadQrCodeInfo()
},
{ immediate: true }
)
// 定义轮询函数
const poll = async () => {
......
<!--
* @Date: 2024-01-15 17:39:29
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-01-30 15:21:50
* @FilePath: /xysBooking/src/views/addVisitor.vue
* @LastEditTime: 2026-01-22 11:39:55
* @FilePath: /git/xysBooking/src/views/addVisitor.vue
* @Description: 添加参观者页面
-->
<template>
......@@ -15,17 +15,14 @@
</div>
<div class="input-item">
<div>证件类型</div>
<!-- <div @click="idTypeChange">
<div @click="idTypeChange">
{{ fieldValue }}&nbsp;<van-icon name="arrow-down" />
</div> -->
<div>
{{ fieldValue }}
</div>
</div>
<div class="input-item">
<div>证件号码</div>
<div>
<input type="text" v-model="idCode" placeholder="请输入证件号码" @blur="checkIdCode" maxlength="18" style="width: 100%;">
<input type="text" v-model="idCode" placeholder="请输入证件号码" @blur="checkIdCode" :maxlength="id_type === 1 ? 18 : 30" style="width: 100%;">
</div>
</div>
<div style="color:#A67939; font-size: 0.85rem;">
......@@ -87,6 +84,13 @@ const checkUsername = () => { // 检查用户名是否为空
const checkIdCode = () => { // 检查身份证号是否为空
let flag = true;
if (!idCode.value) {
show_error.value = true;
error_message.value = '请输入证件号码';
flag = false;
return flag;
}
if (id_type.value !== 1) return true;
if (idCode.value.length === 15) { // 15位身份证号码不校验
flag = true;
} else {
......@@ -102,9 +106,12 @@ const checkIdCode = () => { // 检查身份证号是否为空
const addVisitor = async () => {
// 保存用户信息
if (checkUsername() && checkIdCode()) {
const { code, data } = await addPersonAPI({ name: username.value, id_type: id_type.value, id_number: idCode.value });
const { code, msg } = await addPersonAPI({ name: username.value, id_type: id_type.value, id_number: idCode.value });
if (code) {
$router.go(-1);
} else {
show_error.value = true;
error_message.value = msg || '添加失败';
}
}
}
......@@ -114,12 +121,12 @@ const idTypeChange = () => {
showPicker.value = !showPicker.value;
}
const columns = [
{ text: '身份证', value: '1' },
{ text: '其他证件', value: '3' },
{ text: '身份证', value: 1 },
{ text: '其他', value: 3 },
];
const fieldValue = ref('身份证');
const id_type = ref('1');
const id_type = ref(1);
const onConfirm = ({ selectedOptions }) => { // 切换类型回调
showPicker.value = false;
......
......@@ -9,10 +9,16 @@
<div class="search-page">
<div>
<div v-if="!is_search">
<div class="input-item" @click="idTypeChange">
<div>证件类型</div>
<div>
{{ fieldValue }}&nbsp;<van-icon name="arrow-down" />
</div>
</div>
<div class="input-item">
<div>证件号码</div>
<div>
<input type="text" v-model="idCode" placeholder="请输入证件号码" @blur="checkIdCode" maxlength="18" style="width: 100%;">
<input type="text" v-model="idCode" placeholder="请输入证件号码" @blur="checkIdCode" :maxlength="id_type === 1 ? 18 : 30" style="width: 100%;">
</div>
</div>
<div style="color:#A67939; font-size: 0.95rem; text-align: center;">
......@@ -23,7 +29,7 @@
</div>
</div>
<div v-else>
<qrCodeSearch :id="id_number" />
<qrCodeSearch :id="id_number" :id_type="id_type" />
</div>
<div v-if="!is_search" class="save-wrapper">
<div class="save-btn" @click="searchBtn">查询</div>
......@@ -35,6 +41,14 @@
</div>
<div class="logo"></div>
<van-popup v-model:show="showPicker" position="bottom">
<van-picker
:columns="columns"
@cancel="showPicker = false"
@confirm="onConfirm"
/>
</van-popup>
<van-toast v-model:show="show_error" style="">
<template #message>
{{ error_message }}
......@@ -70,6 +84,13 @@ const error_message = ref('');
const checkIdCode = () => { // 检查身份证号是否为空
let flag = true;
if (!idCode.value) {
show_error.value = true;
error_message.value = '请输入证件号码';
flag = false;
return flag;
}
if (id_type.value !== 1) return true;
if (idCode.value.length === 15) { // 15位身份证号码不校验
flag = true;
} else {
......@@ -96,6 +117,24 @@ const goBack = () => {
const goToHome = () => {
go('/')
}
const showPicker = ref(false);
const idTypeChange = () => {
showPicker.value = !showPicker.value;
}
const columns = [
{ text: '身份证', value: 1 },
{ text: '其他', value: 3 },
];
const fieldValue = ref('身份证');
const id_type = ref(1);
const onConfirm = ({ selectedOptions }) => { // 切换类型回调
showPicker.value = false;
fieldValue.value = selectedOptions[0].text;
id_type.value = selectedOptions[0].value;
};
</script>
<style lang="less" scoped>
......