总结一下运行此项目需要安装的插件:
一、router
二、vuex
三、element ui
前三个可以使用vue ui 进行安装
四、安装less :npm install less -–save-dev
五、安装less-loader(低版本的less-loader):npm install less-loader@5.0.0 --save
六、安装axios:npm install axios --save
七、core-js版本:npm i core-js@3.6.4
八、mokejs:npm install --save mockjs
首先和之前一样把直接创建好的脚手架拿来用
安装三个插件
再次用命令安装axios
npm install axios --save
安装完成后的四个插件
运行后的效果
接下来开始正式写demo
添加公共样式
新建Login页面
<template>
<div class="container">
<div class="wrapper">
<h1>WEB ADMIN</h1>
<el-form
label-width="auto"
:model="form"
:rules="rules"
ref="form"
v-loading="isloading"
>
<el-form-item label="用户" prop="username">
<el-input v-model="form.username" placeholder="请输入用户名">
<i slot="prefix" class="el-input__icon el-icon-user"></i>
</el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input
v-model="form.password"
placeholder="请输入密码"
show-password
>
<i slot="prefix" class="el-input__icon el-icon-lock"></i>
</el-input>
</el-form-item>
<el-row>
<el-button type="primary" size="mini" @click="login">登录</el-button>
<el-button type="success" size="mini" @click="resetForm('form')"
>重置</el-button
>
</el-row>
</el-form>
</div>
</div>
</template>
<script>
export default {
name: "Login",
data() {
return {
form: {
username: "admin",
password: "admin",
},
isloading: false,
rules: {
username: [
{
required: true,
message: "请输入用户名",
trigger: "blur",
},
{
min: 3,
max: 18,
message: "长度在 3 到 18 个字符",
trigger: "blur",
},
],
password: [
{
required: true,
message: "请输入密码",
trigger: "blur",
},
{
min: 3,
max: 18,
message: "长度在 3 到 18 个字符",
trigger: "blur",
},
],
},
};
},
methods: {
resetForm(formName) {
this.$refs[formName].resetFields();
},
login() {
/* this.$axios.post('/login',{
username:this.form.username,
password:this.form.password
}).then(res=>{
console.log(res);
this.$store.commit('setUser',res.data)
window.sessionStorage.setItem('token',res.data.token)
this.$router.push('/')
}) */
this.isloading = true;
this.$api
.login({
username: this.form.username,
password: this.form.password,
})
.then((res) => {
console.log(res);
this.$store.commit("setUser", res.data);
window.sessionStorage.setItem("token", res.data.token);
this.isloading = false;
this.$router.push("/");
this.$message({
message: "恭喜你,登录成功",
type: "success",
});
});
},
},
};
</script>
<style scoped="scoped">
.container {
width: 100%;
height: 100%;
position: absolute;
bottom: 0;
left: 0;
overflow: hidden;
background-color: #2b4b6b;
}
.wrapper {
width: 500px;
height: 320px;
background-color: #fff;
margin: 120px auto;
}
.wrapper {
padding: 0 30px;
}
.wrapper h1 {
color: #666;
text-align: center;
padding: 20px 0 30px 0;
}
.el-row {
float: right;
}
</style>
页面效果如下:
接下来写NotFound页面
当网址输入错误时将出现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 {
}
</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>
引入完毕后安装less-loader插件和less
安装less :
npm install less -–save-dev
安装less-loader(低版本的less-loader):
npm install less-loader@5.0.0 --save
然后运行,如果会报错的话这里给两个参考方案 ,启动成功的话当然是最好的了!
接下来还会有报错建议安装一下这个版本的core-js
npm i core-js@3.6.4
出现下列报错信息就是得重新安装一下element-ui
These dependencies were not found: * element-ui in ./src/plugins/element.js
npm install --save element-ui
运行成功后可以试一下这一页能不能打开
显示出来后可以继续进行下面的操作
写四个公共部分
Aside.vue
<template>
<div class="container">
<div class="wrapper">
<h1>WEB ADMIN</h1>
<el-form
label-width="auto"
:model="form"
:rules="rules"
ref="form"
v-loading="isloading"
>
<el-form-item label="用户" prop="username">
<el-input v-model="form.username" placeholder="请输入用户名">
<i slot="prefix" class="el-input__icon el-icon-user"></i>
</el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input
v-model="form.password"
placeholder="请输入密码"
show-password
>
<i slot="prefix" class="el-input__icon el-icon-lock"></i>
</el-input>
</el-form-item>
<el-row>
<el-button type="primary" size="mini" @click="login">登录</el-button>
<el-button type="success" size="mini" @click="resetForm('form')"
>重置</el-button
>
</el-row>
</el-form>
</div>
</div>
</template>
<script>
export default {
name: "Login",
data() {
return {
form: {
username: "admin",
password: "admin",
},
isloading: false,
rules: {
username: [
{
required: true,
message: "请输入用户名",
trigger: "blur",
},
{
min: 3,
max: 18,
message: "长度在 3 到 18 个字符",
trigger: "blur",
},
],
password: [
{
required: true,
message: "请输入密码",
trigger: "blur",
},
{
min: 3,
max: 18,
message: "长度在 3 到 18 个字符",
trigger: "blur",
},
],
},
};
},
methods: {
resetForm(formName) {
this.$refs[formName].resetFields();
},
login() {
/* this.$axios.post('/login',{
username:this.form.username,
password:this.form.password
}).then(res=>{
console.log(res);
this.$store.commit('setUser',res.data)
window.sessionStorage.setItem('token',res.data.token)
this.$router.push('/')
}) */
this.isloading = true;
this.$api
.login({
username: this.form.username,
password: this.form.password,
})
.then((res) => {
console.log(res);
this.$store.commit("setUser", res.data);
window.sessionStorage.setItem("token", res.data.token);
this.isloading = false;
this.$router.push("/");
this.$message({
message: "恭喜你,登录成功",
type: "success",
});
});
},
},
};
</script>
<style scoped="scoped">
.container {
width: 100%;
height: 100%;
position: absolute;
bottom: 0;
left: 0;
overflow: hidden;
background-color: #2b4b6b;
}
.wrapper {
width: 500px;
height: 320px;
background-color: #fff;
margin: 120px auto;
}
.wrapper {
padding: 0 30px;
}
.wrapper h1 {
color: #666;
text-align: center;
padding: 20px 0 30px 0;
}
.el-row {
float: right;
}
</style>
BreadCrumb.vue
<template>
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item v-for="(item, idx) in breads" :key="idx" :to="{ path: item.path }">
{{ item.name }}
</el-breadcrumb-item>
</el-breadcrumb>
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['breads'])
}
}
</script>
<style>
</style>
Headedr.vue
<template>
<div class="header">
<div class="header-left">
<div class="header-left__logo">
<img src="@/assets/logo.png" alt="">
</div>
<div class="header-left__title">后台管理系统权限Demo</div>
</div>
<div class="header-right">
<div class="header-right__info">
<div class="header-right__info-name">{{user.username}}</div>
</div>
<div class="header-right__logout">
<el-button type="danger" size="20" @click="logout">退出</el-button>
</div>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
methods: {
logout () {
this.$confirm('您确定要退出吗, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
window.sessionStorage.removeItem('rightsList')
window.sessionStorage.removeItem('token')
this.$router.push({ path: '/login' })
}).catch((err) => err)
}
},
computed: {
...mapState(['user'])
}
}
</script>
<style lang="less" scoped>
.header {
width: 100%;
height: 100%;
background-color: #00BFFF;
display: flex;
justify-content: space-between;
padding: 0 15px;
box-shadow: 0 2px 5px #00BFFF;
&-left {
height: 100%;
display: flex;
align-items: center;
&__logo {
width: 80px;
height: 100%;
padding: 5px;
& > img {
width: 100%;
height: 100%;
}
}
&__title {
font-size: 20px;
color: #fff;
text-shadow: 10px 10px rgba(25, 255, 255, .3);
}
}
&-right {
height: 100%;
display: flex;
align-items: center;
&__info {
&-name {
color: #F0FFFF;
font-size: 16px;
margin-right: 15px;
}
}
}
}
</style>
Main.vue
<template>
<div class="main">
<div class="bread">
<v-bread-crumb></v-bread-crumb>
</div>
<div class="content">
<router-view :key="+new Date()"></router-view>
</div>
</div>
</template>
<script>
import BreadCrumb from '@/components/BreadCrumb.vue'
export default {
data () {
return {
activeKey: ''
}
},
components: {
'v-bread-crumb': BreadCrumb
}
}
</script>
<style lang="less" scoped>
.content {
width: 100%;
height: 100%;
background-color: #fff;
padding: 20px 15px;
border-radius: 5px;
transform: translateY(15px);
}
</style>
在main文件夹里写两个页面,添加以及查找
Card.vue
<template>
<div class="card animate__animated animate__zoomIn" v-loading="isOperate">
<div class="card-header">
<div class="card-header__title">
{{ isAdd ? '添加信息' : '删除信息' }}
</div>
<div class="card-header__close" @click="$emit('close')">
<i class="el-icon-close"></i>
</div>
</div>
<div class="card-content">
<el-form :model="formData" :rules="rules" ref="form">
<el-form-item label="姓名:" prop="name">
<el-input v-model="formData.name"></el-input>
</el-form-item>
<el-form-item label="地址:" prop="address">
<el-input v-model="formData.address"></el-input>
</el-form-item>
<el-form-item label="爱好:" prop="likes">
<el-input v-model="formData.likes"></el-input>
</el-form-item>
<el-form-item>
<el-button @click="$emit('close')" type="info">取消</el-button>
<el-button @click="submitForm" type="primary">{{ isAdd ? '添加' : '修改' }}</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
export default {
props: {
isAdd: Boolean,
isOperate: Boolean,
rowData: {
type: Object,
default () {
return {}
}
}
},
data () {
return {
formData: {
name: '',
address: '',
likes: ''
},
rules: {
name: { required: true, message: '请输入姓名', trigger: 'blur' },
address: { required: true, message: '请输入地址', trigger: 'blur' },
likes: { required: true, message: '请输入爱好', trigger: 'blur' }
}
}
},
created () {
if (Object.keys(this.rowData).length && !this.isAdd) {
this.formData = { ...this.rowData }
} else {
this.formData = {
name: '',
address: '',
likes: ''
}
}
},
methods: {
submitForm () {
this.$refs.form.validate(valid => {
if (valid) {
this.$emit('submitAction', {
isAdd: this.isAdd,
rowData: this.formData
})
}
})
}
}
}
</script>
<style lang="less" scoped>
.card {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
transform-origin: 0 0;
z-index: 99;
background: #fff;
box-shadow: 0 0 20px gray;
border-radius: 5px;
padding: 15px 80px;
&-header {
display: flex;
justify-content: space-between;
margin: 0 -50px 30px;
&__title {
font-size: 20px;
}
&__close {
cursor: pointer;
transition: all .5s;
&:hover {
transform: rotate(-15deg);
}
}
}
.el-form-item {
display: flex;
&:last-child {
display: block;
text-align: right;
}
}
.el-input {
width: 200px;
}
}
.animate__animated.animate__zoomIn {
--animate-duration: .8s;
}
</style>
TopBar.vue
<template>
<div class="top-bar">
<el-input placeholder="请输入内容,按回车键搜索..." @keydown.enter.native="handleSearch" v-model="inputValue">
<template slot="append">
搜索
</template>
</el-input>
<el-button type="primary" @click="$emit('show')">添加商品</el-button>
</div>
</template>
<script>
export default {
data () {
return {
inputValue: ''
}
},
methods: {
handleSearch () {
this.$emit('handleSearch', this.inputValue)
}
}
}
</script>
<style lang="less" scoped>
.top-bar {
.el-input {
width: 300px;
}
.el-button {
margin-left: 15px;
}
}
</style>
引入moke文件夹
// main.js
import './mock'
在moke文件夹中写入两种权限的数据
index.js
引入mockjs插件
npm install --save mockjs
// 使用 Mock
const Mock = require('mockjs')
require('./my-radom')
const Random = Mock.Random
Mock.setup({
timeout: '500-1000'
})
const list = []
for (let i = 0; i < 20; i++) {
list.push({
id: i + 1,
date: Random.date(),
name: Random.cname(),
address: Random.address(),
likes: Random.likes()
})
}
const users = [
{
id: 1,
username: 'normal',
password: 'normal',
token: 'abcdefghijklmnopqrstuvwxyz',
rights: [{
id: 1,
authName: '用户管理',
icon: 'icon-menu',
children: [{
id: 11,
authName: '用户项目1',
path: '/menu/one',
rights: ['view', 'edit', 'add', 'delete']
}, {
id: 12,
authName: '用户项目2',
path: '/menu/two',
rights: ['view']
}]
}]
},
{
id: 2,
username: 'admin',
password: 'admin',
token: 'abcdefghijklmnopqrstuvwxyz'.split('').reverse().join(''),
rights: [{
id: 1,
authName: '用户管理',
icon: 'icon-menu',
children: [{
id: 11,
authName: '用户项目1',
path: '/menu/one',
rights: ['view', 'edit', 'add', 'delete']
}, {
id: 12,
authName: '用户项目2',
path: '/menu/two',
rights: ['view', 'edit', 'add', 'delete']
}]
}, {
id: 2,
authName: '用户权限',
icon: 'icon-menu',
children: [{
id: 22,
authName: '权限项目1',
path: '/menu/three',
rights: ['view', 'edit', 'add', 'delete']
}]
}]
}
]
// 获取列表
Mock.mock('/list', 'get', options => {
const { current } = JSON.parse(options.body)
return list.slice(((current - 1) * 10), current * 10)
})
// 总数
Mock.mock('/list/total', 'get', () => {
return list.length
})
// 查询
Mock.mock('/list/value', 'get', options => {
const { value } = JSON.parse(options.body)
const _list = list.filter(item => {
if (item.name.includes(value) || item.address.includes(value) || item.likes.includes(value)) {
return true
}
return false
})
return {
list: _list,
total: _list.length
}
})
// 添加
Mock.mock('/list/add', 'post', options => {
const { rowData } = JSON.parse(options.body)
rowData.id = list[list.length - 1].id + 1
rowData.date = new Date().toLocaleDateString().replace(/\//g, '-')
list.unshift(rowData)
return rowData
})
// 修改
Mock.mock('/list/update', 'put', options => {
const { rowData } = JSON.parse(options.body)
let _rowData = {}
list.forEach((item, idx) => {
if (item.id === rowData.id) {
_rowData = rowData
list[idx] = rowData
}
})
return _rowData
})
// 删除
Mock.mock('/list/delete', 'delete', options => {
const { id } = JSON.parse(options.body)
const index = list.findIndex(item => item.id === id)
const item = index > 0 ? list[index] : {}
list.splice(index, 1)
return item
})
// 用户登录
Mock.mock('/login', 'post', options => {
const { username, password } = JSON.parse(options.body)
const user = users.find(item => {
return item.username === username && item.password === password
})
return user
})
my-radom.js
// 使用 Mock
var Mock = require('mockjs')
Mock.Random.extend({
likes: function () {
const likes = [
'喜欢打游戏,看电影,尤其是英雄联盟和欧美大片。',
'喜欢做饭,尤其是西餐,喜欢做甜点,自己每次都吃得饱饱的。',
'我最爱去游泳了,当然也喜欢潜水,在海底下看各种好看的鱼鱼。',
'我最最喜欢的就是去旅游了,看沿途的风景,真是美呆了。',
'我的爱好是打篮球,我很喜欢打篮球,我的偶像是科比。',
'我超喜欢去蹦迪了,感觉整个身体都在那里放松了。',
'哈哈哈,我喜欢的是和女孩子一起玩,因为男女搭配,干活不累嘛。',
'我没啥爱好,唯一的爱好就是宅。',
'我喜欢看动漫,更喜欢日漫,我可是一个二次元哦。',
'我喜欢cosplay,喜欢cos动漫里的每一个角色。'
]
return this.pick(likes)
}
})
Mock.Random.extend({
address: function () {
const address = [
'深圳市南山区科技园南区R2-B三楼',
'深圳南山区科技园汇景豪苑海欣阁',
'深圳市南山区白石洲中信红树湾',
'上海市普陀区金沙江路 1517 弄',
'四川成都市中德英伦联邦C区',
'北京市中南海老四合院靠左',
'广州市中心中央银行33号'
]
return this.pick(address)
}
})
在store文件夹的index.js中写入以下代码
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
breads: [],
/* user: JSON.parse(window.sessionStorage.getItem('rightsList')||'{}') */
user:JSON.parse(window.sessionStorage.getItem('rightsList')||'{}')
},
mutations: {
addBread (state, bread) {
const index = state.breads.findIndex(_bread => _bread.name === bread.name)
if (index > -1) {
state.breads.splice(index + 1, state.breads.length - index - 1)
} else {
state.breads.push(bread)
}
},
removeBread (state, bread) {
state.breads = state.breads.filter(_bread => _bread !== bread)
},
setUser(state,preload) {
state.user = preload
window.sessionStorage.setItem('rightsList',JSON.stringify(preload))
}
/* setUser (state, user) {
state.user = user
window.sessionStorage.setItem('rightsList',JSON.stringify(user))
} */
},
actions: {
},
modules: {
}
})
接下来做核心的页面部分
Page1.vue
<template>
<div class="page">
<v-card :isOperate="isOperate" v-if="cardShow" @close="cardShow = false" @submitAction="submitAction" :isAdd="isAdd"
:rowData="rowData"></v-card>
<v-top-bar @show="showAddCard" @handleSearch="handleSearch"></v-top-bar>
<el-table :data="tableData" v-loading="loading" border>
<el-table-column type="index" label="#" width="50">
</el-table-column>
<el-table-column prop="date" label="日期" width="180">
</el-table-column>
<el-table-column prop="name" label="姓名" width="180">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
<el-table-column prop="likes" label="爱好">
</el-table-column>
<el-table-column label="操作" width="200">
<template v-slot:default="scope">
<div class="btns">
<el-button type="primary" @click="handleUpdate(scope)">
<i class="el-icon-edit"></i>
</el-button>
<el-button type="danger" @click="handleDelete(scope)">
<i class="el-icon-delete"></i>
</el-button>
</div>
</template>
</el-table-column>
</el-table>
<el-pagination class="pagi" background layout="prev, pager, next" :total="total" @current-change="sizeChange">
</el-pagination>
</div>
</template>
<script>
import TopBar from '@/components/main/TopBar.vue'
import Card from '@/components/main/Card.vue'
import {
mapMutations
} from 'vuex'
export default {
data() {
return {
tableData: [],
page: {
size: 10,
current: 1
},
total: 0,
loading: false,
title: '添加用户',
cardShow: false,
isAdd: true,
rowData: {},
isOperate: false
}
},
methods: {
...mapMutations(['addBread']),
sizeChange(data) {
this.page.current = data
this.getList(this.page.current)
},
initData() {
this.getList(this.page.current)
this.getTotal()
},
showAddCard() {
this.isAdd = true
this.cardShow = true
},
submitAction(info) {
// 添加或修改项目
this.isOperate = true
if (info.isAdd) {
this.$api.addList({
rowData: info.rowData
}).then(() => {
this.initData()
this.cardShow = false
this.isOperate = false
this.$message({
message: '添加成功!',
type: 'success',
customClass: 'v-message',
offset: 100
})
})
} else {
this.$api.updateList({
rowData: info.rowData
}).then(() => {
this.initData()
this.cardShow = false
this.isOperate = false
this.$message({
message: '修改成功!',
type: 'success',
customClass: 'v-message',
offset: 100
})
})
}
},
handleSearch(value) {
if (value === '') {
this.$message({
message: '警告哦,这是一条警告消息',
type: 'warning'
});
this.getList()
return
}
this.loading = true
this.$api.getListByValue({
value
}).then(res => {
this.loading = false
this.tableData = res.data.list
this.total = res.data.total
})
},
handleUpdate(scope) {
this.isAdd = false
this.cardShow = true
this.rowData = scope.row
},
handleDelete(scope) {
this.$confirm('你确定要删除这一条数据吗?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'danger'
}).then(() => {
this.$api.deleteList({
id: scope.row.id
}).then(res => {
this.initData()
this.$message({
message: '删除成功!',
type: 'success',
customClass: 'v-message',
offset: 100
})
})
}).catch(err => err)
},
getList(current) {
this.loading = true
this.$api.getList({
current
}).then(res => {
this.tableData = res.data
this.loading = false
document.querySelector('.page').scrollTop = 0
})
},
getTotal() {
this.$api.getTotal().then(res => {
this.total = res.data
})
}
},
created() {
if (this.$route.query.name) {
this.addBread({
name: this.$route.query.name,
path: this.$route.path
})
}
this.initData()
},
components: {
'v-top-bar': TopBar,
'v-card': Card
}
}
</script>
<style lang="less">
.page {
height: 100%;
overflow-y: scroll;
}
.el-table {
transform: translateY(15px);
}
.pagi {
margin: 30px 0;
text-align: center;
}
.v-message {
left: 58%;
}
</style>
下面写api
http.js 这个页面主要封装的是axios
import Axios from 'axios'
const axios = Axios.create({
// baseURL: process.env.NODE_ENV === 'development' ? '' : '',
})
export default (url, method = 'get', data = {}) => {
return axios({
url,
method,
data
})
}
index.js
require.context是什么
一个webpack的api,通过执行require.context函数获取一个特定的上下文,主要用来实现自动化导入模块,在前端工程中,如果遇到从一个文件夹引入很多模块的情况,可以使用这个api,它会遍历文件夹中的指定文件,然后自动导入,使得不需要每次显式的调用import导入模块
把那三个js导入到这个index.js文件中 (自动化的导入,不需要一个一个的去引入页面)
这个方法有 3 个参数:
- 读取文件的路径
- 是否遍历文件的子目录(上述的图片中只有当前目录没有子目录所以为false)
- 以及一个匹配文件的正则表达式。
const context = require.context('./', false, /.js$/)
const modules = {}
console.log(context.keys());
context.keys().forEach(fileName => {
if (!['./index.js', './http.js'].includes(fileName)) {
Object.assign(modules, context(fileName))
}
})
export default modules
page.js 页面所对应的接口全部获取过来
import http from './http'
export const getList = data => {
return http('/list', 'get', data)
}
export const getTotal = () => {
return http('/list/total')
}
export const getListByValue = data => {
return http('/list/value', 'get', data)
}
export const addList = data => {
return http('/list/add', 'post', data)
}
export const updateList = data => {
return http('/list/update', 'put', data)
}
export const deleteList = data => {
return http('/list/delete', 'delete', data)
}
user.js
import http from './http'
export const login = data => {
return http('/login', 'post', data)
}
在此路径添加common.js
export default {
filters: {
toString (str) {
return str.toString()
}
}
}
最后把Home页面进行绑定
<template>
<div class="home">
<el-container>
<el-header>
<v-header></v-header>
</el-header>
<el-container class="v-container">
<el-aside width="200px">
<v-aside></v-aside>
</el-aside>
<el-main>
<v-main></v-main>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
import Header from '@/components/Header.vue'
import Aside from '@/components/Aside.vue'
import Main from '@/components/Main.vue'
export default {
name: 'Home',
components: {
'v-header': Header,
'v-aside': Aside,
'v-main': Main
}
}
</script>
<style lang="less" scoped>
.home {
height: 100%;
}
.el-container {
height: 100%;
}
.v-container {
height: calc(100% - 60px);
}
.el-header {
padding: 0;
z-index: 9;
}
.el-aside {
height: 100%;
background-color: #00BFFF;
}
.el-main {
height: 100%;
background-color: #eee;
.main {
height: 100%;
overflow: hidden;
}
}
</style>