# 字典系统使用指南 ## 概述 字典(Dictionary)系统是一个用于管理应用中常用的枚举值和标签化数据的功能。通过字典系统,你可以在后台统一管理这些数据,而无需修改代码和重新编译部署。 ### 字典的核心概念 - **字典类型(Dict Type)**:用来分类管理字典项,例如 `user_status`(用户状态)、`gender`(性别)等 - **字典编码(Dict Code)**:字典类型的唯一标识,用于前端查询,例如 `user_status`、`gender` - **字典项(Dict Item)**:具体的字典值和标签,包括: - `dict_value`:存储在数据库中的实际值(例如 `1`、`0`) - `dict_label`:显示给用户的标签文本(例如 "启用"、"禁用") ### 数据库表结构 ```sql -- 字典类型表 CREATE TABLE sys_dict_type ( id BIGINT, dict_code VARCHAR(50) -- 字典编码(唯一) dict_name VARCHAR(100) -- 字典名称 status TINYINT -- 是否启用 ... ) -- 字典项表 CREATE TABLE sys_dict_item ( id BIGINT, dict_type_id BIGINT -- 关联的字典类型ID dict_label VARCHAR(100) -- 显示标签(如 "启用") dict_value VARCHAR(100) -- 存储值(如 "1") status TINYINT -- 是否启用 ... ) ``` --- ## 后端 API 接口 ### 1. 获取字典项(最常用) **根据字典编码获取字典项列表:** ```http GET /api/dict/items/code/:code?include_disabled=0 ``` **请求示例:** ```bash curl -X GET "http://localhost:8080/api/dict/items/code/user_status?include_disabled=0" ``` **响应示例:** ```json { "code": 0, "message": "success", "data": [ { "id": 1, "dict_type_id": 101, "dict_label": "启用", "dict_value": "1", "status": 1, "sort": 1, ... }, { "id": 2, "dict_type_id": 101, "dict_label": "禁用", "dict_value": "0", "status": 1, "sort": 2, ... } ] } ``` **参数说明:** - `code` (string, 必需):字典编码,例如 `user_status` - `include_disabled` (int, 可选):是否包含禁用项,0 = 不包含(默认),1 = 包含 --- ### 2. 字典管理接口 #### 获取字典类型列表 ```http GET /api/dict/types?parentId=&status= ``` #### 添加字典类型 ```http POST /api/dict/types { "dict_code": "user_status", "dict_name": "用户状态", "status": 1 } ``` #### 添加字典项 ```http POST /api/dict/items { "dict_type_id": 101, "dict_label": "启用", "dict_value": "1", "status": 1, "sort": 1 } ``` #### 更新/删除字典项 ```http PUT /api/dict/items/:id DELETE /api/dict/items/:id ``` --- ## 前端 API(Vue/JavaScript) ### 前端 API 文件位置 ``` pc/src/api/dict.js ``` ### 可用函数 #### getDictItemsByCode(code, includeDisabled = false) **最常用的函数**,根据字典编码获取字典项列表。 **参数:** - `code` (string):字典编码,例如 `'user_status'` - `includeDisabled` (boolean):是否包含禁用项,默认 `false` **返回:** Promise,返回字典项数组 **示例:** ```javascript import { getDictItemsByCode } from '@/api/dict' // 获取用户状态字典 const statusItems = await getDictItemsByCode('user_status') console.log(statusItems) // 输出: // [ // { dict_label: '启用', dict_value: '1', ... }, // { dict_label: '禁用', dict_value: '0', ... } // ] ``` --- #### 其他可用函数 ```javascript // 获取字典类型列表 getDictTypes(params) // 根据ID获取字典类型 getDictTypeById(id) // 添加字典类型 addDictType(data) // 更新字典类型 updateDictType(id, data) // 删除字典类型 deleteDictType(id) // 获取字典项列表(需传入参数过滤) getDictItems(params) // 根据ID获取字典项 getDictItemById(id) // 添加字典项 addDictItem(data) // 更新字典项 updateDictItem(id, data) // 删除字典项 deleteDictItem(id) // 批量更新字典项排序 batchUpdateDictItemSort(data) ``` --- ## 前端组件中的使用示例 ### 示例 1:在用户管理页面显示用户状态 **场景**:在用户列表中,根据用户的 `status` 字段显示对应的状态标签。 **文件**:`pc/src/views/system/users/index.vue` **实现步骤**: #### 1. 导入字典 API ```javascript import { getDictItemsByCode } from '@/api/dict' ``` #### 2. 定义状态字典数据和加载函数 ```javascript ``` #### 3. 定义辅助函数 ```javascript // 根据状态值获取字典标签 const getStatusLabel = (status: any) => { const sval = status !== undefined && status !== null ? String(status) : '' // 查找匹配的字典项 const item = statusDict.value.find( (d: any) => String(d.dict_value) === sval || d.dict_value === status ) if (item && item.dict_label) { return item.dict_label } // 兼容旧逻辑:如果没有匹配的字典项 if (status === 1 || sval === '1' || sval === 'active') return '启用' return '禁用' } // 根据标签确定 el-tag 的样式类型 const getStatusTagType = (status: any) => { const label = getStatusLabel(status) if (!label) return 'info' const l = label.toString() if (l.includes('启用') || l.includes('正常') || l.includes('active')) return 'success' if (l.includes('禁用') || l.includes('停用') || l.includes('inactive')) return 'danger' return 'info' } ``` #### 4. 在模板中使用 ```vue ``` --- ### 示例 2:在下拉选择中使用字典 **场景**:在"添加/编辑用户"对话框中,用字典项填充状态下拉选择。 ```vue ``` --- ### 示例 3:多个字典项的场景 **场景**:同时加载多个字典(用户状态、性别、部门类型等)。 ```javascript ``` --- ## 最佳实践 ### 1. 缓存字典数据 避免在每个组件中都调用字典 API。建议在全局 store 中缓存字典数据: **文件**:`pc/src/stores/dict.ts` ```typescript import { defineStore } from 'pinia' import { ref } from 'vue' import { getDictItemsByCode } from '@/api/dict' export const useDictStore = defineStore('dict', () => { const dicts = ref>({}) const fetchDict = async (code: string) => { if (dicts.value[code]) { return dicts.value[code] } try { const res = await getDictItemsByCode(code) const items = res?.data || res || [] dicts.value[code] = Array.isArray(items) ? items : [] return dicts.value[code] } catch (err) { console.error(`Failed to fetch dict ${code}:`, err) return [] } } return { dicts, fetchDict } }) ``` **在组件中使用:** ```javascript import { useDictStore } from '@/stores/dict' const dictStore = useDictStore() const statusDict = await dictStore.fetchDict('user_status') ``` ### 2. 创建字典枚举文件 建议为常用字典创建枚举文件,便于维护: **文件**:`pc/src/constants/dicts.ts` ```typescript // 字典编码常量 export const DICT_CODES = { USER_STATUS: 'user_status', GENDER: 'gender', DEPT_TYPE: 'dept_type', POSITION_LEVEL: 'position_level', } as const // 用于 TypeScript 类型 export type DictCode = typeof DICT_CODES[keyof typeof DICT_CODES] ``` **在组件中使用:** ```javascript import { DICT_CODES } from '@/constants/dicts' import { useDictStore } from '@/stores/dict' const dictStore = useDictStore() const statusDict = await dictStore.fetchDict(DICT_CODES.USER_STATUS) ``` ### 3. 处理不同的数据值类型 字典值可能是数字、字符串或其他类型。确保比较时进行正确的类型转换: ```javascript const getStatusLabel = (status: any) => { // 转换为字符串便于比较 const statusStr = String(status) const item = statusDict.value.find((d: any) => { // 支持多种比较方式 return ( String(d.dict_value) === statusStr || d.dict_value === status || d.dict_value == status // 宽松比较 ) }) return item?.dict_label || '未知' } ``` ### 4. 错误处理 始终为字典加载添加适当的错误处理和回退机制: ```javascript const fetchStatusDict = async () => { try { const res = await getDictItemsByCode('user_status') statusDict.value = res?.data || [] } catch (err) { console.error('Failed to fetch status dict:', err) // 使用默认的回退数据 statusDict.value = [ { dict_label: '启用', dict_value: '1' }, { dict_label: '禁用', dict_value: '0' }, ] } } ``` --- ## 常见问题 ### Q1: 字典数据在页面刷新后丢失了? **A:** 这是正常的,字典数据只在组件的生命周期内存在。建议使用全局 store(Pinia)来缓存字典数据,或在每个需要的组件中通过 `onMounted` 加载。 ### Q2: 后端添加了新的字典项,前端不显示新数据? **A:** 前端缓存了字典数据。有两种解决方案: 1. 刷新浏览器页面,重新加载字典 2. 在后端修改字典后,调用缓存清除接口(如果有的话),或手动清除前端 store 中的字典缓存 ### Q3: 字典编码对应的字典类型不存在? **A:** 确保: 1. 后端已在 `sys_dict_type` 表中添加了对应的字典类型记录 2. 字典类型的状态(`status`)为启用(通常为 1) 3. 至少添加了一项字典项(`sys_dict_item` 表中有数据) 4. 字典编码(`dict_code`)完全匹配(区分大小写) ### Q4: 如何在后台管理系统中管理字典? **A:** 通常在系统设置或配置模块中有"字典管理"功能,可以: - 添加/编辑/删除字典类型 - 管理字典项(标签、值、排序、启用/禁用等) 具体路径取决于你的后台管理系统设计。 --- ## 总结 使用字典系统的核心步骤: 1. **后端准备**:在 `sys_dict_type` 和 `sys_dict_item` 表中添加字典数据 2. **前端导入**:`import { getDictItemsByCode } from '@/api/dict'` 3. **加载字典**:在 `onMounted` 或其他合适位置调用 API 加载 4. **使用字典**:通过 `dict_value` 和 `dict_label` 来显示和存储数据 5. **最优化**:使用 Pinia store 缓存字典,避免重复请求 通过字典系统,你可以灵活地管理应用中的枚举值和标签数据,而无需修改代码。