# Pinia 字典管理系统使用指南 ## 系统架构 ``` ┌─────────────────────────────────────┐ │ API 接口 (getDictItemsByCode) │ │ /api/dict/items/code/{code} │ └──────────────┬──────────────────────┘ │ ↓ ┌─────────────────────────────────────┐ │ Pinia Store (useDictStore) │ │ ✅ 自动缓存字典数据 │ │ ✅ 避免重复请求 │ │ ✅ 支持同步/异步访问 │ └──────────────┬──────────────────────┘ │ ┌──────┴──────┐ ↓ ↓ ┌────────┐ ┌──────────────┐ │组件 │ │Composable │ │直接用 │ │useDict Hook │ └────────┘ └──────────────┘ ``` --- ## 核心文件说明 ### 1. **Store**: `src/stores/dict.js` 字典数据的全局管理器 **主要方法**: ```javascript import { useDictStore } from '@/stores/dict' const dictStore = useDictStore() // ✅ 异步获取字典(推荐) const items = await dictStore.getDictItems('user_status') // ✅ 同步获取字典(已缓存时) const items = dictStore.getDictItemsSync('user_status') // ✅ 获取字典值对应的标签 const label = dictStore.getDictLabel('user_status', 1) // ✅ 预加载多个字典 await dictStore.preloadDicts(['user_status', 'user_role']) // ✅ 清空缓存 dictStore.clearCache('user_status') ``` --- --- --- ## 使用场景 ### 场景1:在列表页加载字典 **文件**: `src/views/system/users/index.vue` ```vue ``` --- ### 场景2:在编辑对话框使用字典 **文件**: `src/views/system/users/components/UserEdit.vue` ```vue ``` --- ### 场景3:直接使用字典Store 直接使用字典Store获取数据: ```vue ``` --- ### 场景4:预加载应用启动时需要的字典 **文件**: `src/main.js` ```javascript import { createApp } from 'vue' import { createPinia } from 'pinia' import { useDictStore } from '@/stores/dict' const app = createApp(App) const pinia = createPinia() app.use(pinia) // 在应用启动后预加载常用字典 const dictStore = useDictStore() await dictStore.preloadDicts([ 'user_status', 'common_status', 'yes_no', ]) app.mount('#app') ``` --- ## 字典数据结构 后端返回的字典数据结构: ```json [ { "dict_id": 1, "dict_value": "1", "dict_label": "启用", "dict_type": "user_status", "remarks": "用户启用状态", "remark": "用户启用状态" }, { "dict_id": 2, "dict_value": "0", "dict_label": "禁用", "dict_type": "user_status", "remarks": "用户禁用状态", "remark": "用户禁用状态" } ] ``` **关键字段**: - `dict_value`: 字典值(存储在数据库中) - `dict_label`: 字典标签(显示给用户) - `dict_type`: 字典类型编码(如 'user_status') --- ## 最佳实践 ### ✅ DO 1. **使用字符串而不是硬编码数字** ```javascript // ✅ 好 dictStore.getDictItems('user_status') // ❌ 差 // 避免直接使用数字,应该使用字符串 ``` 2. **在父组件加载,通过 props 传给子组件** ```javascript // ✅ 父组件负责数据,子组件负责展示 // index.vue const statusDict = await dictStore.getDictItems('user_status') // UserEdit.vue const props = defineProps({ statusDict: Array }) ``` 3. **直接使用字典Store** ```javascript // ✅ 直接使用Store获取数据 const statusDict = await dictStore.getDictItems('user_status') ``` 4. **预加载常用字典** ```javascript // ✅ 应用启动时预加载,避免页面初始化时加载 await dictStore.preloadDicts([...]) ``` ### ❌ DON'T 1. **不要在多个地方重复加载同一个字典** ```javascript // ❌ 糟糕:重复加载 // 页面A const dict1 = await dictStore.getDictItems('user_status') // 页面B(Store 会自动缓存,但代码看起来重复) const dict2 = await dictStore.getDictItems('user_status') ``` 2. **不要忘记处理加载状态** ```javascript // ❌ 可能展示空白 const { statusDict } = useUserStatusDict() // ✅ 处理加载状态 const { statusDict, loading } = useUserStatusDict() if (loading) { /* 显示加载中 */ } ``` 3. **不要混用不同的字典访问方式** ```javascript // ❌ 混乱 const dict1 = await dictStore.getDictItems('user_status') const dict2 = dictStore.getDictItemsSync('user_role') // ✅ 统一使用 const dict1 = await dictStore.getDictItems('user_status') const dict2 = await dictStore.getDictItems('user_role') ``` --- ## 性能优化建议 | 优化项 | 说明 | |------|------| | **缓存** | Store 自动缓存,同一个字典只请求一次 | | **预加载** | 在路由切换前预加载需要的字典 | | **同步访问** | 已加载的字典可用 `getDictItemsSync` 同步获取 | | **避免重复** | 不要在多个组件重复请求同一个字典 | --- ## 故障排查 ### 问题1:状态选项为空 **原因**:字典未加载 **解决**: ```javascript // ❌ 错误:字典还未加载 const statusDict = dictStore.getDictItemsSync('user_status') // 返回 [] // ✅ 正确:等待异步加载完成 const statusDict = await dictStore.getDictItems('user_status') ``` ### 问题2:重复加载字典 **原因**:没有使用 Store 的缓存 **解决**: ```javascript // 所有调用都会自动使用缓存,只请求一次 await dictStore.getDictItems('user_status') // 首次:发送请求 await dictStore.getDictItems('user_status') // 第二次:返回缓存 ``` ### 问题3:字典显示不对 **原因**:value 类型不匹配(如 1 vs "1") **解决**: ```javascript // Store 会自动处理类型匹配 const item = items.find(i => String(i.dict_value) === String(value) || i.dict_value === value ) ``` --- ## 集成检清表 - [x] 创建 `src/stores/dict.js` - Store - [x] 在 `index.vue` 中导入 `useDictStore` - [x] 在 `UserEdit.vue` 中使用 `useDictStore` 获取字典数据 - [x] 测试字典加载和显示 - [x] 验证缓存功能(打开浏览器 DevTools 检查 Network) - [x] 预加载常用字典(可选) --- ## 相关文件修改 已修改的文件: - ✅ `src/stores/dict.js` - 新建 - ✅ `src/views/system/users/index.vue` - 使用 `useDictStore` - ✅ `src/views/system/users/components/UserEdit.vue` - 使用字典功能 - ✅ `src/constants/dictCodes.js` - 删除(不再需要) - ✅ `src/composables/useDict.js` - 删除(不再需要)