Before, the background management system only wrote two pages without separate layout
Technology stack used:
vue-element-ui |
vue-vuex |
vue-router |
vue-axios |
This article has been greatly modified according to the previous article, and uses multi page layout. The effect will look better than before
Let's take a look at the implementation effect of this writing method
The Login page defaults to the Login page
If you enter any path here, you will automatically jump back to the login page
Improved form validation
Administrator rights page
Ordinary user page
The whole page is divided into one part and one page. In this way, the reusability is strong
Here is the page structure
There is also an Axios JS is not intercepted
The following is the actual code:
Header.vue: this page is placed at the head of ordinary user page and administrator page
<template> <div class="header"> <div class="header-left"> <div class="left">KGC Background management system</div> </div> <div class="header-right"> <div class="header-right__logout"> <el-button type="danger" size="20" @click="logout">sign out</el-button> </div> <div class="header-right__info"> <div class="right">{{ name }}</div> </div> </div> </div> </template> <script> import { mapState } from "vuex"; export default { name: "Header", data() { return { name: "", }; }, mounted() { this.name = window.sessionStorage.getItem("username"); }, methods: { logout() { this.$confirm("Are you sure you want to exit, Continue?", "Tips", { confirmButtonText: "determine", cancelButtonText: "cancel", type: "warning", }) .then(() => { window.sessionStorage.clear(); this.$message({ message: "You have logged out! Please log in again", type: "warning", }); this.$router.push({ path: "/" }); }) .catch((err) => err); }, }, computed: { ...mapState(["user"]), }, }; </script> <style > .header { height: 50px; line-height: 50px; background-color: rgb(73, 80, 96); padding: 0 50px; color: #fff; } .left { color: #fff; float: left; } .header-right__info { float: right; margin: 0 20px; } .header-right__logout { float: right; } </style>
axios.js: directly write this interface in let config = {of the generated template}
baseURL: 'http://localhost:3000'
Login.vue page:!! This page is mainly to layout the login page, and then verify the login button. If the entered account does not exist in the account in the data, it will be judged that there is no such account;
If the entered account matches the account in the data, you will judge whether it is an administrator account. If it is an administrator account and the entered password matches the password in the data, you will enter the administrator page;
If it is an ordinary user's account, and the password entered matches the password in the data, then enter the user page
<template> <div class="home"> <div class="homebox" v-loading="loading"> <h3>KGC Background management system</h3> <el-input class="input" v-model="username" style="width: 500px" placeholder="user name" ></el-input> <el-input class="input" placeholder="password" style="width: 500px" v-model="password" show-password ></el-input> <el-button type="primary" size="medium " @click="login" style="width: 500px" >land</el-button > </div> </div> </template> <script> export default { name: "Login", data() { return { username: "admin", password: 123, loading: false, }; }, mounted() {}, methods: { login() { this.$axios.get("/users").then((v) => { this.loading = true; const uname = []; const passw = []; console.log(v); const res = v.data; for (var i = 0; i < res.length; i++) { uname.push(res[i].name); passw.push(res[i].pwd); } console.log(uname); console.log(passw); console.log(uname.indexOf(this.username) === -1); setTimeout(() => { if (uname.indexOf(this.username) === -1) { this.loading = false; this.$message.error("Account does not exist, please re-enter!"); } else if(uname.indexOf(this.username) != -1 && this.username == 'admin'){ var index = uname.indexOf(this.username); console.log(passw[index]); if (passw[index] == this.password) { this.loading = false; this.$message({ message: "Welcome to the administrator page! You have exceeded 99%User", type: "success", }); window.sessionStorage.setItem('username',this.username) this.$router.push("./Page"); } else { this.loading = false; this.$message.error("Password error, please re-enter"); } }else{ var index = uname.indexOf(this.username); console.log(passw[index]); if (passw[index] == this.password) { this.loading = false; this.$message({ message: "Welcome to the user page!!!", type: "success", }); window.sessionStorage.setItem('username',this.username) this.$router.push("./Page2"); } else { this.loading = false; this.$message.error("Password error, please re-enter"); } } }, 2000); }); }, }, }; </script> <style> body { background-color: rgb(238, 243, 250); } .homebox { text-align: center; position: absolute; top: 50%; left: 50%; margin-top: -150px; margin-left: -300px; width: 600px; height: 300px; background-color: rgb(255, 255, 255); } h3 { padding: 20px 0; } .input { margin-bottom: 20px; } </style>
Page.vue page: this page displays two navigation menus: user management and commodity management. Each click will enter the corresponding data page, that is, the data page in user management and commodity management
<template> <div> <el-container> <el-col :span="3"> <el-menu default-active="1" class="el-menu-vertical-demo"> <el-menu-item index="1" @click="btn1"> <i class="el-icon-menu"></i> <span slot="title">user management </span> </el-menu-item> <el-menu-item index="2" @click="btn2"> <i class="el-icon-setting"></i> <span slot="title">Commodity management</span> </el-menu-item> </el-menu> </el-col> <el-main> <router-view></router-view> </el-main> </el-container> </div> </template> <script> import Header from "../components/Header"; export default { name: "Page", data() { return { loading: false, }; }, mounted() {}, components: { Header, }, methods: { btn1() { this.$router.push("./user"); }, btn2() { this.$router.push("./commodity"); }, handleOpen(key, keyPath) { console.log(key, keyPath); }, handleClose(key, keyPath) { console.log(key, keyPath); }, }, }; </script> <style scoped> </style>
Page2.vue page: this page is the page of ordinary users. There is only one navigation menu for commodity management
<template> <div> <el-container> <el-col :span="3"> <el-menu default-active="1" class="el-menu-vertical-demo"> <el-menu-item index="2"> <i class="el-icon-setting"></i> <span slot="title">Commodity management</span> </el-menu-item> </el-menu> </el-col> <el-main> <router-view></router-view> </el-main> </el-container> </div> </template> <script> import Header from "../components/Header"; export default { name: "Page", data() { return { loading: false, }; }, mounted() {}, components: { Header, }, methods: { handleOpen(key, keyPath) { console.log(key, keyPath); }, handleClose(key, keyPath) { console.log(key, keyPath); }, }, }; </script> <style scoped> /* .el-main { padding: 0; } */ </style>
User.vue page: this page mainly writes data items, including a delete button behind it. The delete button is false deletion. There are two methods. I have commented out the second method here. Here, you can get the data directly. Use data="tableData" to get the data
<template> <div> <el-table :data="tableData" v-loading="loading"> <el-table-column prop="id" label="number" width="180"> </el-table-column> <el-table-column prop="name" label="user name" width="180"> </el-table-column> <el-table-column prop="role" label="role"> </el-table-column> <el-table-column prop="phone" label="phone number"> </el-table-column> <el-table-column prop="email" label="mailbox"> </el-table-column> <el-table-column prop="role" label="operation"> <template v-slot="scope"> <el-button type="danger" size="mini" @click="deleteData(scope.$index.tableData)" >delete</el-button > <!-- @click="deleteData(scope.row.name)" --> <el-dialog title="Tips" width="30%"> <span class="warcont" ><i class="el-icon-warning"></i>Are you sure you want to delete this user</span > <span slot="footer" class="dialog-footer"> <el-button>Cancel</el-button> <el-button type="primary">determine</el-button> </span> </el-dialog> </template> </el-table-column> </el-table> </div> </template> <script> import { mapState } from "vuex"; export default { name: "User", data() { return { loading: false, }; }, computed: { ...mapState(["tableData"]), }, mounted() { this.loading = true; setTimeout(() => { this.loading = false; this.$axios.get("/users").then((res) => { const home = res.data; this.$store.commit("addrecord", home); }); }, 500); }, methods: { // deleteData(name) deleteData(index,row){ this.$confirm('This action will permanently delete the file, Continue?', 'Tips', { confirmButtonText: 'determine', cancelButtonText: 'cancel', type: 'warning' }).then(() => { this.$message({ type: 'success', message: 'Delete succeeded!' }); /* var index = this.tableData.findIndex(item => { return item.name === name; }); this.tableData.splice(index,1) */ this.tableData.splice(index,1) }).catch(() => { this.$message({ type: 'info', message: 'Deletion cancelled' }); }); }, handleClick(tab, event) { console.log(tab, event); }, }, }; </script>
Commodity.vue page: with user Vue page has the same method, except that this page is the data of commodity management page
<template> <el-table border style="width: 100%" :data="table" v-loading="loading" element-loading-text="Loading desperately" > <el-table-column prop="id" label="number" width="180"> </el-table-column> <el-table-column prop="name" label="Trade name" width="180"> </el-table-column> <el-table-column prop="price" label="Unit Price"> </el-table-column> <el-table-column prop="number" label="stock"> </el-table-column> </el-table> </template> <script> import { mapState } from "vuex"; export default { name: "Commodity", data() { return { loading: false, }; }, mounted() { this.loading = true; clearTimeout(clear) var clear = setTimeout(() => { this.$axios.get("/goods").then((v) => { const com = v.data; this.$store.commit("record", com); this.loading = false }) }, 300); }, computed: { ...mapState(["table"]), }, }; </script>
* 404 page: this page is to prevent page errors and error reports generated by copying the administrator address. It is not used here and can be ignored
<template> <div class="not-found"> <h1>Ah, oh! No related pages found o(╥﹏╥)o. </h1> <router-link to> <p @click="$router.back(-1)">Return to previous page</p> </router-link> </div> </template> <script> export default { name:'Found' } </script> <style lang="less" scoped> .not-found { width: 100%; height: 100vh; background-color: #6495ED; display: flex; justify-content: center; align-items: center; h1 { margin: 0; color: #fff; } a { color: #E0FFFF; font-size: 14px; font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; transform: translateY(10px); } } </style>
Next is the routing page:
router.js page: this page is the most important. When the page is / it will be redirected to the Login page. Use the navigation guard to limit unnecessary links. Take the page page and Page2 page as the parent route and bind the user and commodity as the child route. It also rewrites the push method on the prototype to solve some information that does not know what error will be reported
import Vue from "vue"; import VueRouter from "vue-router"; import Login from "../views/Login.vue"; import Page from "../views/Page.vue"; import Page2 from "../views/Page2.vue"; import User from "../views/User.vue"; import Commodity from "../views/Commodity.vue"; import Header from "../components/Header.vue"; Vue.use(VueRouter); const routes = [ { path: "/", redirect: "/Login", }, { path: "/Login", name: "Login", component: Login, }, { path: "/page", name: "Page", components: { default: Page, Header, }, children: [ { path: "/page", redirect: "/page/user", }, { path: "/page/user", name: "User", component: User, }, { path: "/page/commodity", name: "Commodity", component: Commodity, }, ], }, { path: "/page2", name: "Page2", components: { default: Page2, Header, }, children: [ { path: "/page2", redirect: "/page2/commodity", }, { path: "/page2/commodity", name: "Commodity", component: Commodity, }, ], }, ]; const router = new VueRouter({ routes, mode: "history", }); router.beforeEach((to, from, next) => { if (to.path == "/login") { next(); } else { let token = window.sessionStorage.getItem("username"); console.log(token); if (!token) { next("/login"); } else { next(); } } }); const originalPush = VueRouter.prototype.push; // The push method on the prototype is rewritten to deal with the error information uniformly VueRouter.prototype.push = function push(location) { return originalPush.call(this, location).catch((err) => err); }; export default router;
store.js page: this page is mainly used to store the obtained data, put them in the array, and use the load method to call other pages
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { tableData:[], table:[], user:JSON.parse(window.sessionStorage.getItem('user') || '[]'), }, // Store user management page data mutations: { addrecord(state,preload){ state.tableData = preload window.sessionStorage.setItem('rightsList',JSON.stringify(preload)) }, // Store commodity management data record(state,preload){ state.table = preload console.log(state.table); window.sessionStorage.setItem('liftList',JSON.stringify(preload)) }, setUser(state,preload){ state.user = preload; window.sessionStorage.setItem('user',JSON.stringify(state.user)); }, }, actions: { }, modules: { } })
Next are some common profile pages
main.js
import Vue from 'vue' import './plugins/axios' import App from './App.vue' import store from './store' import router from './router' import './plugins/element.js' Vue.config.productionTip = false new Vue({ store, router, render: h => h(App) }).$mount('#app')
App.vue page: mainly used to render public styles
<template> <div id="app"> <router-view name="Header"></router-view> <router-view></router-view> </div> </template> <script> export default { name: "app", }; </script> <style> *{margin: 0;padding: 0;} </style>
element.js
import Vue from 'vue' import Element from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' Vue.use(Element)