hookehuyr

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

- 在搜索和添加参观者页面增加证件类型选择器
- 根据证件类型动态调整证件号码输入长度限制
- 优化证件号码验证逻辑,支持不同类型证件
- 重构二维码查询组件,支持按证件类型查询
...@@ -35,34 +35,22 @@ ...@@ -35,34 +35,22 @@
35 </template> 35 </template>
36 36
37 <script setup> 37 <script setup>
38 -import { ref } from 'vue'
39 -import { useRoute, useRouter } from 'vue-router'
40 -import { Cookies, axios, storeToRefs, mainStore, Toast, useTitle } from '@/utils/generatePackage.js'
41 -//import { } from '@/utils/generateModules.js'
42 -//import { } from '@/utils/generateIcons.js'
43 -//import { } from '@/composables'
44 import { formatDatetime } from '@/utils/tools'; 38 import { formatDatetime } from '@/utils/tools';
45 -import { qrcodeListAPI, qrcodeStatusAPI, billPersonAPI, queryQrCodeAPI } from '@/api/index' 39 +import { qrcodeStatusAPI, queryQrCodeAPI } from '@/api/index'
46 -const $route = useRoute();
47 -const $router = useRouter();
48 -useTitle($route.meta.title);
49 40
50 const props = defineProps({ 41 const props = defineProps({
51 id: { 42 id: {
52 type: String, 43 type: String,
53 default: '' 44 default: ''
54 }, 45 },
46 + id_type: {
47 + type: Number,
48 + default: 1,
49 + }
55 }); 50 });
56 51
57 const userinfo = ref({}); 52 const userinfo = ref({});
58 53
59 -watch(
60 - () => props.id,
61 - async (id) => {
62 - console.warn(id);
63 - }
64 -)
65 -
66 /** 54 /**
67 * 生成15位身份证号中间8位替换为*号 55 * 生成15位身份证号中间8位替换为*号
68 * @param {*} inputString 56 * @param {*} inputString
...@@ -101,44 +89,54 @@ const STATUS_CODE = { ...@@ -101,44 +89,54 @@ const STATUS_CODE = {
101 USED: '7', 89 USED: '7',
102 }; 90 };
103 91
104 -const formatStatus = (status) => { 92 +const resetState = () => {
105 - switch (status) { 93 + userinfo.value = {}
106 - case 'success': 94 + useStatus.value = '0'
107 - return { 95 +}
108 - key: 'success', 96 +
109 - value: '预约成功' 97 +const loadQrCodeInfo = async () => {
110 - } 98 + const id_number = String(props.id || '').trim()
111 - case 'cancel': 99 + if (!id_number) {
112 - return { 100 + resetState()
113 - key: 'cancel', 101 + return
114 - value: '已取消'
115 } 102 }
116 - case 'used': 103 +
117 - return { 104 + const params = { id_number }
118 - key: 'used', 105 + if (props.id_type) params.id_type = props.id_type
119 - value: '已使用' 106 +
107 + const { code, data } = await queryQrCodeAPI(params);
108 + if (!code || !data) {
109 + resetState()
110 + return
120 } 111 }
112 +
113 + const raw = Array.isArray(data) ? data?.[0] : data
114 + if (!raw?.qr_code) {
115 + resetState()
116 + return
121 } 117 }
122 -}
123 118
124 -onMounted(async () => {
125 - if (props.id) {
126 - const { code, data } = await queryQrCodeAPI({ id_number: props.id });
127 - if (code) {
128 userinfo.value = { 119 userinfo.value = {
129 - id: formatId(props.id), 120 + id: formatId(id_number),
130 - name: data?.name, 121 + name: raw?.name,
131 - datetime: formatDatetime({ begin_time: data?.begin_time, end_time: data?.end_time }), 122 + datetime: formatDatetime({ begin_time: raw?.begin_time, end_time: raw?.end_time }),
132 - qr_code: data?.qr_code, 123 + qr_code: raw?.qr_code,
133 - qr_code_url: '/admin?m=srv&a=get_qrcode&key=' + data?.qr_code, 124 + qr_code_url: '/admin?m=srv&a=get_qrcode&key=' + encodeURIComponent(String(raw?.qr_code)),
134 } 125 }
135 - const { code: status_code, data: status_data } = await qrcodeStatusAPI({ qr_code: data?.qr_code }); 126 +
127 + const { code: status_code, data: status_data } = await qrcodeStatusAPI({ qr_code: raw?.qr_code });
136 if (status_code) { 128 if (status_code) {
137 - useStatus.value = status_data.status; 129 + useStatus.value = String(status_data.status);
138 } 130 }
139 - } 131 +}
140 - } 132 +
141 -}); 133 +watch(
134 + () => [props.id, props.id_type],
135 + () => {
136 + loadQrCodeInfo()
137 + },
138 + { immediate: true }
139 +)
142 140
143 // 定义轮询函数 141 // 定义轮询函数
144 const poll = async () => { 142 const poll = async () => {
......
1 <!-- 1 <!--
2 * @Date: 2024-01-15 17:39:29 2 * @Date: 2024-01-15 17:39:29
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2024-01-30 15:21:50 4 + * @LastEditTime: 2026-01-22 11:39:55
5 - * @FilePath: /xysBooking/src/views/addVisitor.vue 5 + * @FilePath: /git/xysBooking/src/views/addVisitor.vue
6 * @Description: 添加参观者页面 6 * @Description: 添加参观者页面
7 --> 7 -->
8 <template> 8 <template>
...@@ -15,17 +15,14 @@ ...@@ -15,17 +15,14 @@
15 </div> 15 </div>
16 <div class="input-item"> 16 <div class="input-item">
17 <div>证件类型</div> 17 <div>证件类型</div>
18 - <!-- <div @click="idTypeChange"> 18 + <div @click="idTypeChange">
19 {{ fieldValue }}&nbsp;<van-icon name="arrow-down" /> 19 {{ fieldValue }}&nbsp;<van-icon name="arrow-down" />
20 - </div> -->
21 - <div>
22 - {{ fieldValue }}
23 </div> 20 </div>
24 </div> 21 </div>
25 <div class="input-item"> 22 <div class="input-item">
26 <div>证件号码</div> 23 <div>证件号码</div>
27 <div> 24 <div>
28 - <input type="text" v-model="idCode" placeholder="请输入证件号码" @blur="checkIdCode" maxlength="18" style="width: 100%;"> 25 + <input type="text" v-model="idCode" placeholder="请输入证件号码" @blur="checkIdCode" :maxlength="id_type === 1 ? 18 : 30" style="width: 100%;">
29 </div> 26 </div>
30 </div> 27 </div>
31 <div style="color:#A67939; font-size: 0.85rem;"> 28 <div style="color:#A67939; font-size: 0.85rem;">
...@@ -87,6 +84,13 @@ const checkUsername = () => { // 检查用户名是否为空 ...@@ -87,6 +84,13 @@ const checkUsername = () => { // 检查用户名是否为空
87 84
88 const checkIdCode = () => { // 检查身份证号是否为空 85 const checkIdCode = () => { // 检查身份证号是否为空
89 let flag = true; 86 let flag = true;
87 + if (!idCode.value) {
88 + show_error.value = true;
89 + error_message.value = '请输入证件号码';
90 + flag = false;
91 + return flag;
92 + }
93 + if (id_type.value !== 1) return true;
90 if (idCode.value.length === 15) { // 15位身份证号码不校验 94 if (idCode.value.length === 15) { // 15位身份证号码不校验
91 flag = true; 95 flag = true;
92 } else { 96 } else {
...@@ -102,9 +106,12 @@ const checkIdCode = () => { // 检查身份证号是否为空 ...@@ -102,9 +106,12 @@ const checkIdCode = () => { // 检查身份证号是否为空
102 const addVisitor = async () => { 106 const addVisitor = async () => {
103 // 保存用户信息 107 // 保存用户信息
104 if (checkUsername() && checkIdCode()) { 108 if (checkUsername() && checkIdCode()) {
105 - const { code, data } = await addPersonAPI({ name: username.value, id_type: id_type.value, id_number: idCode.value }); 109 + const { code, msg } = await addPersonAPI({ name: username.value, id_type: id_type.value, id_number: idCode.value });
106 if (code) { 110 if (code) {
107 $router.go(-1); 111 $router.go(-1);
112 + } else {
113 + show_error.value = true;
114 + error_message.value = msg || '添加失败';
108 } 115 }
109 } 116 }
110 } 117 }
...@@ -114,12 +121,12 @@ const idTypeChange = () => { ...@@ -114,12 +121,12 @@ const idTypeChange = () => {
114 showPicker.value = !showPicker.value; 121 showPicker.value = !showPicker.value;
115 } 122 }
116 const columns = [ 123 const columns = [
117 - { text: '身份证', value: '1' }, 124 + { text: '身份证', value: 1 },
118 - { text: '其他证件', value: '3' }, 125 + { text: '其他', value: 3 },
119 ]; 126 ];
120 127
121 const fieldValue = ref('身份证'); 128 const fieldValue = ref('身份证');
122 -const id_type = ref('1'); 129 +const id_type = ref(1);
123 130
124 const onConfirm = ({ selectedOptions }) => { // 切换类型回调 131 const onConfirm = ({ selectedOptions }) => { // 切换类型回调
125 showPicker.value = false; 132 showPicker.value = false;
......
...@@ -9,10 +9,16 @@ ...@@ -9,10 +9,16 @@
9 <div class="search-page"> 9 <div class="search-page">
10 <div> 10 <div>
11 <div v-if="!is_search"> 11 <div v-if="!is_search">
12 + <div class="input-item" @click="idTypeChange">
13 + <div>证件类型</div>
14 + <div>
15 + {{ fieldValue }}&nbsp;<van-icon name="arrow-down" />
16 + </div>
17 + </div>
12 <div class="input-item"> 18 <div class="input-item">
13 <div>证件号码</div> 19 <div>证件号码</div>
14 <div> 20 <div>
15 - <input type="text" v-model="idCode" placeholder="请输入证件号码" @blur="checkIdCode" maxlength="18" style="width: 100%;"> 21 + <input type="text" v-model="idCode" placeholder="请输入证件号码" @blur="checkIdCode" :maxlength="id_type === 1 ? 18 : 30" style="width: 100%;">
16 </div> 22 </div>
17 </div> 23 </div>
18 <div style="color:#A67939; font-size: 0.95rem; text-align: center;"> 24 <div style="color:#A67939; font-size: 0.95rem; text-align: center;">
...@@ -23,7 +29,7 @@ ...@@ -23,7 +29,7 @@
23 </div> 29 </div>
24 </div> 30 </div>
25 <div v-else> 31 <div v-else>
26 - <qrCodeSearch :id="id_number" /> 32 + <qrCodeSearch :id="id_number" :id_type="id_type" />
27 </div> 33 </div>
28 <div v-if="!is_search" class="save-wrapper"> 34 <div v-if="!is_search" class="save-wrapper">
29 <div class="save-btn" @click="searchBtn">查询</div> 35 <div class="save-btn" @click="searchBtn">查询</div>
...@@ -35,6 +41,14 @@ ...@@ -35,6 +41,14 @@
35 </div> 41 </div>
36 <div class="logo"></div> 42 <div class="logo"></div>
37 43
44 + <van-popup v-model:show="showPicker" position="bottom">
45 + <van-picker
46 + :columns="columns"
47 + @cancel="showPicker = false"
48 + @confirm="onConfirm"
49 + />
50 + </van-popup>
51 +
38 <van-toast v-model:show="show_error" style=""> 52 <van-toast v-model:show="show_error" style="">
39 <template #message> 53 <template #message>
40 {{ error_message }} 54 {{ error_message }}
...@@ -70,6 +84,13 @@ const error_message = ref(''); ...@@ -70,6 +84,13 @@ const error_message = ref('');
70 84
71 const checkIdCode = () => { // 检查身份证号是否为空 85 const checkIdCode = () => { // 检查身份证号是否为空
72 let flag = true; 86 let flag = true;
87 + if (!idCode.value) {
88 + show_error.value = true;
89 + error_message.value = '请输入证件号码';
90 + flag = false;
91 + return flag;
92 + }
93 + if (id_type.value !== 1) return true;
73 if (idCode.value.length === 15) { // 15位身份证号码不校验 94 if (idCode.value.length === 15) { // 15位身份证号码不校验
74 flag = true; 95 flag = true;
75 } else { 96 } else {
...@@ -96,6 +117,24 @@ const goBack = () => { ...@@ -96,6 +117,24 @@ const goBack = () => {
96 const goToHome = () => { 117 const goToHome = () => {
97 go('/') 118 go('/')
98 } 119 }
120 +
121 +const showPicker = ref(false);
122 +const idTypeChange = () => {
123 + showPicker.value = !showPicker.value;
124 +}
125 +const columns = [
126 + { text: '身份证', value: 1 },
127 + { text: '其他', value: 3 },
128 +];
129 +
130 +const fieldValue = ref('身份证');
131 +const id_type = ref(1);
132 +
133 +const onConfirm = ({ selectedOptions }) => { // 切换类型回调
134 + showPicker.value = false;
135 + fieldValue.value = selectedOptions[0].text;
136 + id_type.value = selectedOptions[0].value;
137 +};
99 </script> 138 </script>
100 139
101 <style lang="less" scoped> 140 <style lang="less" scoped>
......