149 lines
6.5 KiB
Markdown
149 lines
6.5 KiB
Markdown
# Qing 通用业务操作弹窗设计
|
||
|
||
## 目标
|
||
|
||
所有 Qing 前台业务按钮使用统一、符合实际项目习惯的交互:
|
||
|
||
- 不再按 `requestFields` 逐个弹出输入框。
|
||
- 当前登录用户、当前记录、详情数据和现有页面表单能够提供的参数自动填充。
|
||
- 仍需用户输入的参数集中显示在一个表单弹窗中。
|
||
- 用户提交表单即执行操作,不再出现第二层确认弹窗。
|
||
- 没有待输入参数时,保留页面设计器配置的确认提示;未配置确认提示则直接执行。
|
||
|
||
该行为由通用生成模板提供,借书、预约、归还、审核、上下架等业务按钮自动获得相同行为,不为某个动作编写特例。
|
||
|
||
## 现状与根因
|
||
|
||
`qing/index.vue.vm` 当前通过 `collectBusinessActionPayload` 遍历缺失字段,并为每个字段调用一次 Element UI `$prompt`。业务动作需要多个参数时,用户会连续处理多个彼此割裂的弹窗。
|
||
|
||
当前系统已经具备可复用的上下文:
|
||
|
||
- 行按钮传入当前行数据。
|
||
- 详情页持有 `detailRecord`。
|
||
- 页面持有 `form` 和 `queryParams`。
|
||
- 登录结果保存在 `portal-user`,请求令牌由请求拦截器携带。
|
||
- 后端业务动作控制器能够从令牌解析可信的当前用户,并注入 `__currentUserId`。
|
||
- 数据库字段包含字段注释和表单控件类型,可用于生成友好的输入项。
|
||
|
||
## 方案选择
|
||
|
||
### 采用:通用动态业务操作弹窗
|
||
|
||
模板先解析参数来源,再将全部未解析参数放入同一个 Element UI 对话框。此方案覆盖全部业务按钮,不增加逐按钮配置负担,也与现有页面样式和技术栈一致。
|
||
|
||
### 未采用:页面设计器逐按钮配置业务表单
|
||
|
||
它能处理高度定制的表单,但要求每个生成项目继续人工配置,无法从根本上修复默认生成体验。
|
||
|
||
### 未采用:每个业务动作使用独立页面
|
||
|
||
它适合多步骤、长流程业务,但会让借书、预约、审核等轻量动作变得笨重。独立业务页可作为未来扩展,不属于本次范围。
|
||
|
||
## 参数解析规则
|
||
|
||
执行按钮时,按以下顺序构建请求参数:
|
||
|
||
1. 当前按钮携带的行数据。
|
||
2. 当前详情页的 `detailRecord`。
|
||
3. 当前页面的 `form`。
|
||
4. 当前页面的 `queryParams`。
|
||
5. 可信登录用户上下文。
|
||
6. 单次弹窗中由用户填写的值。
|
||
|
||
字段同时支持 snake_case 和 camelCase,例如 `book_id` 可从记录的 `bookId` 获取。
|
||
|
||
登录用户字段不能依赖用户手工输入。业务动作生成上下文应标记由 `${current_user.id}` 提供的请求字段;前端不渲染这些字段,后端在执行规则和效果前使用认证用户 ID 覆盖对应参数。客户端即使伪造这些值也不能替换认证用户。
|
||
|
||
无法由上下文提供的字段才进入动态表单。字段标题优先使用数据库字段注释,控件优先使用数据库字段的 `htmlType`:
|
||
|
||
- 日期字段使用日期选择器。
|
||
- 字典或枚举字段使用选择器。
|
||
- 长文本使用多行输入。
|
||
- 普通字段使用文本输入。
|
||
|
||
第一期不增加页面设计器中的逐字段表单编排功能。
|
||
|
||
## 交互流程
|
||
|
||
### 有待输入参数
|
||
|
||
点击业务按钮后打开一个以业务动作名称为标题的弹窗。弹窗包含:
|
||
|
||
- 当前操作的简短说明或已有 `confirmMessage`。
|
||
- 所有待输入字段。
|
||
- 取消按钮。
|
||
- `${buttonLabel}` 或“确认执行”按钮。
|
||
|
||
用户提交时统一校验必填字段。校验通过后关闭输入能力、显示提交状态并发送一次请求。提交按钮本身就是确认动作,不再显示第二个确认弹窗。
|
||
|
||
### 无待输入参数
|
||
|
||
- 配置了 `confirmMessage`:显示一次确认框,确认后执行。
|
||
- 未配置 `confirmMessage`:直接执行。
|
||
|
||
### 执行结果
|
||
|
||
- 成功时显示配置的 `successMessage`,并按 `refreshTarget` 刷新列表、详情、整页或不刷新。
|
||
- 业务失败时保留弹窗和用户输入,显示后端返回消息,允许修正后重试。
|
||
- 用户取消时不发送请求。
|
||
- 请求进行中禁止重复提交。
|
||
|
||
## 组件与模板边界
|
||
|
||
`qing/index.vue.vm` 增加一个通用业务操作对话框状态和方法:
|
||
|
||
- 当前动作和当前记录。
|
||
- 自动解析后的请求载荷。
|
||
- 待输入字段定义与表单值。
|
||
- 打开、校验、提交、取消和错误处理。
|
||
|
||
业务按钮仍统一调用 `handleBusinessAction`。该方法不直接串联 `$prompt`,而是选择以下路径:
|
||
|
||
- 打开动态表单。
|
||
- 显示一次简单确认。
|
||
- 直接执行。
|
||
|
||
`BusinessActionDesign` 或生成期等价结构提供渲染所需的临时字段元数据,包括显示名、控件类型、选项和当前用户绑定信息。业务蓝图持久化格式保持向后兼容;已有项目没有新元数据时,生成器从已保存数据库结构推导默认值。
|
||
|
||
`controller.java.vm` 和 `serviceImpl.java.vm` 继续以认证令牌为用户身份来源,并在参数校验、规则检查和效果执行之前注入或覆盖当前用户绑定字段。
|
||
|
||
SQL 中的 Qing 模板副本必须与资源模板同步,保证新数据库和已有模板回退路径行为一致。
|
||
|
||
## 兼容性
|
||
|
||
- 保留现有业务按钮的标签、类型、图标、确认提示、成功提示和刷新目标配置。
|
||
- 保留现有业务动作 API 路径、HTTP 方法和请求字段名称。
|
||
- 行按钮、详情按钮和工具栏按钮使用同一套运行时。
|
||
- 已能从行或详情数据解析全部参数的动作不会多出表单。
|
||
- 旧业务蓝图无需迁移即可生成;缺少字段元数据时使用通用输入控件。
|
||
|
||
## 测试
|
||
|
||
先增加失败测试,再修改实现。
|
||
|
||
模板渲染测试覆盖:
|
||
|
||
- 页面不再包含逐字段 `$prompt`。
|
||
- 页面只渲染一个通用业务操作对话框。
|
||
- 多个缺失字段在同一表单中生成。
|
||
- 行数据和详情数据可自动解析 snake_case/camelCase 参数。
|
||
- 当前用户绑定字段不显示为输入项。
|
||
- 没有待输入字段时保留一次确认或直接执行。
|
||
- 成功提示、错误提示和刷新目标保持原行为。
|
||
- SQL 模板副本与资源模板一致。
|
||
|
||
后端测试覆盖:
|
||
|
||
- 当前用户字段由认证用户覆盖。
|
||
- 缺失普通参数仍返回明确业务错误。
|
||
- 客户端伪造用户字段不能代表其他用户执行操作。
|
||
|
||
浏览器验收至少覆盖借书和另一个多参数业务按钮:
|
||
|
||
- 点击后最多出现一个弹窗。
|
||
- 不需要输入 user id。
|
||
- 当前图书参数自动带入。
|
||
- 表单提交只发送一次请求。
|
||
- 取消不发送请求。
|
||
- 成功后页面按配置刷新。
|