feat(dict): data dictionary module — two-level flat model, CRUD/default/cache/permission/seed (ADR-0015)
- 4 tables (dict_group/dict_item/dict_group_default/dict_ref_count), delete_key soft-delete reuse
- DictGroup/DictItem full CRUD + force-delete + status toggle + enabled-list
- DictReferenceService: increment/decrement/batchApply/isReferenced, same-tx ref_count, no cache
- DictQueryService: Caffeine 10s cache + 2s negative cache for empty results, group.status join
- Default item: INSERT ON DUPLICATE KEY UPDATE, hibernate on group disable, auto-restore
- Permission seeds: 10 perm codes → sys_menu tree, bound to ROLE_ADMIN, no crm-auth import
- Built-in dict initializer: idempotent upsert, builtin=false never touched (US-41), value not overwritten
- 48 tests pass; full project compiles
1 month ago
|
|
|
# 数据字典(crm-dict)
|
|
|
|
|
|
|
|
|
|
平台级的键值字典管理,两级结构(分组 → 字典项),字典项之间可再挂一级/二级父子(parentId 两级树,见「二级字典项」),供业务模块通过稳定编码取值。访问控制走权限点(`dict:*`),不依赖“超级管理员”类角色标记。
|
feat(dict): data dictionary module — two-level flat model, CRUD/default/cache/permission/seed (ADR-0015)
- 4 tables (dict_group/dict_item/dict_group_default/dict_ref_count), delete_key soft-delete reuse
- DictGroup/DictItem full CRUD + force-delete + status toggle + enabled-list
- DictReferenceService: increment/decrement/batchApply/isReferenced, same-tx ref_count, no cache
- DictQueryService: Caffeine 10s cache + 2s negative cache for empty results, group.status join
- Default item: INSERT ON DUPLICATE KEY UPDATE, hibernate on group disable, auto-restore
- Permission seeds: 10 perm codes → sys_menu tree, bound to ROLE_ADMIN, no crm-auth import
- Built-in dict initializer: idempotent upsert, builtin=false never touched (US-41), value not overwritten
- 48 tests pass; full project compiles
1 month ago
|
|
|
|
|
|
|
|
## Language
|
|
|
|
|
|
|
|
|
|
**字典分组**:
|
|
|
|
|
一组同类字典项的容器,是字典的第一级。有全局唯一、创建后不可改的分组编码。停用后其字典项不再进入业务选择器,但不影响历史数据回显。
|
|
|
|
|
_Avoid_: 字典类型、字典分类、category
|
|
|
|
|
|
|
|
|
|
**字典项**:
|
|
|
|
|
分组下的一条键值条目,是字典的第二级。有组内唯一、创建后不可改的字典编码,作为业务数据保存的稳定标识;`parentId=null` 即一级项,可挂二级子项(见「二级字典项」)。
|
feat(dict): data dictionary module — two-level flat model, CRUD/default/cache/permission/seed (ADR-0015)
- 4 tables (dict_group/dict_item/dict_group_default/dict_ref_count), delete_key soft-delete reuse
- DictGroup/DictItem full CRUD + force-delete + status toggle + enabled-list
- DictReferenceService: increment/decrement/batchApply/isReferenced, same-tx ref_count, no cache
- DictQueryService: Caffeine 10s cache + 2s negative cache for empty results, group.status join
- Default item: INSERT ON DUPLICATE KEY UPDATE, hibernate on group disable, auto-restore
- Permission seeds: 10 perm codes → sys_menu tree, bound to ROLE_ADMIN, no crm-auth import
- Built-in dict initializer: idempotent upsert, builtin=false never touched (US-41), value not overwritten
- 48 tests pass; full project compiles
1 month ago
|
|
|
_Avoid_: 字典值、字典条目、dict entry
|
|
|
|
|
|
|
|
|
|
**二级字典项**:
|
|
|
|
|
挂在同分组某个一级项下的子字典项:`parentId` 指向同分组的一级项,层级两级封顶。每个二级项是**独立字典行**、有独立字典编码;业务页面按「先一级再二级」两级联动选择,业务数据保存**所选行**的字典编码。停用一级项则其下二级连带不可选;删除有存活子项的一级项被拦截(先处理子项)。管理端维持 parentId 模型(202609 拍板 10)。
|
|
|
|
|
_Avoid_: 子字典、字典树节点、三级字典
|
|
|
|
|
|
feat(dict): data dictionary module — two-level flat model, CRUD/default/cache/permission/seed (ADR-0015)
- 4 tables (dict_group/dict_item/dict_group_default/dict_ref_count), delete_key soft-delete reuse
- DictGroup/DictItem full CRUD + force-delete + status toggle + enabled-list
- DictReferenceService: increment/decrement/batchApply/isReferenced, same-tx ref_count, no cache
- DictQueryService: Caffeine 10s cache + 2s negative cache for empty results, group.status join
- Default item: INSERT ON DUPLICATE KEY UPDATE, hibernate on group disable, auto-restore
- Permission seeds: 10 perm codes → sys_menu tree, bound to ROLE_ADMIN, no crm-auth import
- Built-in dict initializer: idempotent upsert, builtin=false never touched (US-41), value not overwritten
- 48 tests pass; full project compiles
1 month ago
|
|
|
**内置字典**:
|
|
|
|
|
`builtin=true` 的分组或字典项,由产品以 Excel 随版本发布、初始化脚本幂等导入,业务代码可硬依赖。管理员可改名、改描述、调排序、启停用,**不可删除**。
|
|
|
|
|
_Avoid_: 系统字典、固定字典
|
|
|
|
|
|
|
|
|
|
**用户字典**:
|
|
|
|
|
`builtin=false` 的分组或字典项,管理员在界面上自由新建、修改、删除。初始化脚本绝不触碰用户字典。
|
|
|
|
|
_Avoid_: 自定义字典、临时字典
|
|
|
|
|
|
|
|
|
|
**字典编码**:
|
|
|
|
|
字典项在其所属分组内的稳定标识,组内唯一。前端按原型标必填星号;后端保留未填时按 `dict_` + 32 位小写十六进制 UUID 自动生成的兵底(202609 拍板 3)。业务数据与系统配置只保存字典编码,从不保存字典名称。
|
feat(dict): data dictionary module — two-level flat model, CRUD/default/cache/permission/seed (ADR-0015)
- 4 tables (dict_group/dict_item/dict_group_default/dict_ref_count), delete_key soft-delete reuse
- DictGroup/DictItem full CRUD + force-delete + status toggle + enabled-list
- DictReferenceService: increment/decrement/batchApply/isReferenced, same-tx ref_count, no cache
- DictQueryService: Caffeine 10s cache + 2s negative cache for empty results, group.status join
- Default item: INSERT ON DUPLICATE KEY UPDATE, hibernate on group disable, auto-restore
- Permission seeds: 10 perm codes → sys_menu tree, bound to ROLE_ADMIN, no crm-auth import
- Built-in dict initializer: idempotent upsert, builtin=false never touched (US-41), value not overwritten
- 48 tests pass; full project compiles
1 month ago
|
|
|
_Avoid_: 字典 key、code、字典 ID
|
|
|
|
|
|
|
|
|
|
**字段-分组绑定**:
|
|
|
|
|
每个业务字段在设计期固定绑定唯一一个字典分组的约定。业务数据只存字典编码;分组由字段的绑定隐式提供,二者合成 `(分组编码, 字典编码)` 坐标反查唯一字典项。禁止一个字段跨多个分组取值——需合并选项时另建合并分组。
|
|
|
|
|
_Avoid_: 跨分组下拉、多分组并集字段
|
|
|
|
|
|
|
|
|
|
**字典名称**:
|
|
|
|
|
字典项的展示文案。被引用后仍可修改;改后所有历史数据统一展示最新名称。它是“展示层”,与作为“标识层”的字典编码严格分离。
|
feat(dict): data dictionary module — two-level flat model, CRUD/default/cache/permission/seed (ADR-0015)
- 4 tables (dict_group/dict_item/dict_group_default/dict_ref_count), delete_key soft-delete reuse
- DictGroup/DictItem full CRUD + force-delete + status toggle + enabled-list
- DictReferenceService: increment/decrement/batchApply/isReferenced, same-tx ref_count, no cache
- DictQueryService: Caffeine 10s cache + 2s negative cache for empty results, group.status join
- Default item: INSERT ON DUPLICATE KEY UPDATE, hibernate on group disable, auto-restore
- Permission seeds: 10 perm codes → sys_menu tree, bound to ROLE_ADMIN, no crm-auth import
- Built-in dict initializer: idempotent upsert, builtin=false never touched (US-41), value not overwritten
- 48 tests pass; full project compiles
1 month ago
|
|
|
_Avoid_: 字典标签、显示名
|
|
|
|
|
|
|
|
|
|
**字典值**:
|
|
|
|
|
字典项承载的取值(原型页称「字典键值」),供业务规则或外部接口消费,**必填**(202609 拍板 3:空白直接拒绝、不再归一 null;存量空值行编辑时需补值),在同一分组内唯一。与“字典编码”不同:编码是内部标识,字典值是对外取值。
|
|
|
|
|
_Avoid_: value(与“字典项”口语混用)
|
feat(dict): data dictionary module — two-level flat model, CRUD/default/cache/permission/seed (ADR-0015)
- 4 tables (dict_group/dict_item/dict_group_default/dict_ref_count), delete_key soft-delete reuse
- DictGroup/DictItem full CRUD + force-delete + status toggle + enabled-list
- DictReferenceService: increment/decrement/batchApply/isReferenced, same-tx ref_count, no cache
- DictQueryService: Caffeine 10s cache + 2s negative cache for empty results, group.status join
- Default item: INSERT ON DUPLICATE KEY UPDATE, hibernate on group disable, auto-restore
- Permission seeds: 10 perm codes → sys_menu tree, bound to ROLE_ADMIN, no crm-auth import
- Built-in dict initializer: idempotent upsert, builtin=false never touched (US-41), value not overwritten
- 48 tests pass; full project compiles
1 month ago
|
|
|
|
|
|
|
|
**默认项**:
|
|
|
|
|
分组当前选定的字典项,仅用于新建业务数据时的初始选择,从不修改已有业务数据。默认关系存于独立表 `dict_group_default(group_id PK, item_id)`,以主键约束保证每组最多一个;字典项自身不携带 `is_default` 字段。202609 拍板 2:默认项**禁止停用**——`/status` 端点与编辑保存两条停用路径均拦截(63013「该字典为分组默认项,请先取消默认或指定其他默认项」),替代旧「停用即取消默认」口径;分组停用时默认关系保留为休眠、分组启用后自动恢复的语义不变。
|
feat(dict): data dictionary module — two-level flat model, CRUD/default/cache/permission/seed (ADR-0015)
- 4 tables (dict_group/dict_item/dict_group_default/dict_ref_count), delete_key soft-delete reuse
- DictGroup/DictItem full CRUD + force-delete + status toggle + enabled-list
- DictReferenceService: increment/decrement/batchApply/isReferenced, same-tx ref_count, no cache
- DictQueryService: Caffeine 10s cache + 2s negative cache for empty results, group.status join
- Default item: INSERT ON DUPLICATE KEY UPDATE, hibernate on group disable, auto-restore
- Permission seeds: 10 perm codes → sys_menu tree, bound to ROLE_ADMIN, no crm-auth import
- Built-in dict initializer: idempotent upsert, builtin=false never touched (US-41), value not overwritten
- 48 tests pass; full project compiles
1 month ago
|
|
|
_Avoid_: 默认值、缺省项、is_default 字段
|
|
|
|
|
|
|
|
|
|
**被引用**:
|
|
|
|
|
字典项已被业务数据或系统配置以其字典编码保存的状态。宏观上由 `dict_ref_count` 计数反映。被引用锁定两件事:**删除**(除非管理员强制删除)与**换分组**(拦截,提示「该字典已被引用,不可修改」);字典名称与**字典键值**被引用后仍可改——业务侧只存编码,键值属展示/取值层(202609 拍板 4,原「被引用 ⇒ 值只读」口径废止)。
|
feat(dict): data dictionary module — two-level flat model, CRUD/default/cache/permission/seed (ADR-0015)
- 4 tables (dict_group/dict_item/dict_group_default/dict_ref_count), delete_key soft-delete reuse
- DictGroup/DictItem full CRUD + force-delete + status toggle + enabled-list
- DictReferenceService: increment/decrement/batchApply/isReferenced, same-tx ref_count, no cache
- DictQueryService: Caffeine 10s cache + 2s negative cache for empty results, group.status join
- Default item: INSERT ON DUPLICATE KEY UPDATE, hibernate on group disable, auto-restore
- Permission seeds: 10 perm codes → sys_menu tree, bound to ROLE_ADMIN, no crm-auth import
- Built-in dict initializer: idempotent upsert, builtin=false never touched (US-41), value not overwritten
- 48 tests pass; full project compiles
1 month ago
|
|
|
_Avoid_: 被使用、有关联
|
|
|
|
|
|
|
|
|
|
**引用计数**:
|
|
|
|
|
`(分组编码, 字典编码)` 当前被业务数据引用的总次数。业务侧存入/清除字典编码与计数增减在同一个事务内完成,不走异步。计数只回答“有没有”,不回答“被谁”。业务侧推荐走 `applyFieldChange(分组, 旧编码, 新编码)` 字段级随迁缝(相等不动、空白归 null、旧减新加);导入路径聚合 delta 后一次 `batchApply`(禁循环逐条)。202609 拍板 1:线索/商机/客户全部字典编码写路径已接线。
|
feat(dict): data dictionary module — two-level flat model, CRUD/default/cache/permission/seed (ADR-0015)
- 4 tables (dict_group/dict_item/dict_group_default/dict_ref_count), delete_key soft-delete reuse
- DictGroup/DictItem full CRUD + force-delete + status toggle + enabled-list
- DictReferenceService: increment/decrement/batchApply/isReferenced, same-tx ref_count, no cache
- DictQueryService: Caffeine 10s cache + 2s negative cache for empty results, group.status join
- Default item: INSERT ON DUPLICATE KEY UPDATE, hibernate on group disable, auto-restore
- Permission seeds: 10 perm codes → sys_menu tree, bound to ROLE_ADMIN, no crm-auth import
- Built-in dict initializer: idempotent upsert, builtin=false never touched (US-41), value not overwritten
- 48 tests pass; full project compiles
1 month ago
|
|
|
_Avoid_: 引用登记、引用记录
|
|
|
|
|
|
|
|
|
|
**强制删除**:
|
|
|
|
|
引用计数因业务代码漏写递减而飘高、导致实际无引用的字典项无法删除时,管理员可人工判定后绕过 ref_count 校验直接删除的兵底入口。不是常规删除路径。
|
|
|
|
|
_Avoid_: 硬删、管理员删除
|
|
|
|
|
|
|
|
|
|
**业务选择器**:
|
|
|
|
|
业务页面用于挑选字典项的下拉/选择控件。只有所属分组与字典项自身均为启用状态时,字典项才作为新可选项进入业务选择器;停用只影响新选择,不影响历史回显。
|
|
|
|
|
_Avoid_: 下拉框、选项列表
|
|
|
|
|
|
|
|
|
|
**名称回显**:
|
|
|
|
|
把已保存的字典编码换成中文字典名称在展示层显示。批量入口是读路径服务的 `getNames(分组编码, 一批字典编码)` → `编码 → 名称` 映射,语义等同逐条 `getItem`(含停用项、走 Caffeine 缓存),供 crm-lead / crm-opportunity 等调用方回填 DTO;「填哪些字段」留在各调用方,字典侧只负责「编码 → 名称」这一段。悬空编码兜底:未命中的编码(如 force-delete 后的存量引用)回显编码本身,不返回空名称。
|
|
|
|
|
_Avoid_: 名称翻译、label 回填
|
|
|
|
|
|
feat(dict): data dictionary module — two-level flat model, CRUD/default/cache/permission/seed (ADR-0015)
- 4 tables (dict_group/dict_item/dict_group_default/dict_ref_count), delete_key soft-delete reuse
- DictGroup/DictItem full CRUD + force-delete + status toggle + enabled-list
- DictReferenceService: increment/decrement/batchApply/isReferenced, same-tx ref_count, no cache
- DictQueryService: Caffeine 10s cache + 2s negative cache for empty results, group.status join
- Default item: INSERT ON DUPLICATE KEY UPDATE, hibernate on group disable, auto-restore
- Permission seeds: 10 perm codes → sys_menu tree, bound to ROLE_ADMIN, no crm-auth import
- Built-in dict initializer: idempotent upsert, builtin=false never touched (US-41), value not overwritten
- 48 tests pass; full project compiles
1 month ago
|
|
|
**排序号**:
|
|
|
|
|
字典分组与字典项均可选填的非负整数,人工填写(不提供拖拽自动重排)。DB 存 NULL、不存“大数占位”;查询排序用 `ORDER BY sort_no IS NULL, sort_no ASC, create_time ASC` 实现 “有值升序 → 无值靠后 → 同值或都无值按创建时间升序”。
|
|
|
|
|
_Avoid_: 拖拽重排、大数占位
|