This is the 25th day of my participation in the August Genwen Challenge.More challenges in August
Sources of learning videos (link)
Ps, blogger of Station B (Good point)
Front-end learning notes
Install the front-end Vue environment and create a Vue project
Installation node. Js
websiteaddress After installation fool operation can check whether the installation is complete (command) below is my version If the preceding version information is displayed, the installation is successful
The environment for installing vUE
The command
# Install Taobao NPM can not install, but install the domestic mirror will be faster
npm install -g cnpm --registry=https://registry.npm.taobao.org
# vue - CLI install dependency package
cnpm install --g vue-cli
This can be used to create a vue project with visualization, or not, I use the command line to create a Vue project
vue ui
Copy the code
Create the environment for vUE
The rest is just the next stepYou can see it by running it in the project directory
Set the command access in IDEA Import the project into IDEA
My other Vue installation blog is Vue Notes
Install Element-UI, Axios, QS, MockJS
# installation element - the UI
cnpm install element-ui --save
# installation axios
cnpm install axios --save
CNPM install qs --save
cnpm install qs --save
# installation mockjs
cnpm install mockjs --save-dev
Copy the code
- Axios: A Promise based HTTP library, Ajax
- Qs: Query parameter serialization and parsing library
- Mockjs: A tool that generates random data for us
**Mockjs ** creates a mock. Js file in the SRC directory to write random apis that don’t interact with the back end yet, so import the file in main.js with fake data The main js file
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
// Introduce mock data, annotate the line when closed
require("./mock")
Vue.config.productionTip = false;
new Vue({
router,
store,
render: (h) = > h(App),
}).$mount("#app");
Copy the code
Let’s bring in element-UI, axios. Then we’ll open main.js in our project SRC directory and introduce the element-UI dependency axios.
import Element from 'element-ui'
import "element-ui/lib/theme-chalk/index.css"
import axios from 'axios'
Vue.use(Element)
Copy the code
Page routing
Login and creation of the home page
RouterThe link path management system of WebApp is to establish the mapping relationship between URL and page, mainly in SRC router index. Js is to configure the routeCreate our login page and home page
To configure the mapping between the URL and the Vue page in the routing center, refer to the default format./ SRC /router/index.js
import Vue from "vue";
import VueRouter from "vue-router";
import Login from ".. /views/Login";
Vue.use(VueRouter);
const routes = [
{
path: "/".name: "Home".component: () = > import('.. /views/Home.vue'),}, {path: "/login".name: "Login".component: Login
},
];
const router = new VueRouter({
mode: 'history'.base: process.env.BASE_URL,
routes
});
export default router;
Copy the code
After modifying the index.js page we started the vue project
npm run serve
Copy the code
Start after the completion of the access localhost: 8081 / login page to find the page as shown below, in the Home | the About
The reason:New vue program there is no other configuration, the default is a single page application, means that this application is made by a shell page, and multiple pages, composition at the time of jump page without shell, the shell pressure surface is App. Vue login page is a fragment, we should change our App. Vue web pageApp.vue after modification
<template>
<div id="app">
<router-view/>
</div>
</template>
<style lang="less">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
}
</style>
Copy the code
** Check ** after the modification is complete
Log in to develop
Login development process
You need to go to element-UI to find the component of the form, which is a simple login page, but the verification code of the login page needs to interact with the background. There are two main login and background interactions: 1, obtain the verification code of the login, submit the login form, and complete the login. Since the back-end code has not been written, So we’ll write the data in our mock.js to complete the interaction. Development of the APIInteractive process1. Open the login interface 2. Dynamically load the login verification code. For projects separated from the front and back ends, we do not use session for interaction. Then send the random code and the Base64 string code of the verification code picture to the front end 3. The front end submits the user name, password, verification code, and random code 4 to verify whether the background is correctRough flow chart
Login page
<template>
<el-row type="flex" class="row-bg" justify="center">
<el-col :xl="6" :lg="Seven">
<h2>Welcome to FJJ Management System</h2>
<el-image :src="require('@/assets/img.png')" style="height: 180px; width: 180px;"></el-image>
<p>Scan the QR code to add personal wechat</p>
</el-col>
<el-col :span="1">
<el-divider direction="vertical"></el-divider>
</el-col>
<el-col :span="6" :lg="Seven">
<el-form :model="loginForm" :rules="rules" ref="loginForm" label-width="80px">
<el-form-item label="Username" prop="username" style="width: 380px;">
<el-input v-model="loginForm.username"></el-input>
</el-form-item>
<el-form-item label="Password" prop="password" style="width: 380px;">
<el-input v-model="loginForm.password" type="password"></el-input>
</el-form-item>
<el-form-item label="Verification code" prop="code" style="width: 380px;">
<el-input v-model="loginForm.code" style="width: 172px; float: left" maxlength="5"></el-input>
<el-image :src="captchaImg" class="captchaImg" @click="getCaptcha"></el-image>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('loginForm')">Immediately create</el-button>
<el-button @click="resetForm('loginForm')">reset</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
</template>
<script>
export default {
name: "Login",
data () {
return {
loginForm: {
username: ' '.password: ' '.code: ' '.token: ' '
},
rules: {
username: [{required: true.message: 'Please enter a user name'.trigger: 'blur'}].password: [{required: true.message: 'Please enter your password'.trigger: 'blur'}].code: [{required: true.message: 'Please enter the verification code'.trigger: 'blur' },
{ min: 5.max: 5.message: 'Length of 5 characters'.trigger: 'blur'}},captchaImg: null}},methods: {
submitForm (formName) {
this.$refs[formName].validate((valid) = > {
if (valid) {
this.$axios.post('/login? ' ,this.loginForm).then(res= >{})}else {
console.log('Wrong submission')
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;
justify-content: center;
margin-top: 10%;
}
.el-divider {
height: 200px;
}
.captchaImg {
float: left;
margin-left: 8px;
border-radius: 4px;
}
</style>
Copy the code
The effectOur captcha hasn’t shown up yet and this is where the QR code was introduced
Verification code
At this point, our verification code is not displayed, so we use mock verification code before interacting with the background
Set it to NULL in data first** getCaptcha () method. Call the create image method **
getCaptcha () {
this.$axios.post('/captcha').then(res= > {
this.loginForm.token = res.data.data.token
this.captchaImg = res.data.data.captchaImg
})
}
Copy the code
After creation, don’t forget to call the method below using this method** code, only the content of export default **
<script>
export default {
name: "Login",
data () {
return {
loginForm: {
username: ' '.password: ' '.code: ' '.token: ' '
},
rules: {
username: [{required: true.message: 'Please enter a user name'.trigger: 'blur'}].password: [{required: true.message: 'Please enter your password'.trigger: 'blur'}].code: [{required: true.message: 'Please enter the verification code'.trigger: 'blur' },
{ min: 5.max: 5.message: 'Length of 5 characters'.trigger: 'blur'}},captchaImg: null}},methods: {
submitForm (formName) {
this.$refs[formName].validate((valid) = > {
if (valid) {
// eslint-disable-next-line no-unused-vars
this.$axios.post('/login? ' ,this.loginForm).then(res= >{})}else {
console.log('Wrong submission')
return false
}
})
},
resetForm (formName) {
this.$refs[formName].resetFields()
},
getCaptcha () {
this.$axios.post('/captcha').then(res= > {
// the token value is obtained from the data after the result
// This is the result that we return in the background. If it is correct, there will be a value of data in it
this.loginForm.token = res.data.data.token
// Do the same with our image
this.captchaImg = res.data.data.captchaImg
})
}
},
created() {
this.getCaptcha()
}
}
</script>
<style scoped>
.el-row {
/*background-color: #fafafa; * /
height: 100%;
display: flex;
align-items: center;
text-align: center;
justify-content: center;
margin-top: 10%;
}
.el-divider {
height: 200px;
}
.captchaImg {
float: left;
margin-left: 8px;
border-radius: 4px;
}
</style>
Copy the code
Write data inside our mock.js
// Create the returned object
const Mock = require('mockjs')
// Get Random
const Random = Mock.Random
// Set the result to return
let Result = {
code: 200.msg: 'Operation successful'.data: null
}
// Image request
Mock.mock('/captcha'.'post'.() = > {
Result.data = {
token: Random.string(32),
captchaImg: Random.dataImage('120x40'.'jikof')}return Result
})
Copy the code
At this point our effect, the verification code is now mock generated randomly when interacting with the backend API interface can be used
Login request
/ SRC /store/index.js so that we can store the data in 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: {},});Copy the code
In our login. vue, save our JWT to Settings and jump to the home page after successful Login The same is true for the test data of the request written for our mock. JWT cannot be put in the test for the time being, so JWT identity is not put in the test. It will be directly put in the test first and then put in the test when interacting with the background After login, go to the home page
There is only a temporary interaction with the background, so it is undefined
The minor error log summarizes the error introduced into Axios
There’s a little error here just for the record Error while using AXIos request
The solution Change it in login. vue as well The request can then be sent
Set the global AXIOS at login time
Fail to log in here to set the global because, what we need is the pop-up display error, such as authentication code error, the user name or password is not correct, etc., are not only the login interface, all interface call will have this case, all we want to be a blocker, analysis of the results returned, if it is abnormal pop-up error directly, So we can save each interface and create a file axios.js (the same as main.js) in the SRC directory
import axios from 'axios'
import router from './router'
import Element from 'element-ui'
axios.defaults.baseURL = 'http://localhost:8081'
const request = axios.create({
timeout: 5000.headers: {
'Content-Type': 'application/json; charset=utf-8'
}
})
request.interceptors.request.use(config= > {
config.headers.Authorization = localStorage.getItem('token')
return config
})
request.interceptors.response.use(
response= > {
console.log('response ->' + response)
const res = response.data
if (res.code === 200) {
return response
} else{ Element.Message.error(! res.msg ?'System exception' : res.msg)
return Promise.reject(response.data.msg)
}
},
error= > {
console.log(error)
if (error.response.data) {
error.massage = error.response.data.msg
}
if (error.response.status === 401) {
router.push('/login')
}
Element.Message.error(error.massage, {duration: 3000})
return Promise.reject(error)
}
)
export default request
Copy the code
Pre-interception can assemble the token information of the header for all permission requests. Post-interception can call the login page if status.code and error.response.status are 401 not logged in and have no permission. We need to change the original main.js to our own Axios JS To test this, do we enter the wrong transition in mock.js first The effect
Background interface development
So I’m going to choose theta
<el-container>
<el-header>Header</el-header>
<el-container>
<el-aside width="200px">Aside</el-aside>
<el-main>Main</el-main>
</el-container>
</el-container>
Copy the code
I’m going to create an Index page and I’m going to put it in there, so I can pull out the common ones in a second and copy the styles Add to the route The effect Add a style to set the height
Header navigation bar Settings
The Index. The vue web page
<template>
<el-container>
<el-aside width="200px">
<div>The menu bar</div>
</el-aside>
<el-container>
<el-header style="height: 55px;"><Strong>ManHub background management system</Strong>
<div class="header-avatar block">
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
<el-dropdown><span class="el-dropdown-link">
fjj<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<router-link to="/userCenter">
<el-dropdown-item>Personal center</el-dropdown-item>
</router-link>
<el-dropdown-item @click.native="logout">exit</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-link href="http://markerhub.com">Web site</el-link>
</div>
</el-header>
<el-main>
<div style="margin: 0 15px;">
<router-view></router-view>
</div>
</el-main>
</el-container>
</el-container>
</template>
<script>
export default {
name: "Index"
}
</script>
<style scoped>
/* Dropdown box CSS */
.el-dropdown-link {
cursor: pointer;
color: black;
}
.el-icon-arrow-down {
font-size: 12px;
}
/* Set the header navigation style */
.header-avatar {
float: right;
width: 210px;
display: flex;
justify-content: space-around;
align-items: center;
text-align: center;
}
/* Navigation bar CSS */
.el-container {
padding: 0vh;
margin: 0;
height: 100vh;
}
.el-header {
background-color: #D3DCE6;
color: # 333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #D3DCE6;
color: # 333;
text-align: center;
line-height: 200px;
}
.el-main {
color: # 333;
padding-left: 20px;
}
/* Remove the underscore */ from the a tag
a {
text-decoration: none;
}
/* Set the link to slide up to become little hands */
.el-dropdown-link {
cursor: pointer;
color: black;
}
/* Sets the height of the sidebar */
.el-menu-vertical-demo {
height: 100vh;
}
/* Remove the underscore */ from the a tag
a {
text-decoration: none;
}
</style>
Copy the code
The effect
Side navigation bar Settings
** Almost feels right, go to element-UI and add the menu bar component to home. vue, but make it a dynamic menu, so separate it out and create a new SideMenu
<template>
<el-menu 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">Home page</span></template>
</el-menu-item>
</router-link>
<el-submenu index="1">
<template slot="title"><i class="el-icon-s-operation"></i> <span>System management</span></template>
<el-menu-item index="1-1">
<template slot="title"><i class="el-icon-s-custom"></i> <span slot="title">User management</span></template>
</el-menu-item>
<el-menu-item index="1-2">
<template slot="title"><i class="el-icon-rank"></i> <span slot="title">Role management</span></template>
</el-menu-item>
<el-menu-item index="1-3">
<template slot="title"><i class="el-icon-menu"></i> <span slot="title">Menu management</span></template>
</el-menu-item>
</el-submenu>
<el-submenu index="2">
<template slot="title"><i class="el-icon-s-tools"></i> <span>System tools</span></template>
<el-menu-item index="2-2">
<template slot="title"><i class="el-icon-s-order"></i> <span slot="title">Digital dictionary</span></template>
</el-menu-item>
</el-submenu>
</el-menu>
</template>
<script>
export default {
name: "SideMenu"
}
</script>
<style scoped>
/* Sets the height of the sidebar */
.el-menu-vertical-demo {
height: 100vh;
}
/* Remove the underscore */ from the a tag
a {
text-decoration: none;
}
</style>
Copy the code
At this point sidemenu. vue is added to home.vue as a component. We need to import and declare the component to use the label, so we should declare in index. vue to use the label
The effect Remove the entire frame inside home.vue, leaving only the middle contents in IndexAfter removing home.vue
<template>
<el-container>
<el-aside width="200px">
<SideMenu></SideMenu>
</el-aside>
<el-container>
<el-header style="height: 55px;"><Strong>ManHub background management system</Strong>
<div class="header-avatar block">
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
<el-dropdown><span class="el-dropdown-link">
fjj<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<router-link to="/userCenter">
<el-dropdown-item>Personal center</el-dropdown-item>
</router-link>
<el-dropdown-item @click.native="logout">exit</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-link href="http://markerhub.com">Web site</el-link>
</div>
</el-header>
<el-main>
<div style="margin: 0 15px;">
<router-view></router-view>
</div>
</el-main>
</el-container>
</el-container>
</template>
<script>
import SideMenu from "./inc/SideMenu";
export default {
name: "Home".components: {SideMenu}
}
</script>
<style scoped>
/* Dropdown box CSS */
.el-dropdown-link {
cursor: pointer;
color: black;
}
.el-icon-arrow-down {
font-size: 12px;
}
/* Set the header navigation style */
.header-avatar {
float: right;
width: 210px;
display: flex;
justify-content: space-around;
align-items: center;
text-align: center;
}
/* Navigation bar CSS */
.el-container {
padding: 0vh;
margin: 0;
height: 100vh;
}
.el-header {
background-color: #D3DCE6;
color: # 333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #D3DCE6;
color: # 333;
text-align: center;
line-height: 200px;
}
.el-main {
color: # 333;
padding-left: 20px;
}
/* Remove the underscore */ from the a tag
a {
text-decoration: none;
}
/* Set the link to slide up to become little hands */
.el-dropdown-link {
cursor: pointer;
color: black;
}
/* Sets the height of the sidebar */
.el-menu-vertical-demo {
height: 100vh;
}
/* Remove the underscore */ from the a tag
a {
text-decoration: none;
}
</style>
Copy the code
After removing the index.vue
<template>
<div>The middle section</div>
</template>
<script>
export default {
name: "Index"
}
</script>
<style scoped>
</style>
Copy the code
At this point when we’re accessing Index we can’t just have the middle part without the whole frame We should use index.vue as a child route to the Home, so that when we access index the parent route will be displayedStep 1 Modify the routeSecond, modify home.vue
And then I add this, at this point, when we’re looking at the effect
Side navigation bar routing
Create several new pages, first create a folder under views, and then create a new Vue page.
Add a route to index.js At this point we’re not even going to click on the left side of user management and change the Home page The effect
Display user login information and log out to clear browser cache
The upper right corner of the management interface is written dead. Now we have logged in successfully, so we can request to obtain the current user information through the interface, so that the user information can be dynamically displayed home.vue
Write request and test data inside mock.js
// Personal center test data
Mock.mock('/sys/userInfo'.'get',() =>{
Result.data = {
id: '1',
username :'Feng Jiaojiao',
avatar: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png'
}
return Result
})
Copy the code
The effect Logged out
The mock. Js data
// Log out
Mock.mock('/logout'.'post', () = > {return Result
})
Copy the code
Personal center interface
Create a VUE for your personal center
<template>
<div style="text-align: center;">
<h2>Hello! {{userinfo.username}} student</h2>
<el-form :model="passForm" status-icon :rules="rules" ref="passForm" label-width="100px">
<el-form-item label="Old password" prop="currentPass">
<el-input type="password" v-model="passForm.currentPass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="New password" prop="password">
<el-input type="password" v-model="passForm.password" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="Confirm password" 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')">submit</el-button>
<el-button @click="resetForm('passForm')">reset</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('Please enter your password again'))}else if(value ! = =this.passForm.password) {
callback(new Error('Two input passwords are inconsistent! '))}else {
callback()
}
}
return {
userInfo: {},passForm: {
password: ' '.checkPass: ' '.currentPass: ' '
},
rules: {
password: [{required: true.message: 'Please enter a new password'.trigger: 'blur' },
{ min: 6.max: 12.message: 'Between 6 and 12 characters long'.trigger: 'blur'}].checkPass: [{required: true.validator: validatePass, trigger: 'blur'}].currentPass: [{required: true.message: 'Please enter your current password'.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/updatePass'.this.passForm).then(res= > {
_this.$alert(res.data.msg, 'tip', {
confirmButtonText: 'sure'.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>
Copy the code
You need to write this sentence in home.vue Just set our route in index
After clicking on
Dynamic menu bar development
The above code, the menu bar on the left of the data is written to death, and should not be written in the actual situation, because the menu is needed according to the logged in user’s permission to dynamic display menu, which users see menu bar may not be the same, these data need to get to the backend access should simplify the data into a json array data, The for loop is then shown as sidemenu.vue
<template>
<el-menu 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">Home page</span></template>
</el-menu-item>
</router-link>
<el-submenu :index="menu.name" v-for="menu in menuList" :key="menu.name">
<template slot="title">
<i :class="menu.icon"></i>
<span>{{menu.title}}</span>
</template>
<router-link :to="item.path" v-for="item in menu.children" :key="item.path">
<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: [{
name: 'SysManga'.title: 'System Administration'.icon: 'el-icon-s-operation'.path: ' '.component: ' '.children: [{
name: 'SysUser'.title: 'User Management'.icon: 'el-icon-s-custom'.path: '/user'.children: []}]}, {name: 'SysTools'.title: 'System Tools'.icon: 'el-icon-s-tools'.path: ' '.children: [{
name: 'SysDict'.title: 'Digital dictionary'.icon: 'el-icon-s-order'.path: '/sys/dicts'.children: []},]}],}}}</script>
<style scoped>
/* Sets the height of the sidebar */
.el-menu-vertical-demo {
height: 100vh;
}
/* Remove the underscore */ from the a tag
a {
text-decoration: none;
}
</style>
Copy the code
As you can see, using the for loop to display the data, all you need to do is change the menuList in the data, and the effect is exactly the same as before. Now menuList data we are write directly to the page data, generally we are request to the backend, so you need to define a mock interface, should be dynamic menu, we also want to consider the access problem, so we request data generally out dynamic menu, to access the data, such as a menu to add, Delete whether there is permission, whether can display. Mock.js
Mock.mock('/sys/menu/nav'.'get'.() = > {
/ / the menu json
let nav = [
{
name: 'SysManga'. }, {name: 'SysTools'. }]// Permission data
let authoritys = ['SysUser'."SysUser:save"]
Result.data = {}
Result.data.nav = nav
Result.data.authoritys = authoritys
return Result
Copy the code
The interface defined for the navigation menu should be called after the login has successfully completed, but not every time the login is opened, that is, when the browser has stored the user’s token we do not need to log in again, so we cannot put it in the login completed method. Here we need to consider the routing problem of the navigation menu. When we click the menu to route to the page, we need to declare the solution in the router: Load menu data in router.js. Router has a prefix block, which means we can make some judgments or load data before routing to the page
Add the following code to router.js: SRC /router/index.js
// Dynamic navigation bar
router.beforeEach((to, from, next) = > {
let hasRoute = store.state.menus.hasRoute
const token = localStorage.getItem('token')
if (to.path === '/login') {
next()
} else if(! token) { next({path: '/login'})}if(token && ! hasRoute) { axios.get('/sys/menu/nav', {
headers: {
Authorization: localStorage.getItem('token')
}
}).then(res= > {
console.log(res.data.data)
store.commit('setMenuList', res.data.data.nav)
store.commit('setPermList', res.data.data.authoritys)
// Dynamically bind routes
const newRoutes = router.options.routes
res.data.data.nav.forEach(menu= > {
if (menu.children) {
menu.children.forEach(e= > {
const route = menuToRoute(e)
if (route) {
newRoutes[0].children.push(route)
}
})
}
})
console.log(newRoutes)
console.log('newRoutes')
router.addRoutes(newRoutes)
hasRoute = true
store.commit('changeRouteStatus', hasRoute)
})
}
next()
})
const menuToRoute = (menu) = > {
if(! menu.component) {return null
}
// Copy to properties
const route = {
path: menu.path,
name: menu.name,
meta: {
icon: menu.icon,
title: menu.title
}
}
route.component = () = > import('@/views/' + menu.component + '.vue')
console.log(route)
console.log('route')
return route
}
export default router
Copy the code
Router. AddRoutes (newRoutes) dynamically adds a routing object to the menu object. At the same time, there is a Menu.component in the menu object, which is the corresponding component of the connection. We need to add, say, the /sys/users link to component(sys/User). Also, in the menu object above, there is a menu.component. This is the component of the connection that we need to add. For example, the /sys/ Users link corresponds to the Component (sys/User).
// Json for the menu
const nav = [{
name: 'SysManga'.title: 'System Administration'.icon: 'el-icon-s-operation'.component: ' '.path: ' '.children: [{title: 'User Management'.icon: 'el-icon-s-custom'.path: '/sys/users'.name: 'SysUser'.component: 'sys/User'.children: []}, {name: 'SysRole'.title: 'Role Management'.icon: 'el-icon-rank'.path: '/sys/roles'.component: 'sys/Role'.children: []}, {name: 'SysMenu'.title: 'Menu Management'.icon: 'el-icon-menu'.path: '/sys/menus'.component: 'sys/Menu'.children: []}]}, {name: 'SysTools'.title: 'System Tools'.icon: 'el-icon-s-tools'.path: ' '.component: ' '.children: [{title: 'Digital dictionary'.icon: 'el-icon-s-order'.path: '/sys/dicts'.component: ' '.children: []}}]]Copy the code
At the same time, in the above router, we also judged whether the menu could be loaded in advance by judging whether there was a login page and whether there was a token. At the same time, we also made a switch hasRoute to dynamically judge whether the menu had been loaded. We also need to define a few methods in store for storing data. We define a menu module, so in store we create a folder called Modules, and then new Menus.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default {
state: { // Menu bar data
menuList: [].// Permission data
permList: [].hasRoute: false
}, mutations: {
changeRouteStatus(state, hasRoute) {
state.hasRoute = hasRoute
sessionStorage.setItem("hasRoute", hasRoute)
}, setMenuList(state, menus) {
state.menuList = menus
}, setPermList(state, authoritys) {
state.permList = authoritys
}
}
}
Copy the code
Remember to import this module in store and add it to modules: SRC /store/index.js
import menus from "./modules/menus".export default new Vuex.Store({
... modules:
{ menus }})
Copy the code
In this way, our menu data can be loaded, and then SideMenu. Vue directly obtain the store menuList data to display the menu. src/views/inc/SideMenu.vue
data() {
return {
menuList: this.$store.state.menus.menuList,
}}
Copy the code
Results the following
Dynamic TAB page development
1. When we click the navigation menu, a corresponding TAB will be added at the top. Note that it is not allowed to be added repeatedly, and you can directly switch to this TAB when you find an existing TAB. Tabs. Vue: SRC /views/inc/Tabs. Vue: SRC /views/inc/Tabs
<template>
<el-tabs v-model="editableTabsValue" type="card" closable @tab-remove="removeTab" @tab-click="clickTab">
<el-tab-pane
v-for="(item) 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,
tabIndex: 2}},computed: {
editableTabs: {
get () {
return this.$store.state.menus.editableTabs
},
set (val) {
this.$store.state.menus.editableTabs = val
}
}
},
methods: {
removeTab (targetName) {
const tabs = this.editableTabs
let activeName = this.editableTabsValue
if (targetName === 'Index') {
return
}
if (activeName === targetName) {
tabs.forEach((tab, index) = > {
if (tab.name === targetName) {
const 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 })
},
clickTab (target) {
this.$router.push({ name: target.name })
}
}
}
</script>
<style scoped>
</style>
Copy the code
Computed means that computed attributes are recalculated when the values of the attributes that it depends on change, and if they are not, they are used in the cache. The logic of clickTab removeTab is simpler, especially if removeTab considers multiple cases. Modify the meun. Add editableTabsValue js and editableTabs then home page as the default page SRC/store/modules/menus. Js
state: {
// Menu bar data
menuList: [].// Permission data
permList: [].hasRoute: false.editableTabsValue: 'Index'.editableTabs: [{
title: 'home'.name: 'Index'}},Copy the code
Then we’ll introduce our Tabs. Vue component in home. vue
# Import componentsimport Tabs from "./inc/Tabs"# declare component components: {SideMenu, Tabs}, <el-main> # use component <Tabs></Tabs> <div style="margin: 0 15px;">
<router-view></router-view>
</div>
</el-main>
Copy the code
Current effect Having completed the first step, now we need to click on the menu navigation and add the Tabs to the Tabs list, so we should modify the sideMeun. Vue pageSince the tabs TAB list is stored in the store, we need to commit the event, so we add the addTabs method to menu.js:After refreshing the browser, the link /sys/ Users stays the same, but the Tab is missing, so we need to fix it. When the user opens the page directly by entering the link form, we can also automatically add and activate the specified Tab according to the link. So where do I add this echo method? The router? We can, but we need to make a judgment call, because every navigation click triggers the Router. Is there an easier way? Some! Since refreshing or opening a page is a one-time action, we can perform the echo action in higher level app. vue as follows:
As you can see from the code above, the addTabs method is triggered on all pages except the login page, so we can add a TAB and activate a TAB.
Personal center
Personal center page
Create UserCenCenter. Vue
<template>
<div style="text-align: center;">
<h2>Hello! {{userinfo.username}} student</h2>
<el-form :model="passForm" status-icon :rules="rules" ref="passForm" label-width="100px">
<el-form-item label="Old password" prop="currentPass">
<el-input type="password" v-model="passForm.currentPass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="New password" prop="password">
<el-input type="password" v-model="passForm.password" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="Confirm password" 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')">submit</el-button>
<el-button @click="resetForm('passForm')">reset</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('Please enter your password again'))}else if(value ! = =this.passForm.password) {
callback(new Error('Two input passwords are inconsistent! '))}else {
callback()
}
}
return {
userInfo: {},passForm: {
password: ' '.checkPass: ' '.currentPass: ' '
},
rules: {
password: [{required: true.message: 'Please enter a new password'.trigger: 'blur' },
{ min: 6.max: 12.message: 'Between 6 and 12 characters long'.trigger: 'blur'}].checkPass: [{required: true.validator: validatePass, trigger: 'blur'}].currentPass: [{required: true.message: 'Please enter your current password'.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/updatePass'.this.passForm).then(res= > {
_this.$alert(res.data.msg, 'tip', {
confirmButtonText: 'sure'.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>
Copy the code
Menu interface
The menu page
Menu management we use the Table component of the tree structure data, we just need to assemble the data according to the example, it can be displayed automaticallyThere should be a tree structure But elemenui added – no specific code SRC/views/sys/Menu. The vue
<template>
<div>
<el-form :inline="true" :model="formInline" ref="editForm" class="demo-form-inline">
<el-form-item>
<el-button type="primary" @click="dialogVisible = true">new</el-button>
</el-form-item>
</el-form>
<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="Name"
sortable
width="180">
</el-table-column>
<el-table-column
prop="perm"
label="Permission code"
sortable
width="180">
</el-table-column>
<el-table-column
prop="icon"
label="Icon">
</el-table-column>
<el-table-column
prop="type"
label="Type">
<template slot-scope="scope">
<el-tag size="small" v-if="scope.row.type === 0">directory</el-tag>
<el-tag size="small" v-else-if="scope.row.type === 1" type="success">The menu</el-tag>
<el-tag size="small" v-else-if="scope.row.type === 2" type="info">button</el-tag>
</template>
</el-table-column>
<el-table-column
prop="path"
label=URL "menu">
</el-table-column>
<el-table-column
prop="component"
label="Menu Component">
</el-table-column>
<el-table-column
prop="orderNum"
label="Sort number">
</el-table-column>
<el-table-column
prop="statu"
label="State">
<template slot-scope="scope">
<el-tag size="small" v-if="scope.row.statu === 1" type="success">normal</el-tag>
<el-tag size="small" v-else-if="scope.row.statu === 0" type="danger">disable</el-tag>
</template>
</el-table-column>
<el-table-column
prop="icon"
label="Operation">
<template slot-scope="scope">
<el-button type="text" @click="editHandle(scope.row.id)">The editor</el-button>
<el-divider direction="vertical"></el-divider>
<template>
<el-popconfirm title="Is this a paragraph of content to delete?" @confirm="delHandle(scope.row.id)">
<el-button type="text" slot="reference" >delete</el-button>
</el-popconfirm>
</template>
</template>
</el-table-column>
</el-table>
<! -- New dialog box -->
<el-dialog
title="Tip"
:visible.sync="dialogVisible"
width="600px"
:before-close="handleClose">
<el-form :model="editForm" :rules="editFormRules" ref="editForm" label-width="100px" class="demo-editForm">
<el-form-item label="Superior menu" prop="parentId">
<el-select v-model="editForm.parentId" placeholder="Please select superior menu">
<template v-for="item in tableData">
<el-option :label="item.name" :value="item.id"></el-option>
<template v-for="chid in item.children">
<el-option :label="chid.name" :value="chid.id"></el-option>
<span>{{ '- ' + chid.name}}</span>
</template>
</template>
</el-select>
</el-form-item>
<el-form-item label="Menu name" prop="name" label-width="100px">
<el-input v-model="editForm.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="Permission code" prop="perms" label-width="100px">
<el-input v-model="editForm.perms" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="Icon" prop="icon" label-width="100px">
<el-input v-model="editForm.icon" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label=URL "menu" prop="path" label-width="100px">
<el-input v-model="editForm.path" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="Menu Component" prop="component" label-width="100px">
<el-input v-model="editForm.component" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="Type" prop="type" label-width="100px">
<el-radio-group v-model="editForm.type">
<el-radio :label=0>directory</el-radio>
<el-radio :label=1>The menu</el-radio>
<el-radio :label=2>button</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="State" prop="statu" label-width="100px">
<el-radio-group v-model="editForm.statu">
<el-radio :label=0>disable</el-radio>
<el-radio :label=1>normal</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="Sort number" prop="orderNum" label-width="100px">
<el-input-number v-model="editForm.orderNum" :min="1" label="Sort number">1</el-input-number>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('editForm')">Immediately create</el-button>
<el-button @click="resetForm('editForm')">reset</el-button>
</el-form-item>
</el-form>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'Meun',
data () {
return {
dialogVisible: false.editForm: [].editFormRules: {
parentId: [{required: true.message: 'Please select superior menu'.trigger: 'blur'}].name: [{required: true.message: 'Please enter a name'.trigger: 'blur'}].perms: [{required: true.message: 'Please enter permission code'.trigger: 'blur'}].type: [{required: true.message: 'Please select status'.trigger: 'blur'}].orderNum: [{required: true.message: 'Please fill in the sort number'.trigger: 'blur'}].statu: [{required: true.message: 'Please select status'.trigger: 'blur'}},tableData: []
}
},
created () {
this.getMenuTree()
},
methods: {
getMenuTree () {
this.$axios.get('/sys/menu/list').then(res= > {
this.tableData = res.data.data
})
},
submitForm (formName) {
this.$refs[formName].validate((valid) = > {
if (valid) {
this.$axios.post('/sys/menu/' + (this.editForm.id ? 'update' : 'save'), this.editForm)
.then(res= > {
this.$message({
showClose: true.message: 'Congratulations, it worked.'.type: 'success'.onClose: () = > {
this.getMenuTree()
}
})
this.dialogVisible = false})}else {
console.log('error submit!! ')
return false
}
})
},
editHandle (id) {
this.dialogVisible = true
this.$axios.get('/sys/menu/info/' + id).then(res= > {
console.log(res.data.data + '99999999')
this.editForm = res.data.data
})
},
resetForm (formName) {
this.$refs[formName].resetFields()
this.dialogVisible = false
this.editForm = {}
},
handleClose () {
this.resetForm('editForm')
},
delHandle (id) {
this.$axios.post('/sys/menu/delete/' + id).then(res= > {
this.$message({
showClose: true.message: 'Congratulations, it worked.'.type: 'success'.onClose: () = > {
this.getMenuTree()
}
})
})
}
}
}
</script>
<style scoped>
</style>
Copy the code
Role management
The role page
Roles need to be associated with menu permissions, and the menu is a tree structure,
src/views/sys/Role.vue
<template>
<div>
<el-form :inline="true">
<el-form-item>
<el-input
v-model="searchForm.name"
placeholder="Name"
clearable
>
</el-input>
</el-form-item>
<el-form-item>
<el-button @click="getRoleList">search</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="dialogVisible = true">new</el-button>
</el-form-item>
<el-form-item>
<el-popconfirm title="Is this a definitive batch delete?" @confirm="delHandle(null)">
<el-button type="danger" slot="reference" :disabled="delBtlStatu">Batch delete</el-button>
</el-popconfirm>
</el-form-item>
</el-form>
<el-table
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
style="width: 100%"
border
stripe
@selection-change="handleSelectionChange">
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column
prop="name"
label="Name"
width="120">
</el-table-column>
<el-table-column
prop="code"
label="Unique code"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="remark"
label="Description"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="statu"
label="State">
<template slot-scope="scope">
<el-tag size="small" v-if="scope.row.statu === 1" type="success">normal</el-tag>
<el-tag size="small" v-else-if="scope.row.statu === 0" type="danger">disable</el-tag>
</template>
</el-table-column>
<el-table-column
prop="icon"
label="Operation">
<template slot-scope="scope">
<el-button type="text" @click="permHandle(scope.row.id)">Assign permissions</el-button>
<el-divider direction="vertical"></el-divider>
<el-button type="text" @click="editHandle(scope.row.id)">The editor</el-button>
<el-divider direction="vertical"></el-divider>
<template>
<el-popconfirm title="Is this a paragraph of content to delete?" @confirm="delHandle(scope.row.id)">
<el-button type="text" slot="reference">delete</el-button>
</el-popconfirm>
</template>
</template>
</el-table-column>
</el-table>
<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>
<! -- New dialog box -->
<el-dialog
title="Tip"
:visible.sync="dialogVisible"
width="600px"
:before-close="handleClose">
<el-form :model="editForm" :rules="editFormRules" ref="editForm" label-width="100px" class="demo-editForm">
<el-form-item label="Role Name" prop="name" label-width="100px">
<el-input v-model="editForm.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="Unique code" prop="code" label-width="100px">
<el-input v-model="editForm.code" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="Description" prop="remark" label-width="100px">
<el-input v-model="editForm.remark" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="State" prop="statu" label-width="100px">
<el-radio-group v-model="editForm.statu">
<el-radio :label=0>disable</el-radio>
<el-radio :label=1>normal</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('editForm')">Immediately create</el-button>
<el-button @click="resetForm('editForm')">reset</el-button>
</el-form-item>
</el-form>
</el-dialog>
<el-dialog
title="Assign permissions"
:visible.sync="permDialogVisible"
width="600px">
<el-form :model="permForm">
<el-tree
:data="permTreeData"
show-checkbox
ref="permTree"
:default-expand-all=true
node-key="id"
:check-strictly=true
:props="defaultProps">
</el-tree>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="permDialogVisible = false">Take away</el-button>
<el-button type="primary" @click="submitPermFormHandle('permForm')">determine</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'Role',
data () {
return {
searchForm: {},
delBtlStatu: true.total: 0.size: 10.current: 1.dialogVisible: false.editForm: {},tableData: [].editFormRules: {
name: [{required: true.message: 'Please enter role name'.trigger: 'blur'}].code: [{required: true.message: 'Please enter unique code'.trigger: 'blur'}].statu: [{required: true.message: 'Please select status'.trigger: 'blur'}},multipleSelection: [].permDialogVisible: false.permForm: {},
defaultProps: {
children: 'children'.label: 'name'
},
permTreeData: []
}
},
created () {
this.getRoleList()
this.$axios.get('/sys/menu/list').then(res= > {
this.permTreeData = res.data.data
})
},
methods: {
toggleSelection (rows) {
if (rows) {
rows.forEach(row= > {
this.$refs.multipleTable.toggleRowSelection(row)
})
} else {
this.$refs.multipleTable.clearSelection()
}
},
handleSelectionChange (val) {
console.log('tick')
console.log(val)
this.multipleSelection = val
this.delBtlStatu = val.length === 0
},
handleSizeChange (val) {
console.log(` per page${val}Article `)
this.size = val
this.getRoleList()
},
handleCurrentChange (val) {
console.log('Current page:${val}`)
this.current = val
this.getRoleList()
},
resetForm (formName) {
this.$refs[formName].resetFields()
this.dialogVisible = false
this.editForm = {}
},
handleClose () {
this.resetForm('editForm')
},
getRoleList () {
this.$axios.get('/sys/role/list', {
params: {
name: this.searchForm.name,
current: this.current,
size: this.size
}
}).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
})
},
submitForm (formName) {
this.$refs[formName].validate((valid) = > {
if (valid) {
this.$axios.post('/sys/role/' + (this.editForm.id ? 'update' : 'save'), this.editForm)
.then(res= > {
this.$message({
showClose: true.message: 'Congratulations, it worked.'.type: 'success'.onClose: () = > {
this.getRoleList()
}
})
this.dialogVisible = false
this.resetForm(formName)
})
} else {
console.log('error submit!! ')
return false
}
})
},
editHandle (id) {
this.$axios.get('/sys/role/info/' + id).then(res= > {
this.editForm = res.data.data
this.dialogVisible = true
})
},
delHandle (id) {
var ids = []
if (id) {
ids.push(id)
} else {
this.multipleSelection.forEach(row= > {
ids.push(row.id)
})
}
console.log(ids)
this.$axios.post('/sys/role/delete', ids).then(res= > {
this.$message({
showClose: true.message: 'Congratulations, it worked.'.type: 'success'.onClose: () = > {
this.getRoleList()
}
})
})
},
permHandle (id) {
this.permDialogVisible = true
this.$axios.get('/sys/role/info/' + id).then(res= > {
this.$refs.permTree.setCheckedKeys(res.data.data.menuIds)
this.permForm = res.data.data
})
},
submitPermFormHandle (formName) {
var menuIds = this.$refs.permTree.getCheckedKeys()
console.log(menuIds)
this.$axios.post('/sys/role/perm/' + this.permForm.id, menuIds).then(res= > {
this.$message({
showClose: true.message: 'Congratulations, it worked.'.type: 'success'.onClose: () = > {
this.getRoleList()
}
})
this.permDialogVisible = false
this.resetForm(formName)
})
}
}
}
</script>
<style scoped>
.el-pagination {
float: right;
margin-top: 22px;
}
</style>
Copy the code
The user interface
The user page
User management has an operation called role assignment, which is similar to the operation of adding permissions to roles
<template>
<div>
<el-form :inline="true">
<el-form-item>
<el-input
v-model="searchForm.username"
placeholder="Username"
clearable
>
</el-input>
</el-form-item>
<el-form-item>
<el-button @click="getUserList">search</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="dialogVisible = true" v-if="hasAuth('sys:user:save')">new</el-button>
</el-form-item>
<el-form-item>
<el-popconfirm title="Is this a definitive batch delete?" @confirm="delHandle(null)">
<el-button type="danger" slot="reference" :disabled="delBtlStatu" v-if="hasAuth('sys:user:delete')">Batch delete</el-button>
</el-popconfirm>
</el-form-item>
</el-form>
<el-table
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
style="width: 100%"
border
stripe
@selection-change="handleSelectionChange">
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column
label="Avatar"
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="Username"
width="120">
</el-table-column>
<el-table-column
prop="code"
label="Role Name">
<template slot-scope="scope">
<el-tag size="small" type="info" v-for="item in scope.row.sysRoles">{{item.name}}</el-tag>
</template>
</el-table-column>
<el-table-column
prop="email"
label="Email">
</el-table-column>
<el-table-column
prop="phone"
label="Mobile phone Number">
</el-table-column>
<el-table-column
prop="statu"
label="State">
<template slot-scope="scope">
<el-tag size="small" v-if="scope.row.statu === 1" type="success">normal</el-tag>
<el-tag size="small" v-else-if="scope.row.statu === 0" type="danger">disable</el-tag>
</template>
</el-table-column>
<el-table-column
prop="created"
width="200"
label="Creation time"
>
</el-table-column>
<el-table-column
prop="icon"
width="260px"
label="Operation">
<template slot-scope="scope">
<el-button type="text" @click="roleHandle(scope.row.id)">Assign roles</el-button>
<el-divider direction="vertical"></el-divider>
<el-button type="text" @click="repassHandle(scope.row.id, scope.row.username)">To reset your password</el-button>
<el-divider direction="vertical"></el-divider>
<el-button type="text" @click="editHandle(scope.row.id)">The editor</el-button>
<el-divider direction="vertical"></el-divider>
<template>
<el-popconfirm title="Is this a paragraph of content to delete?" @confirm="delHandle(scope.row.id)">
<el-button type="text" slot="reference">delete</el-button>
</el-popconfirm>
</template>
</template>
</el-table-column>
</el-table>
<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>
<! -- New dialog box -->
<el-dialog
title="Tip"
:visible.sync="dialogVisible"
width="600px"
:before-close="handleClose">
<el-form :model="editForm" :rules="editFormRules" ref="editForm">
<el-form-item label="Username" prop="username" label-width="100px">
<el-input v-model="editForm.username" autocomplete="off"></el-input>
<el-alert
title="Initial password is 888888"
:closable="false"
type="info"
style="line-height: 12px;"
></el-alert>
</el-form-item>
<el-form-item label="Email" prop="email" label-width="100px">
<el-input v-model="editForm.email" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="Mobile phone Number" prop="phone" label-width="100px">
<el-input v-model="editForm.phone" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="State" prop="statu" label-width="100px">
<el-radio-group v-model="editForm.statu">
<el-radio :label="0">disable</el-radio>
<el-radio :label="1">normal</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="resetForm('editForm')">Take away</el-button>
<el-button type="primary" @click="submitForm('editForm')">determine</el-button>
</div>
</el-dialog>
<! Assign permissions dialog box -->
<el-dialog title="Assign roles" :visible.sync="roleDialogFormVisible" width="600px">
<el-form :model="roleForm">
<el-tree
:data="roleTreeData"
show-checkbox
ref="roleTree"
:check-strictly=checkStrictly
node-key="id"
:default-expand-all=true
:props="defaultProps">
</el-tree>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="roleDialogFormVisible=false">Take away</el-button>
<el-button type="primary" @click="submitRoleHandle('roleForm')">determine</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'SysUser',
data () {
return {
searchForm: {},
delBtlStatu: true.total: 0.size: 10.current: 1.dialogVisible: false.editForm: {},tableData: [].editFormRules: {
username: [{required: true.message: 'Please enter user name'.trigger: 'blur'}].email: [{required: true.message: 'Please enter email address'.trigger: 'blur'}].statu: [{required: true.message: 'Please select status'.trigger: 'blur'}},multipleSelection: [].roleDialogFormVisible: false.defaultProps: {
children: 'children'.label: 'name'
},
roleForm: {},
roleTreeData: [].treeCheckedKeys: [].checkStrictly: true
}
},
created () {
this.getUserList()
this.$axios.get('/sys/role/list').then(res= > {
this.roleTreeData = res.data.data.records
})
},
methods: {
toggleSelection (rows) {
if (rows) {
rows.forEach(row= > {
this.$refs.multipleTable.toggleRowSelection(row)
})
} else {
this.$refs.multipleTable.clearSelection()
}
},
handleSelectionChange (val) {
console.log('tick')
console.log(val)
this.multipleSelection = val
this.delBtlStatu = val.length === 0
},
handleSizeChange (val) {
console.log(` per page${val}Article `)
this.size = val
this.getUserList()
},
handleCurrentChange (val) {
console.log('Current page:${val}`)
this.current = val
this.getUserList()
},
resetForm (formName) {
this.$refs[formName].resetFields()
this.dialogVisible = false
this.editForm = {}
},
handleClose () {
this.resetForm('editForm')
},
getUserList () {
this.$axios.get('/sys/user/list', {
params: {
username: this.searchForm.username,
current: this.current,
size: this.size
}
}).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
})
},
submitForm (formName) {
this.$refs[formName].validate((valid) = > {
if (valid) {
this.$axios.post('/sys/user/' + (this.editForm.id ? 'update' : 'save'), this.editForm)
.then(res= > {
this.$message({
showClose: true.message: 'Congratulations, it worked.'.type: 'success'.onClose: () = > {
this.getUserList()
}
})
this.dialogVisible = false})}else {
console.log('error submit!! ')
return false
}
})
},
editHandle (id) {
this.$axios.get('/sys/user/info/' + id).then(res= > {
this.editForm = res.data.data
this.dialogVisible = true
})
},
delHandle (id) {
var ids = []
if (id) {
ids.push(id)
} else {
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: 'Congratulations, it worked.'.type: 'success'.onClose: () = > {
this.getUserList()
}
})
})
},
roleHandle (id) {
this.roleDialogFormVisible = true
this.$axios.get('/sys/user/info/' + id).then(res= > {
this.roleForm = res.data.data
const roleIds = []
res.data.data.sysRoles.forEach(row= > {
roleIds.push(row.id)
})
this.$refs.roleTree.setCheckedKeys(roleIds)
})
},
submitRoleHandle (formName) {
var roleIds = this.$refs.roleTree.getCheckedKeys()
console.log(roleIds)
this.$axios.post('/sys/user/role/' + this.roleForm.id, roleIds).then(res= > {
this.$message({
showClose: true.message: 'Congratulations, it worked.'.type: 'success'.onClose: () = > {
this.getUserList()
}
})
this.roleDialogFormVisible = false
})
},
repassHandle (id, username) {
this.$confirm('will reset user [' + username + '] password, do you want to continue? '.'tip', {
confirmButtonText: 'sure'.cancelButtonText: 'cancel'.type: 'warning'
}).then(() = > {
this.$axios.post('/sys/user/repass', id).then(res= > {
this.$message({
showClose: true.message: 'Congratulations, it worked.'.type: 'success'.onClose: () = >{}})})})}}}</script>
<style scoped>
.el-pagination {
float: right;
margin-top: 22px;
}
</style>
Copy the code
Button permission control
The menu above, the role, the actions that the user has, not every user has, users without permissions we should hide the button. SRC/globalfun.js SRC/globalfun.js
import Vue from 'vue'
Vue.mixin({
methods: {
hasAuth (perm) {
var authority = this.$store.state.menus.permList
return authority.indexOf(perm) > -1}}})Copy the code
In the shelf menu, we need to frame the permission data at the same time. Now we need to use the array of permission data here, so we can pass the button whether the permission is in the permission list. The function of mixins is that multiple components can share data and methods. After being introduced into components that use mixins, methods and attributes in mixins are incorporated into the components and can be directly used to expand existing component data and methods. Import this file SRC \main.js in main.js
import gobal from "./globalFun"
Copy the code
SRC /views/sys/ menu.vue
<el-button type="primary" @click="dialogFormVisible = true" v-if="hasAuth('sys:menu:save')"> new < / el - button >Copy the code
V-if is used to determine whether the return is true.The effectThere is no new button when logging in to testAdmin time is there