41 lines
3.3 KiB
Markdown
41 lines
3.3 KiB
Markdown
# 个人客户新增/编辑——身份证 OCR 识别等待态设计
|
|
|
|
## 背景
|
|
|
|
客户管理 -> 个人客户管理 -> 新增/编辑个人客户表单(`src/views/customer/personal/PersonalForm.vue`)中,上传身份证正面/反面图片后,`IdCardUpload.vue` 组件内部并发调用 `ocrIdCardApi`(身份证 OCR 识别)与 `uploadCustomerFileApi`(文件上传)。后端 OCR 接口响应较慢,识别期间目前只有上传框内一个局部菊花图标(`LoadingOutlined`),用户可以继续操作表单其他字段甚至重复提交,存在数据一致性风险,体验也不够明确。
|
|
|
|
需求:上传身份证正/反面图片后,等待识别结果期间,前端需要展示明显的等待态(菊花),且用户不能对页面进行操作。
|
|
|
|
## 范围确认(与用户确认过的细节)
|
|
|
|
- 遮罩范围:仅覆盖新增/编辑个人客户表单卡片内容区(`<a-form>` + 提交/取消按钮),不包含卡片外的页头(`<a-page-header>`/返回按钮保持可操作)。
|
|
- 并发场景:身份证正面、反面几乎同时上传时,只要任一张仍在识别中,遮罩就保持展示;两张都结束才解除。
|
|
- 适用范围:仅个人客户表单(`PersonalForm.vue`),不改动企业客户表单等其他复用 `IdCardUpload`/文件上传组件的场景。
|
|
- 提示内容:菊花 + 文字提示"身份证识别中,请稍候..."。
|
|
- 生效模式:新增、编辑两种模式都生效(两者共用同一组件与同一段上传/OCR 代码路径,行为保持一致)。
|
|
|
|
## 方案
|
|
|
|
不新建全局 loading/遮罩组件(项目当前无此类基础设施,且需求范围只限于本表单),直接使用 Ant Design Vue 自带的 `a-spin` 嵌套遮罩("nested loading")能力:`:spinning` 为真时,组件会在被包裹内容上叠加菊花 + 半透明遮罩,并对内容添加 `pointer-events: none`,天然满足"菊花 + 阻断操作"的要求,无需额外造轮子。
|
|
|
|
### 改动点 1:`src/components/IdCardUpload.vue`
|
|
|
|
- 新增 `emit('update:uploading', boolean)`,在组件内部已有的 `uploading` ref 变化时同步对外广播(即支持父组件用 `v-model:uploading` 接管此状态)。
|
|
- 组件内部原有的局部菊花图标(`LoadingOutlined`)、`a-upload` 的 `:disabled` 逻辑保持不变。
|
|
|
|
### 改动点 2:`src/views/customer/personal/PersonalForm.vue`
|
|
|
|
- 新增两个 ref:`idCardFrontUploading`、`idCardBackUploading`,分别通过 `v-model:uploading` 绑定到正面/反面两个 `IdCardUpload` 实例。
|
|
- 新增计算属性 `isIdCardOcrProcessing = computed(() => idCardFrontUploading.value || idCardBackUploading.value)`。
|
|
- 用 `<a-spin :spinning="isIdCardOcrProcessing" tip="身份证识别中,请稍候...">` 包裹 `<a-card>` 内的 `<a-form>...</a-form>` 与提交/取消 `<a-space>`,`<a-page-header>` 留在 `a-spin` 外部不受影响。
|
|
|
|
### 异常兜底
|
|
|
|
`IdCardUpload.vue` 的 `handleBeforeUpload` 中 `finally` 块已无条件将 `uploading` 置回 `false`(无论 OCR 成功、识别失败还是请求异常/超时),遮罩会随之自动消失,不需要额外的错误处理分支。
|
|
|
|
## 不做的事
|
|
|
|
- 不新建可复用的全局 loading 组件(超出本次需求范围,且项目暂无其他场景需要)。
|
|
- 不改动企业客户表单等其他复用同一上传组件的页面。
|
|
- 不改变现有 OCR/上传接口调用方式(仍是 base64 并发调用 `ocrIdCardApi` + `uploadCustomerFileApi`)。
|