后台管理系统
创建项目
一、登录页面
下载element-ui插件,引入element-ui
npm i element-ui -S
下载less less-loader
npm install less less-loader --save-dev
设置base.css设置全局样式,然后引入到main.js中,
设置登录框,用到了position:absolute,绝对定位以及transfrom设置登录框居中
利用element-ui 的el-from组件
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="姓名" prop="username">
<el-input v-model:"ruleForm.username"></el-input>
</el-form-item>
</el-form>
export default{
data(){
ruleForm:{
username:"",
password:""
}
}
}
通过v-model双向绑定,获取用户输入的姓名和密码,
给登录按钮添加点击点击事件,点击事件触发后,通过validate方法检验输入是否合法,合法的话,通过axios访问接口,
//在main.js中引入axios
import axios from 'axios'
Vue.prototype.$http = axios
axios.defaults.baseURL = '接口地址'
//使用axios发送 post请求
this.$http({
methods:'post',
url:'login',
data:{
username:username;
password:password
}
}).then(res=>{
consle.log(res)
}).catch(err=>{
console.log(err)
})
res中的信息,data中有一个status参数,就是状态码,登录成功的话为200
如果状态码不是200,则返回登录失败的信息
这里用到了element-ui中的message提示方法
如果登录成功的话,就获取res中的data里的token值,将token保存到本地,并且路由跳转到首页
this.$message.success('登录成功');
window.sessionStorage.setItem("token",res.data.token)
this.$router.push('/home')
路由导航守卫控制访问权限
通过用户想要访问的地址 以及手里是否拿着token 来决定用户具体决定访问哪个界面
如果用户没有登录,但是直接通过URL访问特定页面,需要重新导航到登录页面
beforeEach
前置钩子函数,在路由跳转之前进行回调,将url改掉
router.beforeEach((to,from,next)=>{
})
to:要去的地址
from:从哪来的地址
next:放行
导航守卫
router.beforeEach((to,from,next)=>{
if(to.path === '/login') {
return next() //如果要访问的页面就是登录页,直接放行
}
const tokenStr = window.sessionStorage.getItem('token')
if(!tokenStr){
return next('/login') 如果传过来token为空,则取反为true,满足条件,强制跳转到登录页面
}
next()
})
登录退出
销毁本地的token
//清空token
window.sessionStorge.clear()
//跳转到登录页面
this.$router.push('/login')
请求拦截
axios.interceptors.request.use(config => {
console.log(config);
config.headers.Authorization = window.sessionStorage.getItem("token");
return config;
});
学到的一个小点
想要改变element-ui el-input 组件获得焦点后边框样式的高亮颜色
用到了input的deep深穿透
input的 父级class /deep/ .el-input__inner:focus{ border-color:red}
border-sizing
二、主页面
首先是总体布局,用了element-ui的lContainer 布局容器
侧边栏容器就是放tabbar导航栏,用了NavMenu 导航菜单组件
分为以及标题和二级标题
然后一级标题的具体内容通过v-for循环遍历接口中的数据进行渲染
根据二级标题,建立各个组件的页面,并添加到路由中,
实现二级标题和路由的绑定 是通过element-ui提供了 router属性,给二级标题添加了router属性的话,点击二级标题,url就跳到了对应的路径
/v-for=“item in menulist”//一级标题循环遍历 <el-submenu :index="item.id + ''" v-for="item in menulist" :key="item.id" > //二级标题的v-for循环遍历<el-menu-item :index="subitem.id + ''" v-for="subitem in item.children" :key="subitem.id"> data(){ return { menulist:[] }}created(){ this.getMenulist() //通过生命周期函数,自动执行函数}//通过axios get请求获取数据getMenulist(){ this.$http.get('menus').then(res=>{ console.log(res)}).catch(err=>{ console.log(err)})}
用户管理
1.用户列表

用户列表界面
1.布局
头部用到面包屑布局
中间用到卡片布局
卡片布局中头部是 一个搜索框 和一个按钮
中间是一个table表格
尾部是一个分页组件
2.功能实现
搜索功能
clear 在点击由 clearable 属性生成的清空按钮时触发
clearable 是否可清空
clearable就是后面多了一个小 × 号

clear 动态绑定 获取用户列表方法,就是实现在清空之后 列表回到之前的样子
添加用户
给添加用户按钮添加 点击事件,点击事件触发后 弹出添加用户框
添加dialog组件,布尔值首先设置为false,点击事件触发后,将false 改为true
中间的部分 运用 “From表单”进行布局
调用接口发送 post请求,将表单中的数据 当做post请求的data数据,发送请求,然后通过promise的返回值判断res中的信息,如果status为200那么就是添加成功

用户列表
首先用到table组件进行布局,
然后创建 获取用户列表的事件,通过axios发送get请求,获取到res.data
并在生命周期函数created( )中调用,一经创建就渲染列表
如何将true和false的布尔值 装换成状态按钮
用到template 的插槽,然后用到switch开关组件,
v-model的值就是 获取到的状态值
<template slot-scope="scope">{{scope.row}}</template>
<template slot-scope="scope"> <!-- {{ scope.row }} --> <el-switch v-model="scope.row.mg_state" active-color="#eeb928" @change="userStateChange(scope.row)" > </el-switch> </template>
操作栏
用到了三个插槽,分别写入三个button按钮

第一个为编辑按钮
点击之后,弹出修改对话框,中间布局用到from表单,然后添加点击事件,点击之后发送get请求,通过id获取到当前ida对应的用户数据,并渲染到界面
取消按钮点击之后,就将修改对话框的布尔值改为false,
点击确定按钮之后,要发送put请求,调用接口,返回promise的返回值,判断修改成功还是失败

删除按钮
弹出提示框 提醒是否真正删除

给取消按钮添加 事件,点击取消后,返回信息 “取消成功”
点击确定按钮之后,发送delete请求,通过返回值判断是否删除成功
分配角色

权限管理
2.权限管理

1.布局
头部面包屑
中间 卡片 布局
用到table组件进行布局
2.功能实现
创建 获取权限列表的事件,并添加到生命周期函数created()中,一经创建便渲染到页面上,
然后权限等级列表
通过template插槽,添加button按钮,然后通过v-if , v-else-if, v-else 分别对应获取到了权限的0 1 2的数值,
然后给按钮添加不同的type类型,然后实现等级按钮的出现

权限管理 用户管理 角色管理 三者关系
用户绑定了不同的角色,把权限分配各不同的角色
3.角色列表


1.布局
添加角色按钮
卡片组件布局
(列表分为 展开列 和索引列)
展开列布局:
设置el-row 标签 包含两个el-col标签,分别存放一级权限 和二三级权限

二三级权限的布局

定义el-row标签,存放两个el-col标签,用来存放二级权限列表和三级权限列表
通过v-for 循环遍历 item1.children,渲染到界面,
二级权限每行的值 就是 item2.authName,
三级权限 就在el-tag中 利用v-vor循环 item2.children ,渲染出 item3.authName的值
2.功能实现
展开列
通过设置 type="expand" 和 Scoped slot 可以开启展开行功能,el-table-column 的模板会被渲染成为展开行的内容,展开行可访问的属性与使用自定义列模板时的 Scoped slot 相同。
展开列就是利用 el-table组件 类型值设置为expand, 就是展开列,然后加入template插槽,插槽里有三级菜单,所以进行三次渲染
设置el-row标签 通过v-for循环遍历 scope.row.children ,渲染一级菜单,
然后设置el-col行标签,每一行的值都是 scope.row.children 的每一项的authName
通过el-tag标签 将文字 渲染成 标签样式
<!-- 展开列 --> <el-table-column type="expand"> <template slot-scope="scope"> <el-row v-for="item1 in scope.row.children" :key="item1.id"> <!-- 渲染一级权限 --> <el-col :span="5"> <el-tag>{{ item1.authName }}</el-tag> <i class="el-icon-caret-right"></i> </el-col> <!-- 渲染二级和三级权限 --> <el-col :span="19"> <!-- 通过for循环渲染二级权限 --> <el-row v-for="secitem in item1.children" :key="secitem.id"> <!-- 左边渲染二级权限 --> <el-col :span="6"> <el-tag type="success">{{ secitem.authName }}</el-tag> <i class="el-icon-caret-right"></i> </el-col> <!-- 右边渲染三级权限 --> <el-col :span="18"> <el-tag v-for="thitem in secitem.children" :key="thitem.id" > {{ thitem.authName }} </el-tag> </el-col> </el-row> </el-col> </el-row> </template> </el-table-column>
索引列
通过table组件设置布局,调用接口发送get请求,将数据渲染到页面
设置getroledata函数方法,并添加到生命周期函数中,当访问界面,就请求数据渲染到页面上
添加角色
给按钮添加click点击事件,点击之后弹出dialog的弹出框,将弹出框的布尔值改为true,
然后给确定按钮添加点击事件,
并在方法中发送post请求,data的值就为,设置的表单数据,
根据promise的返回值判断是否成功添加
操作

编辑按钮和操作按钮就是针对这个表格,编辑这一行的数据 或者删除这一行的数据,跟其他无关
编辑按钮,删除按钮,分配权限按钮 都是添加在插槽里的
然后按钮的点击事件都是在插槽里的,
并且能通过插槽的scope 获取到整行的数据scop.row
之后 通过传过来的id进行一些操作
编辑按钮

编辑按钮添加点击事件,点击之后 弹出框的布尔值变为true
并通过接口发送get请求,通过传过来的scope.row.id 作为id值进行数据的调用
修改数据之后,给确定按钮添加事件,发送post请求,通过promise的返回值判断是否修改成功
调用接口数据是在
删除按钮

删除按钮,添加点击事件,点击删除按钮之后,弹出提示框,点击取消的话值为config,确定的话值为confirm,
如果是confirm 就发送delete请求,将数据删除,通过promise返回值判断是否删除成功
给取消添加取消成功的提示,就是当值为config时,返回,this.$message.info('取消成功')
分配权限按钮

弹出框用了el-tree布局
点击分配权限按钮,将弹框的布尔值改为true,
并发送get请求,获取数据列表,
给确定按钮添加点击事件,
//将所有被选中的小标签和半个的小标签都获取到 组成一个新的数组
//将数组改成 以逗号拼接的字符串
const idStr = keys.join(",");
发送post 请求,然后通过promise的返回值判断添加成功或失败
商品管理
4.商品分类



1.布局
面包屑导航条
添加分类的按钮,有父级分类的选择框
然后卡片布局
一个树形表格,将分类级别展示出来
然后 分页组件
2.功能
- 添加分类按钮
给按钮添加点击事件,点击事件触发后,将弹出框的布尔值改为true,
设置弹窗布局,el-from>el-from-item>el-input设置 键值输入框
设置父级分类,el-form-item>el-select
这个选择框的作用就是 选择父级分类之后,获取到最后的父级id的值 以及 自己的等级值
创建 获取父级分类的函数方法,点击按钮之后,调用获取父级分类的方法,得到父级分类列表,
:options 将父级分类列表 动态的添加给参数
选择框里进行选择,通过双向绑定,获取到父级分类的id值,进行判断,如果这个数组里的值的长度大于零时,
说明选择了,然后就将最后一级的父级id值给到数据列表里的id值,然后等级值就是数组的长度值,
点击确定按钮之后,发送post请求,将数据提交,然后通过promise的返回值 确定是否提交成功
- 表格布局
用到了tree-table布局,然后里面的每一列 都通过 columns定义,定义了type=template 之后,通过template标签
定义具体的列
一级 二级 三级 等级列
通过el-tag标签定义 一级二级三级的标签,然后通过v-if v-else-if v-else 来决定哪个标签显示
5.商品列表



时间的转换 用到了filter 过滤器
Vue.filter("dataFormat", function(originVal) { const dt = new Date(originVal); const y = dt.getFullYear(); const m = (dt.getMonth() + 1 + "").padStart(2, "0"); const d = (dt.getDate() + "").padStart(2, "0"); const hh = (dt.getHours() + "").padStart(2, "0"); const mm = (dt.getMinutes() + "").padStart(2, "0"); const ss = (dt.getSeconds() + "").padStart(2, "0"); return `${y}-${m}-${d}-${hh}:${mm}:${ss}`;});
6.分类参数




用到tabs标签,v-model 双向绑定了活跃事件,给两个面板起了名字,谁获取 取到谁的值,
动态设置为many 静态设置为only
<el-tabs v-model=“activename” @click="tabsclick"> <tab-pane></tab-pane> <tab-pane></tab-pane><el-tabs>
弹出框 是共用的 一个弹出框
设置一个函数方法,动态的返回动态属性和静态属性的值,
如果activename当前等于many 那么返回动态属性 否则返回静态属性
就实现了动态获取标题的值
展开列的功能实现
定义一个template组件,然后定义el-tag 标签,并通过v-for 循环遍历本行的 标签值
这里需要补充说明的一点是 标签数据需要经过一些处理
从接口中调用出的数据 是 一个字符串形式
通过forEach 循环遍历 每一项 ,通过spilt添加空格 进行分割
它的返回值为一个数组
就实现了 字符串转换为数组
然后 设置v-tag标签,通过 v-for循环遍历数组 展示到标签列
这里用到的是forEach,没用map ,forEach 是在原来的基础上进行改变,map是产生一个新的数组
这里不能用新的数组,是因为在循环遍历标签的时候,是遍历获取到的数据列表里的值,map的话是产生了一个新的数组,无法进行调用
数据报表

怎么实现数据报表呢
下载Echart 插件,第一步引入echart
第二步,在卡片区域定义一个div 就是dom渲染的区域
第三步,在mounted函数中 基于准备好的dom,初始化echarts实例
初始化图标 必须要在dom元素都渲染完毕之后
第四步 // 指定图表的配置项和数据 (或发送请求获取数据)
第五步 // 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
优化
1.通过nprogress 添加进度条
下载插件,在main.js中引用,在axios拦截之前 nprogress.start( ) 在响应请求时nprogress.done( )

浙公网安备 33010602011771号