很多系统中,诸如“性别、状态、类型、标签”等字段虽然值较少,却频繁出现于表单、下拉框、表格、报表等位置。为了避免硬编码、提升可维护性,“数据字典系统”成为企业级项目的常规需求。
本文将手把手教你如何构建一套灵活、可配置、可扩展的数据字典系统,支持前端动态加载、后端缓存管理、权限控制等能力。
一、典型应用场景
字段 | 示例值 |
---|---|
性别 | 男、女、未知 |
用户状态 | 启用、禁用 |
订单状态 | 待支付、已完成、退款中 |
设备类型 | 安卓、苹果、PC |
二、数据库设计(MySQL)
CREATE TABLE dict_type (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
code VARCHAR(50) NOT NULL UNIQUE,
name VARCHAR(100) NOT NULL
);
CREATE TABLE dict_item (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
type_code VARCHAR(50),
label VARCHAR(100),
value VARCHAR(100),
sort INT DEFAULT 0,
status TINYINT DEFAULT 1 -- 1启用 0停用
);
三、核心设计理念
- 按 type_code 组织字典分组
- item 可被动态添加/禁用/排序
- 前端通过接口拉取,不硬编码
四、Java 后端实现
获取某个字典组接口
@GetMapping("/dict/{code}")
public List<DictItem> getByType(@PathVariable String code) {
return dictItemMapper.selectList(Wrappers.<DictItem>lambdaQuery()
.eq(DictItem::getTypeCode, code)
.eq(DictItem::getStatus, 1)
.orderByAsc(DictItem::getSort));
}
可选缓存(Redis)加速访问
String key = "dict:" + code;
List<DictItem> list = redis.get(key);
if (list == null) {
list = queryFromDB();
redis.set(key, list, 3600);
}
五、Python 实现(Flask 示例)
@app.route("/dict/<code>")
def get_dict(code):
rows = db.query("SELECT label, value FROM dict_item WHERE type_code=%s AND status=1 ORDER BY sort", [code])
return jsonify(rows)
六、Vue 前端动态加载字典
1. 封装通用接口获取方法
async function getDict(code) {
const res = await axios.get(`/dict/${code}`)
return res.data.map(i => ({ label: i.label, value: i.value }))
}
2. 表单 select 使用
<el-select v-model="form.gender" :options="dicts.gender" />
3. 初始化拉取字典
const dicts = reactive({ gender: [] })
onMounted(async () => {
dicts.gender = await getDict('gender')
})
七、接口文档模板
获取某类字典
GET /dict/gender
Response:
[
{ "label": "男", "value": "M" },
{ "label": "女", "value": "F" }
]
八、扩展建议
功能 | 实现说明 |
---|---|
多语言支持 | 添加多语言字段 label_en 等 |
字典管理后台 | 字典类型和项可增删改查 |
数据权限 | 控制某些角色只能看部分字典项 |
字典变更通知 | 通过事件通知清理 Redis 缓存 |
九、总结
层级 | 职责描述 |
---|---|
数据库 | 组织字典类型与字典项数据 |
后端 | 提供统一字典读取接口 + 缓存 |
前端 | 表单、下拉、展示等统一拉取渲染 |
数据字典系统,是高可维护系统的基础设施。规范字典使用、避免硬编码、支持扩展管理,将大幅提升系统灵活性与前后端协同效率。