feat: 新增身份证上传+OCR识别组件
parent
8b390a404b
commit
5d651d626b
|
|
@ -0,0 +1,98 @@
|
|||
<!-- src/components/IdCardUpload.vue -->
|
||||
<template>
|
||||
<div class="id-card-upload">
|
||||
<a-upload
|
||||
list-type="picture-card"
|
||||
:show-upload-list="false"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:disabled="!channelNo || uploading"
|
||||
>
|
||||
<img v-if="previewUrl" :src="previewUrl" class="preview-img" alt="预览" />
|
||||
<div v-else>
|
||||
<LoadingOutlined v-if="uploading" />
|
||||
<PlusOutlined v-else />
|
||||
<div class="upload-text">{{ label }}</div>
|
||||
</div>
|
||||
</a-upload>
|
||||
<div v-if="!channelNo" class="hint">请先选择所属渠道</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { PlusOutlined, LoadingOutlined } from '@ant-design/icons-vue'
|
||||
import { ocrIdCardApi, uploadCustomerFileApi } from '@/api/customer'
|
||||
|
||||
const props = defineProps({
|
||||
side: { type: String, required: true }, // 'front'人像面 | 'back'国徽面
|
||||
channelNo: { type: String, default: undefined }
|
||||
})
|
||||
const emit = defineEmits(['update:fileNo', 'ocr-result', 'ocr-status'])
|
||||
|
||||
const uploading = ref(false)
|
||||
const previewUrl = ref('')
|
||||
const label = computed(() => (props.side === 'front' ? '上传身份证人像面' : '上传身份证国徽面'))
|
||||
const fileType = computed(() => (props.side === 'front' ? '01' : '02'))
|
||||
|
||||
function readAsBase64(file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader()
|
||||
reader.onload = () => resolve(reader.result)
|
||||
reader.onerror = reject
|
||||
reader.readAsDataURL(file)
|
||||
})
|
||||
}
|
||||
|
||||
async function handleBeforeUpload(file) {
|
||||
if (!props.channelNo) {
|
||||
message.warning('请先选择所属渠道')
|
||||
return false
|
||||
}
|
||||
uploading.value = true
|
||||
try {
|
||||
const fileBase64 = await readAsBase64(file)
|
||||
previewUrl.value = fileBase64
|
||||
const [ocrRes, uploadRes] = await Promise.all([
|
||||
ocrIdCardApi({ fileBase64, channelNo: props.channelNo, fileType: fileType.value }),
|
||||
uploadCustomerFileApi({ fileBase64, channelNo: props.channelNo })
|
||||
])
|
||||
if (uploadRes.data.code === 200) {
|
||||
emit('update:fileNo', uploadRes.data.data.fileNo)
|
||||
}
|
||||
if (ocrRes.data.code === 200 && ocrRes.data.data && Object.keys(ocrRes.data.data).length > 0) {
|
||||
emit('ocr-result', ocrRes.data.data)
|
||||
emit('ocr-status', 'SUCCESS')
|
||||
} else {
|
||||
message.warning('识别失败,请手动填写')
|
||||
emit('ocr-status', 'FAILED')
|
||||
}
|
||||
} catch (e) {
|
||||
message.warning('识别失败,请手动填写')
|
||||
emit('ocr-status', 'FAILED')
|
||||
} finally {
|
||||
uploading.value = false
|
||||
}
|
||||
return false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.id-card-upload {
|
||||
display: inline-block;
|
||||
}
|
||||
.preview-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.upload-text {
|
||||
margin-top: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.hint {
|
||||
color: #ff4d4f;
|
||||
font-size: 12px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue