哔哩哔哩Allen老师通用后台管理系统
一、项目效果
二、项目版本,技术栈
node.js 16.16.0
vue-cli 5.0.8
vue-router 3.6.5
技术栈:vue2,vuex,element-ui,ajax,js-cookie,mockjs
三、配置vue-router3
下载vue-router,地址安装 | Vue Router
yarn add vue-router@3.6.5
在src的router目录下创建index.js,引入vue-router
四、下载预处理器stylus,stylus-loader
yarn stylus stylus-loader@5.0.0
关闭eslint
五、设置嵌套路由
六、element-ui按需引入
npm i element-ui -S
npm install babel-plugin-component -D
注意message消息提示,调用方法和其他组件不同
七、首页布局,main组件引入container
element-ui网址 Element - The world's most popular Vue UI framework
选择倒数第二个布局
八、侧边栏commonAside菜单
侧边栏是公共组件,放在components中
调整成我们想要的效果
<template><div><el-menudefault-active="2"class="el-menu-vertical-demo"@open="handleOpen"@close="handleClose"background-color="#545c64"text-color="#fff"active-text-color="#ffd04b"><h3>通用后台管理系统</h3><el-menu-item index="2"><i class="el-icon-menu"></i><span slot="title">导航二</span></el-menu-item><el-menu-item index="3"><i class="el-icon-menu"></i><span slot="title">导航二</span></el-menu-item><el-submenu index="1"><template slot="title"><i class="el-icon-location"></i><span>导航一</span></template><el-menu-item-group><el-menu-item index="1-1">选项1</el-menu-item><el-menu-item index="1-2">选项2</el-menu-item></el-menu-item-group></el-submenu></el-menu></div>
</template><script>export default {methods: {handleOpen(key, keyPath) {console.log(key, keyPath);},handleClose(key, keyPath) {console.log(key, keyPath);}}}
</script><style lang="stylus" scoped>
.el-menuheight: 100vhborder-right: nonecolor #fffh3color: #ffftext-align: centerline-height: 48pxfont-size: 16pxfont-weight: 400
</style>
去掉白边
创建menuData数组,判断有无子菜单,遍历侧边栏菜单
<template><div><el-menudefault-active="2"class="el-menu-vertical-demo"@open="handleOpen"@close="handleClose"background-color="#545c64"text-color="#fff"active-text-color="#ffd04b"><h3>通用后台管理系统</h3><el-menu-item:index="item.name"v-for="item in noChildren":key="item.name"><i :class="`el-icon-${item.icon}`"></i><span slot="title">{{item.label}}</span></el-menu-item><el-submenu :index="item.label"v-for="item in hasChildren":key="item.label"><template slot="title"><i class="`el-icon-${item.icon}`"></i><span>{{item.label}}</span></template><el-menu-item-groupv-for="subItem in item.children":key="subItem.name"><el-menu-item :index="subItem.name">{{subItem.label}}</el-menu-item></el-menu-item-group></el-submenu></el-menu></div>
</template><script>
export default {data () {return {menuData: [{path: '/',name: 'home',label: '首页',icon: 's-home',url: 'Home/Home'},{path: '/mall',name: 'mall',label: '商品管理',icon: 'video-play',url: 'MallManage/MallManage'},{path: '/user',name: 'user',label: '用户管理',icon: 'user',url: 'UserManage/UserManage'},{label: '其他',icon: 'location',children: [{path: '/page1',name: 'page1',label: '页面1',icon: 'setting',url: 'Other/PageOne'},{path: '/page2',name: 'page2',label: '页面2',icon: 'setting',url: 'Other/PageTwo'}]}]}},computed: {noChildren () {return this.menuData.filter(item => !item.children)},hasChildren () {return this.menuData.filter(item => item.children)},},methods: {handleOpen(key, keyPath) {console.log(key, keyPath);},handleClose(key, keyPath) {console.log(key, keyPath);}}
}
</script><style lang="stylus" scoped>
.el-menuheight: 100vhborder-right: nonecolor #fffh3color: #ffftext-align: centerline-height: 48pxfont-size: 16pxfont-weight: 400
</style>
九、侧边栏路由实现
根据menuData
里的path,在路由文件里配置路由
<template><div><el-menudefault-active="2"class="el-menu-vertical-demo"@open="handleOpen"@close="handleClose"background-color="#545c64"text-color="#fff"active-text-color="#ffd04b"><h3>通用后台管理系统</h3><el-menu-item:index="item.name"v-for="item in noChildren":key="item.name"@click="clickMenu(item)"><i :class="`el-icon-${item.icon}`"></i><span slot="title">{{item.label}}</span></el-menu-item><el-submenu :index="item.label"v-for="item in hasChildren":key="item.label"><template slot="title"><i class="`el-icon-${item.icon}`"></i><span>{{item.label}}</span></template><el-menu-item-groupv-for="subItem in item.children":key="subItem.name"><el-menu-item @click="clickMenu(subItem)" :index="subItem.name">{{subItem.label}}</el-menu-item></el-menu-item-group></el-submenu></el-menu></div>
</template><script>
export default {data () {return {menuData: [{path: '/',name: 'home',label: '首页',icon: 's-home',url: 'Home/Home'},{path: '/mall',name: 'mall',label: '商品管理',icon: 'video-play',url: 'MallManage/MallManage'},{path: '/user',name: 'user',label: '用户管理',icon: 'user',url: 'UserManage/UserManage'},{label: '其他',icon: 'location',children: [{path: '/page1',name: 'page1',label: '页面1',icon: 'setting',url: 'Other/PageOne'},{path: '/page2',name: 'page2',label: '页面2',icon: 'setting',url: 'Other/PageTwo'}]}]}},computed: {noChildren () {return this.menuData.filter(item => !item.children)},hasChildren () {return this.menuData.filter(item => item.children)},},methods: {handleOpen(key, keyPath) {console.log(key, keyPath);},handleClose(key, keyPath) {console.log(key, keyPath);},clickMenu (item) {if (this.$route.path !== item.path && !(this.$route.path === '/home' && (item.path === '/'))) {this.$router.push(item.path)}console.log(item, 'item')}}
}
</script><style lang="stylus" scoped>
.el-menuheight: 100vhborder-right: nonecolor #fffh3color: #ffftext-align: centerline-height: 48pxfont-size: 16pxfont-weight: 400
</style>
头部制作
<template><div class="header"><div class="l-content"><el-button icon="el-icon-menu" size="small"></el-button><el-breadcrumb separator="/"><el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item><el-breadcrumb-item><a href="/">活动管理</a></el-breadcrumb-item><el-breadcrumb-item>活动列表</el-breadcrumb-item><el-breadcrumb-item>活动详情</el-breadcrumb-item></el-breadcrumb></div><div class="r-content"><el-dropdown><span class="el-dropdown-link"><img class="user-img" src="../assets/images/user.png"></span><el-dropdown-menu slot="dropdown"><el-dropdown-item>个人中心</el-dropdown-item><el-dropdown-item>退出</el-dropdown-item></el-dropdown-menu></el-dropdown></div></div>
</template><script>export default {}
</script><style lang="stylus" scoped>
.headerpadding: 0 20pxheight: 60pxbackground-color: #333display: flexjustify-content: space-betweenalign-items: center.l-contentdisplay: flexalign-items: center.r-content.user-imgwidth: 40pxheight: 40pxborder-radius: 50%
</style>
菜单折叠效果
vue2中,要用vuex的3版本
vue3中,要用vuex的4版本
yarn add vuex@3.6.2 --save
优化
home页面
layout布局
引入box-card
<template><div><el-row><el-col :span="8"><el-card class="box-card"></el-card><el-card class="box-card"></el-card></el-col><el-col :span="16"><div class="num"><el-card class="box-card"></el-card></div><el-card class="box-card"></el-card><div class="graph"><el-card class="box-card"></el-card></div></el-col></el-row></div>
</template><script>export default {}
</script><style scoped></style>
头像部分
<template><div><el-row><el-col :span="8"><el-card class="box-card" style="height: 285px; margin-bottom: 20px;"><div class="user"><img src="@/assets/images/user.png" /><div class="user-info"><div class="name">Admin</div><div class="access">超级管理员</div></div></div><div class="login"><p>上次登录时间:<span>2021-7-19</span></p><p>上次登录地点:<span>武汉</span></p></div></el-card><el-card class="box-card" style="height: 479px"></el-card></el-col><el-col :span="16"><div class="num"><el-card class="box-card"></el-card></div><el-card class="box-card"></el-card><div class="graph"><el-card class="box-card"></el-card></div></el-col></el-row></div>
</template><script>export default {}
</script><style lang="stylus" scoped>
.userdisplay flexborder-bottom: 1px solid #cccpadding-bottom: 20pximgmargin-right 40pxwidth 150pxheight: 150pxborder-radius: 50%.user-infopadding 35px 20px 20px 20px.namefont-size: 32pxmargin-bottom: 10px.accesscolor: #999
.loginpadding-top: 20pxpline-height: 28pxfont-size: 14pxcolor: #999spancolor: #666666;margin-left: 60px;
</style>
统计购买部分
<template><div><el-row><el-col :span="8"><el-card class="box-card" style="height: 285px; margin-bottom: 20px;"><div class="user"><img src="@/assets/images/user.png" /><div class="user-info"><div class="name">Admin</div><div class="access">超级管理员</div></div></div><div class="login"><p>上次登录时间:<span>2021-7-19</span></p><p>上次登录地点:<span>武汉</span></p></div></el-card><el-card class="box-card" style="height: 479px"><el-table:data="tableData"stripestyle="width: 100%"><el-table-column:prop="key":label="val"v-for="(val, key) in tableLabel"></el-table-column></el-table></el-card></el-col><el-col :span="16"><div class="num"><el-card class="box-card"></el-card></div><el-card class="box-card"></el-card><div class="graph"><el-card class="box-card"></el-card></div></el-col></el-row></div>
</template><script>export default {data () {return {tableData: [{name: 'oppo',todayBuy: 100,monthBuy: 300,totalBuy: 800},{name: 'vivo',todayBuy: 100,monthBuy: 300,totalBuy: 800},{name: '苹果',todayBuy: 100,monthBuy: 300,totalBuy: 800},{name: '小米',todayBuy: 100,monthBuy: 300,totalBuy: 800},{name: '三星',todayBuy: 100,monthBuy: 300,totalBuy: 800},{name: '魅族',todayBuy: 100,monthBuy: 300,totalBuy: 800}],tableLabel: {name: "课程",todayBuy: "今日购买",monthBuy: "本月购买",totalBuy: "总购买"}}}}
</script><style lang="stylus" scoped>
.userdisplay flexborder-bottom: 1px solid #cccpadding-bottom: 20pximgmargin-right 40pxwidth 150pxheight: 150pxborder-radius: 50%.user-infopadding 35px 20px 20px 20px.namefont-size: 32pxmargin-bottom: 10px.accesscolor: #999
.loginpadding-top: 20pxpline-height: 28pxfont-size: 14pxcolor: #999spancolor: #666666;margin-left: 60px;
</style>
订单统计部分
countData
countData: [{name: "今日支付订单",value: 1234,icon: "success",color: "#2ec7c9",},{name: "今日收藏订单",value: 210,icon: "star-on",color: "#ffb980",},{name: "今日未支付订单",value: 1234,icon: "s-goods",color: "#5ab1ef",},{name: "本月支付订单",value: 1234,icon: "success",color: "#2ec7c9",},{name: "本月收藏订单",value: 210,icon: "star-on",color: "#ffb980",},{name: "本月未支付订单",value: 1234,icon: "s-goods",color: "#5ab1ef",},],
<template><div><el-row><el-col :span="8"><el-card class="box-card" style="height: 285px; margin-bottom: 20px;"><div class="user"><img src="@/assets/images/user.png" /><div class="user-info"><div class="name">Admin</div><div class="access">超级管理员</div></div></div><div class="login"><p>上次登录时间:<span>2021-7-19</span></p><p>上次登录地点:<span>武汉</span></p></div></el-card><el-card class="box-card" style="height: 479px"><el-table:data="tableData"stripestyle="width: 100%"><el-table-column:prop="key":label="val"v-for="(val, key) in tableLabel"></el-table-column></el-table></el-card></el-col><el-col :span="16"><div class="num"><el-card class="box-card"v-for="item in countData":key="item.name":body-style="{display: 'flex', padding: 0}"><i class="icon" :class="`el-icon-${item.icon}`":style="{background: item.color}"></i><div class="detail"><p class="price">¥ {{item.value}}</p><p class="desc">{{item.name}}</p></div></el-card></div><el-card class="box-card"></el-card><div class="graph"><el-card class="box-card"></el-card></div></el-col></el-row></div>
</template><script>export default {data () {return {tableData: [{name: 'oppo',todayBuy: 100,monthBuy: 300,totalBuy: 800},{name: 'vivo',todayBuy: 100,monthBuy: 300,totalBuy: 800},{name: '苹果',todayBuy: 100,monthBuy: 300,totalBuy: 800},{name: '小米',todayBuy: 100,monthBuy: 300,totalBuy: 800},{name: '三星',todayBuy: 100,monthBuy: 300,totalBuy: 800},{name: '魅族',todayBuy: 100,monthBuy: 300,totalBuy: 800}],tableLabel: {name: "课程",todayBuy: "今日购买",monthBuy: "本月购买",totalBuy: "总购买"},countData: [{name: "今日支付订单",value: 1234,icon: "success",color: "#2ec7c9",},{name: "今日收藏订单",value: 210,icon: "star-on",color: "#ffb980",},{name: "今日未支付订单",value: 1234,icon: "s-goods",color: "#5ab1ef",},{name: "本月支付订单",value: 1234,icon: "success",color: "#2ec7c9",},{name: "本月收藏订单",value: 210,icon: "star-on",color: "#ffb980",},{name: "本月未支付订单",value: 1234,icon: "s-goods",color: "#5ab1ef",},],}}}
</script><style lang="stylus" scoped>
.userdisplay flexborder-bottom: 1px solid #cccpadding-bottom: 20pximgmargin-right 40pxwidth 150pxheight: 150pxborder-radius: 50%.user-infopadding 35px 20px 20px 20px.namefont-size: 32pxmargin-bottom: 10px.accesscolor: #999
.loginpadding-top: 20pxpline-height: 28pxfont-size: 14pxcolor: #999spancolor: #666666;margin-left: 60px;
.numdisplay: flexflex-wrap: wrap.el-cardmargin-left: 20pxwidth: 30.4%margin-bottom: 20px.iconwidth 80pxheight 80pxline-height 80pxfont-size 30pxtext-align centercolor #fff.detailmargin-left 15pxdisplay flexflex-direction columnjustify-content center.pricefont-size 30pxmargin-bottom 10pxline-height 30pxheight 30px.descfont-size 14pxcolor #999text-align center
</style>
ajax
yarn add axios@0.27.2
封装ajax
axios中文文档|axios中文网 | axios
定义一个请求首页数据的接口
在页面中可以调用
yarn add mockjs@1.1.0
home.js
// mock数据模拟
import Mock from 'mockjs'// 图表数据
let List = []
export default {getStatisticalData: () => {//Mock.Random.float 产生随机数100到8000之间 保留小数 最小0位 最大0位for (let i = 0; i < 7; i++) {List.push(Mock.mock({苹果: Mock.Random.float(100, 8000, 0, 0),vivo: Mock.Random.float(100, 8000, 0, 0),oppo: Mock.Random.float(100, 8000, 0, 0),魅族: Mock.Random.float(100, 8000, 0, 0),三星: Mock.Random.float(100, 8000, 0, 0),小米: Mock.Random.float(100, 8000, 0, 0)}))}return {code: 20000,data: {// 饼图videoData: [{name: '小米',value: 2999},{name: '苹果',value: 5999},{name: 'vivo',value: 1500},{name: 'oppo',value: 1999},{name: '魅族',value: 2200},{name: '三星',value: 4500}],// 柱状图userData: [{date: '周一',new: 5,active: 200},{date: '周二',new: 10,active: 500},{date: '周三',new: 12,active: 550},{date: '周四',new: 60,active: 800},{date: '周五',new: 65,active: 550},{date: '周六',new: 53,active: 770},{date: '周日',new: 33,active: 170}],// 折线图orderData: {date: ['20191001', '20191002', '20191003', '20191004', '20191005', '20191006', '20191007'],data: List},tableData: [{name: 'oppo',todayBuy: 500,monthBuy: 3500,totalBuy: 22000},{name: 'vivo',todayBuy: 300,monthBuy: 2200,totalBuy: 24000},{name: '苹果',todayBuy: 800,monthBuy: 4500,totalBuy: 65000},{name: '小米',todayBuy: 1200,monthBuy: 6500,totalBuy: 45000},{name: '三星',todayBuy: 300,monthBuy: 2000,totalBuy: 34000},{name: '魅族',todayBuy: 350,monthBuy: 3000,totalBuy: 22000}]}}}
}
购买统计数据替换
echarts折线图
yarn add echarts@5.1.2
在home页面引入echarts
import * as echarts from 'echarts';
柱状图
饼状图
<template><div><el-row><el-col :span="8"><el-card class="box-card" style="height: 285px; margin-bottom: 20px;"><div class="user"><img src="@/assets/images/user.png" /><div class="user-info"><div class="name">Admin</div><div class="access">超级管理员</div></div></div><div class="login"><p>上次登录时间:<span>2021-7-19</span></p><p>上次登录地点:<span>武汉</span></p></div></el-card><el-card class="box-card" style="height: 457px"><el-table:data="tableData"stripestyle="width: 100%"><el-table-column:prop="key":label="val"v-for="(val, key) in tableLabel"></el-table-column></el-table></el-card></el-col><el-col :span="16"><div class="num"><el-card class="box-card"v-for="item in countData":key="item.name":body-style="{display: 'flex', padding: 0}"><i class="icon" :class="`el-icon-${item.icon}`":style="{background: item.color}"></i><div class="detail"><p class="price">¥ {{item.value}}</p><p class="desc">{{item.name}}</p></div></el-card></div><el-card class="box-card" style="height: 280px;margin-left: 20px;"><div ref="echarts1" style="height: 280px;"></div></el-card><div class="graph"><el-card class="box-card" style="height: 260px;"><div ref="echarts2" style="height: 260px; width: 340px;"></div></el-card><el-card class="box-card" style="height: 260px;"><div ref="echarts3" style="height: 240px;width: 340px;"></div></el-card></div></el-col></el-row></div>
</template><script>import * as echarts from 'echarts';import { getData } from '../api'export default {data () {return {tableData: [],countData: [],tableLabel: {name: "课程",todayBuy: "今日购买",monthBuy: "本月购买",totalBuy: "总购买"}}},mounted() {getData().then(({ data }) => {console.log(data)const { tableData, countData } = data.datathis.tableData = tableDatathis.countData = countData// 基于准备好的dom,初始化echarts实例const echarts1 = echarts.init(this.$refs.echarts1)// 指定图表的配置项和数据var echarts1Option = {}// 处理数据xAxisconst { orderData, userData, videoData } = data.dataconst xAxis = Object.keys(orderData.data[0])const xAxisData = {data: xAxis}echarts1Option.xAxis = xAxisDataecharts1Option.yAxis = {}echarts1Option.legend = xAxisDataecharts1Option.series = []xAxis.forEach(key => {echarts1Option.series.push({name: key,data: orderData.data.map(item => item[key]),type: 'line'})})console.log(echarts1Option)// 使用刚指定的配置项和数据显示图表。echarts1.setOption(echarts1Option)// 柱状图const echarts2 = echarts.init(this.$refs.echarts2)const eachrts2Option = {legend: {// 图例文字颜色textStyle: {color: "#333",},},grid: {left: "20%",},// 提示框tooltip: {trigger: "axis",},xAxis: {type: "category", // 类目轴data: userData.map(item => item.date),axisLine: {lineStyle: {color: "#17b3a3",},},axisLabel: {interval: 0,color: "#333",},},yAxis: [{type: "value",axisLine: {lineStyle: {color: "#17b3a3",},},},],color: ["#2ec7c9", "#b6a2de"],series: [{name: '新增用户',data: userData.map(item => item.new),type: 'bar'},{name: '活跃用户',data: userData.map(item => item.active),type: 'bar'}],}echarts2.setOption(eachrts2Option)// 饼状图const echarts3 = echarts.init(this.$refs.echarts3)const eachrts3Option = {tooltip: {trigger: "item",},color: ["#0f78f4","#dd536b","#9462e5","#a6a6a6","#e1bb22","#39c362","#3ed1cf",],series: [{data: videoData,type: 'pie'}],}echarts3.setOption(eachrts3Option)})}}
</script><style lang="stylus" scoped>
.userdisplay flexborder-bottom: 1px solid #cccpadding-bottom: 20pximgmargin-right 40pxwidth 150pxheight: 150pxborder-radius: 50%.user-infopadding 35px 20px 20px 20px.namefont-size: 32pxmargin-bottom: 10px.accesscolor: #999
.loginpadding-top: 20pxpline-height: 28pxfont-size: 14pxcolor: #999spancolor: #666666;margin-left: 60px;
.numdisplay: flexflex-wrap: wrap.el-cardmargin-left: 20pxwidth: 30.4%margin-bottom: 20px.iconwidth 80pxheight 80pxline-height 80pxfont-size 30pxtext-align centercolor #fff.detailmargin-left 15pxdisplay flexflex-direction columnjustify-content center.pricefont-size 30pxmargin-bottom 10pxline-height 30pxheight 30px.descfont-size 14pxcolor #999text-align center
.graphdisplay: flexjustify-content: space-betweenmargin: 20px 0 0 20px
</style>
在tab里的state里定义关于面包屑数据
在mutation里定义一个方法selectMenu()
用来更新面包屑数据
tabsList渲染面包屑
深拷贝
让其最后一个子元素是白色
tag标签
tag的删除功能和改变主题
解决删除后标签无高亮的问题
用户管理
dialog和form
表单验证
表单关闭数据清空
渲染table表格
user.js
import Mock from 'mockjs'// get请求从config.url获取参数,post从config.body中获取参数
function param2Obj (url) {const search = url.split('?')[1]if (!search) {return {}}return JSON.parse('{"' +decodeURIComponent(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"') +'"}')
}let List = []
const count = 200for (let i = 0; i < count; i++) {List.push(Mock.mock({id: Mock.Random.guid(),name: Mock.Random.cname(),addr: Mock.mock('@county(true)'),'age|18-60': 1,birth: Mock.Random.date(),sex: Mock.Random.integer(0, 1)}))
}export default {/*** 获取列表* 要带参数 name, page, limt; name可以不填, page,limit有默认值。* @param name, page, limit* @return {{code: number, count: number, data: *[]}}*/getUserList: config => {const { name, page = 1, limit = 20 } = param2Obj(config.url)console.log('name:' + name, 'page:' + page, '分页大小limit:' + limit)const mockList = List.filter(user => {if (name && user.name.indexOf(name) === -1 && user.addr.indexOf(name) === -1) return falsereturn true})const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1))return {code: 20000,count: mockList.length,list: pageList}},/*** 增加用户* @param name, addr, age, birth, sex* @return {{code: number, data: {message: string}}}*/createUser: config => {const { name, addr, age, birth, sex } = JSON.parse(config.body)console.log(JSON.parse(config.body))List.unshift({id: Mock.Random.guid(),name: name,addr: addr,age: age,birth: birth,sex: sex})return {code: 20000,data: {message: '添加成功'}}},/*** 删除用户* @param id* @return {*}*/deleteUser: config => {const { id } = JSON.parse(config.body)if (!id) {return {code: -999,message: '参数不正确'}} else {List = List.filter(u => u.id !== id)return {code: 20000,message: '删除成功'}}},/*** 批量删除* @param config* @return {{code: number, data: {message: string}}}*/batchremove: config => {let { ids } = param2Obj(config.url)ids = ids.split(',')List = List.filter(u => !ids.includes(u.id))return {code: 20000,data: {message: '批量删除成功'}}},/*** 修改用户* @param id, name, addr, age, birth, sex* @return {{code: number, data: {message: string}}}*/updateUser: config => {const { id, name, addr, age, birth, sex } = JSON.parse(config.body)const sex_num = parseInt(sex)List.some(u => {if (u.id === id) {u.name = nameu.addr = addru.age = ageu.birth = birthu.sex = sex_numreturn true}})return {code: 20000,data: {message: '编辑成功'}}}
}
mock中添加模拟的数据接口
slot-scope="scope"
作用域插槽,作用:可以在父组件中获取到子组件的数据
新增和修改
新增按钮和编辑按钮共用一个弹窗, modalType: 0,控制,0 新增,1 编辑
给新增按钮添加一个方法handAdd
它的modalType = 0
, dialogVisible =true
展开弹窗
给编辑按钮添加一个方法handleEdit
,它的modalType = 1
,dialogVisible =true
展开弹窗
查询和删除
分页功能
登录权限
yarn add js-cookie@3.0.1
token信息存入cookie用于不同页面的通信
在main.js里添加全局前置导航守卫
登录接口逻辑实现
引入permission.js
在点击登录按钮的时候,判断这个code来判断账号密码是否正确,正确就跳转至首页,不正确就显示错误信息
个人中心退出按钮
菜单权限
1、不同账号的菜单权限
动态获取菜单栏路由数据
判断当前数据,cookie中没有就去store中获取
2、通过URL输入地址显示页面
router动态注册路由
重新登陆一下
看到这个输出就是成功了
删除之前写死的路由,并将跟路由改成 /home
解决空白页面的问题
笔记参考哔哩哔哩Allen前端vue后台管理系统笔记_杨白鹤的博客-CSDN博客哔哩哔哩Allen前端vue后台管理系统笔记https://blog.csdn.net/weixin_59820248/article/details/128590099
哔哩哔哩Allen老师通用后台管理系统相关推荐
- 哔哩哔哩Allen前端vue后台管理系统笔记
哔哩哔哩Allen前端vue后台管理系统笔记 Element ui 引入 全局引入 按需引入 嵌套路由 左侧菜单栏的样式 Container布局,左侧菜单栏commonAside组件 commonAs ...
- 通用后台管理系统(ExtJS 4.2 + Spring MVC 3.2 + Hibernate)
通用后台管理系统(ExtJS 4.2 +Spring MVC 3.2 + Hibernate) 开发语言JAVA 成品成品 前端技术extjs 数据库mysql,sql server,oracle 系 ...
- 【前端】Vue+Element UI案例:通用后台管理系统-用户管理:Table表格增删查改、Pagination分页、搜索框
文章目录 目标 代码 0.结构 1.按钮-删除 2.按钮-编辑 3.debug 4.样式 5.分页Pagination:功能 6.分页Pagination:样式 7.搜索框:功能 8.搜索框:样式 总 ...
- 【前端】Vue+Element UI案例:通用后台管理系统-用户管理:Form表单填写、Dialog对话框弹出
文章目录 目标 代码 0.页面结构 1.新增按钮和弹出表单:结构 2.新增按钮和弹出表单:点击新增弹出表单 3.表单样式 4.表单验证 5.表单的提交和取消功能:接口.mock相关准备 6.表单的提交 ...
- c#通用后台管理系统
c#通用后台管理系统 C#通用后台管理系统 最近因公司工作需要,要编制一个小型的oa系统,在网上找了一下,发现大多数的功能都不是我们想用的,没办法,只好自己来写一个,开始写了个登录后,懒病又犯了,不想 ...
- Thinkphp 6 + Vue 2 + ElementUI + Vxe-table 前后端分离的,一键生成代码和API接口的,通用后台管理系统 快速开发框架,开发小程序和APP的推荐框架!
Thinkphp 6 + Vue 2 + ElementUI + Vxe-table 前后端分离的,一键生成代码和API接口的,通用后台管理系统 快速开发框架,开发小程序和APP的推荐框架! 概述 R ...
- 用 Vite+Vue3+Ts 搭建通用后台管理系统
大厂技术 高级前端 Node进阶 点击上方 程序员成长指北,关注公众号 回复1,加入高级Node交流群 通用后台管理系统整体架构方案(Vue) 项目创建,脚手架的选择(vite or vue-cl ...
- 用vite+Vue3+ts搭建通用后台管理系统
点击上方关注 前端技术江湖,一起学习,天天进步 通用后台管理系统整体架构方案(Vue) 项目创建,脚手架的选择(vite or vue-cli) vue-cli基于webpack封装,生态非常强大,可 ...
- 【前端】Vue+Element UI案例:通用后台管理系统-登陆不同用户显示不同菜单、动态添加路由
文章目录 目标 代码 0.动态地显示菜单:store 1.动态注册路由 2.解决刷新后摆平问题 总代码 本篇修改的代码文件 tab.js 参考视频: VUE项目,VUE项目实战,vue后台管理系统,前 ...
最新文章
- 《实施Cisco统一通信管理器(CIPT1)》一2.4 使用分布式呼叫处理的多站点WAN部署模型...
- PDF与doc格式互换
- prometheus+consul服务发现+alertmanager配置
- Css3实现波浪线效果1
- [html] 你有使用过webp的图片格式吗?
- python语言学完后学什么_学完Python语言可以做什么?发展前景怎么样?
- redis笔记_源码_内存分配
- pat根据中序遍历和先序遍历_[leetcode/lintcode 题解] 前序遍历和中序遍历树构造二叉树...
- MobileNet V3简单总结
- Windows 8虚拟机不能全屏的解决方法
- 天梯—输出GPLT(C语言)
- MATLAB局部放大
- 太原理工计算机学科评估,太原理工大学学科评估结果及排名情况怎样
- 把tif文件转化成jpg格式报错已解决
- 威斯康星麦迪逊计算机专业排名,威斯康星大学麦迪逊分校计算机工程学科排名...
- 一张图快速了解23种设计模式
- 第九届蓝桥杯大赛软件类国赛
- python数据分析的交叉分析和分组分析 -第三次笔记
- FPGA电源设计方案
- 7 士兵排队---PTA(排序+中位数)(C++)