前言:之前后台管理系统只是写了两个页面并没有分开布局
所用到的技术栈:
vue-element-ui |
vue-vuex |
vue-router |
vue-axios |
这篇文章是按照上篇文章进行了大幅度修改,并且使用多页面进行布局。效果看起来会比之前的好一些
下面我们来看一下这种写法的实现效果
登录页面默认为Login页面
如果这里随便输入路径也会自动跳回登录页面
对表单验证进行了改进
管理员权限页面
普通用户页面
把整个页面进行了分割,一个部分一个页面,这样的话复用性比较强
下面是页面结构
还有一个axios.js上面没有截取到
下面是实战代码:
Header.vue:这个页面就是放在普通用户页面和管理员页面的头部
<template>
<div class="header">
<div class="header-left">
<div class="left">KGC后台管理系统</div>
</div>
<div class="header-right">
<div class="header-right__logout">
<el-button type="danger" size="20" @click="logout">退出</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("您确定要退出吗, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
window.sessionStorage.clear();
this.$message({
message: "你已经退出登陆!请重新登录账号",
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:直接在生成好的模板的let config={里面写入此接口}
baseURL: 'http://localhost:3000'
Login.vue页面:!!这个页面主要就是布局一下登陆页面,然后对登录按钮进行一个验证,如果数据中的账号中不存在所输入的账号,那么就会判断没有这个账号;
如果所输入的账号与数据中的账号相匹配,那么会判断是否为管理员账号,如果是管理员账号并且输入的密码与数据中的密码相匹配,那么就进入管理员页面;
如果是普通用户的账号,并且输入的密码与数据中的密码相匹配那么就进入用户页面
<template>
<div class="home">
<div class="homebox" v-loading="loading">
<h3>KGC后台管理系统</h3>
<el-input
class="input"
v-model="username"
style="width: 500px"
placeholder="用户名"
></el-input>
<el-input
class="input"
placeholder="密码"
style="width: 500px"
v-model="password"
show-password
></el-input>
<el-button
type="primary"
size="medium "
@click="login"
style="width: 500px"
>登陆</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("账号不存在,请重新输入!");
} 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: "欢迎来到管理员页面!您已经超过了99%的用户",
type: "success",
});
window.sessionStorage.setItem('username',this.username)
this.$router.push("./Page");
} else {
this.loading = false;
this.$message.error("密码错误,请重新输入");
}
}else{
var index = uname.indexOf(this.username);
console.log(passw[index]);
if (passw[index] == this.password) {
this.loading = false;
this.$message({
message: "欢迎登陆用户页面!!!",
type: "success",
});
window.sessionStorage.setItem('username',this.username)
this.$router.push("./Page2");
} else {
this.loading = false;
this.$message.error("密码错误,请重新输入");
}
}
}, 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页面:这个页面就是显示了用户管理和商品管理两个导航菜单,当每次点击时会进入所对应的数据页面,也就是存放用户管理中的数据和商品管理中的数据页面
<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">用户管理</span>
</el-menu-item>
<el-menu-item index="2" @click="btn2">
<i class="el-icon-setting"></i>
<span slot="title">商品管理</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页面:这个页面就是普通用户的页面,只有一个商品管理的一个导航菜单
<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">商品管理</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页面:这个页面主要是写了数据项包括后面的一个删除按钮,删除按钮是假删除有两种方法,第二种方法我这里给注释掉了。这里直接获取数据用:data="tableData"获取数据
<template>
<div>
<el-table :data="tableData" v-loading="loading">
<el-table-column prop="id" label="编号" width="180"> </el-table-column>
<el-table-column prop="name" label="用户名" width="180">
</el-table-column>
<el-table-column prop="role" label="角色"> </el-table-column>
<el-table-column prop="phone" label="手机号码"> </el-table-column>
<el-table-column prop="email" label="邮箱"> </el-table-column>
<el-table-column prop="role" label="操作">
<template v-slot="scope">
<el-button
type="danger"
size="mini"
@click="deleteData(scope.$index.tableData)"
>删除</el-button
>
<!-- @click="deleteData(scope.row.name)" -->
<el-dialog title="提示" width="30%">
<span class="warcont"
><i class="el-icon-warning"></i>是否确定要删除该用户</span
>
<span slot="footer" class="dialog-footer">
<el-button>取 消</el-button>
<el-button type="primary">确 定</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('此操作将永久删除该文件, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$message({
type: 'success',
message: '删除成功!'
});
/* 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: '已取消删除'
});
});
},
handleClick(tab, event) {
console.log(tab, event);
},
},
};
</script>
Commodity.vue页面:与user.vue页面方法一致,只不过这个页面是商品管理页面的数据
<template>
<el-table
border
style="width: 100%"
:data="table"
v-loading="loading"
element-loading-text="拼命加载中"
>
<el-table-column prop="id" label="编号" width="180"> </el-table-column>
<el-table-column prop="name" label="商品名称" width="180">
</el-table-column>
<el-table-column prop="price" label="单价"> </el-table-column>
<el-table-column prop="number" label="库存"> </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页面:这个页面就是防止页面出错以及复制管理员地址所产生的报错页面,这里没有用到,可以忽略
<template>
<div class="not-found">
<h1>啊哦!找不到相关页面o(╥﹏╥)o。</h1>
<router-link to>
<p @click="$router.back(-1)">返回上一级页面</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>
接下来就是路由页面了:
router.js页面:这个页面最为重要,当页面为/时会重定向到Login登录页面,用导航守卫去限制不必要的链接把Page页面和Page2页面作为父路由,把user以及commodity作为子路由进行绑定。并且重写了原型上的push方法,解决一些不知道会报啥错误的信息
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;
// 重写了原型上的push方法,统一的处理了错误信息
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch((err) => err);
};
export default router;
store.js页面:这个页面主要是用来存储获取到的数据并把他们放在数组中,使用载荷的方式去其他页面进行调用
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') || '[]'),
},
// 存储用户管理页面数据
mutations: {
addrecord(state,preload){
state.tableData = preload
window.sessionStorage.setItem('rightsList',JSON.stringify(preload))
},
// 存储商品管理数据
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: {
}
})
接下来就是一些常用的配置文件页面
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页面:主要是用来渲染公共样式
<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)