张成 27dcf1e9b3 1
2026-03-26 11:26:37 +08:00
2025-10-20 18:18:27 +08:00
1
2026-03-26 11:04:18 +08:00
1
2026-03-25 11:28:45 +08:00
2025-10-08 15:10:33 +08:00
1
2025-10-09 16:26:02 +08:00
1
2025-10-09 16:26:02 +08:00
1
2026-03-24 11:18:40 +08:00
1
2025-10-09 16:09:53 +08:00
1
2026-03-26 11:26:37 +08:00
1
2026-03-26 11:23:57 +08:00

Admin Frameworkadmin-framework2

基于 Vue 2Vue Router 3Vuex 3View DesigniView 4 的后台管理框架登录、布局、动态菜单与路由、权限、HTTP 封装、系统管理页面等。


1. 依赖与环境

1.1 Peer 依赖(由业务项目安装)

框架不打包以下依赖,需在宿主项目中安装并与框架版本兼容:

说明
vue ^2.6 运行时
vue-router ^3 路由
vuex ^3 状态
view-design ^4 UI 组件库
axios HTTP与框架内封装配合

1.2 构建产物(dist/

文件 说明
admin-framework.js UMDTerser 压缩,对外默认导出为框架单例;浏览器中为 window.AdminFramework,也可由 Webpack 等从该文件解析 import
admin-framework.md 与根目录 README.md 内容相同,随 npm run build 一并复制到 dist/,便于随包分发使用说明

在项目根目录执行:

npm run build

2. 引入方式

2.1 与 Webpack / Vue CLI 等业务工程配合

先安装 peer 依赖,将构建好的 dist/admin-framework.js 拷贝到业务项目或通过路径引用;在入口中:

import AdminFramework from './vendor/admin-framework.js'
// 若已将包发布到 npm 且 package.json 的 main 指向 dist
// import AdminFramework from 'admin-framework'

打包器需将 vuevue-routervuexview-designaxios 作为外部依赖或正常解析(与 UMD 的 externals 一致)。

2.2 页面中通过 <script> 引入

按顺序引入 Vue、VueRouter、Vuex、View Design、axios 的 UMD 脚本,再引入 admin-framework.js,使用全局 AdminFramework 调用 createApp 等 API。


3. 核心 API一键创建应用

3.1 AdminFramework.createApp(config)

创建并配置 Vue 根实例:注册插件、全局属性、componentMap、Store、Router、布局等。返回 Vue 实例,需自行 $mount

config 常用字段:

字段 类型 说明
title string 站点标题;未登录或接口失败时用作默认 document.title
apiUrl string 后端 API 根地址(必填,用于 http baseURL
uploadUrl string 可选;不传时由 apiUrl 自动推导为 apiUrl + 'upload'apiUrl + '/upload'
componentMap object 动态路由组件映射,见 §7
HomePage Vue 组件 可选,自定义首页;默认框架内置欢迎页
onReady function 可选,根实例 created 末尾调用,this 为 Vue 根实例

示例:

import AdminFramework from 'admin-framework'
import componentMap from './router/component-map.js'

const app = AdminFramework.createApp({
  title: '某某管理系统',
  apiUrl: 'https://api.example.com/admin_api/',
  componentMap,
  HomePage: null,
  onReady() {
    console.log('框架与路由就绪', this.$route.path)
  }
})

app.$mount('#app')

4. 框架实例(AdminFramework / window.framework

默认导出为单例。构建后也会挂到 window.framework(浏览器环境)。

4.1 常用属性

属性 说明
version 框架版本号字符串
config 最近一次 createApp 传入的配置
store Vuex Store 实例(createApp 之后可用)
router Vue Router 实例
HomePage 当前使用的首页组件引用
http HTTP 封装实例,同 §5
uiTool UI 与菜单工具类,同 §6
tools 工具方法集合,同 §6.2
systemApi src/api/system 聚合导出,同 §8
pages 框架内置页面组件集合(登录、错误页、部分系统页等)
components 布局与子组件导出Main、TreeGrid 等)
storeModules 默认 userapp 模块描述,扩展 Store 时可参考
createBaseRoutes / setupRouterGuards / registerComponents 高级自定义路由/组件时使用

4.2 addComponentMap(customMap)

在运行时追加组件映射(与 createApp 里的 componentMap 语义相同)。

import Games from './views/ball/games.vue'

AdminFramework.addComponentMap({
  'ball/games': Games,
  'ball/games.vue': Games
})

4.3 initHttp(config, store)

若未走 createApp、自行组装 Store 时,可用此方法初始化 http(一般使用 createApp 即可,内部已调用)。

AdminFramework.initHttp(
  { apiUrl: 'https://api.example.com/admin_api/', timeout: 60000 },
  storeInstance
)

5. HTTP 模块

通过 this.$http(组件内)或 AdminFramework.http / window.framework.http 访问。

5.1 初始化

createApp({ apiUrl, ... }) 自动完成;请求头会带 admin-token(来自 store.state.user.token)。

5.2 约定

  • 成功:后端 JSON 需 code === 0,否则走全局错误提示并 reject
  • 401:清空 token并跳转登录路由依赖 window.framework.router)。

5.3 方法说明

方法 说明
init(config, store) 合并 timeout 等,绑定 Store
baseUrl() 当前 apiUrl
ImgSrc(src) 拼接图片完整 URLbaseUrl() + src
getHttpInstance(extra) 返回带拦截器的 axios 实例
get(url, params, config) GETparams 会序列化Date 会格式化为字符串
post(url, body, config) POST JSON
postFormData(url, data) application/x-www-form-urlencoded
fileExport(url, param, filename, is_down) 下载导出;内部可用 uiTool.downloadFile
formatParamete / formatFormDataParam 参数预处理
showLoad / hideLoad / showError 与全局 loading、Message 联动

示例(在 Vue 组件中):

export default {
  async mounted() {
    try {
      const res = await this.$http.get('/sys_user/index', { page: 1, pageSize: 20 })
      this.list = res.data
    } catch (e) {
      // 已全局提示
    }
  }
}

隐藏 loading

await this.$http.get('/xxx', { id: 1 }, { hideLoad: true })

6. uiTool 模块

通过 this.$uiToolAdminFramework.uiTool 使用(类静态方法)。

方法 说明
setComponentMap(map) 合并组件映射表
getComponent(path) 按路径取组件,path 可带或不带 .vue
downloadFile(res, fileName) Blob 下载
setRem() 根据屏宽设置根字体(自适应)
getImgSrc(src) 图片地址(同 http 规则)
getBtn(h, options) Render 函数里生成操作按钮组
getDropdown(h, items) 下拉更多菜单
delConfirm(callback) 删除确认框
showConfirm({ title, content }, callback) 通用确认框
transformTree(list, cb) 扁平列表转树
subTree / menuToRoute / getRoutes 菜单转路由(框架内部与权限菜单配合)

树表示例:

const tree = this.$uiTool.transformTree(flatListFromApi)

6.2 通用工具 tools

通过 this.$tools 使用(具体以源码 src/utils/tools.js 为准)。

常用包括:

  • Cookie / TokengetTokensetTokenTOKEN_KEY
  • 日期formatDate(val, fmt)dayjs
  • 数组forEachhasOneOfgetUniongetIntersection
  • 对象objEqualremoveEmptyObjectisNullorEmpty
  • 路由/菜单getBreadCrumbListgetHomeRoutegetMenuByRouterfilterMenu
  • 本地存储localSavelocalRead
  • 其它generateUUIDgetUrlParamdownStreamscrollTop

示例:

if (this.$tools.getToken()) { /* 已登录 */ }

7. 组件映射与动态路由

后端菜单里配置的「组件地址」会对应到字符串路径(如 system/sys_user)。框架通过 componentMap 把路径映射到真实 Vue 组件。

createApp 中传入:

import SysUser from './views/system/sys_user.vue'

AdminFramework.createApp({
  apiUrl: '...',
  componentMap: {
    'system/sys_user': SysUser,
    'system/sys_user.vue': SysUser
  }
})

未映射的路径会显示占位提示(控制台 warn),便于排查。

框架内置已注册一批系统页(如 system/sys_menu 等),见 src/views/index.jssetupComponentMap;业务模块在 componentMap 中追加即可。


8. 系统 APIsystemApi

AdminFramework.systemApi 聚合导出 src/api/system 下各 *Server,例如:

导出名 模块文件 典型用途
userServer userServer.js 登录、用户 CRUD、权限菜单
menuServer menuServer.js 菜单管理
roleServer / rolePermissionServer 角色与权限
paramSetupServer 系统参数如站点标题、Logo
fileServe 文件上传下载
modelServer / tableServer / formServer 低代码/表单相关

调用示例:

const { userServer } = AdminFramework.systemApi

async function login() {
  const res = await userServer.login({ username: 'admin', password: '***' })
  if (res.code === 0) {
    // 写入 token、拉菜单等由登录页与 store 配合完成
  }
}

实际请求仍走全局配置的 httpapiUrl、token 头)。


9. Vuexthis.$store

默认模块:

9.1 usernamespaced: true

说明
state tokenuserNameauthorityMenusmenuList
mutations setTokensetUserNamesetAuthorityMenussetMenuList
actions setAuthorityMenus:拉取或传入菜单 JSON生成动态路由并写入 localStorage

登录后刷新菜单示例:

await this.$store.dispatch('user/setAuthorityMenus', {
  Main: this.$framework.components.Main,
  ParentView: this.$framework.components.ParentView,
  Page404: this.$framework.pages.Page404,
  HomePage: this.$framework.HomePage
})

(具体参数以当前框架版本 user 模块为准。)

9.2 appnamespaced: true

说明
state sysFormModel标题、Logo、面包屑、首页路由
actions getSysTitle:根据参数与接口更新站点标题与 Logo
await this.$store.dispatch('app/getSysTitle', {
  defaultTitle: this.$config.title,
  defaultLogo: ''
})

10. 全局 Vue 原型(组件内)

属性 说明
this.$config createAppconfig
this.$http HTTP 封装
this.$tools 工具集
this.$uiTool UI 工具类
this.$framework 框架单例(同 AdminFramework

11. 内置页面(pages

  • 页面LoginPagePage401Page404Page500HomePage 及多套 system/* 管理页(见 src/views/index.js)。
  • 业务中也可通过 AdminFramework.pages 取到上述导出。

12. 组件使用说明(src/components

createApp 执行时会对下列组件全局注册(见 src/components/index.jsregisterGlobalComponents),在任意 .vue 模板中可直接写 PascalCase 或 kebab-case 标签名(如 <Tables> / <tree-grid>)。也可按需:

import { Tables, TreeGrid, editModal } from 'admin-framework'
// 或在源码工程中import Tables from '@/components/tables'
const { TreeGrid, Main } = AdminFramework.components

以下按功能分类;Props / 事件以源码为准,此处列出常用项。

12.1 布局与路由壳

组件 说明
Main 后台主布局:左侧 SideMenu、顶栏 HeaderBar、用户信息、Terminal、主内容区 <router-view />、内嵌 LoadFlower、返回顶部。无业务 Props标题/Logo 来自 Vuex app/sysFormModel,菜单来自 user/menuList
ParentView 仅渲染一层 <router-view />,用于菜单多级嵌套时的中间层。
<!-- 动态路由中由框架注册一般不在页面手写 Main -->

Main 子模块说明(src/components/main/components

以下组件默认未在 registerGlobalComponents 中注册,由 Main 内部引用;若要在自定义布局中复用,需从路径手动 import(示例路径以源码工程 @/components/... 为准)。

组合关系(main.vueLayout 左侧为 SideMenu + 品牌区;右侧顶部 HeaderBar,其默认插槽内为 TerminalUser;内容区为 <router-view />LoadFlowerABackTop


1. SideMenuside-menu/side-menu.vue

侧栏菜单,基于 iView Menu,支持折叠态下的 CollapsedMenu 下拉。

Props 类型 说明
menuList Array 菜单树,项需含 namemeta(如 icontitle)、子节点 children 等,与动态路由菜单结构一致
collapsed Boolean 是否折叠(仅图标 / 下拉)
theme String 菜单主题,默认 lightMain 中传入 dark
activeName String 当前激活菜单 name,一般传 $route.name
openNames Array 初始展开的 Submenu 名称列表
rootIconSize / iconSize Number 折叠/展开时图标大小,默认 20 / 16
插槽 说明
默认 菜单上方的额外区域(可选)
事件 说明
on-select 选中菜单项时,参数为路由 name 字符串(或外链特殊格式 isTurnByHref_xxx,由 Main 中 turnToPage 处理)
<SideMenu
  theme="dark"
  :menu-list="menuList"
  :collapsed="collapsed"
  :active-name="$route.name"
  @on-select="handleMenuSelect"
/>

2. SideMenuItemside-menu/side-menu-item.vue

SideMenu 内部递归子组件:渲染 Submenu 标题与一层子 menu-item。依赖 mixin 提供的 parentItemchildren 等逻辑,一般不单独使用

3. CollapsedMenuside-menu/collapsed-menu.vue

侧栏折叠时的下拉菜单(Dropdown 嵌套)。由 SideMenu 使用。

Props 说明
parentItem 当前菜单节点
hideTitle 为 true 时仅图标(侧栏窄条场景)
rootIconSize / iconSize 图标尺寸
theme 与侧栏主题一致,用于图标颜色

| 事件 | on-click — 点击子项时传出菜单 name |


4. HeaderBarheader-bar/header-bar.vue

顶栏:左侧 折叠开关 + 面包屑,右侧 默认插槽Main 里放终端图标、用户区等)。

Props 说明
collapsed 当前侧栏是否折叠,传给 SiderTrigger
插槽 说明
默认 顶栏右侧自定义内容(如 TerminalUser
事件 说明
on-coll-change 折叠按钮切换,payload新的 collapsed 布尔值(与 SiderTriggeron-change 一致)

面包屑数据来自 $route.matched(去掉第一项),每项包含 namepathmeta;展示标题用 tools.showTitle

<HeaderBar :collapsed="collapsed" @on-coll-change="collapsed = $event">
  <Terminal /><User :userName="name" :user-avator="avatar" />
</HeaderBar>

5. SiderTriggerheader-bar/sider-trigger/sider-trigger.vue

折叠侧栏的图标按钮。

| Props | collapsedicon(默认 navicon-roundMain 里为 md-menu)、size(默认 26 | | 事件 | on-change — 参数为切换后的 collapsed 状态(布尔) |

6. customBreadCrumbheader-bar/custom-bread-crumb/custom-bread-crumb.vue

自定义面包屑(Breadcrumb)。

| Props | list { name, path, meta, to?, icon? }[] )、fontSize(默认 14)、showIcon | | 说明 | 文案通过 showTitle(item, this) 解析,支持 meta.title 等 |


7. Useruser/user.vue

右上角用户名 + 头像下拉,退出登录走 Vuex user/handleLogOut

| Props | userNameuserAvator(字符串 URL也可传对象未用字符串时显示内置默认图 | | 说明 | 内置 message 方法曾跳转 message_page,可按需扩展菜单项 |

8. Terminalterminal/index.vue + terminal/terminal.vue

入口为一颗 iView Icon,点击后用 AsyncModal 弹层展示内层终端视图。当前实现中日志区域为占位文案(终端功能暂未启用),按钮「重新加载 / 清空」会提示未启用。

复用时需保证工程内已注册 AsyncModalindex.vueref="asyncModal" 调用 show() 打开弹窗。

9. Languagelanguage/language.vue

语言下拉(zh-CN / zh-TW / en-US)。需在工程中配置 vue-i18nthis.$i18n)方可切换文案。

| Props | lang 当前语言代码 | | 事件 | on-lang-change — 选中的语言 key |

main.vue 当前模板未挂载 Language,若在自定义 Main 中需要多语言顶栏,可自行加入。

10. Fullscreenfullscreen/fullscreen.vue

全屏切换;非 IE 显示按钮。支持 v-modelvalue 是否全屏),全屏状态变化时触发 inputon-change

main.vue 当前未使用该组件,可按需放入 HeaderBar 插槽。

11. ABackTopa-back-top/index.vue

回到顶部浮动按钮,监听滚动容器滚动。

| Props | height(显示阈值,默认 400)、bottomrightduration(滚动动画 mscontainer(默认 window,可为选择器字符串如 '.content-wrapper' | | 插槽 | 默认:自定义按钮外观;未提供时用内置箭头图标 | | 方法 | 内部 scrollTop 滚动;点击触发回到顶部 |

Main 中示例:<ABackTop container=".content-wrapper" :height="100" :bottom="80" :right="50" />


小结:自定义后台壳时,可照搬 main.vue 结构,替换或增删 HeaderBar 插槽内子组件;侧栏行为与菜单数据结构强相关,需与 user/menuList路由 meta 保持一致。

12.2 表格:Tables

基于 View Design Table 封装,支持分页条、导出、列配置、可编辑列等。

Props 说明
value 表格数据数组
columns 列配置(同 iView Table columns,框架内会做对齐等默认处理)
title / tip 表格标题与灰色提示
isDown 为 true 且 value 非空时显示「下载」链接触发导出
pageOption 分页:{ page, pageSize, total },存在则显示 Page
width / height 传给内部 Table
maxHeightOffset 表格外层最大高度:auto(默认,按视口计算)或数字,用于 calc(100vh - offset)
插槽 说明
header 标题行右侧区域
默认 透传给内部 Tableslot-scope 列)
footer / loading 透传 Table 同名插槽
事件 说明
changePage 分页变更(内部已更新 pageOption.page
on-select 多选变化
downExecl 点击下载时,{ value, columns }
<Tables
  :value="tableData"
  :columns="columns"
  :page-option="{ page: 1, pageSize: 10, total: 100 }"
  title="用户列表"
  @changePage="loadData"
/>

12.3 树形表格:TreeGrid

树形多级表格,表头与行由 columnsdata 驱动(数据需含 children 等树结构)。

Props 说明
columns 列配置
data 树形数据

其余属性通过 v-bind="$attrs" 传到内部子组件。

<TreeGrid :columns="gridOption.columns" :data="gridOption.data" />

12.4 上传:UploadSingle / UploadMultiple

组件 说明
UploadSingle 单图。v-model 绑定服务器返回的相对路径字符串;上传地址为 apiUrl + 'sys_file/upload_oos_img',请求头带 admin-token。成功:inputchange。预览/删除支持。
UploadMultiple 多图(内部列表最多约 4 张)。@handleSuccess 回调 { file, uploadList };可调用 setList(list) / getList() 同步列表。
<UploadSingle v-model="form.avatar" />
<UploadMultiple ref="multi" @handleSuccess="onUploaded" />

12.5 富文本:Editor

基于 wangEditor。使用 this.$config.apiUrl(或等价配置)作为图片上传地址。

Props 说明
value HTML 字符串,支持 v-model
<Editor v-model="form.content" />

12.6 弹窗:AsyncModal / editModal

AsyncModal — 简单确认弹窗:

Props 说明
title 标题
width 宽度,默认约 80Modal 数字宽度)
方法 说明
show(callback) 打开;确定时执行 callback(可 asyncon-ok 并关闭
<AsyncModal ref="asyncModal" title="提示">
  <p>自定义内容</p>
</AsyncModal>
<!-- this.$refs.asyncModal.show(async () => { await api(); }) -->

editModal — 由 columns 驱动表单项(内部用 FieldRenderer),用于新增/编辑:

Props 说明
columns 列/字段配置:keytitlecomInput、Select、Radio、editRender 等)
width 弹窗宽度
rules 可通过父级传入覆盖默认校验(与 Form 一致)
插槽 说明
top 表单最上方
bottom 表单最下方(如额外表单项)
方法 说明
addShow(row, callback) 新增;确定后 callback(提交行数据)
editShow(row, callback) 编辑
showModal(row) id 走编辑,否则新增
hide / setFooter / refresh 关闭、控制底部按钮、强制重渲染表单
事件 说明
on-save { data, isEdit }
on-visible-change Modal 显隐
<editModal ref="editModal" :columns="editColumns" :rules="rules">
  <div slot="bottom"><fieldItem name="备注"><Input v-model="extra" /></fieldItem></div>
</editModal>

12.7 表单项辅助:fieldItem / FieldRenderer

组件 说明
fieldItem 简单包装:name(标签)、required,默认插槽放控件。
FieldRenderer 根据 col.com 渲染 Input、Select、Radio、UploadSingleDatePicker 等;一般被 editModal 使用,也可在自定义表单中复用。
<fieldItem name="名称" :required="true">
  <Input v-model="form.name" />
</fieldItem>

12.8 卡片:InfoCard

左侧色块 + 图标,右侧自定义内容。

Props 说明
left 左侧宽度占比,默认 36(即 36%
color 左侧背景色
icon / iconSize 图标名与尺寸(走 CommonIcon
shadow 是否 Card 阴影
<InfoCard icon="md-person" color="#19be6b">
  <p>自定义统计文案</p>
</InfoCard>

12.9 分割面板:SplitPane

可拖拽调整左右或上下比例。

Props 说明
value 0~1 或带 px 的字符串,初始分割位置
mode horizontal(左右)或 vertical(上下)
min / max 拖拽极限,默认约 40px
插槽 说明
left / righttop / bottom 两侧内容
trigger 自定义拖拽条
事件 说明
on-move-start / on-moving / on-move-end 拖拽过程;on-moving 事件对象上可带 atMinatMax
<SplitPane v-model="split" mode="horizontal">
  <div slot="left"></div>
  <div slot="right"></div>
</SplitPane>

12.10 侧滑层:FloatPanel

从一侧滑出的面板,带返回/关闭。

Props 说明
title 标题
width / height 尺寸,支持数字或带单位字符串
position left / right / top / bottom / center
showBack / backText 返回按钮与文案
showClose 右上角关闭
closeOnClickBackdrop 点击遮罩是否关闭
mask 是否遮罩
zIndex 层级
方法 说明
show(callback) 显示;可选回调
hide() 隐藏
插槽 说明
默认 主体内容
header-right 标题栏右侧
<FloatPanel ref="panel" title="详情" position="right" :width="480">
  <p>内容</p>
</FloatPanel>
<!-- this.$refs.panel.show() -->

12.11 其他全局组件

组件 说明
TextArea 多行输入,value + input 事件,封装 iView Input type="textarea"
CommonIcon type:普通 Icon 名;自定义图标以 _ 开头配合 md-iconssizecolor 可选。
LoadFlower 全屏 loading 占位(与 httpshowLoad 通过 DOM id 联动),一般随 Main 挂载,无需单独使用。

12.12 未全局注册、按需引用的组件

以下在 src/components 下,需在页面中 import 后注册或局部引用:

路径/名称 说明
login-form 登录表单:userNameRulespasswordRules;校验通过 @on-success-valid 抛出 { userName, password }
date-picker/index.vue DatePickerv-model 封装,change/input
switch/index.vue Switchv-model 封装。
cron-input Cron 表达式下拉选择。
main/pageHead.vue 页面顶栏条:当 $route.meta.type === '功能' 时显示返回;默认插槽放按钮。
markdowncropper 见各目录 index.js / 入口组件。

13. 调试

  • 浏览器中:window.frameworkwindow.rootVue(根实例,在 createApp 创建后设置)。
  • 需要未压缩源码调试时,可在业务工程里直接引用框架 src/index.js(需配置好 alias、loader 与 peer 依赖),或使用浏览器「在源映射中黑盒脚本」等能力。

14. Demo 项目

demo/ 为示例:请先在仓库根目录执行 npm run build 生成 dist/admin-framework.js,再在 demo 目录安装依赖并执行 npm run devdemo/src/main.js 通过相对路径引用上级 dist 中的 UMD 包。


以上为框架对外使用方式的说明;内部实现以 src/ 源码为准。若升级版本,请同时核对 peer 依赖与本文档中的 API 是否变更。

Description
前端框架库
Readme 1.9 MiB
Languages
Vue 54.6%
JavaScript 38.7%
Less 5.3%
CSS 1.4%