vueAdmin前端學習筆記
- 1.安裝VUE專案
- 第一步:vue-ui
- 第二步:創建
- 第三步:詳情
- 第四步:選擇手動
- 第五步:配置
- 第六步:點擊創建專案
- 第七步:啟動專案
- 第八步:vsCode啟動專案
- 2.安裝element-ui
- 3.洗掉不必要的頁面
- 3.1洗掉/viwes/Home.vue
- 3.2洗掉App.vue
- 4.安裝axios、qs、mockjs
- 4.1安裝axios
- 4.2安裝qs
- 4.3安裝mockjs
- 5.頁面路由
- 5.1洗掉頁面
- 5.2創建頁面
- 5.3頁面router/index.js
- 6.登錄頁面
- 6.1頁面展示
- 6.2在src/App.vue調整全域樣式
- 6.3src/views/Login.vue
- 6.4獲取驗證碼
- 6.4.1安裝mockjs
- 6.4.2創建mock.js
- 6.4.3注冊
- 6.4.4login頁面(重要)
- 6.4.5頁面展示
- 6.5登錄
- 6.5.1使用mockjs模擬登錄
- 6.5.2將token存到localStorage
- 6.5.3發送login請求
- 6.5.4測驗
- 7.定義全域axios攔截器
- 7.1在src/axios.js
- 7.2在main.js全域引入
- 7.3測驗
- 8.index頁面撰寫
- 8.1頁面
- 8.2效果圖
- 9.抽取代碼
- 9.1抽取后的導航欄
- 9.2抽取后的頭部
- 9.3抽取后的Home
- 9.4抽取后的index
- 9.5抽取的router.js
- 9.5抽取后的頁面
- 10.創建頁面
- 10.1在views新建system/User.vue
- 10.2在views新建system/Role.vue
- 10.3在views新建system/Menuvue
- 10.4在router.js添加
- 10.4測驗
- 11.導航欄系結頁面
- 12修改頭像和用戶名
- 13.個人中心
- 13.1在views/system/新建UserCenter.vue
- 13.2在router.js添加
- 13.3修改SideHeader.vue
- 13.4測驗頁面
- 14退出
- 15將導航改為動態獲取(可忽略)
- 15.1主要修改
- 15.2修改后SideMenu.vue的頁面
- 15.3mock.js
- 15.4修改后的導航欄
- 16.將導航欄改為動態獲取
- 16.1mock.js模擬后端回傳的資料
- 16.2將選單/權限存放到全域
- 16.3將menus.js注冊到src/store/index.js
- 16.4修改route/index.js方法
- 16.5修改/inc/SideMenu.vue
- 17動態標簽頁
- 17.1在/store/modules/menus.js添加
- 17.2在inc/新建Tabs.vue
- 17.3頁面使用
- 17.4修改inc/SideMenu.vue
- 18通過url地址跳轉
- 19退出清空資訊
- 20.菜單頁面
- 20.1是文字不居中
- 20.2mock.js模擬后端
- 20.3選單頁面
- 20.4頁面展示
- 21角色頁面
- 21.1mock.js模擬后端
- 21.2views/system/Role.vue頁面
- 22用戶頁面
- 22.1mock.js模擬后端
- 22.2views/system/User.vue頁面
- 23前端權限控制
- 23.1在src/main.js添加
- 23.2使用權限
- 23.2mock.js模擬回傳權限
- 23.3其他
- 24結束語
1.安裝VUE專案
第一步:vue-ui
# 安裝淘寶npm
npm install -g cnpm --registry=https://registry.npm.taobao.org
# vue-cli 安裝依賴包
cnpm install --g vue-cli
# 打開vue的可視化管理工具界面
vue ui

第二步:創建

第三步:詳情

第四步:選擇手動

第五步:配置

第六步:點擊創建專案

第七步:啟動專案

第八步:vsCode啟動專案
npm run serve
2.安裝element-ui
npm install element-ui --save
然后我們打開專案src目錄下的main.js,引入element-ui依賴,
import Element from 'element-ui'
import "element-ui/lib/theme-chalk/index.css"
Vue.use(Element)

這樣我們就可以愉快得在官網上選擇組件復制代碼到我們專案中直接使用啦,
3.洗掉不必要的頁面
3.1洗掉/viwes/Home.vue

3.2洗掉App.vue

4.安裝axios、qs、mockjs
-
axios:一個基于 promise 的 HTTP 庫,類ajax
-
qs:查詢引數序列化和決議庫
-
mockjs:為我們生成隨機資料的工具庫
4.1安裝axios
npm install axios --save
# 然后同樣我們在main.js中全域引入axios
import axios from 'axios'
Vue.prototype.$axios = axios //全域使用
4.2安裝qs
npm install qs --save
4.3安裝mockjs
npm install mockjs --save-dev
5.頁面路由
學習視頻
5.1洗掉頁面

5.2創建頁面
1.創建Login.vue
<template>
<div>登錄頁面</div>
</template>
<script>
export default {
name: "Login"
}
</script>
<style scoped>
</style>
1.創建Home.vue
<template>
<div>測驗主頁 </div>
</template>
<script>
export default {
name: 'Home',
}
</script>
<style>
</style>
5.3頁面router/index.js

import Home from '../views/Home.vue'
import Login from '../views/Login.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/login',
name: 'Login',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
// component: () => import(/* webpackChunkName: "about" */ '../views/Login.vue') 方式一
component: Login //方式二
}
]
6.登錄頁面
6.1頁面展示

6.2在src/App.vue調整全域樣式
我們先調整一下全域的樣式
將原頁面的style便簽洗掉,更換為一下的style便簽內容,下面是調整后的整個頁面
<template>
<div id="app">
<router-view/>
</div>
</template>
<style>
html, body, #app {
font-family: 'Helvetica Neue', 'Hiragino Sans GB', 'WenQuanYi Micro Hei', 'Microsoft Yahei', sans-serif;
height: 100%;
padding: 0;
margin: 0;
font-size: 15px;
}
</style>
6.3src/views/Login.vue
一下頁面是寫好后的頁面,還未發請求前
<template>
<el-row style="height: 100%">
<el-col :xl="6" :lg="7">
<!-- 標題 -->
<h2>歡迎來到VueAdmin管理界面</h2>
<!-- 使用 el-image引入圖片 -->
<el-image
:src="require('@/assets/微信圖片_20210919105336.jpg')"
style="height: 180px; width: 180px"
></el-image>
<p>公眾號:MarkerHup</p>
<p>掃描二維碼,回復</p>
</el-col>
<el-col :span="1">
<!-- 分割線 -->
<el-divider direction="vertical"></el-divider>
</el-col>
<el-col :xl="6" :lg="7">
<!--
:model="loginForm" 系結的表單
:rules="rules" 校驗規則
ref="loginForm" 注冊實體,可以通過 this.$refs[loginForm]獲取
-->
<el-form
:model="loginForm"
:rules="rules"
ref="loginForm"
label-width="80px"
class="demo-loginForm"
>
<el-form-item label="用戶名" prop="userName" style="width: 380px">
<el-input v-model="loginForm.userName"></el-input>
</el-form-item>
<el-form-item label="密碼" prop="passWord" style="width: 380px">
<el-input v-model="loginForm.passWord"></el-input>
</el-form-item>
<el-form-item label="驗證碼" prop="code" style="width: 380px">
<el-input
v-model="loginForm.code"
style="width: 170px; float: left"
></el-input>
<el-image src="" class="captchaImg"></el-image>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('loginForm')"
>登錄
</el-button>
<el-button @click="resetForm('loginForm')">重置</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
</template>
<script>
export default {
name: "Login",
data() {
return {
// 表單
loginForm: {
userName: "",
passWord: "",
code: "",
},
// 校驗
rules: {
userName: [
{required: true, message: "請輸入用戶名", trigger: "blur"},
{
min: 3,
max: 50,
message: "長度在 3 到 50 個字符",
trigger: "blur",
},
],
passWord: [
{required: true, message: "請輸入密碼", trigger: "change"},
],
code: [{required: true, message: "請輸入驗證碼", trigger: "change"}],
},
};
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert("submit!");
} else {
console.log("error submit!!");
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
},
},
};
</script>
<style scoped>
/**
* el-row 的設定
* background-color: #fafafa; 設定背景顏色
* height: 100%; 設定高度,覆寫所有的高度
* display: flex; 橫向居中
* align-items: center; 上下居中
* text-align: center; 文字居中
*/
.el-row {
background-color: #fafafa;
height: 100%;
display: flex;
align-items: center;
text-align: center;
justify-content: center;
}
/*.el-row {*/
/* height: 100%;*/
/* background-color: #fafafa; !*設定背景顏色*!*/
/* display: flex;*/
/* justify-content: center;*/
/* align-items: center;*/
/* text-align: center;*/
/*}*/
/* 分割線的高度 */
.el-divider {
height: 200px;
}
.captchaImg {
/*靠左邊*/
float: left;
/*驗證碼偏移8px*/
margin-left: 8px;
/*圓角*/
border-radius: 4px;
}
</style>
6.4獲取驗證碼
現在沒有后端,用mockjs模擬生成驗證碼
6.4.1安裝mockjs
npm install mockjs --save-dev
6.4.2創建mock.js
// 引入mockjsconst
const Mock = require('mockjs')
// 獲取 mock.Random 物件
// 參考:https://github.com/nuysoft/Mock/wiki/Mock.Random
const Random = Mock.Random
let Result = {
code: 200,
msg: '操作成功',
data: null
}
Mock.mock('/captcha','get',()=>{
Result.data = {
UUID: Random.string(32), // 獲取一個32位的隨機字串,
captchaImg: Random.dataImage('120x40','p7n5w') //生成驗證碼為11111的base64圖片編碼
}
return Result
})
6.4.3注冊
// 在src/main,js
require("./mock.js")
6.4.4login頁面(重要)
- 在methods添加請求驗證碼的方法
// 獲取驗證碼
getCaptCha() {
this.$axios.get('/captcha').then(res => {
debugger;
this.loginForm.UUID = res.data.data.token;
this.captchaImg = res.data.data.captchaImg;
})
}
- 新增created在進入頁面時加載
created() {
this.getCaptCha();
},
- 新增引數
1.在loginForm里添加UUID,
2.在data里面添加captchaImg,
3.驗證碼展示
<el-image :src="captchaImg" class="captchaImg"></el-image>
6.4.5頁面展示

6.5登錄
6.5.1使用mockjs模擬登錄
在mock.js添加
Mock.mock('/login','post',()=>{ return Result})
6.5.2將token存到localStorage

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
token: ''
},
mutations: {
SET_TOKEN: (state, token) => {
state.token = token;
localStorage.setItem("token", token)
}
},
actions: {},
modules: {}
})
6.5.3發送login請求

this.$axios.post('/login', this.loginForm).then(res => {
const jwt = res.headers['authorization'];
this.$store.commit("SET_TOKEN", jwt);
this.$router.push("/index");
})
6.5.4測驗

7.定義全域axios攔截器
7.1在src/axios.js
import axios from "axios";import router from "@/router";import Element from "element-ui"axios.defaults.daseURL = "http://localhost:8081"const request = axios.create({ timeout: 5000, //超時時間 headers: { 'Content-Type': 'application/json; charset=utf-8' // 回傳的JSON型別資料 }})// 請求的攔截,查看是否有tokenrequest.interceptors.request.use(config => { config.headers['Authorization'] = localStorage.getItem("token") // 請求頭帶上token return config})// 回傳的結果request.interceptors.response.use(response => { let res = response.data; console.log("response") console.log(res) if (res.code === 200) { return response } else { Element.Message.error(res.msg ? res.msg : '系統例外!', {duration: 3 * 1000}) return Promise.reject(response.data.msg) }}, error => { // 例外的情況 console.log(error) if (error.response.data) { error.message = error.response.data.msg } // 401沒有權限 if (error.response.status === 401) { router.push("/login") } Element.Message.error(error.message, {duration: 3 * 1000}) return Promise.reject(error)})export default request
7.2在main.js全域引入

7.3測驗
1.在mock.js中的login方法添加錯誤資訊

2.頁面測驗

8.index頁面撰寫
8.1頁面
在src/views/創建index.vue
<template>
<el-container>
<!-- 側邊欄-->
<el-aside width="200px">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<router-link to="/index">
<el-menu-item index="Index">
<template slot="title"><i class="el-icon-s-home"></i> <span slot="title">首頁</span></template>
</el-menu-item>
</router-link>
<el-submenu index="1">
<template slot="title"><i class="el-icon-s-operation"></i> <span>系統管理</span></template>
<el-menu-item index="1-1">
<template slot="title"><i class="el-icon-s-custom"></i> <span slot="title">用戶管理</span></template>
</el-menu-item>
<el-menu-item index="1-2">
<template slot="title"><i class="el-icon-rank"></i> <span slot="title">角色管理</span></template>
</el-menu-item>
<el-menu-item index="1-3">
<template slot="title"><i class="el-icon-menu"></i> <span slot="title">選單管理</span></template>
</el-menu-item>
</el-submenu>
<el-submenu index="2">
<template slot="title"><i class="el-icon-s-tools"></i> <span>系統工具</span></template>
<el-menu-item index="2-2">
<template slot="title"><i class="el-icon-s-order"></i> <span slot="title">數字字典</span></template>
</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<!-- 頭部資訊-->
<el-header>
<strong>VueAdmin后臺管理系統學習</strong>
<div class="header-avatar">
<!-- 頭像-->
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
<!-- 下拉框-->
<el-dropdown>
<span class="el-dropdown-link">
Admin<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>個人中心</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<!-- 最后面的文字跳轉-->
<el-link href="https://shimowendang.com/docs/pxwyJHgqcWjWkTKX/read" target="_blank">網站</el-link>
<el-link href="https://shimowendang.com/docs/pxwyJHgqcWjWkTKX/read" target="_blank">學習</el-link>
</div>
</el-header>
<!-- 主體資訊-->
<el-main>主體資訊</el-main>
</el-container>
</el-container>
</template>
<script>
export default {
name: 'Index',
}
</script>
<style>
.el-container {
padding: 0;
margin: 0;
height: 100%;
}
.el-header {
background-color: cadetblue;
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #D3DCE6;
color: #333;
line-height: 200px;
}
.el-main {
color: #333;
text-align: center;
line-height: 160px;
}
.header-avatar {
float: right;
width: 210px;
display: flex;
justify-content: space-around;
align-items: center;
}
.el-dropdown-link {
cursor: pointer;
color: #409EFF;
}
.el-menu-vertical-demo {
height: 100%;
}
</style>
8.2效果圖

9.抽取代碼
將index中的左側導航欄代碼和頭部代碼抽取為公共的
9.1抽取后的導航欄
在views新建inc/SideMenu
<template>
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<router-link to="/index">
<el-menu-item index="Index">
<template slot="title"><i class="el-icon-s-home"></i> <span slot="title">首頁</span></template>
</el-menu-item>
</router-link>
<el-submenu index="1">
<template slot="title"><i class="el-icon-s-operation"></i> <span>系統管理</span></template>
<el-menu-item index="1-1">
<template slot="title"><i class="el-icon-s-custom"></i> <span slot="title">用戶管理</span></template>
</el-menu-item>
<el-menu-item index="1-2">
<template slot="title"><i class="el-icon-rank"></i> <span slot="title">角色管理</span></template>
</el-menu-item>
<el-menu-item index="1-3">
<template slot="title"><i class="el-icon-menu"></i> <span slot="title">選單管理</span></template>
</el-menu-item>
</el-submenu>
<el-submenu index="2">
<template slot="title"><i class="el-icon-s-tools"></i> <span>系統工具</span></template>
<el-menu-item index="2-2">
<template slot="title"><i class="el-icon-s-order"></i> <span slot="title">數字字典</span></template>
</el-menu-item>
</el-submenu>
</el-menu>
</template>
<script>
export default {
name: 'SideMenu',
}
</script>
<style>
.el-menu-vertical-demo {
height: 100%;
}
</style>
9.2抽取后的頭部
<template>
<el-header>
<strong>VueAdmin后臺管理系統學習</strong>
<div class="header-avatar">
<!-- 頭像-->
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
<!-- 下拉框-->
<el-dropdown>
<span class="el-dropdown-link">
Admin<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>個人中心</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<!-- 最后面的文字跳轉-->
<el-link href="https://shimowendang.com/docs/pxwyJHgqcWjWkTKX/read" target="_blank">網站</el-link>
<el-link href="https://shimowendang.com/docs/pxwyJHgqcWjWkTKX/read" target="_blank">學習</el-link>
</div>
</el-header>
</template>
<script>
export default {
name: 'SideHeader',
}
</script>
<style>
.header-avatar {
float: right;
width: 210px;
display: flex;
justify-content: space-around;
align-items: center;
}
.el-dropdown-link {
cursor: pointer;
color: #409EFF;
}
.el-container {
padding: 0;
margin: 0;
height: 100%;
}
.el-header {
background-color: cadetblue;
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #D3DCE6;
color: #333;
line-height: 200px;
}
</style>
9.3抽取后的Home
<!--<template>-->
<!-- <div>測驗主頁 </div>-->
<!--</template>-->
<!--<script> -->
<!--export default {-->
<!-- name: 'Home',-->
<!-- -->
<!--}-->
<!--</script>-->
<!--<style>-->
<!--</style>-->
<template>
<el-container>
<!-- 側邊欄-->
<el-aside width="200px">
<SideMenu></SideMenu>
</el-aside>
<el-container>
<!-- 頭部資訊-->
<el-header>
<SideHeader></SideHeader>
</el-header>
<!-- 主體資訊-->
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</template>
<script>
import SideMenu from "@/views/inc/SideMenu";
import SideHeader from "@/views/inc/SideHeader";
export default {
name: 'Home',
components: {SideMenu, SideHeader},
}
</script>
<style>
.el-container {
padding: 0;
margin: 0;
height: 100%;
}
.el-header {
background-color: cadetblue;
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #D3DCE6;
color: #333;
line-height: 200px;
}
.el-main {
color: #333;
text-align: center;
line-height: 160px;
}
.header-avatar {
float: right;
width: 210px;
display: flex;
justify-content: space-around;
align-items: center;
}
.el-dropdown-link {
cursor: pointer;
color: #409EFF;
}
</style>
9.4抽取后的index
<template>
<div>測驗主頁 </div>
</template>
<script>
export default {
name: 'Index',
}
</script>
<style>
</style>
9.5抽取的router.js
將index路由放到children中

9.5抽取后的頁面

10.創建頁面
10.1在views新建system/User.vue
<template>
<div>用戶測驗</div>
</template>
<script>
export default {
name: 'User',
}
</script>
<style>
</style>
10.2在views新建system/Role.vue
<template>
<div>角色測驗</div>
</template>
<script>
export default {
name: 'Role',
}
</script>
<style>
</style>
10.3在views新建system/Menuvue
<template>
<div>選單測驗</div>
</template>
<script>
export default {
name: 'Menu',
}
</script>
<style>
</style>
10.4在router.js添加

以下是代碼router.js代碼
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Login from '../views/Login.vue'
import Index from '@/views/index'
import User from "@/views/system/User";
import Role from "@/views/system/Role";
import Menu from "@/views/system/Menu";
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home,
children: [
{
path: '/index',
name: 'Index',
component: Index
},
{
path: '/users',
name: 'SysUser',
component: User
},
{
path: '/roles',
name: 'SysRole',
component: Role
},
{
path: '/menus',
name: 'SysMenu',
component: Menu
},
]
},
{
path: '/login',
name: 'Login',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
// component: () => import(/* webpackChunkName: "about" */ '../views/Login.vue') 方式一
component: Login //方式二
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
10.4測驗
分別訪問:看頁面的變化
http://localhost:8080/menus
http://localhost:8080/roles
http://localhost:8080/users
11.導航欄系結頁面
完成后點擊頁面測驗看是否發生變化
<router-link to="/users">
</router-link>

12修改頭像和用戶名
在inc/SideHeader中修改頭像和用戶名從后端獲取

13.個人中心
13.1在views/system/新建UserCenter.vue
<template>
<div style="text-align: center;"><h2>你好!{{ userInfo.username }} 同學</h2>
<el-form :model="passForm" status-icon :rules="rules" ref="passForm" label-width="100px">
<el-form-item label="舊密碼" prop="currentPass">
<el-input type="password" v-model="passForm.currentPass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="新密碼" prop="password">
<el-input type="password" v-model="passForm.password" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="確認密碼" prop="checkPass">
<el-input type="password" v-model="passForm.checkPass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('passForm')">提交</el-button>
<el-button @click="resetForm('passForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: "Login", data() {
var validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('請再次輸入密碼'));
} else if (value !== this.passForm.password) {
callback(new Error('兩次輸入密碼不一致!'));
} else {
callback();
}
};
return {
userInfo: {},
passForm: {password: '111111', checkPass: '111111', currentPass: '111111'},
rules: {
password: [{required: true, message: '請輸入新密碼', trigger: 'blur'}, {
min: 6,
max: 12,
message: '長度在 6 到 12 個字符',
trigger: 'blur'
}],
checkPass: [{required: true, validator: validatePass, trigger: 'blur'}],
currentPass: [{required: true, message: '請輸入當前密碼', trigger: 'blur'},]
}
}
}, created() {
this.getUserInfo()
}, methods: {
getUserInfo() {
this.$axios.get("/sys/userInfo").then(res => {
this.userInfo = res.data.data;
})
}, submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
const _this = this
this.$axios.post('/sys/user/updataPass', this.passForm).then(res => {
_this.$alert(res.data.msg, '提示', {
confirmButtonText: '確定', callback: action => {
this.$refs[formName].resetFields();
}
});
})
} else {
console.log('error submit!!');
return false;
}
});
}, resetForm(formName) {
this.$refs[formName].resetFields();
}
}
}
</script>
<style scoped>
.el-form {
width: 420px;
margin: 50px auto;
}
</style>
13.2在router.js添加
{
path: '/userCenter',
name: 'UserCenter',
component: ()=>import("@/views/system/UserCenter")
},
13.3修改SideHeader.vue
洗掉所有頁面的 line-height: 160px;

13.4測驗頁面

14退出
- 在SideHeader.vue給退出添加點擊按鈕
<!-- 在el-dropdown-item標簽里, @click不可以用,要使用@click.native-->
<el-dropdown-item @click.native="logout">退出</el-dropdown-item>
- 在SideHeader.vue的methods撰寫點擊退出方法
logout(){
this.$axios.post("/logout").then(res => {
localStorage.clear();
sessionStorage.clear();
this.$store.commit("resetState");
this.$router.push("/login")
})
},
- 在store/index.js添加洗掉的方法

- 在mock.js模擬退出請求
Mock.mock('/logout','post',()=>{ return Result})
- 測驗
點擊頁面退出看效果
15將導航改為動態獲取(可忽略)
可以忽略,直接過16
先用mock.js模擬從服務器回傳資料
15.1主要修改

15.2修改后SideMenu.vue的頁面
<template>
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<router-link to="/index">
<el-menu-item index="Index">
<template slot="title"><i :class="el-icon-s-home"></i> <span slot="title">首頁</span></template>
</el-menu-item>
</router-link>
<el-submenu :index=menu.name
v-for="menu in menuList">
<template slot="title">
<i :class="menu.icon"></i>
<span>{{ menu.title }}</span>
</template>
<router-link :to="item.path" v-for="item in menu.children">
<el-menu-item :index="item.name">
<template slot="title">
<i :class="item.icon"></i>
<span slot="title">{{ item.title }}</span>
</template>
</el-menu-item>
</router-link>
</el-submenu>
</el-menu>
</template>
<script>
export default {
name: 'SideMenu',
data() {
return {
menuList: [],
}
},
created() {
this.getMenuList();
},
methods: {
getMenuList() {
this.$axios.get("/sys/menuList").then(res => {
this.menuList = res.data.data;
})
}
}
}
</script>
<style>
.el-menu-vertical-demo {
height: 100%;
}
.a {
text-decoration: none;
}
</style>
15.3mock.js
Mock.mock('/sys/menuList', 'get', () => {
Result.data = [
{
name: 'SysManga',
title: '系統管理',
icon: 'el-icon-s-operation',
path: '',
component: '',
children: [
{
name: 'SysUser',
title: '用戶管理',
icon: 'el-icon-s-custom',
path: '/users',
children: []
}]
}, {
name: 'SysTools',
title: '系統工具',
icon: 'el-icon-s-tools',
path: '',
children: [
{
name: 'SysDict',
title: '數字字典',
icon: 'el-icon-s-order',
path: '/dicts',
children: []
},]
}
]
return Result
})
15.4修改后的導航欄

16.將導航欄改為動態獲取
16.1mock.js模擬后端回傳的資料
修改15的mock.js后的方法
Mock.mock('/sys/menuList', 'get', () => {
// 導航選單
let nav = [
{
name: 'SysManga',
title: '系統管理',
component:'',
icon: 'el-icon-s-operation',
path: '',
component: '',
children: [
{
name: 'SysUser',
title: '用戶管理',
component:'system/User',
icon: 'el-icon-s-custom',
path: '/users',
children: []
}]
}, {
name: 'SysTools',
title: '系統工具',
component:'',
icon: 'el-icon-s-tools',
path: '',
children: [
{
name: 'SysDict',
title: '數字字典',
component:'',
icon: 'el-icon-s-order',
path: '/dicts',
children: []
},]
}
]
// 權限
let authoritys = []
Result.data = {
nav: nav,
authoritys: authoritys
}
return Result
})
16.2將選單/權限存放到全域
在/store/創建modules/menus.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default {
state: {
// 導航欄選單
menuList: [],
// 權限
permList: [],
// 每次重繪都獲取選單,消耗服務器,可以將他存到sessionStorage中
hasRoute: false
},
mutations: {
setMenuList(state, menuList) {
state.menuList = menuList
},
setPermList(state, permList) {
state.setPermList = permList;
},
changeRouteStatus(state, hasRoute) {
state.hasRoute = hasRoute;
sessionStorage.setItem("hasRoute", hasRoute)
},
},
actions: {},
modules: {}
}
16.3將menus.js注冊到src/store/index.js

16.4修改route/index.js方法
添加這個方法,注釋掉寫死的children的選單,動態獲取,下面有修改后的整個頁面
router.beforeEach(((to, from, next) => {
let hasRoute = store.state.menus.hasRoute
console.log("hasRoute", hasRoute)
// 當它沒有的時候獲取選單
if (!hasRoute) {
// 獲取選單的方法,并校驗token(token是之前存到localStorage中的)
axios.get("/sys/menuList", {
headers: {
Authorization: localStorage.getItem("token")
}
}).then(res => {
// 拿到menuList
store.commit("setMenuList", res.data.data.nav)
// 拿到用戶權限
store.commit("setPermList", res.data.data.authoritys)
// 動態系結路由(把拿到的menuList回圈)
let newRoutes = router.options.routes
res.data.data.nav.forEach(menu => {
if (menu.children) {
menu.children.forEach(e => {
// 轉換成路由
if (e.component) {
console.log("e.component", e.component)
let route = {
name: e.name,
path: e.path,
mate: {
icon: e.icon,
title: e.title
},
component: () => import("@/views/" + e.component + '.vue')
}
// 把轉換后的路由添加到路由管理器
if (route) {
newRoutes[0].children.push(route)
}
}
})
}
})
console.log("newRoutes", newRoutes)
router.addRoutes(newRoutes)
// 獲取到選單,將他改為true
hasRoute = true
store.commit("changeRouteStatus", hasRoute)
})
}
next()
}))
修改后的整個頁面
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Login from '../views/Login.vue'
import Index from '@/views/index'
import User from "@/views/system/User";
import Role from "@/views/system/Role";
import Menu from "@/views/system/Menu";
import axios from "axios";
import store from "@/store"
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home,
children: [
{
path: '/index',
name: 'Index',
component: Index
},
{
path: '/userCenter',
name: 'UserCenter',
component: () => import("@/views/system/UserCenter")
},
// {
// path: '/users',
// name: 'SysUser',
// component: User
// },
// {
// path: '/roles',
// name: 'SysRole',
// component: Role
// },
// {
// path: '/menus',
// name: 'SysMenu',
// component: Menu
// },
]
},
{
path: '/login',
name: 'Login',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
// component: () => import(/* webpackChunkName: "about" */ '../views/Login.vue') 方式一
component: Login //方式二
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
router.beforeEach(((to, from, next) => {
let hasRoute = store.state.menus.hasRoute
console.log("hasRoute", hasRoute)
// 當它沒有的時候獲取選單
if (!hasRoute) {
// 獲取選單的方法,并校驗token(token是之前存到localStorage中的)
axios.get("/sys/menuList", {
headers: {
Authorization: localStorage.getItem("token")
}
}).then(res => {
// 拿到menuList
store.commit("setMenuList", res.data.data.nav)
// 拿到用戶權限
store.commit("setPermList", res.data.data.authoritys)
// 動態系結路由(把拿到的menuList回圈)
let newRoutes = router.options.routes
res.data.data.nav.forEach(menu => {
if (menu.children) {
menu.children.forEach(e => {
// 轉換成路由
if (e.component) {
console.log("e.component", e.component)
let route = {
name: e.name,
path: e.path,
mate: {
icon: e.icon,
title: e.title
},
component: () => import("@/views/" + e.component + '.vue')
}
// 把轉換后的路由添加到路由管理器
if (route) {
newRoutes[0].children.push(route)
}
}
})
}
})
console.log("newRoutes", newRoutes)
router.addRoutes(newRoutes)
hasRoute = true
console.log("hasRoute2", hasRoute)
store.commit("changeRouteStatus", hasRoute)
})
}
next()
}))
export default router
16.5修改/inc/SideMenu.vue

修改后的整個頁面
<template>
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<router-link to="/index">
<el-menu-item index="Index">
<template slot="title">
<i :class="el-icon-s-home"></i>
<span slot="title">首頁</span></template>
</el-menu-item>
</router-link>
<el-submenu :index=menu.name
v-for="menu in menuList">
<template slot="title">
<i :class="menu.icon"></i>
<span>{{ menu.title }}</span>
</template>
<router-link :to="item.path" v-for="item in menu.children">
<el-menu-item :index="item.name">
<template slot="title">
<i :class="item.icon"></i>
<span slot="title">{{ item.title }}</span>
</template>
</el-menu-item>
</router-link>
</el-submenu>
</el-menu>
</template>
<script>
export default {
name: 'SideMenu',
data() {
return {
// menuList: [],
}
},
computed: {
// this.getMenuList();
menuList: {
get() {
//return this.$store.state+ menus.js的模塊名+menuList
return this.$store.state.menus.menuList
}
}
},
methods: {
// getMenuList() {
// this.$axios.get("/sys/menuList").then(res => {
// this.menuList = res.data.data.nav;
// })
// }
}
}
</script>
<style>
.el-menu-vertical-demo {
height: 100%;
}
.a {
text-decoration: none;
}
</style>
17動態標簽頁
17.1在/store/modules/menus.js添加

17.2在inc/新建Tabs.vue
<template>
<el-tabs v-model="editableTabsValue" type="card" closable @tab-remove="removeTab" @tab-click="clickTab">
<el-tab-pane
v-for="(item, index) in editableTabs"
:key="item.name"
:label="item.title"
:name="item.name"
>
</el-tab-pane>
</el-tabs>
</template>
<script>
export default {
name: 'Tabs',
data() {
return {
// editableTabsValue: this.$store.state.menus.editableTabsValue,
// editableTabs: this.$store.state.menus.editableTabs,
}
},
// tab標簽放到computed里面監聽
computed: {
editableTabsValue: {
// getter方法
get() {
return this.$store.state.menus.editableTabsValue
},
// setter方法
set(val) {
this.$store.state.menus.editableTabsValue = val
}
},
editableTabs: {
// getter方法
get() {
return this.$store.state.menus.editableTabs
},
// setter方法
set(val) {
this.$store.state.menus.editableTabs = val
}
}
},
methods: {
// 點擊tab標簽切換頁面資料
clickTab(target) {
this.$router.push({name: target.name})
},
removeTab(targetName) {
let tabs = this.editableTabs;
let activeName = this.editableTabsValue;
// 首頁不能洗掉
if (activeName==='Index'){
return
}
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
let nextTab = tabs[index + 1] || tabs[index - 1];
if (nextTab) {
activeName = nextTab.name;
}
}
});
}
this.editableTabsValue = activeName;
this.editableTabs = tabs.filter(tab => tab.name !== targetName);
// 洗掉標簽,就切換標簽
this.$router.push({name: activeName})
}
}
}
</script>
<style>
</style>
17.3頁面使用
在視圖上面添加Tabs組件

17.4修改inc/SideMenu.vue
添加selectMenu點擊事件添加tab標簽
:default-active是標簽點擊是相應的選單高亮
<template>
<!--點擊tab時選單高亮 :default-active=this.$store.state.menus.editableTabsValue-->
<el-menu
:default-active=this.$store.state.menus.editableTabsValue
class="el-menu-vertical-demo"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<router-link to="/index">
<el-menu-item index="Index">
<template slot="title">
<i class="el-icon-s-home"></i>
<span slot="title">首頁</span></template>
</el-menu-item>
</router-link>
<el-submenu :index=menu.name
v-for="menu in menuList">
<template slot="title">
<i :class="menu.icon"></i>
<span>{{ menu.title }}</span>
</template>
<router-link :to="item.path" v-for="item in menu.children">
<el-menu-item :index="item.name" @click="selectMenu(item)">
<template slot="title">
<i :class="item.icon"></i>
<span slot="title">{{ item.title }}</span>
</template>
</el-menu-item>
</router-link>
</el-submenu>
</el-menu>
</template>
<script>
export default {
name: 'SideMenu',
data() {
return {
// menuList: [],
}
},
computed: {
// this.getMenuList();
menuList: {
get() {
//return this.$store.state+ menus.js的模塊名+menuList
return this.$store.state.menus.menuList
}
}
},
methods: {
// getMenuList() {
// this.$axios.get("/sys/menuList").then(res => {
// this.menuList = res.data.data.nav;
// })
// }
selectMenu(item){
this.$store.commit("addTab",item)
}
},
}
</script>
<style>
.el-menu-vertical-demo {
height: 100%;
}
.a {
text-decoration: none;
}
</style>
18通過url地址跳轉
在src/App.vue添加方法
http://localhost:8080/users跳轉不過去,添加以下代碼
<script>
export default {
name: "App",
watch: {
$route(to, from) {
debugger;
console.log("to",to)
if (to.path != "/login") {
let obj = {
name: to.name,
title: to.name
}
this.$store.commit("addTab", obj)
}
}
}
}
</script>
19退出清空資訊
在src/store/modules/menus.js的mutations方法里添加,因為退出已經呼叫過resetState這個,直接添加即可
resetState: (state) => {
// 導航欄選單
state.menuList = [],
// 權限
state.permList = [],
// 每次重繪都獲取選單,消耗服務器,可以將他存到sessionStorage中
state.hasRoute = false,
// tab標簽默認為首頁
state.editableTabsValue = 'Index',
state.editableTabs = [{
title: '首頁',
name: 'Index',
}]
},
20.菜單頁面
20.1是文字不居中
將.el-main的text-align: center;刪除
.el-main {
color: #333;
/*text-align: center;*/
/*line-height: 160px;*/
padding: 0;
}
20.2mock.js模擬后端
選單管理
// 獲取選單管理串列
Mock.mock('/sys/menu/list', 'get', () => {
let menus = [
{
"id": 1,
"created": "2021-01-15T18:58:18",
"updated": "2021-01-15T18:58:20",
"statu": 1,
"parentId": 0,
"name": "系統管理",
"path": "",
"perms": "sys:manage",
"component": "",
"type": 0,
"icon": "el-icon-eleme",
"ordernum": 1,
"children": [
{
"id": 2,
"created": "2021-01-15T19:03:45",
"updated": "2021-01-15T19:03:48",
"statu": 1,
"parentId": 1,
"name": "用戶管理",
"path": "/sys/users",
"perms": "sys:user:list",
"component": "sys/User",
"type": 1,
"icon": "el-icon-s-custom",
"ordernum": 1,
"children": [
{
"id": 9,
"created": "2021-01-17T21:48:32",
"updated": null,
"statu": 1,
"parentId": 2,
"name": "添加用戶",
"path": null,
"perms": "sys:user:save",
"component": null,
"type": 2,
"icon": null,
"ordernum": 1,
"children": []
},
{
"id": 10,
"created": "2021-01-17T21:49:03",
"updated": "2021-01-17T21:53:04",
"statu": 1,
"parentId": 2,
"name": "修改用戶",
"path": null,
"perms": "sys:user:update",
"component": null,
"type": 2,
"icon": null,
"ordernum": 2,
"children": []
},
{
"id": 11,
"created": "2021-01-17T21:49:21",
"updated": null,
"statu": 1,
"parentId": 2,
"name": "洗掉用戶",
"path": null,
"perms": "sys:user:delete",
"component": null,
"type": 2,
"icon": null,
"ordernum": 3,
"children": []
},
{
"id": 12,
"created": "2021-01-17T21:49:58",
"updated": null,
"statu": 1,
"parentId": 2,
"name": "分配角色",
"path": null,
"perms": "sys:user:role",
"component": null,
"type": 2,
"icon": null,
"ordernum": 4,
"children": []
},
{
"id": 13,
"created": "2021-01-17T21:50:36",
"updated": null,
"statu": 1,
"parentId": 2,
"name": "重置密碼",
"path": null,
"perms": "sys:user:repass",
"component": null,
"type": 2,
"icon": null,
"ordernum": 5,
"children": []
}
]
},
{
"id": 3,
"created": "2021-01-15T19:03:45",
"updated": "2021-01-15T19:03:48",
"statu": 1,
"parentId": 1,
"name": "角色管理",
"path": "/sys/roles",
"perms": "sys:role:list",
"component": "sys/Role",
"type": 1,
"icon": "el-icon-rank",
"ordernum": 2,
"children": []
},
]
},
{
"id": 5,
"created": "2021-01-15T19:06:11",
"updated": null,
"statu": 1,
"parentId": 0,
"name": "系統工具",
"path": "",
"perms": "sys:tools",
"component": null,
"type": 0,
"icon": "el-icon-s-tools",
"ordernum": 2,
"children": [
{
"id": 6,
"created": "2021-01-15T19:07:18",
"updated": "2021-01-18T16:32:13",
"statu": 1,
"parentId": 5,
"name": "數字字典",
"path": "/sys/dicts",
"perms": "sys:dict:list",
"component": "sys/Dict",
"type": 1,
"icon": "el-icon-s-order",
"ordernum": 1,
"children": []
}
]
}
]
Result.data = menus
return Result
})
// 根據id獲取
Mock.mock(RegExp('/sys/menu/info/*'), 'get', () => {
Result.data = {
"id": 3,
"statu": 1,
"parentId": 1,
"name": "角色管理",
"path": "/sys/roles",
"perms": "sys:role:list",
"component": "sys/Role",
"type": 1,
"icon": "el-icon-rank",
"orderNum": 2,
"children": []
}
return Result
})
// 新增修改選單
Mock.mock(RegExp('/sys/menu/*'), 'post', () => {
return Result
})
// 查出選單
Mock.mock(RegExp('/sys/menu/*'), 'delete', () => {
return Result
})
20.3選單頁面
<template>
<div>
<!-- 新增表單-->
<el-form :inline="true">
<el-form-item>
<el-button type="primary" @click="onSubmit">新增</el-button>
</el-form-item>
</el-form>
<!-- Table表格-->
<el-table
:data="tableData"
style="width: 100%;margin-bottom: 20px;"
row-key="id"
border
stripe
default-expand-all
:tree-props="{children: 'children', hasChildren: 'hasChildren'}">
<el-table-column
prop="name"
label="名稱"
sortable
width="180">
</el-table-column>
<el-table-column prop="perms" label="權限編碼" width="180"></el-table-column>
<el-table-column prop="icon" label="圖示">
<template slot-scope="scope">
<i :class="scope.row.icon"></i>
</template>
</el-table-column>
<el-table-column prop="type" label="型別" width="120">
<template slot-scope="scope">
<el-tag v-if="scope.row.type === 0" size="small">目錄</el-tag>
<el-tag v-else-if="scope.row.type === 1" size="small" type="success">選單</el-tag>
<el-tag v-else-if="scope.row.type === 2" size="small" type="info">按鈕</el-tag>
</template>
</el-table-column>
<el-table-column prop="path" label="選單URL"></el-table-column>
<el-table-column prop="component" label="選單組件"></el-table-column>
<el-table-column prop="orderNum" label="排序號"></el-table-column>
<el-table-column prop="statu" label="狀態" width="120">
<template slot-scope="scope">
<el-tag v-if="scope.row.statu === 0" size="small" type="danger">禁用</el-tag>
<el-tag v-else-if="scope.row.statu === 1" size="small" type="success">正常</el-tag>
</template>
</el-table-column>
<!-- fixed="right"固定操作欄-->
<el-table-column prop="icon" label="操作" width="120" fixed="right">
<template slot-scope="scope">
<el-button type="text" @click="changeUpdate(scope.row)">編輯</el-button>
<el-divider direction="vertical"></el-divider>
<!-- <el-button type="text">洗掉</el-button>-->
<!-- 洗掉-->
<template>
<el-popconfirm title="這是一段內容確定洗掉嗎?" @confirm="delHandle(scope.row)">
<el-button type="text" slot="reference">洗掉</el-button>
</el-popconfirm>
</template>
</template>
</el-table-column>
</el-table>
<!-- 新增或修改的彈窗-->
<el-dialog
title="新增"
:visible.sync="dialogVisible"
width="500px"
:before-close="handleClose">
<!-- 彈框里的表單-->
<el-form :model="editForm" :rules="rules" ref="editForm" label-width="100px" class="demo-editForm">
<!-- 三級分類-->
<el-form-item label="上級選單" prop="parentId">
<el-select v-model="editForm.parentId" placeholder="請選擇上級選單">
<!-- 一級目錄-->
<template v-for="(item,index) in tableData">
<el-option :label=item.name :value=item.id></el-option>
<!-- 二級目錄-->
<template v-for="child in item.children">
<el-option :label=child.name :value=child.id>
<span>{{ ' - ' + child.name }}</span>
</el-option>
</template>
</template>
</el-select>
</el-form-item>
<el-form-item label="選單名稱" prop="name" label-width="100px">
<el-input v-model="editForm.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="權限編碼" prop="perms" label-width="100px">
<el-input v-model="editForm.perms" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="圖示" prop="icon" label-width="100px">
<el-input v-model="editForm.icon" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="選單URL" prop="path" label-width="100px">
<el-input v-model="editForm.path" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="選單組件" prop="component" label-width="100px">
<el-input v-model="editForm.component" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="型別" prop="type" label-width="100px">
<el-radio-group v-model="editForm.type">
<el-radio :label=0>目錄</el-radio>
<el-radio :label=1>選單</el-radio>
<el-radio :label=2>按鈕</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="狀態" prop="statu" label-width="100px">
<el-radio-group v-model="editForm.statu">
<el-radio :label=0>禁用</el-radio>
<el-radio :label=1>正常</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="排序號" prop="orderNum" label-width="100px">
<el-input-number v-model="editForm.orderNum" :min="1" label="排序號">1</el-input-number>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="resetForm('editForm')">取 消</el-button>
<el-button type="primary" @click="submitEditForm('editForm')">確 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'Role',
data() {
return {
// 彈框
dialogVisible: false,
// 新增資料
editForm: {},
// form表單
tableData: [],
// 表單校驗
rules: {
parentId: [{required: true, message: '請選擇上級選單', trigger: 'blur'}],
name: [{required: true, message: '請輸入名稱', trigger: 'blur'}],
perms: [{required: true, message: '請輸入權限編碼', trigger: 'blur'}],
type: [{required: true, message: '請選擇狀態', trigger: 'blur'}],
orderNum: [{required: true, message: '請填入排序號', trigger: 'blur'}],
statu: [{required: true, message: '請選擇狀態', trigger: 'blur'}]
},
}
},
created() {
this.getMenuTree()
},
methods: {
// 獲取串列
getMenuTree() {
this.$axios.get("/sys/menu/list").then(res => {
this.tableData = res.data.data
})
},
// 點擊新增
onSubmit() {
// 點擊新增彈窗
this.dialogVisible = true
},
// X 關閉
handleClose(done) {
this.editForm = {}
this.dialogVisible = false
},
// 清空表單的方法
resetForm(formName) {
debugger;
this.$refs[formName].resetFields();
this.editForm = {}
this.dialogVisible = false
},
// 新增或修改方法
submitEditForm(editForm) {
this.$refs["editForm"].validate((valid) => {
if (valid) {
// 如果id不為null,修改
if (this.editForm.id != null) {
debugger
this.$axios.post("/sys/menu/update", editForm).then(res => {
// 保存成功彈框訊息提醒
this.$message({
message: '修改成功',
type: 'success',
// onClose是保存成功后關閉后查詢串列
onClose: () => {
this.getMenuTree()
}
});
this.editForm = {}
this.dialogVisible = false;
})
} else { // 否則新增
debugger
this.$axios.post("/sys/menu/save", editForm).then(res => {
// 保存成功彈框訊息提醒
this.$message({
message: '保存成功',
type: 'success',
// onClose是保存成功后關閉后查詢串列
onClose: () => {
this.getMenuTree()
}
});
this.editForm = {}
this.dialogVisible = false;
})
}
}
});
},
// 點擊編輯查詢回顯
changeUpdate(row) {
let id = row.id;
this.$axios.get("/sys/menu/info/" + id).then(res => {
this.editForm = res.data.data;
// 打開視窗
this.dialogVisible = true;
})
},
// 洗掉方法
delHandle(row) {
let id = row.id;
this.$axios.delete("/sys/menu/delete/" + id).then(res => {
// 洗掉成功彈框訊息提醒
this.$message({
message: '洗掉成功',
type: 'success',
// onClose是保存成功后關閉后查詢串列
onClose: () => {
this.getMenuTree()
}
});
})
},
}
}
</script>
<style>
</style>
20.4頁面展示

21角色頁面
21.1mock.js模擬后端
角色管理
// 角色串列
Mock.mock(RegExp('/sys/role/list*'), 'get', () => {
Result.data = {
"records": [
{
"id": 3,
"created": "2021-01-04T10:09:14",
"updated": "2021-01-30T08:19:52",
"statu": 1,
"name": "普通用戶",
"code": "normal",
"remark": "只有基本查看功能",
"menuIds": []
},
{
"id": 6,
"created": "2021-01-16T13:29:03",
"updated": "2021-01-17T15:50:45",
"statu": 1,
"name": "超級管理員",
"code": "admin",
"remark": "系統默認最高權限,不可以編輯和任意修改",
"menuIds": []
}
],
"total": 2,
"size": 10,
"current": 1,
"orders": [],
"optimizeCountSql": true,
"hitCount": false,
"countId": null,
"maxLimit": null,
"searchCount": true,
"pages": 1
}
return Result
})
// 根據id獲取角色資訊
Mock.mock(RegExp('/sys/role/info/*'), 'get', () => {
Result.data = {
"id": 6,
"created": "2021-01-16T13:29:03",
"updated": "2021-01-17T15:50:45",
"statu": 1,
"name": "超級管理員",
"code": "admin",
"remark": "系統默認最高權限,不可以編輯和任意修改",
"menuIds": [1,3]
}
return Result
})
// 保存或修改角色
Mock.mock(RegExp('/sys/role/*'), 'post', () => {
return Result
})
// 洗掉角色
Mock.mock(RegExp('/sys/role/delete/*'), 'delete', () => {
return Result
})
21.2views/system/Role.vue頁面
<template>
<div>
<!-- 頂部搜索新增洗掉按鈕 start-->
<el-form :inline="true" :model="searchForm" class="demo-form-inline">
<el-form-item label="名稱">
<el-input v-model="searchForm.name"
placeholder="角色名稱"
clearable></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getRoleList()">查詢</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">新增</el-button>
</el-form-item>
<el-form-item>
<el-popconfirm title="這是一段內容確定批量洗掉嗎?" @confirm="delByIds">
<el-button type="danger" slot="reference" :disabled="delStatus">批量洗掉</el-button>
</el-popconfirm>
</el-form-item>
</el-form>
<!-- 頂部搜索新增洗掉按鈕 end-->
<!-- 資料table start -->
<el-table
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
border
stripe
style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="name" label="名稱" width="120"></el-table-column>
<el-table-column prop="code" label="唯一編碼" width="120"></el-table-column>
<el-table-column prop="remark" label="描述"></el-table-column>
<el-table-column prop="statu" label="狀態" width="120">
<template slot-scope="scope">
<el-tag v-if="scope.row.statu === 0" size="small" type="danger">禁用</el-tag>
<el-tag v-else-if="scope.row.statu === 1" size="small" type="success">正常</el-tag>
</template>
</el-table-column>
<!-- fixed="right"固定操作欄-->
<el-table-column prop="icon" label="操作" width="200" fixed="right">
<template slot-scope="scope">
<el-button type="text" @click="perHandle(scope.row)">分配權限</el-button>
<el-divider direction="vertical"></el-divider>
<el-button type="text" @click="changeUpdate(scope.row)">編輯</el-button>
<el-divider direction="vertical"></el-divider>
<!-- <el-button type="text">洗掉</el-button>-->
<!-- 洗掉-->
<template>
<el-popconfirm title="這是一段內容確定洗掉嗎?" @confirm="delHandle(scope.row)">
<el-button type="text" slot="reference">洗掉</el-button>
</el-popconfirm>
</template>
</template>
</el-table-column>
</el-table>
<!-- 資料table end -->
<!-- 分頁功能 start
:current-page="current" 當前頁
:page-size="size" 每頁有幾條
:total="total" 總條數
-->
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
layout="total, sizes, prev, pager, next, jumper"
:page-sizes="[10, 20, 50, 100]"
:current-page="current"
:page-size="size"
:total="total">
</el-pagination>
<!-- 分頁功能 end-->
<!-- 新增或修改的彈窗 start-->
<el-dialog
title="新增"
:visible.sync="dialogVisible"
width="500px"
:before-close="handleClose">
<!-- 彈框里的表單-->
<el-form :model="editForm" :rules="rules" ref="editForm" label-width="100px" class="demo-editForm">
<el-form-item label="角色名稱" prop="name" label-width="100px">
<el-input v-model="editForm.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="唯一編碼" prop="code" label-width="100px">
<el-input v-model="editForm.code" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="描述" prop="remark" label-width="100px">
<el-input v-model="editForm.remark" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="狀態" prop="statu" label-width="100px">
<el-radio-group v-model="editForm.statu">
<el-radio :label=0>禁用</el-radio>
<el-radio :label=1>正常</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="resetForm('editForm')">取 消</el-button
<el-button type="primary" @click="submitEditForm('editForm')">確 定</el-button>
</div>
</el-dialog>
<!-- 新增或修改的彈窗 end-->
<!-- 分配權限 start-->
<el-dialog
title="分配權限"
:visible.sync="dialogPrem"
width="500px"
>
<!-- 分配權限樹
defaultProps 分配權限指定label和children
:default-expand-all=true 屬性全部展開
check-strictly="true" 子父節點不再強制關聯
-->
<el-tree
:data="premData"
show-checkbox
node-key="id"
ref="premTree"
:check-strictly="true"
:default-expand-all=true
:props="defaultProps">
</el-tree>
<div slot="footer" class="dialog-footer">
<el-button @click="handleClose">取 消</el-button>
<el-button type="primary" @click="submitPremForm('permForm')">分配權限</el-button>
</div>
</el-dialog>
<!-- 分配權限 end-->
</div>
</template>
<script>
export default {
name: 'Role',
data() {
return {
// 分配權限彈框
dialogPrem: false,
// 分配權限資料來源
premData: [],
// 分配權限指定label和children
defaultProps: {
children: 'children',
label: 'name'
},
// 搜索引數
params: {},
// 新增或修改提交的資料
editForm: {},
// 新增或修改彈框
dialogVisible: false,
// 分頁引數(默認為第一頁,每頁10條,總條數0)
current: 1,
size: 10,
total: 0,
// 搜索條件
searchForm: {},
// 頂部洗掉
delStatus: true,
// 多選框
multipleSelection: [],
// 洗掉時的ids
ids: [],
// 串列資料
tableData: [],
// 表單校驗
rules: {
name: [{required: true, message: '請輸入角色名稱', trigger: 'blur'}],
code: [{required: true, message: '請輸入唯一編碼', trigger: 'blur'}],
statu: [{required: true, message: '請選擇狀態', trigger: 'blur'}]
},
}
},
created() {
this.getRoleList()
},
methods: {
toggleSelection(rows) {
if (rows) {
rows.forEach(row => {
this.$refs.multipleTable.toggleRowSelection(row);
});
} else {
this.$refs.multipleTable.clearSelection();
}
},
// 分頁方法
handleSizeChange(val) {
console.log(`每頁 ${val} 條`);
this.size = val;
this.getRoleList();
},
// 分頁方法
handleCurrentChange(val) {
console.log(`當前頁: ${val}`);
this.current = val;
this.getRoleList();
},
// 點擊新增
onSubmit() {
// 點擊新增彈窗
this.dialogVisible = true
},
// X 關閉
handleClose(done) {
this.editForm = {}
this.dialogVisible = false
// 分配權限彈框
this.dialogPrem = false,
// 分配權限資料來源
this.premData = []
},
// 清空表單的方法
resetForm(formName) {
debugger;
this.$refs[formName].resetFields();
this.editForm = {}
this.dialogVisible = false
},
// 查詢串列
getRoleList() {
// 搜索的引數
this.params = {
name: this.searchForm.name,
current: this.current,
size: this.size
},
// 發起請求
this.$axios.get("/sys/role/list", this.params).then(res => {
this.tableData = res.data.data.records;
this.size = res.data.data.size;
this.current = res.data.data.current;
this.total = res.data.data.total;
})
},
// 新增或修改方法
submitEditForm(editForm) {
this.$refs["editForm"].validate((valid) => {
if (valid) {
// 如果id不為null,修改
debugger
this.$axios.post("/sys/role/" + (this.editForm.id ? 'update' : 'save'), editForm).then(res => {
// 保存成功彈框訊息提醒
this.$message({
message: '操作成功',
type: 'success',
// onClose是保存成功后關閉后查詢串列
onClose: () => {
this.getRoleList()
}
});
this.editForm = {}
this.dialogVisible = false;
})
}
});
},
// 編輯回顯資料
changeUpdate(row) {
this.$axios.get("/sys/role/info/" + row.id).then(res => {
this.editForm = res.data.data
this.dialogVisible = true
})
},
// 單個洗掉
delHandle(row) {
let id = row.id;
this.$axios.delete("/sys/role/delete/" + id).then(res => {
// 洗掉成功彈框訊息提醒
this.$message({
message: '洗掉成功',
type: 'success',
// onClose是保存成功后關閉后查詢串列
onClose: () => {
this.getMenuTree()
}
});
})
},
// 批量洗掉(選擇多選框激活批量洗掉)
handleSelectionChange(val) {
console.log("多選框", val)
this.multipleSelection = val;
// 來判斷是否激活批量洗掉
this.delStatus = val.length == 0
},
// 批量洗掉
delByIds() {
this.multipleSelection.forEach(row => {
this.ids.push(row.id)
})
console.log(this.ids)
this.$axios.delete("/sys/role/delete/" + this.ids).then(res => {
// 洗掉成功彈框訊息提醒
this.$message({
message: '批量洗掉成功',
type: 'success',
// onClose是保存成功后關閉后查詢串列
onClose: () => {
this.getMenuTree()
}
});
})
},
// 點擊分配權限
perHandle(row) {
// 查詢所有的選單資料
this.$axios.get("/sys/menu/list").then(res => {
this.premData = res.data.data;
console.log(this.premData)
})
// 查詢已經存在的
this.$axios.get("/sys/role/info/" + row.id).then(res => {
// 通過這個賦值,menuIds里是已選擇的id集合
this.$refs.premTree.setCheckedKeys(res.data.data.menuIds);
this.permForm = res.data.data;
})
// 彈窗打開
this.dialogPrem = true
},
// 分配權限提交
submitPremForm() {
// 通過key已選擇的id
let menus = this.$refs.premTree.getCheckedKeys();
console.log(menus);
this.$axios.post("/sys/role/perm" + this.permForm.id, menus).then(res => {
// 洗掉成功彈框訊息提醒
this.$message({
message: '分配權限成功',
type: 'success',
// onClose是保存成功后關閉后查詢串列
onClose: () => {
this.getRoleList()
}
});
this.dialogPrem = false;
})
},
}
}
</script>
<style>
/*分頁樣式,向右便宜,上下有10個邊框*/
.el-pagination {
float: right;
margin-top: 10px;
}
</style>
22用戶頁面
22.1mock.js模擬后端
用戶管理
Mock.mock(RegExp('/sys/user/list*'), 'get', () => {
Result.data = {
"records": [
{
"id": 1,
"created": "2021-01-12T22:13:53",
"updated": "2021-01-16T16:57:32",
"statu": 1,
"username": "admin",
"password": "$2a$10$R7zegeWzOXPw871CmNuJ6upC0v8D373GuLuTw8jn6NET4BkPRZfgK",
"avatar": "https://image-1300566513.cos.ap-guangzhou.myqcloud.com/upload/images/5a9f48118166308daba8b6da7e466aab.jpg",
"email": "123@qq.com",
"city": "廣州",
"lastLogin": "2020-12-30T08:38:37",
"roles": [
{
"id": 6,
"created": "2021-01-16T13:29:03",
"updated": "2021-01-17T15:50:45",
"statu": 1,
"name": "超級管理員",
"code": "admin",
"remark": "系統默認最高權限,不可以編輯和任意修改",
"menuIds": []
},
{
"id": 3,
"created": "2021-01-04T10:09:14",
"updated": "2021-01-30T08:19:52",
"statu": 1,
"name": "普通用戶",
"code": "normal",
"remark": "只有基本查看功能",
"menuIds": []
}
]
},
{
"id": 2,
"created": "2021-01-30T08:20:22",
"updated": "2021-01-30T08:55:57",
"statu": 1,
"username": "test",
"password": "$2a$10$0ilP4ZD1kLugYwLCs4pmb.ZT9cFqzOZTNaMiHxrBnVIQUGUwEvBIO",
"avatar": "https://image-1300566513.cos.ap-guangzhou.myqcloud.com/upload/images/5a9f48118166308daba8b6da7e466aab.jpg",
"email": "test@qq.com",
"city": null,
"lastLogin": null,
"roles": [
{
"id": 3,
"created": "2021-01-04T10:09:14",
"updated": "2021-01-30T08:19:52",
"statu": 1,
"name": "普通用戶",
"code": "normal",
"remark": "只有基本查看功能",
"menuIds": []
}
]
}
],
"total": 2,
"size": 10,
"current": 1,
"orders": [],
"optimizeCountSql": true,
"hitCount": false,
"countId": null,
"maxLimit": null,
"searchCount": true,
"pages": 1
}
return Result
})
Mock.mock(RegExp('/sys/user/*'), 'post', () => {
return Result
})
Mock.mock(RegExp('/sys/user/info/*'), 'get', () => {
Result.data = {
"id": 2,
"created": "2021-01-30T08:20:22",
"updated": "2021-01-30T08:55:57",
"statu": 1,
"username": "test",
"password": "$2a$10$0ilP4ZD1kLugYwLCs4pmb.ZT9cFqzOZTNaMiHxrBnVIQUGUwEvBIO",
"avatar": "https://image-1300566513.cos.ap-guangzhou.myqcloud.com/upload/images/5a9f48118166308daba8b6da7e466aab.jpg",
"email": "test@qq.com",
"city": null,
"lastLogin": null,
"roles": []
}
return Result
})
22.2views/system/User.vue頁面
<template>
<div> <!--搜索框-->
<el-form :inline="true" :model="searchForm">
<el-form-item>
<el-input v-model="searchForm.username" placeholder="名稱" clearable></el-input>
</el-form-item>
<el-form-item>
<el-button>搜索</el-button>
<!-- :v-if="hasAuth('sys:user:save')-->
<el-button type="primary"
@click="dialogFormVisible = true"
:v-if="hasAuth('sys:user:save')"
>新增
</el-button>
<el-popconfirm title="確定要洗掉這些記錄嗎?" @confirm="delHandle(null)" style="margin-left: 10px;"
>
<el-button type="danger" slot="reference" :disabled="delBtnStu">批量洗掉</el-button>
</el-popconfirm>
</el-form-item>
</el-form>
<!--串列-->
<el-table ref="multipleTable" border stripe :data="tableData" tooltip-effect="dark" style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="頭像" width="50">
<template slot-scope="scope">
<el-avatar size="small" :src="scope.row.avatar"></el-avatar>
</template>
</el-table-column>
<el-table-column prop="username" label="用戶名" width="120"></el-table-column>
<el-table-column label="角色名稱" width="180">
<template slot-scope="scope">
<el-tag style="margin-right: 5px;" size="small" type="info" v-for="item in scope.row.roles">{{ item.name }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="email" label="郵箱"></el-table-column>
<el-table-column prop="phone" label="手機號"></el-table-column>
<el-table-column label="狀態">
<template slot-scope="scope">
<el-tag v-if="scope.row.statu === 0" size="small" type="danger">禁用</el-tag>
<el-tag v-else-if="scope.row.statu === 1" size="small" type="success">正常</el-tag>
</template>
</el-table-column>
<el-table-column prop="created" label="創建時間" width="200"></el-table-column>
<el-table-column width="260px" label="操作">
<template slot-scope="scope">
<el-button type="text" @click="roleHandle(scope.row.id)">分配角色</el-button>
<el-divider direction="vertical"></el-divider>
<el-button type="text" @click="repassHandle(scope.row.id, scope.row.username)"
>重置密碼
</el-button>
<el-divider direction="vertical"></el-divider>
<el-button type="text" @click="editHandle(scope.row.id)">編輯</el-button>
<el-divider direction="vertical"></el-divider>
<el-popconfirm title="確定要洗掉這條記錄嗎?" @confirm="delHandle(scope.row.id)">
<el-button type="text" slot="reference">洗掉</el-button>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<!--頁碼-->
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="current"
:page-sizes="[10, 20, 50, 100]" :page-size="size" layout="total, sizes, prev, pager, next, jumper"
:total="total"></el-pagination>
<el-dialog title="用戶資訊" :visible.sync="dialogFormVisible" width="600px">
<el-form :model="editForm" :rules="editFormRules" ref="editForm">
<el-form-item label="用戶名" prop="username" label-width="100px">
<el-input v-model="editForm.username" autocomplete="off"></el-input>
<el-alert title="初始密碼為888888" :closable="false" type="info" style="line-height: 12px;"></el-alert>
</el-form-item>
<el-form-item label="郵箱" prop="email" label-width="100px">
<el-input v-model="editForm.email" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="手機號" prop="phone" label-width="100px">
<el-input v-model="editForm.phone" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="狀態" prop="statu" label-width="100px">
<el-radio-group v-model="editForm.statu">
<el-radio :label="0">禁用</el-radio>
<el-radio :label="1">正常</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="resetForm('editForm')">取 消</el-button>
<el-button type="primary" @click="submitEditForm('editForm')">確 定</el-button>
</div>
</el-dialog>
<!-- 分配權限對話框 -->
<el-dialog title="分配角色" :visible.sync="roleDialogFormVisible" width="600px" @closed="resetForm('roleForm')">
<el-form :model="roleForm" ref="roleForm">
<el-tree :data="roleTreeData" show-checkbox ref="roleTree" node-key="id" :default-expand-all=true
:props="defaultProps"></el-tree>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="resetForm('roleForm')">取 消</el-button>
<el-button type="primary" @click="submitRoleForm('roleForm')">確 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'User',
data() {
return {
searchForm: {username: ''},
editForm: {},
editFormRules: {
username: [{required: true, message: '請輸入用戶名稱', trigger: 'blur'}],
email: [{required: true, message: '請輸入郵箱', trigger: 'blur'}],
statu: [{required: true, message: '請選擇狀態', trigger: 'blur'}]
},
current: 1,
total: 0,
size: 10,
dialogFormVisible: false,
tableData: [],
multipleSelection: [],
delBtnStu: true,
roleDialogFormVisible: false,
roleForm: {},
defaultProps: {children: 'children', label: 'name'},
roleTreeData: [],
treeCheckedKeys: [],
}
}, methods: {
toggleSelection(rows) {
if (rows) {
rows.forEach(row => {
this.$refs.multipleTable.toggleRowSelection(row);
});
} else {
this.$refs.multipleTable.clearSelection();
}
}, handleSelectionChange(rows) {
this.multipleSelection = rows;
this.delBtnStu = rows.length == 0
}, getUserList() {
this.$axios.get('/sys/user/list', {
params: {
name: this.searchForm.name,
current: this.current,
size: this.size
}
}).then(res => {
this.tableData = res.data.data.records
this.current = res.data.data.current
this.size = res.data.data.size
this.total = res.data.data.total
})
}, handleSizeChange(val) {
this.size = val
this.getUserList()
}, handleCurrentChange(val) {
this.current = val
this.getUserList()
}, submitEditForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.$axios.post('/sys/user/' + (this.editForm.id ? "update" : "save"), this.editForm).then(res => {
console.log(res.data)
this.resetForm(formName)
this.$message({
showClose: true, message: '恭喜你,操作成功', type: 'success', onClose: () => {
this.getUserList()
}
});
})
} else {
console.log('error submit!!');
return false;
}
});
}, editHandle(id) {
console.log(id)
this.$axios.get("/sys/user/info/" + id).then(res => {
this.editForm = res.data.data
this.dialogFormVisible = true
})
}, delHandle(id) {
var ids = []
id ? ids.push(id) : this.multipleSelection.forEach(row => {
ids.push(row.id)
})
console.log(ids)
this.$axios.post("/sys/user/delete", ids).then(res => {
this.$message({
showClose: true, message: '恭喜你,操作成功', type: 'success', onClose: () => {
this.getUserList()
}
});
})
}, resetForm(formName) {
this.$refs[formName].resetFields();
this.editForm = {}
this.dialogFormVisible = false
this.roleDialogFormVisible = false
}, roleHandle(id) {
this.$axios.get("/sys/user/info/" + id).then(res => {
const sysuser = res.data.data
var roleIds = []
sysuser.roles.forEach(row => {
roleIds.push(row.id)
})
console.log("roleIds")
console.log(roleIds)
this.roleForm = res.data.data
console.log("this.treeCheckedKeys")
console.log(this.treeCheckedKeys)
this.$axios.get("/sys/role/list").then(res => {
this.roleTreeData = res.data.data.records
this.$refs.roleTree.setCheckedKeys(roleIds);
})
})
this.roleDialogFormVisible = true
}, submitRoleForm(formName) {
var roleIds = []
roleIds = this.$refs.roleTree.getCheckedKeys()
console.log(roleIds)
console.log(this.roleForm.id)
this.$axios.post("/sys/user/role/" + this.roleForm.id, roleIds).then(res => {
this.$message({
showClose: true, message: '恭喜你,操作成功', type: 'success', onClose: () => {
this.resetForm(formName)
this.getUserList()
}
});
this.roleDialogFormVisible = false
})
}, repassHandle(id, username) {
this.$confirm('將重置用戶【' + username + '】的密碼, 是否繼續?', '提示', {
confirmButtonText: '確定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$axios.post("/sys/user/repass", id).then(res => {
this.$message({
showClose: true, message: '恭喜你,操作成功', type: 'success', onClose: () => {
}
});
})
})
}
},
created() {
this.getUserList()
},
}</script>
<style>
</style>
23前端權限控制
23.1在src/main.js添加
Vue.mixin({
methods: {
hasAuth(perm) {
var authority = this.$store.state.menus.permList
console.log(authority)
return authority.indexOf(perm) > -1
}
}
})
23.2使用權限
:v-if="hasAuth('sys:user:save')"

23.2mock.js模擬回傳權限
// 權限
let authoritys = ['sys:user:save']
23.3其他
之前寫的
1.在src/store/modules/menus.js設定權限的方法
2.在src/router/index.js拿到權限并設定到localStorage中
// 拿到用戶權限
store.commit("setPermList", res.data.data.authoritys)
24結束語
VueAdmin - 前后端分離后臺管理系統
線上演示:https://www.markerhub.com/vueadmin
登錄密碼:1234567
前端筆記:https://shimo.im/docs/pxwyJHgqcWjWkTKX/
后端筆記:https://shimo.im/docs/OnZDwoxFFL8bnP1c/
原始碼分享:
https://github.com/markerhub/vueadmin
https://gitee.com/markerhub/VueAdmin
視頻講解:https://www.bilibili.com/video/BV1af4y1s7Wh/
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/302249.html
標籤:其他
上一篇:ES6 新特性知識點總結
下一篇:Java專案:在線水果商城系統(java+JSP+Spring+SpringMVC +MyBatis+html+mysql)
