字典管理
字典管理是后台管理系统中常用的功能,用于统一管理系统中的配置项,如性别、状态、类型等枚举值。
什么是字典?
字典是一组键值对数据,用于存储系统配置项,例如:
| 字典编码 | 字典名称 | 字典项 |
|---|---|---|
| gender | 性别 | 男(1)、女(2)、未知(0) |
| status | 状态 | 启用(1)、禁用(0) |
| user_type | 用户类型 | 普通用户(1)、管理员(2) |
字典组件
DictSelect 字典选择器
用于表单中选择字典值:
vue
<template>
<!-- 下拉选择(默认) -->
<DictSelect v-model="form.gender" code="gender" />
<!-- 单选框 -->
<DictSelect v-model="form.status" code="status" type="radio" />
<!-- 复选框(多选) -->
<DictSelect v-model="form.tags" code="tags" type="checkbox" />
</template>
<script setup lang="ts">
const form = reactive({
gender: 1,
status: 1,
tags: []
})
</script>DictTag 字典标签
用于表格或详情页展示字典值:
vue
<template>
<el-table :data="tableData">
<el-table-column label="性别" prop="gender">
<template #default="{ row }">
<DictTag :value="row.gender" code="gender" />
</template>
</el-table-column>
</el-table>
</template>字典缓存
缓存机制
字典数据会自动缓存到 Pinia Store 中,避免重复请求:
typescript
// src/store/modules/dict.ts
export const useDictStore = defineStore('dict', () => {
const dictCache = ref<Map<string, DictItem[]>>(new Map())
// 获取字典数据(带缓存)
async function getDict(code: string) {
if (dictCache.value.has(code)) {
return dictCache.value.get(code)
}
const data = await DictAPI.getDictItems(code)
dictCache.value.set(code, data)
return data
}
// 清除缓存
function clearCache(code?: string) {
if (code) {
dictCache.value.delete(code)
} else {
dictCache.value.clear()
}
}
return { dictCache, getDict, clearCache }
})使用缓存
typescript
import { useDictStore } from '@/store/modules/dict'
const dictStore = useDictStore()
// 获取字典数据
const genderOptions = await dictStore.getDict('gender')
// 清除指定字典缓存
dictStore.clearCache('gender')
// 清除所有缓存
dictStore.clearCache()字典同步
系统支持通过实时通信(WebSocket)实时同步字典数据,当后台修改字典后,前端会自动更新。
启用字典同步
typescript
import { useDictSync } from '@/composables'
// 在 App.vue 或布局组件中
const { startSync, stopSync } = useDictSync()
onMounted(() => {
startSync()
})
onUnmounted(() => {
stopSync()
})同步原理
- 前端通过 WebSocket 订阅字典变更主题
- 后台修改字典后发送变更消息
- 前端收到消息后清除对应字典缓存
- 下次使用时重新请求最新数据
typescript
// 订阅字典变更
subscribe('/topic/dict/change', (message) => {
const { code, action } = JSON.parse(message.body)
// 清除变更的字典缓存
dictStore.clearCache(code)
// 可选:显示通知
if (action === 'update') {
ElMessage.info(`字典 ${code} 已更新`)
}
})字典 API
获取字典列表
typescript
// 分页查询字典类型
const { list, total } = await DictAPI.getDictPage({
pageNum: 1,
pageSize: 10,
keywords: ''
})获取字典项
typescript
// 根据字典编码获取字典项
const items = await DictAPI.getDictItems('gender')
// 返回: [{ label: '男', value: 1 }, { label: '女', value: 2 }]字典管理
typescript
// 新增字典类型
await DictAPI.addDict({ code: 'level', name: '等级' })
// 更新字典类型
await DictAPI.updateDict(id, { name: '用户等级' })
// 删除字典类型
await DictAPI.deleteDict(id)
// 新增字典项
await DictAPI.addDictItem({ dictId, label: '高级', value: 3 })最佳实践
1. 字典编码规范
使用小写字母和下划线命名:
gender # 性别
user_status # 用户状态
order_type # 订单类型2. 字典值类型
建议使用数字类型作为字典值,便于存储和比较:
typescript
// 推荐
{ label: '启用', value: 1 }
{ label: '禁用', value: 0 }
// 不推荐
{ label: '启用', value: 'enable' }
{ label: '禁用', value: 'disable' }3. 预加载常用字典
在应用启动时预加载常用字典:
typescript
// main.ts 或 App.vue
const dictStore = useDictStore()
// 预加载常用字典
await Promise.all([
dictStore.getDict('gender'),
dictStore.getDict('status'),
dictStore.getDict('user_type')
])4. 字典翻译函数
封装字典翻译工具函数:
typescript
// utils/dict.ts
export function getDictLabel(
code: string,
value: number | string
): string {
const dictStore = useDictStore()
const items = dictStore.dictCache.get(code) || []
const item = items.find(i => i.value === value)
return item?.label || String(value)
}
// 使用
const label = getDictLabel('gender', 1) // '男'