@ruovea/dict
v1.1.0
Published
KeGie.Admin 字典管理模块
Readme
@ruovea/dict
KeGie.Admin 字典管理模块(字典类型 / 字典值常规/动态/定制/图片),以 pnpm 源码包 形式提供给各宿主项目复用。
- 不打 dist、不发 npm——
exports直指./src/*,由宿主 Vite 编译 - 内置字典兜底——包内自带 38 个常用枚举常量(
GenderEnum/AccountTypeEnum/StatusEnum/MenuTypeEnum/DataScopeEnum等),宿主零配置即可使用 - 依赖注入解耦——
request/auth/i18n/ModifyRecord/userApi由宿主装配时注入 - 零侵入——包内不含
/@/等宿主别名引用,可脱离 KeGie.Admin 运行
一、目录结构
src/
├─ index.ts # 入口:导出 DictPlugin + API + 类型 + 路由
├─ plugin.ts # Vue install(校验必填项 / provide / 全局注册 GSysDict / mergeLocaleMessage)
├─ context.ts # InjectionKey + useDictContext() + mergeDictList 合并逻辑
├─ types.ts # DictPluginOptions / DictEndpoints / DictContext
├─ builtinDictList.ts # 内置字典常量(38 个枚举,3000+ 条目,零配置兜底)
├─ routes.ts # 路由 + dictDynamicComponents 动态组件映射
├─ api/
│ ├─ index.ts # dict-type + dict-data
│ ├─ http.ts # request 注入点
│ ├─ endpoints.ts # URL 前缀(可覆盖)
│ ├─ dict-type.ts # 字典类型 API
│ └─ dict-data.ts # 字典值 API
├─ components/
│ ├─ SysDict.vue # 字典显示组件(全局注册为 GSysDict)
│ ├─ dictForm.vue # 字典类型新增弹窗
│ └─ dictData.vue # 字典值查看弹窗
├─ i18n/locales/ # 6 语言(en / fr-fr / ja-jp / vi-vn / zh-cn / zh-tw)
└─ views/dicttyp/
├─ index.vue # 字典类型+字典值双栏管理
├─ component/editDictType.vue # 字典类型编辑弹窗
├─ component/editDictData.vue # 字典值编辑弹窗
└─ values/
├─ normal/ # 常规字典值
├─ dynamic/ # 动态字典值
├─ custom/ # 定制字典值
└─ image/ # 图片字典值二、字典数据策略(核心设计)
2.1 内置常量兜底
src/builtinDictList.ts 内置 38 个常用枚举的完整字典数据(从历史项目硬编码常量恢复),包括但不限于:
| Code | 说明 |
|------|------|
| GenderEnum | 性别 |
| AccountTypeEnum | 账号类型 |
| StatusEnum | 启用/禁用状态 |
| MenuTypeEnum | 菜单类型 |
| DataScopeEnum | 数据范围 |
| YesNoEnum | 是/否 |
| NoticeTypeEnum | 通知类型 |
| JobStatusEnum | 任务状态 |
| ... | (共 38 个) |
宿主即使不注入任何字典数据,<g-sys-dict> 也能用内置常量渲染——零配置可用。
2.2 合并策略:已有则更新,没有则补充,多余则删除
context.ts 的 buildDictContext 自动合并两层数据,宿主后端数据为权威来源:
getDictList() → mergeDictList(宿主注入的 dictList)
├─ 内置 builtinDictList 作为基底(始终保留)
└─ 遍历宿主数据,逐 code 合并| 场景 | 结果 |
|------|------|
| 内置有 GenderEnum,宿主也有 | 用宿主数据(更新为最新) |
| 内置没有 CustomCode,宿主有 | 补充宿主数据 |
| 内置有 GenderEnum,宿主没有 | 保留内置(兜底) |
| 内置有 SomeEnum,宿主返回空数组 | 删除该 code(宿主要求清空) |
| 宿主未注入 getDictList | 全部用内置 |
2.3 引用内置常量
宿主可直接导入内置常量,用于自定义视图:
import { builtinDictList } from '@ruovea/dict/builtinDictList';
// 查看某 code 是否有内置数据
console.log(builtinDictList['GenderEnum']);三、宿主接入
3.1 安装
{
"dependencies": {
"@ruovea/dict": "link:../../module/dict-module/packages/dict"
}
}3.2 Vite 预构建排除
宿主 vite.config.ts 必须将包加入 optimizeDeps.exclude,否则预构建产物与源码各持一份模块级 _request,导致 request 未注入 运行时报错:
optimizeDeps: {
exclude: ['vue-demi', '@ruovea/dict'],
},3.3 装配插件
// plugins/dict.ts
import { defineAsyncComponent, type App } from 'vue';
import { DictPlugin } from '@ruovea/dict';
import request from '/@/utils/request';
import { auth } from '/@/utils/authFunction';
import { i18n } from '/@/i18n/index';
import { useUserInfo } from '/@/stores/userInfo';
export function setupDict(app: App) {
const userStore = useUserInfo();
app.use(DictPlugin, {
request: request as any,
auth,
i18n: i18n as any,
components: {
ModifyRecord: defineAsyncComponent(() => import('/@/components/table/modifyRecord.vue')),
},
userApi: {
getUserInfo: () => userStore.userInfos,
refreshDict: () => userStore.setDictList(),
getDictList: () => userStore.dictList, // 可选,缺失时用内置常量兜底
},
});
}// main.ts
import { setupDict } from '/@/plugins/dict';
// ... app.use(pinia) 之后
setupDict(app);3.4 最小化接入(零配置)
如果宿主只需 <g-sys-dict> 组件显示字典,不需要字典管理页面,最小化配置如下:
app.use(DictPlugin, {
request: request as any,
components: {
ModifyRecord: defineAsyncComponent(() => import('...')),
},
});不传 userApi.getDictList 时,<g-sys-dict> 自动用内置常量渲染。
四、DictPluginOptions 说明
| 字段 | 必填 | 说明 |
|------|------|------|
| request | ✅ | 宿主 axios 实例(已配 baseURL / token / 拦截器) |
| components.ModifyRecord | ✅ | 修改记录展示组件 |
| components.GSysDict | ➖ | 字典显示组件(已下沉到包内,插件自动全局注册。仅需要自定义覆盖时传入) |
| auth | ➖ | (code: string) => boolean,按钮权限校验,缺省 () => true |
| i18n | ➖ | 宿主 vue-i18n 实例(传入后自动合并模块语言包) |
| registerI18n | ➖ | 是否自动注册 i18n,默认 true |
| userApi.getUserInfo | ➖ | 获取当前用户信息(含 accountType,用于判断超管) |
| userApi.refreshDict | ➖ | 刷新字典缓存 |
| userApi.getDictList | ➖ | 获取字典全量数据(按 typeCode 分组)。缺失时用内置常量兜底 |
| endpoints | ➖ | 覆盖 API URL 前缀 |
五、GSysDict 组件
5.1 全局注册
DictPlugin.install 执行 app.component('GSysDict', SysDict) 全局注册,宿主模板中直接使用,无需手动注册:
<g-sys-dict v-model="row.status" code="StatusEnum" />5.2 Props
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| modelValue | any | — | 绑定值(必填) |
| code | string | — | 字典类型编码,如 GenderEnum(必填) |
| renderAs | 'tag'\|'select'\|'radio'\|'checkbox' | 'tag' | 渲染方式 |
| propLabel | string | 'label' | 显示文字字段名 |
| propValue | string | 'value' | 值字段名 |
| onItemFilter | (dict) => boolean | () => true | 过滤字典项 |
| onItemFormatter | (dict) => string | — | 自定义显示文字 |
| multiple | boolean | false | 多选(仅 select / checkbox) |
5.3 使用示例
<!-- tag 显示(表格列内) -->
<g-sys-dict v-model="scope.row.isDisable" code="StatusEnum" />
<!-- 下拉选择(搜索栏) -->
<g-sys-dict v-model="queryParams.type" code="MenuTypeEnum" render-as="select"
placeholder="请选择" clearable />
<!-- 单选(表单) -->
<g-sys-dict v-model="form.sex" code="GenderEnum" render-as="radio" />
<!-- 带过滤 -->
<g-sys-dict v-model="form.adminType" code="AccountTypeEnum" render-as="select"
:on-item-filter="(data) => data.code !== 'SuperAdmin'" />六、路由
6.1 路由清单
| path | name | isHide | keepAlive | 说明 |
|------|------|--------|-----------|------|
| /system/dicttyp | dicttyp | ❌ | ✅ | 字典类型+字典值双栏(主页) |
| /system/dicttyp/values/normal | dictValueNomal | ✅ | ✅ | 常规字典值 |
| /system/dicttyp/values/dynamic | dictValueDynamic | ✅ | ✅ | 动态字典值 |
| /system/dicttyp/values/custom | dictValueCustom | ✅ | ✅ | 定制字典值 |
| /system/dicttyp/values/image | dictValueImage | ✅ | ✅ | 图片字典值 |
6.2 dictDynamicComponents(后端动态路由映射)
// router/backEnd.ts
import { dictDynamicComponents } from '@ruovea/dict';
export function dynamicImport(dynamicViewsModules, component) {
if (dictDynamicComponents[component]) return dictDynamicComponents[component];
// ...
}6.3 dictValueRoutes(4 条隐藏子页)
4 条子页由 dicttyp 主页 router.push 带 query 跳转,不由后端菜单下发。宿主必须在静态路由中展开:
// router/route.ts
import { dictValueRoutes } from '@ruovea/dict';
export const notFoundAndNoPower = [
// ... 404 / 401 / dashboard / userCenter
...dictValueRoutes,
];七、权限编码清单
| 编码 | 位置 | 说明 |
|------|------|------|
| sysDictType:pages | 字典类型列表 | 查询 |
| sysDictType:addData | 字典类型列表 | 新增 |
| sysDictType:updateData | 字典类型列表 | 编辑 |
| sysDictType:deleteData | 字典类型列表 | 删除 |
| sysDictValue:pages | 字典值列表 | 查询 |
| sysDictValue:addData | 字典值列表 | 新增 |
| sysDictValue:updateData | 字典值列表 | 编辑 |
| sysDictValue:deleteData | 字典值列表 | 删除 |
八、i18n 注入约定
包内视图使用 message.dict.xxx、message.dicttyp.xxx、message.dictValueNomal.xxx 等 key。插件双层 merge(顶层 + message 层),菜单翻译资源自包含。
支持 6 种语言:zh-cn / zh-tw / en / ja-jp / fr-fr / vi-vn。
九、被其他包依赖
@ruovea/dict 可被其他 @ruovea/* 包作为 peerDependencies 引用。例如 @ruovea/system 的视图内大量使用 <g-sys-dict code="GenderEnum">,只要宿主已装配 DictPlugin,这些视图就能正常渲染——字典数据来自内置常量或宿主注入,无需额外配置。
十、License
MIT
