数据字典
在业务开发中,数据字典是管理关键枚举、状态和下拉选项的基础能力。它可以让数据库值、页面展示、Excel 导入导出、代码生成器和业务校验保持同一套口径。
v2.0.0 在原有“字典类型 + 字典项”的基础上新增了 字典来源,用于区分框架内置字典、业务自定义字典以及派生模块字典,避免后续升级时 ID 号段和初始化脚本相互覆盖。
当前模型
v2.0.0 的数据字典由三层组成:
| 层级 | 表 / 实现 | 说明 |
|---|---|---|
| 字典来源 | sys_dict_source | 管理来源编码、来源名称和字典类型 ID 号段,例如 framework、custom |
| 字典类型 | sys_dict_type | 管理 type_code、type_name,并通过 source_code 归属到某个来源 |
| 字典项 | sys_dict | 管理具体选项,包含 code_name、alias、callback_show_style、排序和显示状态 |
默认来源如下:
| source_code | source_name | ID 区间 | 说明 |
|---|---|---|---|
framework | 框架内置 | 1000 - 1999 | 官方内置字典,升级时应尽量跟随官方 |
custom | 业务自定义 | 2000 - 2999 | 默认业务字典来源,适合普通二开业务 |
字典 ID 仍保持可读规则:
- 字典类型 ID:在来源区间内递增,例如
framework下的1000、1001。 - 字典项 ID:
字典类型ID + 三位自增序号,例如类型1001下的字典项为1001001、1001002。
TIP
如果你维护独立业务模块,建议新增自己的字典来源,例如 shop、sso、crm,并规划独立号段。这样生成初始化脚本、迁移字典和合并官方升级时更容易判断归属。
管理入口
字典类型与字典项
字典管理页面包含“字典类型”和“字典来源”两个页签:
- “字典类型”页签用于新增、编辑、删除字典类型,并通过类型编码进入字典项维护。
- 新增字典类型时必须选择
sourceCode;编辑时来源不允许修改。 - 框架锁定的字典类型和字典项不建议在页面直接删除或改名。
- 字典类型列表展示来源名称和来源区间,便于判断当前字典属于框架还是业务。


字典来源
字典来源页签用于维护来源编码与 ID 号段。它解决的是“哪些字典由框架维护、哪些字典由业务维护、不同模块是否会抢占同一段 ID”的问题。
字典来源字段:
| 字段 | 说明 |
|---|---|
sourceCode | 来源编码,唯一,新增后不允许修改 |
sourceName | 来源名称,用于页面展示 |
startId / endId | 字典类型 ID 可用区间 |
status | 启用状态 |
remark | 备注 |
后端校验规则:
startId不能大于endId。- 来源编码不能重复。
- 新来源区间不能与已有来源区间重叠。
- 新来源区间不能覆盖已有字典类型 ID。
- 修改来源区间时,如果原来源下已有字典类型落在新区间外,则不允许缩小或移动该区间。
- 删除来源前,必须确保该来源下没有字典类型。
NOTE
sys_dict_source 使用 TableSysDictSourceListener 自动清理 dynamic_dict_source_options 缓存。前端新增、编辑或删除来源后,也会重新拉取该动态字典,让“新增字典类型”弹窗里的来源下拉保持最新。
TIP
截图占位:后续可补充“字典来源列表页”“新增/编辑字典来源弹窗”“字典类型关联来源字段”的截图。
静态字典与动态字典
静态字典
静态字典来自 sys_dict_type 和 sys_dict。系统通过 DefaultStaticDictLoader 加载并缓存字典数据,前端路由初始化时优先获取静态字典,动态字典再按页面需要延迟加载。
常用接口:
| 能力 | 接口 |
|---|---|
| 查询全部字典 | GET /sys-dict/dict |
| 查询静态字典 | GET /sys-dict/static |
| 批量按类型查询 | GET /sys-dict/code?typeCode=account_status&typeCode=data_scope |
当前没有 GET /sys-dict/dict/{typeCode} 路径;按类型查询请使用 GET /sys-dict/code,并通过多个 typeCode 参数批量传入。
字典项新增、修改、删除后,后端会清除对应 typeCode 的 Redis 缓存,重新加载字典,并通过 WebSocket 同步字典变更。静态字典全量加载后会写入以下 Redis Key:
| Key | 说明 |
|---|---|
sys_dict | 字典 hash 数据,field 为 typeCode |
sys_dict:static_loaded | 静态字典是否已全量加载的标记 |
sys_dict:static_types | 已加载的静态字典 typeCode 列表 |
动态字典
动态字典不固定落库到 sys_dict,而是由业务 Loader 实时生成。例如系统用户、部门、角色、字典来源等选项,会随业务表变化而变化。
当前内置动态字典:
| typeCode | 说明 |
|---|---|
dynamic_user_options | 用户信息 |
dynamic_dept_options | 部门信息 |
dynamic_role_options | 角色信息 |
dynamic_dict_source_options | 字典来源 |
动态字典实现接口为 DynamicDictLoader:
public interface DynamicDictLoader extends DictLoader {
String getTypeCode();
String getTypeName();
default String getDynamicPrefix() {
return DYNAMIC_DICT_PREFIX;
}
default String getDynamicTypeCode() {
return getDynamicPrefix() + getTypeCode();
}
}DictLoaderFactory 会按完整动态 typeCode 精确注册动态字典加载器。完整 typeCode 默认为 dynamic_ + getTypeCode(),例如 dict_source_options 会变成 dynamic_dict_source_options。如果动态 typeCode 为空或重复,服务启动时会抛出异常,避免同一个下拉来源被多个 Loader 覆盖。
示例:字典来源动态字典会把 sys_dict_source 转为页面下拉选项:
@Component
@RequiredArgsConstructor
public class DictSourceOptionDictLoader implements DynamicDictLoader {
private final RedisCache redisCache;
private final SysDictSourceService sysDictSourceService;
@Override
public String getTypeCode() {
return DynamicDictEnum.DYNAMIC_DICT_SOURCE_OPTIONS.getTypeCode();
}
@Override
public String getTypeName() {
return DynamicDictEnum.DYNAMIC_DICT_SOURCE_OPTIONS.getName();
}
@Override
public Map<String, List<DictVO>> loadDict() {
String key = getDynamicTypeCode();
if (redisCache.hasHashKey(key)) {
return Map.of(key, redisCache.getDictByType(key));
}
List<DictVO> list = new ArrayList<>();
// 查询来源并转换为 DictVO 后写入 list
redisCache.setDict(key, list);
return Map.of(key, list);
}
}前端使用
页面中可以通过 useDict 主动加载字典,并通过 useDictOptions 获取响应式选项:
<script setup lang="ts">
import { useDict } from '@/hooks/useDict';
import { useDictOptions } from '@/hooks/useDictOptions';
useDict(['account_status', 'data_scope', 'dynamic_user_options']);
const accountStatusOptions = useDictOptions('account_status');
const dataScopeOptions = useDictOptions('data_scope');
</script>在 ProTable 中,可以把字典选项传给 enum,并通过 fieldNames 指定展示字段:
{
prop: 'status',
label: '状态',
tag: true,
enum: useDictOptions('account_status'),
fieldNames: { label: 'codeName', value: 'id', tagType: 'callbackShowStyle' }
}前端 optionsStore 的加载策略:
getAllDictList()调用GET /sys-dict/static,用于预热静态字典。getDictOptions(typeCode)如果发现当前 typeCode 未加载或已过期,会触发ensureDictByCodes([typeCode])。getDictByCodes(typeCodes)调用GET /sys-dict/code批量补拉静态或动态字典。- Store 内部通过
loadedTypes、expiredTypes、loadingTypes避免重复请求,并在收到 WebSocketSYNC_DICT后标记已加载字典过期。
脚本预览与导出
字典管理原本已支持脚本预览与导出。v2.0.0 主要对该能力做了数据库兼容性适配:导出的初始化脚本可按目标数据库生成 MySQL 或 PostgreSQL 口径,便于在不同数据库部署、模块初始化、字典迁移和二开模块发布时复用。
导出前建议确认字典类型、字典项和 sourceCode 都已归属到正确来源,并根据实际部署数据库选择对应脚本类型。MySQL 与 PostgreSQL 在批量插入、冲突处理、字段类型和转义细节上存在差异,不建议跨数据库直接混用导出脚本。
TIP

使用场景
1. Table、Excel 的展示
表格中显示的数据可以根据字典关联项自动将值转换为对应的名称。例如字段存储的是状态 ID,页面展示的是“正常、禁用、禁言”等可读名称。


2. 编辑页面选择
在编辑页面,字典提供了统一的下拉选项来源。静态字典适合固定状态,动态字典适合用户、部门、角色等实时变化的数据。

3. 代码生成器与字典关联设置
代码生成器支持为字段选择字典类型和字典展示方式。v2.0.0 中生成器会读取静态字典和动态字典类型,并按来源分组展示,便于选择框架内置字典或业务字典。

4. Excel 导入导出
Excel 模板下载和导入解析可以复用字典能力:下载模板时提供可选项,导入时将展示值转换为系统内的字典 ID,减少用户手填编码的错误率。
