# 数据字典 — 前端对接文档 > 遵循《业务中台产品接口说明书》全局契约 > 接口基础路径:`/api/dict` > 权限控制:纯 `hasAuthority`,权限码 `dict:*` 由初始化器种子化到权限资源树 > 需求来源:蓝湖原型「itc信息化业务中台 web端」页面 `A7-4-1 数据字典` > 架构决策:见 `docs/adr/0015-data-dictionary-crm-dict-two-level.md`;领域术语见 `crm-dict/CONTEXT.md` 本文档供前端**做原型**与**联调**使用。字典是两级结构:**字典分组**(第一级容器)→ **字典项**(第二级键值条目)。页面有两个页签:字典分组、字典列表。 --- ## 1. 接口总览 | 方法 | 路径 | 用途 | 权限码 | |------|------|------|--------| | `POST` | `/api/dict/group/page` | 分组分页查询 | `dict:group:list` | | `POST` | `/api/dict/group/saveOrUpdate` | 新增/编辑分组 | `dict:group:save` | | `POST` | `/api/dict/group/delete` | 删除分组 | `dict:group:delete` | | `POST` | `/api/dict/group/status` | 启用/停用分组 | `dict:group:status` | | `GET` | `/api/dict/group/enabled-list` | 启用分组列表(选分组用) | `dict:group:list` | | `POST` | `/api/dict/item/page` | 字典项分页查询 | `dict:item:list` | | `POST` | `/api/dict/item/saveOrUpdate` | 新增/编辑字典项 | `dict:item:save` | | `POST` | `/api/dict/item/delete` | 删除字典项 | `dict:item:delete` | | `POST` | `/api/dict/item/force-delete` | 强制删除字典项 | `dict:item:force-delete` | | `POST` | `/api/dict/item/status` | 启用/停用字典项 | `dict:item:status` | | `POST` | `/api/dict/item/set-default` | 设为分组默认项 | `dict:item:default` | | `GET` | `/api/dict/item/enabled-list` | 某分组启用项列表(业务选择器) | `dict:item:list` | **认证**:所有接口请求头携带 `Authorization: Bearer {token}`,token 对应用户须持有对应权限码。 **请求格式**:GET 参数走 URL query;POST 用 `Content-Type: application/x-www-form-urlencoded`,参数为表单字段(不是 JSON body)。 **ID**:所有 id 按**字符串**收发(雪花 ID 超出 JS Number 安全范围),前端回传原样传字符串,不要转 Number。 --- ## 2. 数据模型 ### 2.1 DictGroup(字典分组) ```typescript interface DictGroup { id: string; // 分组 ID name: string; // 分组名称(必填) code: string; // 分组编码(全局唯一,创建后不可改;新建必填) itemCount: number; // 字典数量(该分组下未删除字典项数,含启用+停用) sortNo: number | null; // 排序号(可空,非负整数,值越小越靠前,空排最后) status: number; // 状态:1=启用 0=停用 description: string | null; // 描述 builtin: boolean; // 是否内置分组(true=平台内置,不可删除,可改名/描述/排序/启停) } ``` ### 2.2 DictItem(字典项) ```typescript interface DictItem { id: string; // 字典项 ID groupId: string; // 所属分组 ID(创建后不可改) groupName: string; // 所属分组名称(列表展示用) name: string; // 字典名称(必填,展示文案,改名后历史数据展示最新名) code: string; // 字典编码(分组内唯一,创建后不可改;未填自动生成 dict_+32位hex) value: string | null; // 字典值(同组唯一,空值不校验;被引用后只读) sortNo: number | null; // 排序号(同 DictGroup) status: number; // 状态:1=启用 0=停用 isDefault: boolean; // 是否分组默认项(派生字段,非独立存储) referenced: boolean; // 是否被业务数据引用(true 时不可删、分组/值只读) effectiveSelectable: boolean; // 有效可选 = 分组启用 且 本项启用 builtin: boolean; // 是否内置字典项 description: string | null; } ``` > **失活标记**:当 `status===1`(自身启用)但 `effectiveSelectable===false`(因所属分组已停用)时,列表行应加**视觉标记**(角标/灰化)并提示"所属分组已停用,当前字典暂不可用"。 ### 2.3 状态枚举 | 值 | 含义 | |----|------| | 1 | 启用 | | 0 | 停用 | --- ## 3. 统一响应结构 ```typescript interface Result { code: number; // 200 成功,其余为业务错误码 message: string; data: T; } interface PageResult { records: T[]; total: number; current: number; size: number; } ``` --- ## 4. 字典分组接口 ### 4.1 分组分页 `POST /api/dict/group/page` 请求(表单):`current`、`size`、`keyword`(可选,匹配名称/编码)、`status`(可选,1/0) 响应:`Result>` ### 4.2 分组保存 `POST /api/dict/group/saveOrUpdate` 请求(表单): | 字段 | 必填 | 说明 | |------|------|------| | `id` | 编辑必填 | 新建不传 | | `name` | 是 | 去首尾空格 | | `code` | 是 | **仅新建可传**;仅字母/数字/下划线。**编辑时忽略/只读** | | `sortNo` | 否 | 非负整数 | | `description` | 否 | | 错误:`name` 空 → 提示必填;`code` 格式非法 → 提示;`code` 全局重复 → "分组编码已存在"。 ### 4.3 分组删除 `POST /api/dict/group/delete` 请求(表单):`id` 规则:分组下**存在任何未删除字典项**→ 阻断,提示"该分组下仍有字典,无法删除";`builtin=true` → 阻断"内置分组不可删除"。 ### 4.4 分组启停 `POST /api/dict/group/status` 请求(表单):`id`、`status`(1/0) 前端**二次确认**后调用。停用后该分组下所有字典项都不进入业务选择器(即使项自身启用);默认项关系保留(休眠),重新启用后原默认项继续生效(若其自身启用)。 ### 4.5 启用分组列表 `GET /api/dict/group/enabled-list` 无参。返回所有启用状态分组(`Result`),供"新建字典项"时选择所属分组——**只能选启用分组**。 --- ## 5. 字典项接口 ### 5.1 字典项分页 `POST /api/dict/item/page` 请求(表单):`current`、`size`、`groupId`(可选,按分组筛选)、`keyword`(可选,匹配名称/编码/值)、`status`(可选) 响应:`Result>` ### 5.2 字典项保存 `POST /api/dict/item/saveOrUpdate` 请求(表单): | 字段 | 必填 | 说明 | |------|------|------| | `id` | 编辑必填 | | | `groupId` | 新建必填 | **仅新建可传**;只能选启用分组。**编辑时只读**(分组创建后不可改) | | `name` | 是 | 去首尾空格;被引用后**仍可改** | | `code` | 否 | **仅新建可传**;仅字母/数字/下划线;未填自动生成。编辑只读 | | `value` | 否 | 同组唯一(空不校验);**被引用后只读** | | `sortNo` | 否 | 非负整数 | | `description` | 否 | | 错误:`name` 空 → 必填;`code` 非法/组内重复 → 提示;`value` 组内重复 → "字典值已存在";被引用后传了 `groupId`/`code`/`value` 改动 → 拒绝并提示只读。 > 前端编辑态:`referenced===true` 时,把「分组」「编码」「字典值」置灰只读;「名称」「排序」「描述」仍可编辑。`referenced===false` 时「字典值」可编辑,「分组」「编码」始终只读。 ### 5.3 字典项删除 `POST /api/dict/item/delete` 请求(表单):`id` 规则:`referenced===true` → 阻断,提示"该字典已被引用,无法删除";`builtin=true` → 阻断;未被引用可直接删(不要求先停用)。 ### 5.4 强制删除 `POST /api/dict/item/force-delete` 请求(表单):`id` 用途:引用计数因故飘高、实际已无引用但常规删除被阻断时的**管理员兜底**。前端需**强二次确认**("确认强制删除?此操作绕过引用校验")。需 `dict:item:force-delete` 权限,界面上仅对有此权限者显示。 ### 5.5 字典项启停 `POST /api/dict/item/status` 请求(表单):`id`、`status`(1/0) 前端二次确认。停用时若该项是默认项 → 后端自动取消其默认状态(不自动补新默认)。 ### 5.6 设为默认项 `POST /api/dict/item/set-default` 请求(表单):`id` 后端一次事务内:清除同分组原默认项 + 将本项设为默认。每组至多一个默认项。仅用于新建业务数据的初始选择,不改已有业务数据。 ### 5.7 分组启用项列表 `GET /api/dict/item/enabled-list` 请求(query):`groupCode`(或 `groupId`,二选一,建议 `groupCode`) 返回该分组下**有效可选**(分组启用且项启用)的字典项列表,供业务页面的**业务选择器**(下拉)渲染。分组停用 → 返回空列表。 --- ## 6. 业务侧取值约定(供其他业务页面开发者) - 业务数据**只保存字典编码**(`code`),不保存 id、不保存名称。 - 每个业务字段在设计期**固定绑定一个字典分组**(如客户「行业」字段永远读 `industry` 分组)。禁止一个字段跨多个分组取值。 - 展示业务数据时,用 `(该字段绑定的分组编码, 存的字典编码)` 反查字典项,显示其**最新名称**。 - 渲染新建/编辑业务表单的下拉时,调 `enabled-list` 拿有效选项。 - 编辑历史业务数据时:若原选中的字典项已停用,仍需**回显**该值并标注"已停用";用户清除后该项不可再选。 --- ## 7. 排序规则 列表排序:有排序号的按号升序 → 无排序号的排在后面 → 排序号相同或都为空的按创建时间升序。字典项分页先按分组、再按项排序。前端**不做拖拽重排**(后端只接受手填 `sortNo`);如需拖拽体验,前端可在保存时重算该组所有项的 `sortNo` 逐条提交。 --- ## 8. 权限码一览 | 权限码 | 控制 | |--------|------| | `dict:group:list` | 分组查询、启用分组列表 | | `dict:group:save` | 分组新增/编辑 | | `dict:group:delete` | 分组删除 | | `dict:group:status` | 分组启停 | | `dict:item:list` | 字典项查询、启用项列表 | | `dict:item:save` | 字典项新增/编辑 | | `dict:item:delete` | 字典项删除 | | `dict:item:force-delete` | 字典项强制删除 | | `dict:item:status` | 字典项启停 | | `dict:item:default` | 设默认项 | 无对应权限 → 后端返回无权限错误码;前端应据登录用户权限码隐藏对应入口/按钮(但服务端强制校验为准,前端隐藏不可替代)。