返回 导航

Vue.js

hangge.com

Vue.js - 后台管理系统模板项目推荐2(Soybean Admin、高颜值、轻量化首选)

作者:hangge | 2026-09-15 09:34
    Soybean Admin 是一款基于 Vue3 + Vite5 + TypeScript + Naive UI + UnoCSS 构建的高颜值、轻量、高性能企业级后台管理模板,凭借简洁优雅的 UI 设计、规范的代码结构、完善的权限体系和开箱即用的功能模块,成为目前主流的中后台开源模板之一。

二、 Soybean Admin(高颜值、轻量化首选)

1,基本介绍

(1)SoybeanAdmin 是一个清新优雅、高颜值且功能强大的后台管理模板,基于最新的前端技术栈,包括 Vue3Vite8TypeScriptPiniaUnoCSS。它内置了丰富的主题配置和组件,代码规范严谨,实现了自动化的文件路由系统。此外,它还采用了基于 ApiFox 的在线 Mock 数据方案。SoybeanAdmin 为您提供了一站式的后台管理解决方案,无需额外配置,开箱即用。同样是一个快速学习前沿技术的最佳实践。

(2)SoybeanAdmin 主打轻盈美观、极简高效,基于 Naive UI 开发,UI 设计质感远超传统 Element 系列模板,高颜值后台项目的热门选择,尤其适配 AI 对话、工具类后台系统。

2,核心技术栈

  • 前沿技术应用:采用 Vue3Vite8TypeScriptPiniaUnoCSS 等最新流行的技术栈。
  • 清晰的项目架构:采用 pnpm monorepo 架构,结构清晰,优雅易懂。
  • 严格的代码规范:遵循 SoybeanJS 规范,集成了 eslintprettiersimple-git-hooks,保证代码的规范性。
  • TypeScript: 支持严格的类型检查,提高代码的可维护性。
  • 丰富的主题配置:内置多样的主题配置,与 UnoCSS 完美结合。
  • 内置国际化方案:轻松实现多语言支持。
  • 自动化文件路由系统:自动生成路由导入、声明和类型。更多细节请查看 Elegant Router
  • 灵活的权限路由:同时支持前端静态路由和后端动态路由。
  • 丰富的页面组件:内置多样页面和组件,包括 403404500 页面,以及布局组件、标签组件、主题配置组件等。
  • 命令行工具:内置高效的命令行工具,git 提交、删除文件、发布等。
  • 移动端适配:完美支持移动端,实现自适应布局。

3,项目优缺点

(1)优点:
  • Naive UI 原生轻量化设计,界面简洁高级,无冗余样式,适配异形布局、对话气泡、打字机特效等个性化场景
  • UnoCSS 原子化样式开发,大幅提升样式编写效率,按需加载极致瘦身
  • 架构简洁清晰,注释规范,新手易上手,二次开发效率极高
  • 内置完整的权限管理、主题切换、暗黑模式、国际化适配
(2)缺点:
  • 大型复杂业务组件生态不如 AntDElement 完善

4,准备工作

(1)首先需求安装 Node.js,并且官方要求 Node.js 20.19.0 及以上版本,我们只需要访问其官网下载安装即可。

(2)同时项目只支持使用 pnpm 进行依赖安装,我们还需要执行如下命令安装 pnpm
npm i -g pnpm

(3)安装完毕可以通过 pnpm -v 命令进行验证:

5,下载项目

(1)在 CMD 终端种执行如下命令克隆代码,然后进入项目:
git clone https://github.com/soybeanjs/soybean-admin.git
cd soybean-admin

(2)整个项目的核心目录结构如下:
soybean-admin
├── build                # Vite构建配置、代理、插件配置
├── packages             # 项目公共子包(请求、工具、Hooks、组件物料)
├── public               # 静态资源(图标、静态文件,打包直接复制)
├── src
│  ├── assets            # 图片、SVG图标、全局静态资源、样式素材
│  ├── components        # 全局公共组件、自定义业务组件、高级封装组件
│  ├── constants         # 全局常量配置(固定不变的静态常量、文本、配置项)
│  ├── enum              # 全局TS枚举定义(业务枚举、状态枚举、类型枚举)
│  ├── hooks             # 全局组合式hooks(封装通用业务逻辑、复用逻辑)
│  ├── layouts           # 系统全局布局(侧边栏、头部导航、标签页、底部布局)
│  ├── locales           # 国际化多语言配置(中英文、多语言适配)
│  ├── plugins           # 全局插件注册(UI、图标、路由、全局功能插件挂载)
│  ├── router            # 路由配置、路由守卫、动态路由、自动路由声明
│  ├── service           # 全局请求封装、API接口模块、请求拦截器
│  ├── store             # Pinia全局状态管理(权限、主题、菜单、标签页、用户状态)
│  ├── styles            # 全局通用样式、重置样式、全局SCSS样式
│  ├── theme             # 主题配色、样式变量、暗黑模式、主题默认配置
│  ├── typings           # 全局TS类型声明、全局接口、模块类型定义
│  ├── utils             # 全局通用工具函数、格式化、校验、浏览器工具
│  ├── views             # 所有业务页面(核心二次开发目录)
│  ├── App.vue           # 根组件
│  └── main.ts           # 项目入口文件
├── .env/.env.test/.env.prod  # 多环境配置文件
├── vite.config.ts       # Vite核心配置
└── tsconfig.json        # TypeScript配置

(3)然后再项目目录下执行如下命令安装依赖:
pnpm install

6,启动项目

(1)执行如下命令可启动开发服务器。
pnpm dev

(3)使用浏览器访问,默认显示登录页:

(2)登录后内页显示效果如下:

(3)切换成深色模式效果如下:

7,打包与部署

(1)开发完成后,执行如下打包命令,生成可部署的静态资源。打包完成后,项目根目录会生成 dist 文件夹,即为最终部署文件。
pnpm build

(2)执行如下命令可以本地预览打包文件。通过本地验证打包后的项目是否正常运行,可以避免部署后出现报错。
pnpm preview

附:项目常用功能与主要代码详解

1,主题与样式配置

(1)系统启动后,用户可自由切换主题模式。

(2)若需要定义项目默认主题样式(所有用户、首次打开项目统一生效),可修改核心配置文件 src/theme/settings.ts,该文件为项目主题全局唯一配置源。
/** Default theme settings */
export const themeSettings: App.Theme.ThemeSetting = {
  /** 主题模式: 'light' - 亮色 | 'dark' - 暗色 | 'auto' - 跟随系统 */
  themeScheme: 'light',
  /** 灰色模式(无障碍功能),开启后页面呈灰度显示 */
  grayscale: false,
  /** 色弱模式(无障碍功能),适合色弱用户 */
  colourWeakness: false,
  /** 是否使用推荐色板配色方案 */
  recommendColor: false,
  /** 主题主色调,支持任意 HEX 颜色值 */
  themeColor: '#646cff',
  /** 全局圆角大小,单位 px */
  themeRadius: 6,
  /** 辅助色配置 */
  otherColor: {
    /** 信息提示色(蓝色) */
    info: '#2080f0',
    /** 成功状态色(绿色) */
    success: '#52c41a',
    /** 警告状态色(橙色) */
    warning: '#faad14',
    /** 错误状态色(红色) */
    error: '#f5222d'
  },
  /** info 色是否跟随主色调变化 */
  isInfoFollowPrimary: true,
  /** 布局配置 */
  layout: {
    /** 布局模式: 'vertical' - 垂直侧边栏 | 'horizontal' - 水平顶部菜单 | 
     * 'vertical-mix' - 双栏混合 | 'vertical-hybrid-header-first' | 
     * 'top-hybrid-sidebar-first' | 'top-hybrid-header-first' */
    mode: 'vertical',
    /** 滚动区域: 'wrapper' - 整体滚动 | 'content' - 内容区滚动 */
    scrollMode: 'content'
  },
  /** 页面动画配置 */
  page: {
    /** 是否启用页面切换动画 */
    animate: true,
    /** 动画类型: 'fade' | 'fade-slide' | 'fade-bottom' | 'fade-scale' |
     *  'zoom-fade' | 'zoom-out' | 'none' */
    animateMode: 'fade-slide'
  },
  /** 顶部 Header 配置 */
  header: {
    /** 顶部栏高度,单位 px */
    height: 56,
    /** 面包屑导航配置 */
    breadcrumb: {
      /** 是否显示面包屑导航 */
      visible: true,
      /** 面包屑是否显示图标 */
      showIcon: true
    },
    /** 多语言切换配置 */
    multilingual: {
      /** 是否显示语言切换按钮 */
      visible: true
    },
    /** 全局搜索配置 */
    globalSearch: {
      /** 是否显示全局搜索入口 */
      visible: true
    }
  },
  /** 标签页 Tab 配置 */
  tab: {
    /** 是否显示标签页栏 */
    visible: true,
    /** 是否缓存标签页状态(刷新后保留已打开的标签) */
    cache: true,
    /** 标签栏高度,单位 px */
    height: 44,
    /** 标签样式: 'chrome' - Chrome风格 | 'button' - 按钮风格 | 'slider' - 滑块风格 */
    mode: 'chrome',
    /** 是否支持鼠标中键点击关闭标签 */
    closeTabByMiddleClick: false
  },
  /** 是否固定顶部和标签栏(滚动时保持可见) */
  fixedHeaderAndTab: true,
  /** 侧边栏 Sider 配置 */
  sider: {
    /** 是否反色(深色侧边栏样式) */
    inverted: false,
    /** 侧边栏展开宽度,单位 px */
    width: 220,
    /** 侧边栏折叠宽度,单位 px */
    collapsedWidth: 64,
    /** 混合布局时一级菜单宽度,单位 px */
    mixWidth: 90,
    /** 混合布局时折叠宽度,单位 px */
    mixCollapsedWidth: 64,
    /** 混合布局时子菜单宽度,单位 px */
    mixChildMenuWidth: 200,
    /** 展开菜单时是否自动选中第一个子菜单 */
    autoSelectFirstMenu: false
  },
  /** 底部 Footer 配置 */
  footer: {
    /** 是否显示底部栏 */
    visible: true,
    /** 是否固定底部栏 */
    fixed: false,
    /** 底部栏高度,单位 px */
    height: 48,
    /** 混合布局时底部是否靠右对齐 */
    right: true
  },
  /** 水印配置 */
  watermark: {
    /** 是否显示水印 */
    visible: false,
    /** 水印文字内容 */
    text: 'SoybeanAdmin',
    /** 水印是否包含当前用户名 */
    enableUserName: false,
    /** 水印是否包含当前时间 */
    enableTime: false,
    /** 水印时间显示格式 */
    timeFormat: 'YYYY-MM-DD HH:mm'
  },
  /** 主题 Token(高级 CSS 变量),用于自定义容器颜色、阴影等 */
  tokens: {
    /** 亮色主题 Token */
    light: {
      /** 颜色配置 */
      colors: {
        /** 容器背景色(卡片、弹窗等) */
        container: 'rgb(255, 255, 255)',
        /** 布局背景色(页面整体背景) */
        layout: 'rgb(247, 250, 252)',
        /** 反色背景(深色侧边栏等) */
        inverted: 'rgb(0, 20, 40)',
        /** 基础文字颜色 */
        'base-text': 'rgb(31, 31, 31)'
      },
      /** 阴影配置 */
      boxShadow: {
        /** 顶部栏阴影 */
        header: '0 1px 2px rgb(0, 21, 41, 0.08)',
        /** 侧边栏阴影 */
        sider: '2px 0 8px 0 rgb(29, 35, 41, 0.05)',
        /** 标签栏阴影 */
        tab: '0 1px 2px rgb(0, 21, 41, 0.08)'
      }
    },
    /** 暗色主题 Token(未设置的属性会自动从 light 推导) */
    dark: {
      colors: {
        /** 容器背景色 */
        container: 'rgb(28, 28, 28)',
        /** 布局背景色 */
        layout: 'rgb(18, 18, 18)',
        /** 基础文字颜色 */
        'base-text': 'rgb(224, 224, 224)'
      }
    }
  }
};

export const overrideThemeSettings: Partial<App.Theme.ThemeSetting> = {};

2,新增业务页面

(1)Soybean Admin 摒弃传统手动配置路由的繁琐操作,内置自动化文件路由系统,遵循「文件即路由」规则,新手只需新建页面文件,通过命令自动生成路由、菜单、类型声明,全程无需手写路由代码。

(2)例如我们需要新增一个“用户管理”模块,首先新建 src/views/user 文件夹。同时文件夹内必须创建 index.vue 作为页面入口文件(路由默认识别 index.vue
提示:如果页面复杂需要拆分组件,可以在当前文件夹下新建 components 存放页面私有组件,不影响路由生成。
  • 页面文件创建完成后,我们重启服务,项目便会自动解析页面、生成路由文件、TS 类型、菜单配置,无需手动配置 router/index.ts,彻底避免路由配置报错。
  • 我们只需要对 router/index.ts 中刚生成的路由做些许修改(菜单名字、排序、使用图标等)即可。
  {
    name: 'user',
    path: '/user',
    component: 'layout.base$view.user',
    meta: {
      title: '用户管理',
      icon: 'mdi:account-cog',
      order: 2
    }
  }

(3)如果菜单要分组的话也很简单,只要在 src/views 下创建一个一级目录,然后在该目录下再创建子模块目录即可。
  • 页面文件创建完成后,我们重启服务,项目便会自动解析页面、生成路由文件、TS 类型、菜单配置,无需手动配置 router/index.ts,彻底避免路由配置报错。
  • 我们只需要对 router/index.ts 种刚生成的路由做些许修改(菜单名字、排序、使用图标等)即可。
{
  name: 'system',
  path: '/system',
  component: 'layout.base',
  meta: {
    title: '系统管理',
    icon: 'mdi:cog',
    order: 2
  },
  children: [
    {
      name: 'system_menu',
      path: '/system/menu',
      component: 'view.system_menu',
      meta: {
        title: '菜单管理',
        icon: 'mdi:menu',
        order: 1
      }
    },
    {
      name: 'system_user',
      path: '/system/user',
      component: 'view.system_user',
      meta: {
        title: '用户管理',
        icon: 'mdi:account-group',
        order: 2
      }
    }
  ]
}

3,权限管理

(1)Soybean Admin 内置标准 RBAC 权限模型(角色-权限-用户),同时支持前端静态权限和后端动态权限,精细化支持“菜单权限、角色权限、按钮权限”,完全满足企业级后台权限管控需求。
  • 菜单权限:控制不同角色是否可以看到、访问指定页面,无权限角色侧边栏自动隐藏对应菜单,禁止路由跳转
  • 角色权限:基于角色分配权限,支持超级管理员、普通管理员、普通用户等多角色权限隔离
  • 按钮权限:页面级精细化权限控制,针对新增、编辑、删除、导出等按钮,控制角色是否可操作

(2)下面是一个菜单权限配置样例,修改 router/index.ts 文件将用户管理菜单设置为只允许管理员和超级管理员访问,若干普通用户登录会看不到这个菜单。
{
  name: 'system',
  path: '/system',
  component: 'layout.base',
  meta: {
    title: '系统管理',
    icon: 'mdi:cog',
    order: 2
  },
  children: [
    {
      name: 'system_menu',
      path: '/system/menu',
      component: 'view.system_menu',
      meta: {
        title: '菜单管理',
        icon: 'mdi:menu',
        order: 1
      }
    },
    {
      name: 'system_user',
      path: '/system/user',
      component: 'view.system_user',
      meta: {
        title: '用户管理',
        icon: 'mdi:account-group',
        order: 2,
        roles: ['R_ADMIN', 'R_SUPER']  // 管理员和超级管理员可访问
      }
    }
  ]
}

(3)下面是一个通过代码获取当前用户角色,通过角色动态控制按钮显示隐藏的样例,其中“批量删除”按钮只允许管理员和超级管理员使用,若普通用户登录则看不到这个按钮。
<template>
    <div class="menu-manage">
        <NCard :bordered="false">
            <NSpace>
                <!-- 普通按钮:所有用户都可以访问 -->
                <NButton type="primary">
                    <template #icon>
                        <SvgIcon icon="mdi:plus" />
                    </template>
                    新增菜单
                </NButton>

                <!-- 权限按钮:只有管理员和超级管理员可以访问 -->
                <NButton v-if="hasAdminRole" type="error">
                    <template #icon>
                        <SvgIcon icon="mdi:delete" />
                    </template>
                    批量删除
                </NButton>
            </NSpace>
        </NCard>
    </div>
</template>

<script setup lang="ts">
import { computed } from 'vue';
import { useAuthStore } from '@/store/modules/auth';
import SvgIcon from '@/components/custom/svg-icon.vue';

defineOptions({
    name: 'SystemMenu'
});

const authStore = useAuthStore();

// 判断是否为管理员或超级管理员
const hasAdminRole = computed(() => {
    const adminRoles = ['R_ADMIN', 'R_SUPER'];
    return authStore.userInfo.roles.some(role => adminRoles.includes(role));
});
</script>

<style scoped>
.menu-manage {
    padding: 16px;
}
</style>

(4)对于按钮显示与否,我们也可以直接通过按钮权限了控制:
<template>
    <div class="menu-manage">
        <NCard :bordered="false">
            <NSpace>
                <!-- 新增菜单按钮:需要 menu:add 权限 -->
                <NButton v-if="authStore.userInfo.buttons.includes('menu:add')" type="primary">
                    <template #icon>
                        <SvgIcon icon="mdi:plus" />
                    </template>
                    新增菜单
                </NButton>

                <!-- 批量删除按钮:需要 menu:delete 权限 -->
                <NButton v-if="authStore.userInfo.buttons.includes('menu:delete')" type="error">
                    <template #icon>
                        <SvgIcon icon="mdi:delete" />
                    </template>
                    批量删除
                </NButton>
            </NSpace>
        </NCard>
    </div>
</template>

<script setup lang="ts">
import SvgIcon from '@/components/custom/svg-icon.vue';
import { useAuthStore } from '@/store/modules/auth';

defineOptions({
    name: 'SystemMenu'
});

const authStore = useAuthStore();
</script>

<style scoped>
.menu-manage {
    padding: 16px;
}
</style>

4,接口请求使用

(1)接口请求使用项目已基于 Axios 完成全局二次封装,统一处理请求拦截、响应拦截、Token 自动携带、超时重试、错误统一提示、请求加载状态,无需开发者重复封装,直接调用即可。同时内置 Mock 数据,支持前后端分离开发。

(2)所有 API 接口统一存放于 src/service/api 目录,严格按业务模块拆分文件,统一管理、便于维护。

(3)默认后端接口地址是基于 ApiFox 在线 Mock,本地开发无需对接后端,所有页面、表格、表单功能可直接预览调试。如果需要对接真实后端接口,只需修改环境配置文件,切换接口请求地址即可。

(4)dev 模式下默认会开启本地代理,防止对接后端接口出现跨域问题。可以修改环境配置文件关闭。
评论

全部评论(0)

回到顶部