SFT/docs/superpowers/specs/2026-07-23-personal-open-co...

75 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 个人开户"确认"二次确认弹窗 + 邀请扫码办理 设计文档
## 背景
`src/views/wallet/personal-open/PersonalOpenForm.vue`(新增个人开户申请页)当前点击顶部"确认"按钮后,直接执行前置校验并调用 `create-draft` 接口提交,没有任何二次确认环节。产品要求新增二次确认弹窗,并在弹窗中提供"邀请扫码办理"选项,允许柜员生成二维码交由客户扫码办理(扫码后走向的移动端 H5 页面本身不在本项目前端实现范围内,仅需生成二维码内容并展示)。
本次改动只影响 `PersonalOpenForm.vue` 的**新增create模式**"确认"按钮流程编辑edit模式的"保存"按钮不受影响。
## 交互流程
1. 用户在新增个人开户表单页填写完信息,点击顶部"确认"按钮。
2. 前端执行现有的全部前置校验(原 `handleSubmit` 中 441-470 行逻辑):
- 是否已勾选协议
- 是否已选择渠道归属
- 是否已选择客户
- 证件照片是否仍在上传中
- 创建模式下是否已上传身份证正反面 + 正面免冠照
- 身份证 OCR 信息是否与所选客户一致
- 表单 `formRef.value.validate()` 是否通过
- 任意一项不通过:按现有方式提示错误(`showErrorModal`**不弹出二次确认弹窗**。
3. 全部通过后,弹出"提示"二次确认弹窗(对应产品提供的截图),弹窗内容:"是否确认开户?",三个按钮:`保存`(主按钮)/ `取消` / `邀请扫码办理`
4. 弹窗内点击**保存**
- 调用 `create-draft` 接口(逻辑与现有提交一致:构造 `payload` + `fileList`)。
- 成功(`code === 200`):记录 `submittedApplicationNo``message.success('申请已提交')`,关闭弹窗。表单页因 `submittedApplicationNo` 有值而自动切换到现有的"开户申请已提交"结果面板(既有 template 条件不变)。
- 失败:由全局响应拦截器统一弹出错误提示(`showErrorModal`,见 `src/api/request.js` 响应拦截器),弹窗保持打开,允许用户重试或取消。
5. 弹窗内点击**取消**:仅关闭弹窗,不发任何请求,不做页面跳转,表单数据保留,用户可以继续修改后重新点击"确认"。
6. 弹窗内点击**邀请扫码办理**
- 调用与"保存"完全相同的提交逻辑(同一个 `create-draft` 接口),拿到 `applicationNo` 并同样记录到 `submittedApplicationNo`(因此背后的表单页状态与点"保存"效果一致,会进入"已提交"结果面板)。
- 成功后**不关闭弹窗**,而是把弹窗内容切换为"二维码展示"态:显示二维码图片 + "申请编号:{applicationNo}" 文字 + "关闭"按钮;不额外弹出"申请已提交"的 message 提示(避免和二维码展示态叠加打扰)。
- 二维码内容为一个完整 URL`${VITE_H5_QRCODE_BASE_URL}${VITE_H5_QRCODE_PATH}?applicationNo=${applicationNo}`。域名/路径通过环境变量配置(见下),当前域名尚未确定,未配置时使用占位域名照常生成二维码(不阻断流程)。
- 用户点击"关闭"或弹窗右上角 X仅关闭弹窗此时表单页已处于"已提交"结果面板状态(与点保存效果一致)。
- 失败:同上由全局拦截器提示,弹窗保持在"确认"态,允许重试。
## UI 结构
复用 `ant-design-vue``a-modal`
- `title="提示"`
- `:footer="null"`(按钮放在正文里自定义,与截图一致)
- `:mask-closable="false"`(避免误触遮罩关闭)
- 内部用一个 `confirmModalStep` ref`'confirm' | 'qrcode'`)控制展示"确认文案+三按钮"还是"二维码+关闭按钮"两种视图。
二维码组件使用新增依赖 `qrcode.vue`Vue3 兼容,`peerDependencies: vue ^3.0.0`),以 `<qrcode-vue :value="qrCodeUrl" :size="200" />` 方式渲染。
## 代码结构调整(`PersonalOpenForm.vue`
将原 `handleSubmit` 拆分为职责更清晰的几个函数,避免重复代码:
- `validateBeforeSubmit()`:抽取原 441-470 行的全部前置校验(含 `formRef.value.validate()`),返回 `boolean`(或 reject。供"确认"按钮预检和 `isEdit` 保存流程共用。
- `buildSubmitPayload()`:抽取原 473-495 行 `fileList`/`payload` 构造逻辑,供 create 提交与 edit 保存共用。
- `submitCreateDraft()`:仅负责调用 `createPersonalOpenDraftApi`,成功后设置 `submittedApplicationNo` 并返回 `applicationNo`;失败返回 `null`(错误提示交给全局拦截器)。供弹窗内"保存"与"邀请扫码办理"共用,各自维护自己的 loading ref`modalSaving` / `modalInviting`),防止重复点击。
- `handleConfirmButtonClick()`:新增个人开户"确认"按钮的点击处理——调用 `validateBeforeSubmit()`,通过后打开确认弹窗(`confirmModalVisible = true``confirmModalStep = 'confirm'`)。
- `handleEditSubmit()`:原 `handleSubmit``isEdit` 分支逻辑原样保留(校验 + 调用 `updatePersonalOpenApplicationApi`),仅改名,行为不变,绑定到编辑模式"保存"按钮。
## 环境变量
新增于 `.env.development``.env.production`
```
VITE_H5_QRCODE_BASE_URL=
VITE_H5_QRCODE_PATH=/mobile/personal-open
```
`VITE_H5_QRCODE_BASE_URL` 留空时使用代码内占位域名(如 `https://example.com`)兜底拼接,保证二维码始终可以生成;域名确定后运维/开发只需在 `.env.production` 中填入真实域名即可,无需改代码。
## 依赖变更
新增 `qrcode.vue`dependencies
## 范围边界
- 不实现移动端 H5 扫码后的确认页面(`personal-opening/mobile/*`),本次改动只负责柜员端生成二维码内容并展示。
- 不改动 `isEdit`(编辑)模式的提交流程与按钮。
- 不改动 `isDetail`(查看)模式。
- 不引入全局的 `busy`/`a-spin` 统一遮罩规范补齐(该页面现状缺口不在本次需求范围内,维持现状,仅用按钮级 loading 防重复点击)。