开发430天提交1900次commit!这款让程序员准时下班的Admin系统到底有多颠覆?
作者:佚名 时间:2025-11-16 17:57
前言
为了做好这款 Admin,我们累计开发了430+天、提交了1900+commit,做了一款和市面上都不一样的 Admin,目标是为了让大家在使用这款系统时少一点加班,多一点时间陪伴家人!!!
技术栈
使用 vite、vue3、typescript、unocss 开发,和市面上所有开源 admin 的架构方案设计都不一样,真正意义上做到了高内聚、低耦合、可扩展,值得一提的是此套架构方案在让您阅读源码时可以很清晰的看到每一块功能的实现。
预览
因为目前 Admin 的 ui 已经足够成熟,开发者、产品、客户也习惯了,所以这一块我们并没有去做创新的设计,但是在逻辑实现层面做了完全不一样的设计。






痛点
在使用其他后台 Admin 的时候,有没有碰到过以下的问题
以上这些不是刻意在贬低其他的 Admin,因为我为了方便,也会去使用它们,这是在开发项目时遇到的实际问题。
解决方案
以上的痛点我们总结归类一下,分为几大块
以上几块的设计几乎贯穿了 Admin 架构的所有功能,我们一个一个聊。
路由的插件化设计
路由想设计成可扩展、可维护的,插件化的架构设计才能做到这一点!我们在 Admin 中定义了一个子包 @pro/router,它的使用方式和 vue-router 完全一致,只不过我们做了额外的扩展,多了一个 plugins 属性,我们向外暴露了 Admin 系统所需要的全部插件,你可以按需引用、渐进式扩展功能,如图

以上的每一个插件都单独实现一个功能,插件和插件之间不存在联动关系,所以你可以按需引用,这里我们拿一个简单的 breadcrumbPlugin 面包屑插件举例,如图

面包屑的数据很容易被我们组装出来,如何提供给外界对应的组件使用呢?我们可以在 router 上自定义字段,如图

外界如下使用即可

是不是挺简单呢?一个插件对应一个功能,我们的 Admin 就是按照搭积木的方式组装而成,由于篇幅有限,更多的插件实现大家可以在文章底部查看对应源码或者文档。
布局的策略模式设计
布局组件不一定会被用在 Admin 系统中,所以我们把它放进了基于 naive-ui 封装的高级组件库 pro-naive-ui 中,顺便简单介绍一下,pro-naive-ui 也是完全开源的,对表单、表格、大量组件做了高级封装,真正能落地在企业级项目中。
说回正题,现在的布局组件支持 7种 布局模式,当然也支持移动端模式,布局组件支持大量的属性和插槽,如图

我们在 Admin 中如下图使用

对于有很多种布局模式,内部如何避免掉大量的 if else 之类的判断呢?策略模式可以做到这一点,我们只需要对每种不同的布局模式应用不同的 css 即可。如图:

通过策略模式,我们在未来可以很轻松的继续扩展布局!问题来了,用户如何能在不依赖布局组件的情况下继续扩展布局呢?比如想个性化的自定义布局,如图

答案我们在菜单的无头能力设计中揭晓!
菜单的无头能力设计
布局组件帮我们解决了 css 问题,然而在 Admin 中布局组件下往往会包含多个菜单,多个菜单之间还会根据一些属性去做一些联动行为,这里的菜单指的不一定是 n-menu,可能还会有上面提到的个性化菜单,如果单独把 n-menu 封装一下,可能很难去满足各种个性化场景的需求,所以我们将这种多个菜单进行联动的场景抽象成了一个 composable,它与 ui 无关,它专注于解决菜单之间的联动问题,然后将处理好的菜单数据交给外层,外层可以直接消费这个数据传递给对应的菜单组件,在我们的 Admin 中是这么使用的

内部会根据完整的 menus 数据以及 mode 属性自动分割相关菜单,layout 中的数据可以被菜单直接消费,除了 layout 属性,它还导出了以下属性

而完成以上个性化的菜单功能,我们只需要取暴露出来的 mixedSidebarLayout 属性即可实现联动,由于篇幅有限,也不是整体文章的重点,所以代码我们暂且略过。。。
多页签的拦截器模式设计
多页签也是布局设计中的一环,他们一般长这样
如果你看过其他 Admin 多页签的实现,你可能会感慨一句“设计的好复杂”,想做一些扩展难度比较大。之所以复杂难扩展是因为内部涉及了很多功能扭转,比如固定状态下无法被删除、给用户预留了新的 title 属性等等之类的判断。
我们将多页签设计成了一个路由插件,因为多页签代表的是访问过的路由记录列表,我们将它命名为 visitedRoutesPlugin。
我们如何满足用户的特定场景呢?答案就是拦截器模式,路由记录列表实则就是一个数组,我们只需要对这个数组的增、删、移做拦截即可,代码如下

可以看到代码很简单,就是在增、删、移做了前置拦截和后置通知,除了这些操作外,还需要一个当前高亮的索引记录正在访问的路由,它的实现也很简单,因为它本身也可以基于拦截器模式,代码如下

那用户想实现个性化的场景怎么完成?我们可以向外导出这些拦截器,如下

以上几乎能满足用户的各种个性化需求,我们简单举几个例子,完整例子请参考我们 Admin 中 Demo 示例
场景一:自定义 title
用户可能想在添加多页签的时候自定义 title,可以如下编写

场景二:单独的页签
用户可能想给表格中的每一行数据跳转去详情的时候单独开一个页签,可以如下编写

相关链接
最后
篇幅有限,一篇文章很难说清楚每个功能的实现细节,说的不对之处还请指正!
项目上线不久,我们欢迎并感谢所有形式的贡献。如果您有任何想法或建议,欢迎通过提交 pull requests 或创建 issue 来分享。



