You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cz-hjjc-budget/docs/choice类型字段说明与数据供给.md

85 lines
5.1 KiB

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.

# OA「choice」类型字段说明与数据供给
本文先说明 OA 模块里 **choice** 相关字段类型的含义(用普通人能懂的话),再说明在「选择事前流程」弹窗里,这类字段的数据从哪里来、如何展示。
---
## 一、OA 里「choice」到底是什么意思
在 OA 的**流程表单设计**里,配置字段时有两种和「选择」有关的类型,最终在库里都存成 `type = choice`,靠另一个字段 `multiple` 区分:
| 配置时选的类型 | 界面上叫法 | 实际含义(人话) | 存库后 |
|----------------|------------|------------------|--------|
| **choice** | **人员选择** | 从系统用户名单里**选人**,可多选。例如「经办人」「参与人」。选项固定为「用户」,不能改成别的。 | `type=choice``multiple=10``selection_model=App\Models\User` |
| **choices** | **多选** | 从某一类**数据**里勾选多项。例如部门、项目、预算来源等。具体选项来自「下拉数据」配置的模型,或「数据选项」里手写的列表。 | 保存时被改成 `type=choice``multiple=1``selection_model` 按配置来 |
所以:
- **「人员选择」**:专门用来选人的,只能选用户,可多选。
- **「多选」**:通用多选,选什么是配置决定的(用户、部门、项目等),可多选。
两种在系统里都叫 **choice 类型**,只是「人员选择」和「多选」的配置不同。
---
## 二、选项从哪里来?(数据供给,人话版)
**无论是「人员选择」还是「多选」,选项列表都是同一条链路:**
1. 配置里有一个 **「下拉数据」**(即 `selection_model`),表示:从哪个**数据表/模型**拉选项。
- 人员选择:固定为用户表(`App\Models\User`)。
- 多选:在表单设计里选,比如用户、部门、项目等。
2. 前端调用接口:**根据「下拉数据」去要选项列表**。
接口:`GET /oa/flow/selection-options?selection_model=xxx`
后端按这个模型查数据,返回 `[{id, value, label, name}, ...]`
3. 用户填表时**选中的是 id**;存库时,多选一般存成 **一串 id**
- 有的地方用 `|` 分隔,如 `123|456|789`
- 有的地方用 `,` 分隔,如 `123,456,789`
- 也可能是数组 `[123, 456, 789]`
**总结**
选项 = 按「下拉数据」从系统里查出来的列表;
用户选的是 id存的是多个 id 拼成的一串或数组。展示时,再用 id 去选项列表里找对应的「名称」来显示。
---
## 三、在「选择事前流程」弹窗里choice 列怎么回事?
弹窗里流程列表的**列**,有一部分来自 OA 流程模型的「列表展示字段」。如果某列是 **choice 类型**(即「人员选择」或「多选」),逻辑应该是:
- **选项**:和上面一样,按 `selection_model``getSelectionOptions` 拿选项列表。
- **展示**:每个格子里存的是 id`id1|id2`、`id1,id2`),应当查选项列表转成「张三、李四」这类名称再显示。
但当前 **PreApprovalFlowPicker** 组件里:
- 加载选项时,只处理了 `select`、`radio`**没有单独处理 `choice`**。
所以,如果某一列**仅是 choice**(没有同列的 select/radio 共用同一个 selection_model这根列**不会去拉选项**。
- 格式化展示时,也只处理了 `select`、`radio`**没有 `choice` 分支**。
结果就是:**直接显示原始存值**(例如 `123|456``123,456`),不会变成「张三、李四」。
因此:
**从设计上**choice 的选项和数据供给与 select/radio 一样,都是 `selection_model` → 选项接口;
**从实现上**,弹窗里的 choice 列目前没有按「多选 + 选项映射」完整做,所以会看到一串 id 而不是人名或名称。
---
## 四、若要让 choice 列正常显示「名称」
需要至少做两件事:
1. **拉选项**:在加载列表列配置时,把 `choice` 也当作「有 `selection_model` 就要拉选项」的类型,和 select/radio 一起调 `getSelectionOptions`
2. **展示时按多选解析**
- 把单元格里的值解析成多个 id支持 `|`、`,`、数组等);
- 用选项列表把每个 id 转成对应的 label/name
- 用顿号或逗号拼接后显示,例如:「张三、李四、王五」。
这样,**choice 类型在「选择事前流程」弹窗里的数据供给和展示**就与 OA 的设计一致了,普通用户看到的是可读的「名称」而不是 id 串。
---
## 五、相关代码与接口(给开发看)
- OA 字段配置与保存:`backend/Modules/Oa/resources/views/admin/custom-model/set-fields.blade.php``choice` / `choices` 的隐藏、保存逻辑)。
- 选项接口:`GET /oa/flow/selection-options``FlowController::getSelectionOptions`;前端 `oaFlowAPI.getSelectionOptions(selection_model)`
- 弹窗列表与格式化:`PreApprovalFlowPicker.vue` 的 `loadSubFormFieldsAndOptions`、`formatFieldValue`;可选参考 `ProcessQuery.vue` 里对 choice/choices 的 `parseChoiceValueToIds` 及多选展示逻辑。