Skip to content

字典管理

字典管理是后台管理系统中常用的功能,用于统一管理系统中的配置项,如性别、状态、类型等枚举值。

什么是字典?

字典是一组键值对数据,用于存储系统配置项,例如:

字典编码字典名称字典项
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()
})

同步原理

  1. 前端通过 WebSocket 订阅字典变更主题
  2. 后台修改字典后发送变更消息
  3. 前端收到消息后清除对应字典缓存
  4. 下次使用时重新请求最新数据
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) // '男'

相关链接

基于 MIT 许可发布