Vue3 后臺管理系統模板
gie倉庫地址
一個基于 Vue3 + TypeScript + Element Plus 的后臺管理系統模板,集成了動態路由和權限管理功能。
技術棧
- Vue 3.2
- TypeScript 4.5
- Vue Router 4
- Vuex 4
- Element Plus 2.9
- Axios
- Less
功能特性
- 🚀 基于 Vue3 最新技術棧開發
- 📦 使用 TypeScript 進行開發,提供更好的類型檢查和開發體驗
- 🔐 完整的權限管理解決方案,支持動態路由和按鈕級權限控制
- 🎨 使用 Element Plus 組件庫,提供美觀的 UI 界面
- 📱 響應式設計,支持多種設備訪問
- 🔧 支持 PWA,可離線訪問
- 📝 集成 ESLint + Prettier,統一代碼風格
項目結構
src/
├── assets/ # 靜態資源
├── components/ # 公共組件
├── hooks/ # Vue3 組合式 API 鉤子
├── network/ # 網絡請求相關
├── plugins/ # 插件
├── router/ # 路由配置
├── store/ # Vuex 狀態管理
├── utils/ # 工具函數
└── views/ # 頁面組件
安裝和使用
環境要求
- Node.js >= 14.0.0
- npm >= 6.0.0
安裝依賴
npm install
開發環境運行
npm run serve
生產環境構建
npm run build
代碼檢查
npm run lint
權限管理
本項目實現了完整的權限管理功能,包括動態路由和按鈕級權限控制。以下是詳細的實現說明:
1. 權限管理架構
權限管理主要包含以下幾個部分:
- 路由權限控制
- 菜單權限控制
- 按鈕級權限控制
- 數據權限控制
2. 實現細節
2.1 路由權限控制
-
路由守衛實現
- 在
router/index.ts
中實現全局路由守衛 - 檢查用戶是否登錄(通過 token)
- 動態添加路由配置
- 在
-
動態路由生成
- 用戶登錄后獲取權限菜單數據
- 通過
addDynamicRoutes
工具函數動態生成路由 - 支持路由懶加載,提高性能
-
路由配置示例
// 路由守衛實現
router.beforeEach((to, from, next) => {const token = localStorage.getItem('token');if (!token && to.meta.check) {next({ name: 'login' });return;}// 動態添加路由if (token && !layoutRoute.children.length) {const menus = JSON.parse(localStorage.getItem('menus') || '[]');addDynamicRoutes(router, menus);next({ ...to, replace: true });return;}next();
});
2.2 菜單權限控制
-
菜單數據結構
- 支持多級菜單
- 包含路徑、名稱、組件、元數據等信息
- 支持菜單圖標、權限標識等擴展屬性
-
菜單渲染
- 根據用戶權限動態生成菜單
- 支持菜單緩存,提高性能
- 支持菜單排序和分組
2.3 按鈕級權限控制
-
權限指令實現
- 通過自定義指令
v-permission
控制按鈕顯示 - 支持權限表達式,如:
v-permission="['add', 'edit']"
- 支持權限組合判斷
- 通過自定義指令
-
使用示例
<template><el-button v-permission="['add']">添加</el-button><el-button v-permission="['edit']">編輯</el-button><el-button v-permission="['delete']">刪除</el-button>
</template>
2.4 數據權限控制
-
數據過濾
- 根據用戶角色過濾數據
- 支持數據范圍控制
- 支持字段級權限控制
-
實現方式
- 在 API 請求中添加權限參數
- 后端根據權限參數過濾數據
- 前端處理權限數據展示
3. 權限管理流程
-
登錄流程
- 用戶輸入賬號密碼登錄
- 獲取用戶 token 和權限信息
- 存儲權限信息到本地存儲
-
權限驗證流程
- 路由跳轉時驗證權限
- 動態生成路由和菜單
- 控制按鈕和數據的訪問權限
-
權限更新流程
- 支持動態更新權限
- 支持權限緩存清理
- 支持權限實時生效
4. 安全考慮
-
前端安全
- 敏感信息加密存儲
- 路由權限雙重驗證
- XSS 防護
-
后端安全
- 接口權限驗證
- 數據權限過濾
- 防 SQL 注入
接口封裝
本項目采用統一的接口封裝方案,提供了完整的請求攔截、響應攔截和錯誤處理機制。以下是詳細的實現說明:
1. 接口封裝架構
接口封裝主要包含以下幾個部分:
- 請求實例配置
- 請求攔截器
- 響應攔截器
- 接口模塊化
- 統一錯誤處理
2. 實現細節
2.1 請求實例配置
const service = axios.create({baseURL: "/api/pc",timeout: 40000,headers: {"Access-Control-Allow-Origin": "*","Connection": "Keep-Alive","Content-Type": "application/json; charset = utf-8"}
})
2.2 請求攔截器
service.interceptors.request.use(config => {const token = localStorage.getItem("token");if (token) {config.headers["access-token"] = token}return config;}
)
2.3 響應攔截器
service.interceptors.response.use((res) => {const code = res.data.codeif (code == 100) {router.push({ name: "login" });} else if (code == 1) {ElMessage({message: res.data.msg,type: 'warning'});}return res}, (error) => {return Promise.reject(error);}
)
2.4 接口模塊化
- 目錄結構
src/network/
├── index.ts # 請求配置和攔截器
└── apis/ # 接口模塊├── home.ts # 首頁相關接口├── work.ts # 工作相關接口└── user.ts # 用戶相關接口
- 接口定義示例
// apis/home.ts
export default {// 獲取首頁數據getHomeData: (params: any) => ({url: '/home/data',method: 'get',params}),// 更新首頁數據updateHomeData: (data: any) => ({url: '/home/update',method: 'post',data})
}
- 接口調用示例
import getData from '@/network';// 獲取首頁數據
const getHomeData = async () => {try {const res = await getData('home/getHomeData', { page: 1 });return res.data;} catch (error) {console.error('獲取首頁數據失敗:', error);}
}
3. 接口封裝特點
-
統一配置
- 統一的 baseURL 配置
- 統一的超時時間設置
- 統一的請求頭配置
-
自動處理
- 自動添加 token
- 自動處理登錄過期
- 自動處理錯誤提示
-
模塊化管理
- 按功能模塊劃分接口
- 支持接口自動導入
- 支持接口命名空間
-
類型支持
- 完整的 TypeScript 類型支持
- 接口參數類型檢查
- 響應數據類型定義
4. 錯誤處理機制
-
請求錯誤處理
- 網絡錯誤處理
- 超時錯誤處理
- 請求取消處理
-
響應錯誤處理
- 狀態碼錯誤處理
- 業務錯誤處理
- 登錄過期處理
-
錯誤提示
- 統一的錯誤提示組件
- 可配置的錯誤提示方式
- 支持自定義錯誤處理
5. 使用建議
-
接口定義
- 使用 TypeScript 定義接口類型
- 添加詳細的接口注釋
- 遵循統一的命名規范
-
接口調用
- 使用 async/await 處理異步
- 添加適當的錯誤處理
- 注意請求參數的合法性
-
性能優化
- 合理使用請求緩存
- 避免重復請求
- 控制并發請求數量
貢獻指南
歡迎提交 Issue 和 Pull Request 來幫助改進項目。
權限說明
<!-- 路由格式 -->使用方式,登錄后后端返回數據格式,根據這個格式,把所有路徑路由配置放在這里,讀取的時候讓后臺判斷,返回那些路徑,與后端溝通好.<!-- 把路由配置放在這里 -->parentId: id;index: index;title:一級路由名稱icon:圖標 我用的是iconfont 的圖標 根據自己情況替換就行了;type: group;children: [ //子級路由index:index;title:二級路由名稱path:path;name:name;component:文件讀取路徑 讀取pages 文件 路徑// 看不明白的就把這里的路徑和pages 下的路徑對比一下就明白了menuType:menuType;meta: 路由原信息] ;"nav": [{"parentId": "1","index": "1","title": "首頁","icon": "icon-shouye","type": "group","children": [{"index": "1-1","title": "首頁","name": "home","path": "/home","component": "shouYe/index","menuType": 0,"meta": {"selectIndex": "1-1","check": true}}]},{"parentId": "2","index": "2","title": "設備管理","icon": "icon-shebei","type": "group","children": [{"index": "2-1","title": "設備列表","name": "shebei","path": "/shebei","component": "shebei/shebei","menuType": 0,"meta": {"selectIndex": "2-1","check": true}}]},{"parentId": "3","index": "3","title": "模塊管理","icon": "icon-mokuai","type": "group","children": [{"index": "3-1","title": "模塊列表","name": "mokuai","path": "/mokuai","component": "mokuai/Mokuai","menuType": 0,"meta": {"selectIndex": "3-1","check": true}}]},{"parentId": "4","index": "4","title": "標靶檢測","icon": "icon-mubiaobachang1","type": "group","children": [{"index": "4-1","title": "報警列表","name": "jingIndex","path": "/jingIndex","component": "biaoba/index","menuType": 0,"meta": {"selectIndex": "4-1","check": true}},{"index": "4-2","title": "標靶檢測","name": "biaoba","path": "/biaoba","component": "biaoba/biaoba","menuType": 0,"meta": {"selectIndex": "4-2","check": true}},{"index": "4-3","title": "標靶報警","name": "baojing","path": "/baojing","component": "biaoba/baojing","menuType": 0,"meta": {"selectIndex": "4-3","check": true}},{"index": "4-4","title": "報警等級","name": "dengji","path": "/dengji","component": "biaoba/dengji","menuType": 0,"meta": {"selectIndex": "4-4","check": true}}]}]
許可證
MIT