@ruovea/system
v1.0.4
Published
系统管理模块(菜单 / 机构 / 职位 / 角色 / 用户 / 注册方案)
Readme
@ruovea/system
系统管理模块(菜单 / 机构 / 职位 / 角色 / 用户 / 注册方案),以 pnpm 源码包 形式提供给各宿主项目复用。
- 不打 dist、不发 npm——
exports直指./src/*,由宿主 Vite 编译 - 依赖注入解耦——
request/auth/i18n/userInfos/AccountTypeEnum/ 宿主组件全部由宿主装配时注入 - 零侵入——包内不含
/@/等宿主别名引用,可独立运行,不绑定特定宿主 - 字典数据自包含——内置 5 个枚举常量 + 自带
<sys-dict>组件,不依赖@ruovea/dict,宿主零配置可用
一、目录结构
src/
├─ index.ts # 入口:导出 SystemPlugin + API + 类型 + 路由
├─ plugin.ts # Vue install(校验必填项 / provide / 全局注册 SysDict / mergeLocaleMessage)
├─ context.ts # InjectionKey + useSystemContext() + resolveUserInfos() + mergeDictList()
├─ types.ts # SystemPluginOptions
├─ builtinDictList.ts # 内置字典常量(5 个枚举,1600 行,零配置兜底)
├─ routes.ts # 6 条静态路由 + systemDynamicComponents 动态组件映射
├─ api/
│ ├─ index.ts # menu + org + pos + role + user + user-reg-way
│ ├─ http.ts # request 注入点
│ ├─ endpoints.ts # URL 前缀(可覆盖)
│ ├─ menu.ts # 菜单 API(8 个)
│ ├─ org.ts # 机构 API(5 个)
│ ├─ pos.ts # 职位 API(5 个)
│ ├─ role.ts # 角色 API(11 个)
│ ├─ user.ts # 用户 API(20 个)
│ └─ user-reg-way.ts # 注册方案 API(4 个)
├─ components/
│ └─ sysDict.vue # 包内字典显示组件(全局注册为 SysDict)
├─ i18n/locales/ # 6 语言(en / fr-fr / ja-jp / vi-vn / zh-cn / zh-tw)
└─ views/
├─ menu/ # 菜单管理(index + editMenu)
├─ organization/ # 机构管理(index + editOrg + orgTree)
├─ position/ # 职位管理(index + editPos)
├─ role/ # 角色管理(index + editRole + grantMenu + grantData)
├─ user/ # 用户管理(index + editUser + grantRole)
└─ userRegWay/ # 注册方案(index + editRegWay)二、字典数据策略(核心设计)
2.1 内置字典常量
src/builtinDictList.ts 内置 5 个枚举的完整字典数据,覆盖包内全部视图所需:
| Code | 说明 | 使用位置 |
|------|------|----------|
| GenderEnum | 性别 | user/editUser |
| AccountTypeEnum | 账号类型 | user/index、user/editUser |
| StatusEnum | 启用/禁用 | menu/index、org/index、pos/index |
| MenuTypeEnum | 菜单类型 | menu/index、menu/editMenu |
| DataScopeEnum | 数据范围 | role/index、role/grantData |
宿主即使不注入任何字典数据,<sys-dict> 也能用内置常量渲染——零配置可用。
2.2 合并策略:已有则更新,没有则补充,多余则删除
context.ts 的 buildSystemContext 自动合并两层数据,宿主数据为权威来源:
getDictList() → mergeDictList(宿主注入的 dictList)
├─ 包内置 builtinDictList 作为基底(始终保留)
└─ 遍历宿主数据,逐 code 合并| 场景 | 结果 |
|------|------|
| 内置有 GenderEnum,宿主也有 | 用宿主数据(更新为最新) |
| 内置没有 CustomCode,宿主有 | 补充宿主数据 |
| 内置有 GenderEnum,宿主没有 | 保留内置(兜底) |
| 内置有 SomeEnum,宿主返回空数组 | 删除该 code(宿主要求清空) |
| 宿主未注入 getDictList | 全部用内置 |
2.3 字典数据链路
@ruovea/system 视图
→ <sys-dict code="GenderEnum"> ← 包内自带组件,plugin 全局注册
→ useSystemContext().getDictList() ← 包内 context 提供
→ mergeDictList(宿主dictList) ← 内置为基底,宿主已有则更新包内字典完全自包含,不依赖 @ruovea/dict,@ruovea/dict 更新不影响本包。
2.4 引用内置常量
宿主可直接导入内置常量,用于自定义视图:
import { builtinDictList } from '@ruovea/system/builtinDictList';
// 查看某 code 是否有内置数据
console.log(builtinDictList['GenderEnum']);三、依赖关系
peerDependencies
| 包 | 用途 |
|----|------|
| vue | 框架 |
| vue-router | 路由 |
| vue-i18n | 国际化 |
| element-plus | UI 组件库 |
| @element-plus/icons-vue | 图标 |
| splitpanes | 分栏布局(机构树) |
| vue3-tree-org | 组织架构树 |
| axios | HTTP 客户端类型 |
不依赖
@ruovea/dict——字典组件和内置数据已自包含。
四、宿主接入
4.1 安装
{
"dependencies": {
"@ruovea/system": "link:../../module/system-module/packages/system"
}
}4.2 Vite 预构建排除
// vite.config.ts
optimizeDeps: {
exclude: ['vue-demi', '@ruovea/system'],
},4.3 装配插件
// plugins/system.ts
import { defineAsyncComponent, type App } from 'vue';
import { storeToRefs } from 'pinia';
import { SystemPlugin } from '@ruovea/system';
import request from '/@/utils/request';
import { auth, auths } from '/@/utils/authFunction';
import { i18n } from '/@/i18n/index';
import { useUserInfo } from '/@/stores/userInfo';
import { AccountTypeEnum } from '/@/api/enums';
export function setupSystem(app: App) {
const userStore = useUserInfo();
const { userInfos } = storeToRefs(userStore);
app.use(SystemPlugin, {
request: request as any,
auth,
auths,
i18n: i18n as any,
userInfos,
accountTypeEnum: AccountTypeEnum,
getDictList: () => userStore.dictList, // 可选,缺失时用内置常量兜底
components: {
ModifyRecord: defineAsyncComponent(() => import('/@/components/table/modifyRecord.vue')),
IconSelector: defineAsyncComponent(() => import('/@/components/iconSelector/index.vue')),
SvgIcon: defineAsyncComponent(() => import('/@/components/svgIcon/index.vue')),
},
});
}// main.ts
import { setupSystem } from '/@/plugins/system';
// ... app.use(pinia) 之后
setupSystem(app);无顺序要求——不依赖其他
@ruovea/*包。
4.4 路由接入
后端动态路由(推荐)
后端菜单下发 Component = "@ruovea/system/menu/index",宿主 backEnd.ts 用 systemDynamicComponents 映射:
// router/backEnd.ts
import { systemDynamicComponents } from '@ruovea/system';
export function dynamicImport(dynamicViewsModules, component) {
// ...其他包的映射
if (systemDynamicComponents[component]) return systemDynamicComponents[component];
// ...
}前端静态路由(可选)
// router/route.ts
import { systemRoutes } from '@ruovea/system/routes';
export const dynamicRoutes = [
{
path: '/',
component: () => import('/@/layout/index.vue'),
children: [
// ...其他路由
...systemRoutes,
],
},
];五、SystemPluginOptions 说明
| 字段 | 必填 | 说明 |
|------|------|------|
| request | ✅ | 宿主 axios 实例(已配 baseURL / 拦截器 / token) |
| components.ModifyRecord | ✅ | 修改记录展示组件(列表页用) |
| components.IconSelector | ➖ | 图标选择器(menu 编辑用,缺省时图标选择列隐藏) |
| components.SvgIcon | ➖ | SVG 图标组件(menu 列表用,缺省时图标列退化) |
| auth | ➖ | (code: string) => boolean,单权限校验,缺省 () => true |
| auths | ➖ | (codes: string[]) => boolean,多权限校验,缺省 () => true |
| i18n | ➖ | 宿主 vue-i18n 实例(传入后自动合并模块语言包) |
| registerI18n | ➖ | 是否自动注册 i18n,默认 true |
| userInfos | ➖ | 当前登录用户信息(Ref<any> 或 () => any),用于 user/editUser 过滤账号类型 |
| accountTypeEnum | ➖ | 账号类型枚举(含 NUMBER_SuperAdmin 字段),缺省 { NUMBER_SuperAdmin: 999 } |
| getDictList | ➖ | 字典数据(按 typeCode 分组),缺省时用包内置常量兜底 |
| dictComponentName | ➖ | 字典全局组件名,默认 g-sys-dict |
| authDirectiveName | ➖ | 权限指令名,默认 auth |
| endpoints | ➖ | 覆盖 API URL 前缀 |
六、SysDict 组件
6.1 全局注册
SystemPlugin.install 执行 app.component('SysDict', ...) 全局注册,宿主模板中直接使用:
<sys-dict v-model="row.status" code="StatusEnum" />6.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) |
6.3 使用示例
<!-- tag 显示(表格列内) -->
<sys-dict v-model="scope.row.isDisable" code="StatusEnum" />
<!-- 下拉选择(搜索栏) -->
<sys-dict v-model="queryParams.type" code="MenuTypeEnum" render-as="select"
placeholder="请选择" clearable />
<!-- 单选(表单) -->
<sys-dict v-model="form.sex" code="GenderEnum" render-as="radio" />
<!-- 带过滤 -->
<sys-dict v-model="form.adminType" code="AccountTypeEnum" render-as="select"
:on-item-filter="(data) => data.code !== 'SuperAdmin'" />七、路由清单
| path | name | keepAlive | 说明 |
|------|------|-----------|------|
| /system/menu | sysMenu | ✅ | 菜单管理 |
| /system/organization | sysOrg | ✅ | 机构管理 |
| /system/position | sysPos | ✅ | 职位管理 |
| /system/role | sysRole | ✅ | 角色管理 |
| /system/user | sysUser | ✅ | 用户管理 |
| /system/userRegWay | sysUserRegWay | ✅ | 注册方案管理 |
八、权限编码清单
| 编码 | 位置 | 说明 |
|------|------|------|
| sysMenu:list | menu | 查询 |
| sysMenu:addMenu | menu | 新增/复制 |
| sysMenu:updateMenu | menu | 编辑 |
| sysMenu:deleteMenu | menu | 删除 |
| sysOrg:list | organization | 查询 |
| sysOrg:addOrg | organization | 新增/复制 |
| sysOrg:updateOrg | organization | 编辑 |
| sysOrg:deleteOrg | organization | 删除 |
| sysPos:list | position | 查询 |
| sysPos:addPos | position | 新增/复制 |
| sysPos:updatePos | position | 编辑 |
| sysPos:deletePos | position | 删除 |
| sysRole:page | role | 查询 |
| sysRole:addRole | role | 新增 |
| sysRole:updateRole | role | 编辑 |
| sysRole:deleteRole | role | 删除 |
| sysRole:grantMenu | role | 分配菜单 |
| sysRole:grantDataScope | role | 分配数据 |
| sysRole:setStatus | role | 状态切换 |
| sysUser:page | user | 查询 |
| sysUser:addUser | user | 新增/复制 |
| sysUser:updateUser | user | 编辑 |
| sysUser:deleteUser | user | 删除 |
| sysUser:grantRole | user | 分配角色 |
| sysUser:setStatus | user | 状态切换 |
| sysUser:resetPwd | user | 重置密码 |
| sysUser:unlockLogin | user | 解除锁定 |
| sysUserRegWay:list | userRegWay | 查询 |
| sysUserRegWay:add | userRegWay | 新增 |
| sysUserRegWay:update | userRegWay | 编辑 |
| sysUserRegWay:delete | userRegWay | 删除 |
未注入 auth 时所有按钮可见(缺省 () => true)。
九、API 清单
9.1 菜单(8 个)
| 函数 | 说明 |
|------|------|
| apiSysMenuLoginMenuTreeGet | 获取登录菜单树 |
| apiSysMenuDataGet | 根据主键查询菜单 |
| apiSysMenuListGet | 获取菜单列表 |
| apiSysMenuAddMenuPost | 新增菜单 |
| apiSysMenuAddMenusPost | 新增菜单和权限 |
| apiSysMenuUpdateMenuPost | 更新菜单 |
| apiSysMenuDeleteMenuPost | 删除菜单 |
| apiSysMenuOwnBtnPermListGet | 获取用户按钮权限集合 |
9.2 机构(5 个)、职位(5 个)、角色(11 个)、用户(20 个)、注册方案(4 个)
共 53 个 API 函数,详见 src/api/ 各文件。
十、i18n 注入约定
包内视图使用 message.btn.xxx、message.common.xxx、message.menu.xxx、message.organization.xxx 等 key。插件双层 merge(顶层 + message 层),翻译资源自包含。
支持 6 种语言:zh-cn / zh-tw / en / ja-jp / fr-fr / vi-vn。
十一、License
MIT
