UI架构说明
1. 系统架构概述
Wimoor UI3 是一个基于 Vue 3 + Element Plus 构建的企业级前端应用框架,采用现代化的技术栈和架构设计理念。系统采用了组件化、模块化和分层架构,具有良好的可扩展性、可维护性和性能。
1.1 技术栈
| 技术 | 版本 | 用途 |
|---|---|---|
| Vue | 3.x | 前端框架 |
| Element Plus | 2.x | UI组件库 |
| Vue Router | 4.x | 路由管理 |
| Vuex | 4.x | 状态管理 |
| Axios | 0.27.x | HTTP客户端 |
| Vite | 3.x | 构建工具 |
| SVG | - | 图标系统 |
1.2 系统分层
- 表示层:Vue 组件、视图、布局
- 控制层:路由、导航守卫
- 业务逻辑层:Vuex Store、API服务
- 数据访问层:Axios请求封装
- 工具层:全局工具函数、指令
2. 核心架构组件
2.1 应用入口 (main.js)
应用入口文件负责初始化 Vue 应用,注册全局组件、指令、过滤器和方法。
核心功能:
- Vue 应用创建与挂载
- Element Plus 注册与配置
- 路由与状态管理注册
- 全局组件注册 (SvgIcon, DictTag, Pagination, GlobalTable等)
- 自定义指令注册 (v-hasPerm, v-hasPermi, v-dataType)
- 全局方法挂载 (parseTime, download, useDict等)
关键代码:
// 创建Vue应用
const app = createApp(App);
// 注册核心依赖
app.use(store).use(router).use(ElementPlus).use(print).use(plugins);
// 注册全局组件
app.component('GlobalTable', GlobalTable);
app.component('Pagination', Pagination);
// 注册自定义指令
app.use(hasPerm).use(hasPermi).use(dataType);
// 挂载应用
app.mount('#app');
2.2 路由系统
路由系统采用 Vue Router 4,支持静态路由和动态路由结合的方式。
2.2.1 路由配置
路由配置分为静态路由和动态路由两部分:
- 静态路由:在前端代码中定义的固定路由,如登录页、首页等
- 动态路由:从后端API获取的业务路由,根据用户权限动态加载
路由模块划分:
- sysRouter.js:系统管理相关路由
- erp.js:ERP模块路由
- amazon.js:亚马逊模块路由
- finance.js:财务模块路由
2.2.2 路由守卫
使用 beforeEach 导航守卫实现权限控制和动态路由加载:
router.beforeEach(async (to, from, next) => {
if (whitePath.includes(to.path)) {
// 白名单路由直接放行
next();
} else {
if (store.state.routerStore.router.length === 0) {
// 动态加载路由
await axios.get('/api/admin/api/v1/menus/route').then(res => {
store.dispatch("routerStore/setRouter", res.data.data);
addRoute(router, res.data.data);
});
}
next();
}
});
2.2.3 动态路由加载
通过 addRoute 函数实现动态路由的递归加载:
function addRoute(router, data) {
data.forEach(v => {
let item = {
path: v.path,
name: v.name,
component: modules[`../views/${v.component}.vue`],
meta: v.meta || { keepAlive: true }
};
// 过滤不需要缓存的页面
if (['/sys/notepad', '/fin/voucher/create'].includes(item.path)) {
item.meta.keepAlive = false;
}
router.addRoute('index', item);
// 递归加载子路由
if (v.children) {
addRoute(router, v.children);
}
});
}
2.3 Layout 结构
Layout 采用了经典的三栏布局结构,使用 Element Plus 的 el-container 组件实现。
2.3.1 布局组件结构
<el-container>
<el-aside> <!-- 左侧菜单 -->
<AsideMenu />
</el-aside>
<el-container>
<el-header> <!-- 顶部导航 -->
<HeaderTab />
<HeaderAvatar />
</el-header>
<el-main> <!-- 主内容区 -->
<router-view>
<!-- 页面内容 -->
</router-view>
</el-main>
</el-container>
</el-container>
2.3.2 布局组件说明
2.3.3 组件缓存机制
使用 Vue 的 keep-alive 组件实现页面缓存,提高用户体验:
<keep-alive ref="keepAlive" :exclude="excludes">
<component :is="wrap($route.query.title, Component)" v-if="$route.meta.keepAlive" :key="$route.query.title" />
</keep-alive>
<component :is="wrap($route.query.title, Component)" v-if="!$route.meta.keepAlive" :key="$route.query.title" />
动态缓存控制:
- 通过
meta.keepAlive控制页面是否需要缓存 - 使用
excludes数组动态移除不需要缓存的组件 - 提供
clearCache方法实现页面刷新
2.4 状态管理
采用 Vuex 4 实现状态管理,按功能模块划分为多个子模块。
2.4.1 Store 模块划分
- routerStore:路由相关状态管理
- permissionStore:权限相关状态管理
- jessionStore:会话相关状态管理
- dateStore:日期相关状态管理
- finance:财务模块状态管理
- dict:字典数据状态管理
2.4.2 核心状态管理
routerStore:
- 管理动态路由数据
- 提供路由设置和获取方法
permissionStore:
- 管理用户权限列表
- 提供权限判断方法
2.5 权限控制
系统实现了基于指令的权限控制机制,通过 v-hasPerm 和 v-hasPermi 指令控制元素的显示。
2.5.1 权限指令
// v-hasPerm 指令:判断用户是否拥有特定权限
export const hasPerm = {
install: (app) => {
app.directive('hasPerm', {
mounted(el, binding) {
const permissions = store.state.permissionStore.permission;
const value = binding.value;
const hasPermission = permissions.has(value);
if (!hasPermission) {
el.parentNode.removeChild(el);
}
}
});
}
};
// v-hasPermi 指令:判断用户是否拥有任一指定权限
export const hasPermi = {
install: (app) => {
app.directive('hasPermi', {
mounted(el, binding) {
const permissions = Array.from(store.state.permissionStore.permission);
const permissionFlag = binding.value;
const hasPermissions = permissions.some(permission => {
return "*:*:*" === permission || permissionFlag.includes(permission);
});
if (!hasPermissions) {
el.parentNode.removeChild(el);
}
}
});
}
};
3. 公共组件与工具
3.1 全局组件
系统提供了一系列可复用的全局组件:
3.1.1 GlobalTable 组件
基于 Element Plus Table 封装的全局表格组件,提供了丰富的功能和配置选项。
核心功能:
- 数据加载与分页
- 排序与筛选
- 选择与点击事件
- 行展开与树形结构
- 自定义列与表头
- 空数据提示
使用示例:
<GlobalTable
:table-data="tableData"
:loading="loading"
@row-click="handleRowClick"
@selection-change="handleSelectionChange"
>
<el-table-column prop="name" label="名称" />
<el-table-column prop="status" label="状态" />
</GlobalTable>
3.1.2 Pagination 组件
分页组件,与 GlobalTable 配合使用。
3.1.3 SvgIcon 组件
SVG 图标组件,支持动态加载和自定义样式。
3.1.4 DictTag 组件
字典标签组件,用于显示字典值对应的标签。
3.2 全局工具函数
系统提供了丰富的全局工具函数,挂载在 Vue 实例上:
- parseTime:日期时间格式化
- resetForm:表单重置
- addDateRange:日期范围处理
- handleTree:树形数据处理
- selectDictLabel:字典标签选择
- download:文件下载
3.3 自定义指令
- v-hasPerm:单个权限控制
- v-hasPermi:多个权限控制
- v-dataType:数据类型验证
4. 通信机制
4.1 组件通信
系统使用多种组件通信方式:
- Props/Emits:父子组件通信
- Provide/Inject:跨组件层级通信
- Event Bus:基于 mitt 的事件总线
- Vuex:全局状态共享
4.2 API 通信
使用 Axios 作为 HTTP 客户端,实现与后端 API 的通信。
API 请求流程:
- 前端组件发起请求
- API 服务层处理请求参数
- Axios 拦截器处理请求头和响应
- 后端处理请求并返回数据
- 前端接收响应并处理
5. 性能优化
5.1 组件缓存
使用 keep-alive 缓存常用页面组件,减少重复渲染。
5.2 路由懒加载
采用动态导入方式实现路由懒加载:
component: () => import("@/views/dashboard/index.vue")
5.3 图片优化
使用 SVG 图标代替 PNG/JPG 图标,减少网络请求。
5.4 代码分割
利用 Vite 的代码分割功能,按需加载模块。
6. 开发规范
6.1 目录结构
src/
├── api/ # API服务
├── assets/ # 静态资源
├── components/ # 公共组件
├── directive/ # 自定义指令
├── filters/ # 过滤器
├── layout/ # 布局组件
├── router/ # 路由配置
├── store/ # 状态管理
├── styles/ # 样式文件
├── utils/ # 工具函数
├── views/ # 页面视图
├── App.vue # 根组件
└── main.js # 入口文件
6.2 命名规范
- 组件名:PascalCase,如
GlobalTable - 文件名:kebab-case,如
global-table.vue - 变量名:camelCase
- 常量名:UPPER_SNAKE_CASE
6.3 代码风格
- 使用 Vue 3 Composition API
- 优先使用模板语法
- 合理使用 TypeScript 类型
- 保持代码简洁和可读性
7. 部署与维护
7.1 构建流程
# 安装依赖
npm install
# 开发环境
npm run dev
# 生产构建
npm run build
7.2 环境配置
- 开发环境:配置
.env.development - 测试环境:配置
.env.test - 生产环境:配置
.env.production
7.3 常见问题
- 路由加载失败:检查后端API返回的路由格式是否正确
- 权限控制不生效:检查用户权限列表是否正确获取
- 组件缓存问题:检查
meta.keepAlive配置是否正确
8. 总结
Wimoor UI3 是一个架构清晰、功能完善的企业级前端应用框架,采用了现代化的技术栈和设计理念。系统具有良好的可扩展性、可维护性和性能,能够满足企业不断发展的业务需求。
通过本架构说明文档,希望能帮助开发人员更好地理解系统架构和设计思想,提高开发效率和代码质量。
文档版本:1.0 更新日期:2023-07-01 编写人员:Wimoor UI3 开发团队