Compare commits
4 Commits
167916057e
...
fbca24d9af
| Author | SHA1 | Date |
|---|---|---|
|
|
fbca24d9af | |
|
|
86c430eedf | |
|
|
379fcd1bfa | |
|
|
faba34294a |
|
|
@ -79,17 +79,32 @@
|
||||||
<span class="inline-block w-25 text-right">男方姓名:</span>
|
<span class="inline-block w-25 text-right">男方姓名:</span>
|
||||||
<span class="pl-2">{{ formData.husbandName }}</span>
|
<span class="pl-2">{{ formData.husbandName }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mt-2">
|
||||||
|
<span class="inline-block w-25 text-right">男方身份证:</span>
|
||||||
|
<span class="pl-2 break-all">{{ formData.husbandId || '-' }}</span>
|
||||||
|
</div>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<span class="inline-block w-25 text-right">女方姓名:</span>
|
<span class="inline-block w-25 text-right">女方姓名:</span>
|
||||||
<span class="pl-2">{{ formData.wifeName }}</span>
|
<span class="pl-2">{{ formData.wifeName }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mt-2">
|
||||||
|
<span class="inline-block w-25 text-right">女方身份证:</span>
|
||||||
|
<span class="pl-2 break-all">{{ formData.wifeId || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="mt-2">
|
||||||
|
<span class="inline-block w-25 text-right">登记日期:</span>
|
||||||
|
<span class="pl-2">{{ formData.registerDate || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="eligibilityError" class="mt-3 text-sm text-[#E8424D] bg-[#FFF5F5] border border-[#FFD7DF] rounded-lg p-3 leading-6">
|
||||||
|
{{ eligibilityError }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 提交按钮 -->
|
<!-- 提交按钮 -->
|
||||||
<button @click="submitForm" :disabled="!formData.marriageNo"
|
<button @click="goToIdUpload" :disabled="isNextDisabled"
|
||||||
class="w-full h-14 bg-gradient-to-r from-[#E8424D]! to-[#FF7A7A]! text-white! rounded-full text-lg font-bold transition-all hover:opacity-90 active:scale-98 disabled:from-[#8a8a8a]! disabled:to-[#8a8a8a]!">
|
class="w-full h-14 bg-gradient-to-r from-[#E8424D]! to-[#FF7A7A]! text-white! rounded-full text-lg font-bold transition-all hover:opacity-90 active:scale-98 disabled:from-[#8a8a8a]! disabled:to-[#8a8a8a]!">
|
||||||
<div class="text-lg">提交领取喜礼</div>
|
<div class="text-lg">下一步</div>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -204,7 +219,8 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import apiService from '../../services/apiService'
|
import apiService from '../../services/apiService'
|
||||||
import { ref, onMounted, nextTick } from 'vue'
|
import { ref, onMounted, nextTick, computed, watch } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import QrcodeVue from 'qrcode.vue'
|
import QrcodeVue from 'qrcode.vue'
|
||||||
import { showLoading, hideLoading } from '../../components/loading'
|
import { showLoading, hideLoading } from '../../components/loading'
|
||||||
|
|
@ -214,6 +230,29 @@ import 'vant/es/dialog/style';
|
||||||
const ocrUploadId = ref<HTMLInputElement>();
|
const ocrUploadId = ref<HTMLInputElement>();
|
||||||
const qrCodeWrapper = ref<HTMLDivElement | null>(null);
|
const qrCodeWrapper = ref<HTMLDivElement | null>(null);
|
||||||
const qrImageSrc = ref('');
|
const qrImageSrc = ref('');
|
||||||
|
const router = useRouter();
|
||||||
|
const eligibilityError = ref('');
|
||||||
|
|
||||||
|
const STORAGE_KEY_USER = 'userAs';
|
||||||
|
const STORAGE_KEY_MARRIAGE = 'marriageOcr';
|
||||||
|
|
||||||
|
type MarriageStorage = {
|
||||||
|
marriageNo?: string
|
||||||
|
husbandName?: string
|
||||||
|
wifeName?: string
|
||||||
|
registerDate?: string
|
||||||
|
certificateHolder?: string
|
||||||
|
wifeId?: string
|
||||||
|
husbandId?: string
|
||||||
|
wifeGender?: string | null
|
||||||
|
husbandGender?: string | null
|
||||||
|
wifeBirthDate?: string
|
||||||
|
husbandBirthDate?: string
|
||||||
|
wifeNationality?: string
|
||||||
|
husbandNationality?: string
|
||||||
|
phone: string
|
||||||
|
smsCode: string
|
||||||
|
}
|
||||||
|
|
||||||
const syncQrImage = () => {
|
const syncQrImage = () => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
|
|
@ -240,9 +279,19 @@ const formData = ref({
|
||||||
husbandName: '', // 男方姓名
|
husbandName: '', // 男方姓名
|
||||||
wifeName: '', // 女方姓名
|
wifeName: '', // 女方姓名
|
||||||
registerDate: '', // 登记日期
|
registerDate: '', // 登记日期
|
||||||
|
certificateHolder: '',
|
||||||
|
husbandId: '',
|
||||||
|
wifeId: '',
|
||||||
|
husbandGender: '',
|
||||||
|
wifeGender: '',
|
||||||
|
husbandBirthDate: '',
|
||||||
|
wifeBirthDate: '',
|
||||||
|
husbandNationality: '',
|
||||||
|
wifeNationality: '',
|
||||||
qrCode: '', // 二维码
|
qrCode: '', // 二维码
|
||||||
status: 0, // 状态 0-未核销 1-已核销
|
status: 0, // 状态 0-未核销 1-已核销
|
||||||
})
|
})
|
||||||
|
const isNextDisabled = computed(() => !formData.value.marriageNo || !!eligibilityError.value);
|
||||||
|
|
||||||
const activityInfo = ref<any>({}); // 活动信息
|
const activityInfo = ref<any>({}); // 活动信息
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
@ -256,7 +305,7 @@ onMounted(() => {
|
||||||
// activityStartTime: dayjs(response.data.activityStartTime).format('YYYY年MM月DD日'),
|
// activityStartTime: dayjs(response.data.activityStartTime).format('YYYY年MM月DD日'),
|
||||||
// activityEndTime: dayjs(response.data.activityEndTime).format('YYYY年MM月DD日'),
|
// activityEndTime: dayjs(response.data.activityEndTime).format('YYYY年MM月DD日'),
|
||||||
activityStartTime: '2026年1月1日',
|
activityStartTime: '2026年1月1日',
|
||||||
activityEndTime: '12月31日',
|
activityEndTime: '2026年12月31日',
|
||||||
};
|
};
|
||||||
|
|
||||||
if (new Date(response.data.activityEndTime) < new Date()) {
|
if (new Date(response.data.activityEndTime) < new Date()) {
|
||||||
|
|
@ -265,7 +314,7 @@ onMounted(() => {
|
||||||
});
|
});
|
||||||
activityInfo.value.status = 2;
|
activityInfo.value.status = 2;
|
||||||
} else {
|
} else {
|
||||||
const user = JSON.parse(localStorage.getItem('userAs') || '{}');
|
const user = JSON.parse(localStorage.getItem(STORAGE_KEY_USER) || '{}');
|
||||||
if (user.phone && user.smsCode) {
|
if (user.phone && user.smsCode) {
|
||||||
formData.value.phone = user.phone;
|
formData.value.phone = user.phone;
|
||||||
formData.value.smsCode = user.smsCode;
|
formData.value.smsCode = user.smsCode;
|
||||||
|
|
@ -285,6 +334,47 @@ onMounted(() => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const pickYear = (value?: string) => {
|
||||||
|
if (!value) return '';
|
||||||
|
return value.trim().slice(0, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
const computeEligibilityError = () => {
|
||||||
|
if (!formData.value.marriageNo) return '';
|
||||||
|
|
||||||
|
if (!formData.value.marriageNo.startsWith('640')) {
|
||||||
|
return '本活动仅限在宁夏办理结婚登记的新人参与,当前结婚证字号不符合活动要求。';
|
||||||
|
}
|
||||||
|
|
||||||
|
const registerYear = pickYear(formData.value.registerDate);
|
||||||
|
const startYear = pickYear(activityInfo.value.activityStartTime);
|
||||||
|
const endYear = pickYear(activityInfo.value.activityEndTime);
|
||||||
|
|
||||||
|
if (![startYear, endYear].includes(registerYear)) {
|
||||||
|
return `您的结婚证登记年份不在活动范围内,暂无法领取。`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [
|
||||||
|
formData.value.marriageNo,
|
||||||
|
formData.value.registerDate,
|
||||||
|
activityInfo.value.activityStartTime,
|
||||||
|
activityInfo.value.activityEndTime,
|
||||||
|
],
|
||||||
|
() => {
|
||||||
|
const nextReason = computeEligibilityError();
|
||||||
|
const hasNewReason = nextReason && nextReason !== eligibilityError.value;
|
||||||
|
eligibilityError.value = nextReason;
|
||||||
|
if (hasNewReason) {
|
||||||
|
showDialog({ message: nextReason });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
// 倒计时
|
// 倒计时
|
||||||
const countdown = ref(0)
|
const countdown = ref(0)
|
||||||
let countdownTimer: number | null = null
|
let countdownTimer: number | null = null
|
||||||
|
|
@ -297,6 +387,15 @@ const clearPhone = () => {
|
||||||
formData.value.husbandName = '';
|
formData.value.husbandName = '';
|
||||||
formData.value.wifeName = '';
|
formData.value.wifeName = '';
|
||||||
formData.value.registerDate = '';
|
formData.value.registerDate = '';
|
||||||
|
formData.value.certificateHolder = '';
|
||||||
|
formData.value.husbandId = '';
|
||||||
|
formData.value.wifeId = '';
|
||||||
|
formData.value.husbandGender = '';
|
||||||
|
formData.value.wifeGender = '';
|
||||||
|
formData.value.husbandBirthDate = '';
|
||||||
|
formData.value.wifeBirthDate = '';
|
||||||
|
formData.value.husbandNationality = '';
|
||||||
|
formData.value.wifeNationality = '';
|
||||||
formData.value.qrCode = '';
|
formData.value.qrCode = '';
|
||||||
formData.value.status = 0;
|
formData.value.status = 0;
|
||||||
qrImageSrc.value = '';
|
qrImageSrc.value = '';
|
||||||
|
|
@ -305,7 +404,8 @@ const clearPhone = () => {
|
||||||
clearInterval(countdownTimer);
|
clearInterval(countdownTimer);
|
||||||
countdownTimer = null;
|
countdownTimer = null;
|
||||||
}
|
}
|
||||||
localStorage.removeItem('userAs');
|
localStorage.removeItem(STORAGE_KEY_USER);
|
||||||
|
localStorage.removeItem(STORAGE_KEY_MARRIAGE);
|
||||||
if (ocrUploadId.value) ocrUploadId.value.value = '';
|
if (ocrUploadId.value) ocrUploadId.value.value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -326,6 +426,7 @@ const sendVerificationCode = () => {
|
||||||
mobile: phone,
|
mobile: phone,
|
||||||
type: 3,
|
type: 3,
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
localStorage.removeItem(STORAGE_KEY_MARRIAGE);
|
||||||
formData.value.verifyCode = false;
|
formData.value.verifyCode = false;
|
||||||
formData.value.smsCode = '';
|
formData.value.smsCode = '';
|
||||||
formData.value.qrCode = '';
|
formData.value.qrCode = '';
|
||||||
|
|
@ -374,7 +475,7 @@ const verifyCode = (flag: any) => {
|
||||||
smsCode: smsCode,
|
smsCode: smsCode,
|
||||||
type: 3,
|
type: 3,
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
localStorage.setItem('userAs', JSON.stringify({
|
localStorage.setItem(STORAGE_KEY_USER, JSON.stringify({
|
||||||
phone: formData.value.phone,
|
phone: formData.value.phone,
|
||||||
smsCode: formData.value.smsCode,
|
smsCode: formData.value.smsCode,
|
||||||
}));
|
}));
|
||||||
|
|
@ -402,8 +503,10 @@ const verifyCode = (flag: any) => {
|
||||||
qrCode: ""
|
qrCode: ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
restoreMarriageInfo();
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
localStorage.removeItem('userAs');
|
localStorage.removeItem(STORAGE_KEY_USER);
|
||||||
|
localStorage.removeItem(STORAGE_KEY_MARRIAGE);
|
||||||
|
|
||||||
flag && showDialog({
|
flag && showDialog({
|
||||||
message: error.msg || '验证码验证失败,请重试',
|
message: error.msg || '验证码验证失败,请重试',
|
||||||
|
|
@ -415,6 +518,15 @@ const verifyCode = (flag: any) => {
|
||||||
husbandName: "",
|
husbandName: "",
|
||||||
wifeName: "",
|
wifeName: "",
|
||||||
registerDate: "",
|
registerDate: "",
|
||||||
|
certificateHolder: "",
|
||||||
|
husbandId: "",
|
||||||
|
wifeId: "",
|
||||||
|
husbandGender: "",
|
||||||
|
wifeGender: "",
|
||||||
|
husbandBirthDate: "",
|
||||||
|
wifeBirthDate: "",
|
||||||
|
husbandNationality: "",
|
||||||
|
wifeNationality: "",
|
||||||
qrCode: ""
|
qrCode: ""
|
||||||
}
|
}
|
||||||
qrImageSrc.value = '';
|
qrImageSrc.value = '';
|
||||||
|
|
@ -422,6 +534,65 @@ const verifyCode = (flag: any) => {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const restoreMarriageInfo = () => {
|
||||||
|
const user = JSON.parse(localStorage.getItem(STORAGE_KEY_USER) || '{}');
|
||||||
|
const marriageStorage: MarriageStorage | null = (() => {
|
||||||
|
const raw = localStorage.getItem(STORAGE_KEY_MARRIAGE);
|
||||||
|
if (!raw) return null;
|
||||||
|
try {
|
||||||
|
return JSON.parse(raw);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
if (!marriageStorage || marriageStorage.smsCode !== user.smsCode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
formData.value = {
|
||||||
|
...formData.value,
|
||||||
|
marriageNo: marriageStorage.marriageNo || '',
|
||||||
|
husbandName: marriageStorage.husbandName || '',
|
||||||
|
wifeName: marriageStorage.wifeName || '',
|
||||||
|
registerDate: marriageStorage.registerDate || '',
|
||||||
|
certificateHolder: marriageStorage.certificateHolder || '',
|
||||||
|
husbandId: marriageStorage.husbandId || '',
|
||||||
|
wifeId: marriageStorage.wifeId || '',
|
||||||
|
husbandGender: marriageStorage.husbandGender || '',
|
||||||
|
wifeGender: marriageStorage.wifeGender || '',
|
||||||
|
husbandBirthDate: marriageStorage.husbandBirthDate || '',
|
||||||
|
wifeBirthDate: marriageStorage.wifeBirthDate || '',
|
||||||
|
husbandNationality: marriageStorage.husbandNationality || '',
|
||||||
|
wifeNationality: marriageStorage.wifeNationality || '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const persistMarriageInfo = () => {
|
||||||
|
const user = JSON.parse(localStorage.getItem(STORAGE_KEY_USER) || '{}');
|
||||||
|
if (!user?.smsCode || !formData.value.marriageNo) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const payload: MarriageStorage = {
|
||||||
|
phone: user.phone,
|
||||||
|
smsCode: user.smsCode,
|
||||||
|
marriageNo: formData.value.marriageNo,
|
||||||
|
husbandName: formData.value.husbandName,
|
||||||
|
wifeName: formData.value.wifeName,
|
||||||
|
registerDate: formData.value.registerDate,
|
||||||
|
certificateHolder: formData.value.certificateHolder,
|
||||||
|
husbandId: formData.value.husbandId,
|
||||||
|
wifeId: formData.value.wifeId,
|
||||||
|
husbandGender: formData.value.husbandGender,
|
||||||
|
wifeGender: formData.value.wifeGender,
|
||||||
|
husbandBirthDate: formData.value.husbandBirthDate,
|
||||||
|
wifeBirthDate: formData.value.wifeBirthDate,
|
||||||
|
husbandNationality: formData.value.husbandNationality,
|
||||||
|
wifeNationality: formData.value.wifeNationality,
|
||||||
|
};
|
||||||
|
localStorage.setItem(STORAGE_KEY_MARRIAGE, JSON.stringify(payload));
|
||||||
|
}
|
||||||
// 重置结婚证信息
|
// 重置结婚证信息
|
||||||
function resetMarriageInfo() {
|
function resetMarriageInfo() {
|
||||||
formData.value = {
|
formData.value = {
|
||||||
|
|
@ -430,9 +601,19 @@ function resetMarriageInfo() {
|
||||||
husbandName: "",
|
husbandName: "",
|
||||||
wifeName: "",
|
wifeName: "",
|
||||||
registerDate: "",
|
registerDate: "",
|
||||||
|
certificateHolder: "",
|
||||||
|
husbandId: "",
|
||||||
|
wifeId: "",
|
||||||
|
husbandGender: "",
|
||||||
|
wifeGender: "",
|
||||||
|
husbandBirthDate: "",
|
||||||
|
wifeBirthDate: "",
|
||||||
|
husbandNationality: "",
|
||||||
|
wifeNationality: "",
|
||||||
qrCode: ""
|
qrCode: ""
|
||||||
}
|
}
|
||||||
ocrUploadId.value && (ocrUploadId.value.value = '');
|
ocrUploadId.value && (ocrUploadId.value.value = '');
|
||||||
|
localStorage.removeItem(STORAGE_KEY_MARRIAGE);
|
||||||
|
|
||||||
ocrUploadId.value?.click();
|
ocrUploadId.value?.click();
|
||||||
}
|
}
|
||||||
|
|
@ -456,16 +637,26 @@ const handleImageChange = () => {
|
||||||
|
|
||||||
showLoading();
|
showLoading();
|
||||||
apiService.uploadOcrImage(formFormData).then((response: any) => {
|
apiService.uploadOcrImage(formFormData).then((response: any) => {
|
||||||
apiService.parseOcrInfo({
|
apiService.marriageParseOcrInfo({
|
||||||
mobile: formData.value.phone,
|
mobile: formData.value.phone,
|
||||||
smsCode: formData.value.smsCode,
|
smsCode: formData.value.smsCode,
|
||||||
uploadId: response.data.uploadId,
|
uploadId: response.data.uploadId,
|
||||||
}).then((res: any) => {
|
}).then((res: any) => {
|
||||||
if (res?.data?.parsed?.marriageNo) {
|
if (res?.data?.parsed?.marriageNo) {
|
||||||
formData.value.marriageNo = res?.data?.parsed?.marriageNo;
|
formData.value.marriageNo = res?.data?.parsed?.marriageNo || '';
|
||||||
formData.value.husbandName = res?.data?.parsed?.husbandName;
|
formData.value.husbandName = res?.data?.parsed?.husbandName || '';
|
||||||
formData.value.wifeName = res?.data?.parsed?.wifeName;
|
formData.value.wifeName = res?.data?.parsed?.wifeName || '';
|
||||||
formData.value.registerDate = res?.data?.parsed?.registerDate;
|
formData.value.registerDate = res?.data?.parsed?.registerDate || '';
|
||||||
|
formData.value.certificateHolder = res?.data?.parsed?.certificateHolder || '';
|
||||||
|
formData.value.husbandId = res?.data?.parsed?.husbandId || '';
|
||||||
|
formData.value.wifeId = res?.data?.parsed?.wifeId || '';
|
||||||
|
formData.value.husbandGender = res?.data?.parsed?.husbandGender || '';
|
||||||
|
formData.value.wifeGender = res?.data?.parsed?.wifeGender || '';
|
||||||
|
formData.value.husbandBirthDate = res?.data?.parsed?.husbandBirthDate || '';
|
||||||
|
formData.value.wifeBirthDate = res?.data?.parsed?.wifeBirthDate || '';
|
||||||
|
formData.value.husbandNationality = res?.data?.parsed?.husbandNationality || '';
|
||||||
|
formData.value.wifeNationality = res?.data?.parsed?.wifeNationality || '';
|
||||||
|
persistMarriageInfo();
|
||||||
} else {
|
} else {
|
||||||
showDialog({
|
showDialog({
|
||||||
message: '解析OCR信息失败,请稍后重试',
|
message: '解析OCR信息失败,请稍后重试',
|
||||||
|
|
@ -489,33 +680,21 @@ const handleImageChange = () => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const goToIdUpload = () => {
|
||||||
|
if (!formData.value.marriageNo) {
|
||||||
// 提交表单
|
|
||||||
const submitForm = () => {
|
|
||||||
if (!formData.value.phone || !formData.value.smsCode) {
|
|
||||||
showDialog({
|
showDialog({
|
||||||
message: '请完善所有信息',
|
message: '请先完成结婚证识别',
|
||||||
});
|
});
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
if (eligibilityError.value) {
|
||||||
showLoading();
|
|
||||||
apiService.receiveCheck({
|
|
||||||
marriageNo: formData.value.marriageNo,
|
|
||||||
receiveName: formData.value.husbandName,
|
|
||||||
receiveMobile: formData.value.phone,
|
|
||||||
smsCode: formData.value.smsCode,
|
|
||||||
}).then((res: any) => {
|
|
||||||
formData.value.qrCode = res.data.code;
|
|
||||||
syncQrImage();
|
|
||||||
}).catch((error) => {
|
|
||||||
showDialog({
|
showDialog({
|
||||||
message: error?.msg || '提交失败,请稍后重试',
|
message: eligibilityError.value,
|
||||||
});
|
});
|
||||||
}).finally(() => {
|
return;
|
||||||
hideLoading();
|
}
|
||||||
})
|
persistMarriageInfo();
|
||||||
|
router.push('/idcard');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 组件卸载时清理定时器
|
// 组件卸载时清理定时器
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,357 @@
|
||||||
|
<template>
|
||||||
|
<div class="min-h-screen bg-[#FFF7F9] p-4 pb-8">
|
||||||
|
<div
|
||||||
|
class="relative overflow-hidden rounded-2xl border border-[#FFD7DF] bg-gradient-to-br from-[#FFF7F9] via-white to-[#FFE4EA] shadow-[0_12px_32px_rgba(232,66,77,0.08)] p-6 sm:p-7 backdrop-blur-sm">
|
||||||
|
<div class="absolute -right-10 -top-16 h-40 w-40 rounded-full bg-[#FFE3EA] blur-3xl opacity-70"></div>
|
||||||
|
<div class="absolute -left-14 -bottom-16 h-40 w-40 rounded-full bg-[#FFD6E2] blur-3xl opacity-60"></div>
|
||||||
|
|
||||||
|
<div class="relative z-10 space-y-5">
|
||||||
|
<div class="text-center text-xl text-[#E8424D] font-semibold">身份证核验</div>
|
||||||
|
|
||||||
|
<!-- <div class="bg-white/90 rounded-xl p-4 shadow-[0_6px_18px_rgba(232,66,77,0.06)] border border-[#FFD7DF]">
|
||||||
|
<div class="flex items-center justify-between mb-3">
|
||||||
|
<div class="text-base font-semibold text-gray-800">结婚证信息</div>
|
||||||
|
<button class="text-xs text-[#E8424D]" @click="goBack">返回上一页</button>
|
||||||
|
</div>
|
||||||
|
<div class="text-sm text-[#7A5967] space-y-2">
|
||||||
|
<div>结婚证字号:{{ marriageInfo?.marriageNo || '-' }}</div>
|
||||||
|
<div class="grid grid-cols-1 gap-2">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<span class="inline-block w-24 text-gray-500">男方姓名:</span>
|
||||||
|
<span class="text-gray-800">{{ marriageInfo?.husbandName || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<span class="inline-block w-24 text-gray-500">男方证件号:</span>
|
||||||
|
<span class="text-gray-800 break-all">{{ marriageInfo?.husbandId || '未识别' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<span class="inline-block w-24 text-gray-500">女方姓名:</span>
|
||||||
|
<span class="text-gray-800">{{ marriageInfo?.wifeName || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<span class="inline-block w-24 text-gray-500">女方证件号:</span>
|
||||||
|
<span class="text-gray-800 break-all">{{ marriageInfo?.wifeId || '未识别' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>登记日期:{{ marriageInfo?.registerDate || '-' }}</div>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-5">
|
||||||
|
<div class="bg-white/95 rounded-2xl p-5 shadow-[0_6px_18px_rgba(232,66,77,0.06)] border border-[#FFD7DF] flex flex-col gap-4">
|
||||||
|
<div class="flex items-start gap-3">
|
||||||
|
<div class="space-y-1">
|
||||||
|
<div class="text-base font-semibold text-gray-800">上传男方身份证(人像面)</div>
|
||||||
|
<div class="text-xs text-[#7A5967] leading-relaxed space-y-1">
|
||||||
|
<div>需与结婚证信息一致:</div>
|
||||||
|
<div class="flex flex-col gap-0.5 text-gray-800">
|
||||||
|
<span>姓名:{{ marriageInfo?.husbandName || '-' }}</span>
|
||||||
|
<span class="break-all">证件号:{{ marriageInfo?.husbandId || '身份证号未识别' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-xs text-[#7A5967] bg-[#FFF3F5] border border-[#FFE0E7] rounded-lg p-3 leading-relaxed">
|
||||||
|
身份证照片需清晰无遮挡,保持文字方向正确,四角完整,避免反光或模糊。
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-3">
|
||||||
|
<button
|
||||||
|
class="flex-1 h-14! px-5 py-3! rounded-xl text-base font-semibold border border-[#E8424D]! text-[#E8424D]! bg-white! hover:bg-[#FFE8EE]! active:bg-[#FFD6E2]! active:scale-98 transition disabled:border-gray-300! disabled:text-gray-400! disabled:bg-gray-100!"
|
||||||
|
@click="triggerUpload('husband')" :disabled="!userInfo">
|
||||||
|
上传
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
:class="['flex items-center gap-2 text-sm font-medium rounded-lg border px-3 py-3 min-h-[48px] sm:w-48', statusPanelClass(husbandMatchedStatus)]">
|
||||||
|
<span :class="['inline-block w-2.5 h-2.5 rounded-full', statusDotClass(husbandMatchedStatus)]"></span>
|
||||||
|
<span>{{ husbandMatchedStatus === '待上传' ? '等待上传' : husbandMatchedStatus }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-white/95 rounded-2xl p-5 shadow-[0_6px_18px_rgba(232,66,77,0.06)] border border-[#FFD7DF] flex flex-col gap-4">
|
||||||
|
<div class="flex items-start gap-3">
|
||||||
|
<div class="space-y-1">
|
||||||
|
<div class="text-base font-semibold text-gray-800">上传女方身份证(人像面)</div>
|
||||||
|
<div class="text-xs text-[#7A5967] leading-relaxed space-y-1">
|
||||||
|
<div>需与结婚证信息一致:</div>
|
||||||
|
<div class="flex flex-col gap-0.5 text-gray-800">
|
||||||
|
<span>姓名:{{ marriageInfo?.wifeName || '-' }}</span>
|
||||||
|
<span class="break-all">证件号:{{ marriageInfo?.wifeId || '身份证号未识别' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-xs text-[#7A5967] bg-[#FFF3F5] border border-[#FFE0E7] rounded-lg p-3 leading-relaxed">
|
||||||
|
身份证照片需清晰无遮挡,保持文字方向正确,四角完整,避免反光或模糊。
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-3">
|
||||||
|
<button
|
||||||
|
class="flex-1 h-14! px-5 py-3! rounded-xl text-base font-semibold border border-[#E8424D]! text-[#E8424D]! bg-white! hover:bg-[#FFE8EE]! active:bg-[#FFD6E2]! active:scale-98 transition disabled:border-gray-300! disabled:text-gray-400! disabled:bg-gray-100!"
|
||||||
|
@click="triggerUpload('wife')" :disabled="!userInfo">
|
||||||
|
上传
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
:class="['flex items-center gap-2 text-sm font-medium rounded-lg border px-3 py-3 min-h-[48px] sm:w-48', statusPanelClass(wifeMatchedStatus)]">
|
||||||
|
<span :class="['inline-block w-2.5 h-2.5 rounded-full', statusDotClass(wifeMatchedStatus)]"></span>
|
||||||
|
<span>{{ wifeMatchedStatus === '待上传' ? '等待上传' : wifeMatchedStatus }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pt-2">
|
||||||
|
<button
|
||||||
|
class="w-full h-14 bg-gradient-to-r from-[#E8424D]! to-[#FF7A7A]! text-white! rounded-full text-lg font-bold transition-all hover:opacity-90 active:scale-98 disabled:from-[#8a8a8a]! disabled:to-[#8a8a8a]!"
|
||||||
|
@click="submitClaim" :disabled="!canSubmit || submitting">
|
||||||
|
<div class="text-lg">{{ submitting ? '提交中...' : '提交领取喜礼' }}</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="file" ref="husbandUpload" class="hidden" accept="image/*" @change="handleIdChange('husband')" />
|
||||||
|
<input type="file" ref="wifeUpload" class="hidden" accept="image/*" @change="handleIdChange('wife')" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, ref, computed } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import apiService, { type IdCardOcrParseResponse } from '@/services/apiService'
|
||||||
|
import { showLoading, hideLoading } from '@/components/loading'
|
||||||
|
import { showDialog } from 'vant'
|
||||||
|
import 'vant/es/dialog/style'
|
||||||
|
|
||||||
|
type Role = 'husband' | 'wife'
|
||||||
|
type MarriageInfo = {
|
||||||
|
marriageNo?: string
|
||||||
|
husbandName?: string
|
||||||
|
wifeName?: string
|
||||||
|
registerDate?: string
|
||||||
|
certificateHolder?: string
|
||||||
|
wifeId?: string
|
||||||
|
husbandId?: string
|
||||||
|
wifeGender?: string | null
|
||||||
|
husbandGender?: string | null
|
||||||
|
wifeBirthDate?: string
|
||||||
|
husbandBirthDate?: string
|
||||||
|
wifeNationality?: string
|
||||||
|
husbandNationality?: string
|
||||||
|
phone?: string
|
||||||
|
smsCode?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const STORAGE_KEY_USER = 'userAs'
|
||||||
|
const STORAGE_KEY_MARRIAGE = 'marriageOcr'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
const userInfo = ref<{ phone: string; smsCode: string } | null>(null)
|
||||||
|
const marriageInfo = ref<MarriageInfo | null>(null)
|
||||||
|
const husbandUpload = ref<HTMLInputElement>()
|
||||||
|
const wifeUpload = ref<HTMLInputElement>()
|
||||||
|
const husbandIdParsed = ref<IdCardOcrParseResponse['parsed'] | null>(null)
|
||||||
|
const wifeIdParsed = ref<IdCardOcrParseResponse['parsed'] | null>(null)
|
||||||
|
const submitting = ref(false)
|
||||||
|
|
||||||
|
const loadFromStorage = () => {
|
||||||
|
const userRaw = localStorage.getItem(STORAGE_KEY_USER)
|
||||||
|
const marriageRaw = localStorage.getItem(STORAGE_KEY_MARRIAGE)
|
||||||
|
|
||||||
|
if (!userRaw || !marriageRaw) {
|
||||||
|
showDialog({
|
||||||
|
message: '请先完成手机验证与结婚证识别',
|
||||||
|
}).then(() => router.replace('/claim'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const user = JSON.parse(userRaw)
|
||||||
|
const marriage = JSON.parse(marriageRaw)
|
||||||
|
if (!user?.smsCode || marriage?.smsCode !== user.smsCode) {
|
||||||
|
localStorage.removeItem(STORAGE_KEY_MARRIAGE)
|
||||||
|
showDialog({
|
||||||
|
message: '验证码已失效,请重新验证后再试',
|
||||||
|
}).then(() => router.replace('/claim'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userInfo.value = { phone: user.phone, smsCode: user.smsCode }
|
||||||
|
marriageInfo.value = marriage
|
||||||
|
} catch (error) {
|
||||||
|
console.error('读取本地缓存失败', error)
|
||||||
|
showDialog({
|
||||||
|
message: '身份信息读取失败,请重新验证',
|
||||||
|
}).then(() => router.replace('/claim'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadFromStorage()
|
||||||
|
})
|
||||||
|
|
||||||
|
const normalize = (val?: string | null) => (val || '').replace(/\s+/g, '').toUpperCase()
|
||||||
|
|
||||||
|
const checkMatch = (parsed: IdCardOcrParseResponse['parsed'] | null, target: { name?: string; id?: string; gender?: string | null }) => {
|
||||||
|
if (!parsed || !target.name) return false
|
||||||
|
const nameMatched = normalize(parsed.name) === normalize(target.name)
|
||||||
|
const idMatched = target.id ? normalize(parsed.id_number) === normalize(target.id) : true
|
||||||
|
const genderMatched = target.gender ? parsed.gender === target.gender : true
|
||||||
|
return nameMatched && idMatched && genderMatched
|
||||||
|
}
|
||||||
|
|
||||||
|
const IMAGE_STATUS_TEXT: Record<IdCardOcrParseResponse['parsed']['image_status'], string> = {
|
||||||
|
normal: '识别正常',
|
||||||
|
reversed_side: '身份证正反面颠倒',
|
||||||
|
non_idcard: '上传的图片中不包含身份证',
|
||||||
|
blurred: '身份证模糊',
|
||||||
|
other_type_card: '其他类型证照',
|
||||||
|
over_exposure: '身份证关键字段反光或过曝',
|
||||||
|
over_dark: '身份证欠曝(亮度过低)',
|
||||||
|
unknown: '未知状态',
|
||||||
|
}
|
||||||
|
|
||||||
|
const isImageNormal = (parsed: IdCardOcrParseResponse['parsed'] | null) => parsed?.image_status === 'normal'
|
||||||
|
|
||||||
|
const husbandMatched = computed(() =>
|
||||||
|
isImageNormal(husbandIdParsed.value) &&
|
||||||
|
checkMatch(husbandIdParsed.value, {
|
||||||
|
name: marriageInfo.value?.husbandName,
|
||||||
|
id: marriageInfo.value?.husbandId,
|
||||||
|
gender: marriageInfo.value?.husbandGender,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
const wifeMatched = computed(() =>
|
||||||
|
isImageNormal(wifeIdParsed.value) &&
|
||||||
|
checkMatch(wifeIdParsed.value, {
|
||||||
|
name: marriageInfo.value?.wifeName,
|
||||||
|
id: marriageInfo.value?.wifeId,
|
||||||
|
gender: marriageInfo.value?.wifeGender,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const resolveIdCardStatus = (parsed: IdCardOcrParseResponse['parsed'] | null, matched: boolean) => {
|
||||||
|
if (!parsed) return '待上传'
|
||||||
|
if (!isImageNormal(parsed)) return IMAGE_STATUS_TEXT[parsed.image_status] || '未知状态'
|
||||||
|
return matched ? '已匹配' : '信息不一致'
|
||||||
|
}
|
||||||
|
|
||||||
|
const husbandMatchedStatus = computed(() => resolveIdCardStatus(husbandIdParsed.value, husbandMatched.value))
|
||||||
|
const wifeMatchedStatus = computed(() => resolveIdCardStatus(wifeIdParsed.value, wifeMatched.value))
|
||||||
|
|
||||||
|
const statusPanelClass = (status: string) => {
|
||||||
|
if (status === '已匹配') return 'text-green-700 bg-green-50 border-green-200'
|
||||||
|
if (status === '待上传') return 'text-gray-600 bg-gray-50 border-gray-200'
|
||||||
|
return 'text-[#E8424D] bg-[#FFF3F5] border-[#FFD7DF]'
|
||||||
|
}
|
||||||
|
|
||||||
|
const statusDotClass = (status: string) => {
|
||||||
|
if (status === '已匹配') return 'bg-green-500 shadow-[0_0_0_4px_rgba(34,197,94,0.15)]'
|
||||||
|
if (status === '待上传') return 'bg-gray-400 shadow-[0_0_0_4px_rgba(156,163,175,0.15)]'
|
||||||
|
return 'bg-[#E8424D] shadow-[0_0_0_4px_rgba(232,66,77,0.15)]'
|
||||||
|
}
|
||||||
|
|
||||||
|
const canSubmit = computed(() => husbandMatched.value && wifeMatched.value && !!marriageInfo.value && !!userInfo.value)
|
||||||
|
|
||||||
|
const triggerUpload = (role: Role) => {
|
||||||
|
if (role === 'husband') {
|
||||||
|
husbandUpload.value?.click()
|
||||||
|
} else {
|
||||||
|
wifeUpload.value?.click()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleIdChange = async (role: Role) => {
|
||||||
|
const input = role === 'husband' ? husbandUpload.value : wifeUpload.value
|
||||||
|
const file = input?.files?.[0]
|
||||||
|
if (!file) {
|
||||||
|
showDialog({
|
||||||
|
message: '请选择图片文件',
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!userInfo.value) {
|
||||||
|
showDialog({
|
||||||
|
message: '请先返回上一页完成验证',
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const formFormData = new FormData()
|
||||||
|
formFormData.append('file', file)
|
||||||
|
|
||||||
|
showLoading()
|
||||||
|
try {
|
||||||
|
const response: any = await apiService.uploadOcrImage(formFormData)
|
||||||
|
const res: any = await apiService.idCardParseOcrInfo({
|
||||||
|
mobile: userInfo.value.phone,
|
||||||
|
smsCode: userInfo.value.smsCode,
|
||||||
|
uploadId: response.data.uploadId,
|
||||||
|
})
|
||||||
|
const parsed = res?.data?.parsed
|
||||||
|
if (!parsed) {
|
||||||
|
throw new Error('识别失败,请重试')
|
||||||
|
}
|
||||||
|
if (role === 'husband') {
|
||||||
|
husbandIdParsed.value = parsed
|
||||||
|
} else {
|
||||||
|
wifeIdParsed.value = parsed
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('身份证识别失败', error)
|
||||||
|
const msg = error?.msg || error?.message || '身份证识别失败,请稍后重试'
|
||||||
|
showDialog({
|
||||||
|
message: msg,
|
||||||
|
}).then(() => {
|
||||||
|
if (msg.includes('验证码')) {
|
||||||
|
localStorage.removeItem(STORAGE_KEY_MARRIAGE)
|
||||||
|
router.replace('/claim')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
hideLoading()
|
||||||
|
if (input) {
|
||||||
|
input.value = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitClaim = async () => {
|
||||||
|
if (!canSubmit.value || !marriageInfo.value || !userInfo.value) return
|
||||||
|
submitting.value = true
|
||||||
|
showLoading()
|
||||||
|
try {
|
||||||
|
await apiService.receiveCheck({
|
||||||
|
marriageNo: marriageInfo.value.marriageNo,
|
||||||
|
receiveName: marriageInfo.value.husbandName || marriageInfo.value.certificateHolder || marriageInfo.value.wifeName,
|
||||||
|
receiveMobile: userInfo.value.phone,
|
||||||
|
smsCode: userInfo.value.smsCode,
|
||||||
|
})
|
||||||
|
showDialog({
|
||||||
|
message: '提交成功,请返回首页查看核销二维码',
|
||||||
|
}).then(() => {
|
||||||
|
router.replace('/claim')
|
||||||
|
})
|
||||||
|
} catch (error: any) {
|
||||||
|
const msg = error?.msg || '提交失败,请稍后重试'
|
||||||
|
showDialog({
|
||||||
|
message: msg,
|
||||||
|
}).then(() => {
|
||||||
|
if (msg.includes('验证码')) {
|
||||||
|
localStorage.removeItem(STORAGE_KEY_MARRIAGE)
|
||||||
|
router.replace('/claim')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
hideLoading()
|
||||||
|
submitting.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const goBack = () => {
|
||||||
|
router.back()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -26,6 +26,14 @@ const routes: Array<RouteRecordRaw> = [
|
||||||
meta: {
|
meta: {
|
||||||
title: '宁福您彩 活动规则'
|
title: '宁福您彩 活动规则'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/idcard',
|
||||||
|
name: 'IdCard',
|
||||||
|
component: () => import('../pages/idcard/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '宁福您彩 身份核验'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,53 @@ export interface OcrUploadResponse {
|
||||||
uploadId: string
|
uploadId: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OcrParseResponse {
|
export interface IdCardOcrParseResponse {
|
||||||
raw: string
|
raw: string
|
||||||
words: string[]
|
words: string[]
|
||||||
parsed: {
|
parsed: {
|
||||||
marriageNo: string
|
birthday?: string
|
||||||
husbandName: string
|
id_number: string
|
||||||
wifeName: string
|
address: string
|
||||||
registerDate: string
|
image_status:
|
||||||
|
| 'normal'
|
||||||
|
| 'reversed_side'
|
||||||
|
| 'non_idcard'
|
||||||
|
| 'blurred'
|
||||||
|
| 'other_type_card'
|
||||||
|
| 'over_exposure'
|
||||||
|
| 'over_dark'
|
||||||
|
| 'unknown'
|
||||||
|
risk_type:
|
||||||
|
| 'normal'
|
||||||
|
| 'copy'
|
||||||
|
| 'scan'
|
||||||
|
| 'temporary'
|
||||||
|
| 'screen'
|
||||||
|
| 'screenshot'
|
||||||
|
| 'unknown'
|
||||||
|
gender: '男' | '女' | '未知' | null | undefined
|
||||||
|
name?: string
|
||||||
|
nationality?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarriageOcrParseResponse {
|
||||||
|
raw: string
|
||||||
|
words: string[]
|
||||||
|
parsed: {
|
||||||
|
marriageNo?: string
|
||||||
|
registerDate?: string
|
||||||
|
certificateHolder?: string
|
||||||
|
wifeId?: string
|
||||||
|
wifeName?: string
|
||||||
|
wifeBirthDate?: string
|
||||||
|
wifeNationality?: string
|
||||||
|
wifeGender?: '男' | '女' | '未知' | null | undefined
|
||||||
|
husbandId?: string
|
||||||
|
husbandName?: string
|
||||||
|
husbandGender?: '男' | '女' | '未知' | null | undefined
|
||||||
|
husbandBirthDate?: string
|
||||||
|
husbandNationality?: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,12 +125,21 @@ export const apiService = {
|
||||||
},
|
},
|
||||||
|
|
||||||
// OCR识别并返回证件信息
|
// OCR识别并返回证件信息
|
||||||
parseOcrInfo(data: {
|
marriageParseOcrInfo(data: {
|
||||||
mobile: string
|
mobile: string
|
||||||
smsCode: string
|
smsCode: string
|
||||||
uploadId: string
|
uploadId: string
|
||||||
}) {
|
}) {
|
||||||
return request.post<OcrParseResponse>('/marriage/ocr/parse', data)
|
return request.post<MarriageOcrParseResponse>('/marriage/ocr/parse', data)
|
||||||
|
},
|
||||||
|
|
||||||
|
// OCR 识别身份证
|
||||||
|
idCardParseOcrInfo(data: {
|
||||||
|
mobile: string
|
||||||
|
smsCode: string
|
||||||
|
uploadId: string
|
||||||
|
}) {
|
||||||
|
return request.post<IdCardOcrParseResponse>('/marriage/ocr/parseIdCard', data)
|
||||||
},
|
},
|
||||||
|
|
||||||
// 领取流程相关接口
|
// 领取流程相关接口
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,53 @@ export interface OcrUploadResponse {
|
||||||
uploadId: string
|
uploadId: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OcrParseResponse {
|
export interface IdCardOcrParseResponse {
|
||||||
raw: string
|
raw: string
|
||||||
words: string[]
|
words: string[]
|
||||||
parsed: {
|
parsed: {
|
||||||
marriageNo: string
|
birthday?: string
|
||||||
husbandName: string
|
id_number: string
|
||||||
wifeName: string
|
address: string
|
||||||
registerDate: string
|
image_status:
|
||||||
|
| 'normal'
|
||||||
|
| 'reversed_side'
|
||||||
|
| 'non_idcard'
|
||||||
|
| 'blurred'
|
||||||
|
| 'other_type_card'
|
||||||
|
| 'over_exposure'
|
||||||
|
| 'over_dark'
|
||||||
|
| 'unknown'
|
||||||
|
risk_type:
|
||||||
|
| 'normal'
|
||||||
|
| 'copy'
|
||||||
|
| 'scan'
|
||||||
|
| 'temporary'
|
||||||
|
| 'screen'
|
||||||
|
| 'screenshot'
|
||||||
|
| 'unknown'
|
||||||
|
gender: '男' | '女' | '未知' | null | undefined
|
||||||
|
name?: string
|
||||||
|
nationality?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarriageOcrParseResponse {
|
||||||
|
raw: string
|
||||||
|
words: string[]
|
||||||
|
parsed: {
|
||||||
|
marriageNo?: string
|
||||||
|
registerDate?: string
|
||||||
|
certificateHolder?: string
|
||||||
|
wifeId?: string
|
||||||
|
wifeName?: string
|
||||||
|
wifeBirthDate?: string
|
||||||
|
wifeNationality?: string
|
||||||
|
wifeGender?: '男' | '女' | '未知' | null | undefined
|
||||||
|
husbandId?: string
|
||||||
|
husbandName?: string
|
||||||
|
husbandGender?: '男' | '女' | '未知' | null | undefined
|
||||||
|
husbandBirthDate?: string
|
||||||
|
husbandNationality?: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,7 +92,8 @@ export interface MarriageCodeListVO {
|
||||||
|
|
||||||
export interface CommSmsDTO {
|
export interface CommSmsDTO {
|
||||||
mobile: string
|
mobile: string
|
||||||
type: number // 0=登录;1=兑换领取;2=OCR识别
|
smsCode?: string
|
||||||
|
type: 0 | 1 | 2 | 3 // 0=登录;1=兑换领取;2=OCR识别;3=本流程使用
|
||||||
}
|
}
|
||||||
|
|
||||||
// API服务接口定义
|
// API服务接口定义
|
||||||
|
|
@ -70,7 +110,14 @@ export interface ApiService {
|
||||||
sendSms(data: CommSmsDTO): Promise<any>
|
sendSms(data: CommSmsDTO): Promise<any>
|
||||||
|
|
||||||
// OCR识别并返回证件信息
|
// OCR识别并返回证件信息
|
||||||
parseOcrInfo(data: {
|
marriageParseOcrInfo(data: {
|
||||||
|
mobile: string
|
||||||
|
smsCode: string
|
||||||
|
uploadId: string
|
||||||
|
}): Promise<any>
|
||||||
|
|
||||||
|
// OCR 识别身份证
|
||||||
|
idCardParseOcrInfo(data: {
|
||||||
mobile: string
|
mobile: string
|
||||||
smsCode: string
|
smsCode: string
|
||||||
uploadId: string
|
uploadId: string
|
||||||
|
|
@ -103,8 +150,8 @@ export interface ApiService {
|
||||||
// 登录
|
// 登录
|
||||||
login(data: {
|
login(data: {
|
||||||
mobile: string
|
mobile: string
|
||||||
password: string
|
password?: string
|
||||||
smsCode: string
|
smsCode?: string
|
||||||
}): Promise<any>
|
}): Promise<any>
|
||||||
|
|
||||||
// 后台活动管理接口(可选,用于管理端)
|
// 后台活动管理接口(可选,用于管理端)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue