IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 权限管理前端篇(二)之权限管理页面的详细搭建过程 -> 正文阅读

[JavaScript知识库]权限管理前端篇(二)之权限管理页面的详细搭建过程

创建前端项目

1.创建项目有两种方式

vue ui

进入页面

?下一步:

?下一步选手动:

?下一步:

?下一步选2.x版本创建项目

开发工具用WebStorm 2020.3.3

引入Element-ui

yarn add element-ui

main.js中添加如下:

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);

测试element是否添加成功

在HomeView.vue进行测试,测试代码如下:

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
    <el-button>测试elementui</el-button>
  </div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'

export default {
  name: 'HomeView',
  components: {
    HelloWorld
  }
}
</script>

安装axios、qs、mockjs

axios:一个基于promise的HTTP库,类ajax

qs:查询参数序列化和解析库

mockjs:为我们生成随机数数据的工具类

安装axios

进入项目目录,添加axios依赖

yarn add axios

main.js中添加如下:

import axios from 'axios'
Vue.prototype.$http = axios

安装qs

进入项目目录,添加qs依赖

yarn add qs

安装mockjs:为我们生成随机数据的工具库

yarn add mockjs -S

页面路由的开发

删除本身自带的页面

vue模板代码

<template>

</template>
<script>
export default {
  name:"Login"
}
</script>
<style scoped>

</style>

在views下创建两个页面Login.vue(登录页面)和Home.vue(首页)

修改路由

import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/Home.vue'
import LoginView from '../views/Login.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import( '../views/Login.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

开发登陆页面

在login.vue下进行编写

<template>
  <el-row type="flex" class="row-bg" justify="center">
<!--    <el-col :span="6"><div class="grid-content bg-purple"></div></el-col>-->
<!--    <el-col :span="6"><div class="grid-content bg-purple-light"></div></el-col>-->
    <el-col :span="6" :lg="7">
      <el-form :model="loginForm" :rules="rules" ref="loginForm" label-width="100px" >
        <el-form-item label="用户名" prop="username" style="width: 380px">
          <el-input v-model="loginForm.username"></el-input>
        </el-form-item>

        <el-form-item label="密码" prop="password" style="width: 380px">
          <el-input v-model="loginForm.password">
          </el-input>
        </el-form-item>

        <el-form-item label="验证码" prop="code" style="width: 380px">
          <el-input v-model="loginForm.code" style="width: 172px; float: left;"></el-input>
          <el-image srx=""></el-image>
        </el-form-item>

        <el-form-item>
          <el-button type="primary" @click="submitForm('loginForm')">立即创建</el-button>
          <el-button @click="resetForm('loginForm')">重置</el-button>
        </el-form-item>
      </el-form>
    </el-col>
  </el-row>
</template>
<script>
export default {
  name:"Login",
  data() {
    return {
      loginForm: {
        username: '',
        password: '',
        code: ''
      },
      rules: {
        username: [
          { required: true, message: '请输入用户名', trigger: 'blur' }
        ],
        password: [
          { required: true, message: '请输入密码', trigger: 'blur' }
        ],
        code: [
          { required: true, message: '请输入验证码', trigger: 'blur' },
          { min: 5, max: 5, message: '长度在5个字符', trigger: 'blur' }
        ]
      }
    };
  },
  methods: {
    submitForm(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          alert('submit!');
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    resetForm(formName) {
      this.$refs[formName].resetFields();
    }
  }
}
</script>
<style scoped>
.el-row{
  height: 100%;
  display: flex;
  align-items: center;
  text-align: center;
}
.captchaIng{
  float: left;
  margin-left: 8px;
  border-radius: 4px;
}
</style>

效果比较难看进行优化调整优化代码如下

<template>
  <div class="loginbody">
    <div class="logindata">
      <div class="logintext">
        <h2>永远商城权限管理</h2>
      </div>
      <div class="formdata">
      <el-form :model="loginForm" :rules="rules" ref="loginForm" label-width="100px" >
        <el-form-item label="用户名" prop="username" style="width: 380px">
          <el-input v-model="loginForm.username"></el-input>
        </el-form-item>

        <el-form-item label="密码" prop="password" style="width: 380px">
          <el-input v-model="loginForm.password">
          </el-input>
        </el-form-item>

        <el-form-item label="验证码" prop="code" style="width: 380px">
          <el-input v-model="loginForm.code" style="width: 172px; float: left;"></el-input>
          <el-image srx=""></el-image>
        </el-form-item>
        <div class="butt">
        <el-form-item>
          <el-button type="primary" @click="submitForm('loginForm')">登录</el-button>
          <el-button @click="resetForm('loginForm')">重置</el-button>
        </el-form-item>
        </div>
      </el-form>

      </div>
    </div>
  </div>
</template>
<script>
export default {
  name:"Login",
  data() {
    return {
      loginForm: {
        username: '',
        password: '',
        code: ''
      },
      checked: false,
      rules: {
        username: [
          { required: true, message: '请输入用户名', trigger: 'blur' }
        ],
        password: [
          { required: true, message: '请输入密码', trigger: 'blur' }
        ],
        code: [
          { required: true, message: '请输入验证码', trigger: 'blur' },
          { min: 5, max: 5, message: '长度在5个字符', trigger: 'blur' }
        ]
      }
    };
  },
  methods: {
    submitForm(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          alert('submit!');
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    resetForm(formName) {
      this.$refs[formName].resetFields();
    }
  }
}
</script>
<style scoped>
.loginbody {
  width: 100%;
  height: 100%;
  min-width: 1000px;
  background-image: url("../assets/login2.jpg");
  background-size: 100% 100%;
  background-position: center center;
  overflow: auto;
  background-repeat: no-repeat;
  position: fixed;
  line-height: 100%;
  padding-top: 150px;
}

.logintext {
  margin-bottom: 20px;
  line-height: 50px;
  text-align: center;
  font-size: 30px;
  font-weight: bolder;
  color: white;
  text-shadow: 2px 2px 4px #000000;
}

.logindata {
  width: 400px;
  height: 300px;
  transform: translate(-50%);
  margin-left: 50%;
}


.butt {
  margin-top: 10px;
  text-align: center;
}


</style>

发起登录请求,Mock返回测试结果

代码如下:

Login.vue

<template>
  <div class="loginbody">
    <div class="logindata">
      <div class="logintext">
        <h2>永远商城权限管理</h2>
      </div>
      <div class="formdata">
      <el-form :model="loginForm" :rules="rules" ref="loginForm" label-width="80px" >
        <el-form-item label="用户名" prop="username" style="width: 380px">
          <el-input v-model="loginForm.username"></el-input>
        </el-form-item>

        <el-form-item label="密码" prop="password" style="width: 380px">
          <el-input v-model="loginForm.password">
          </el-input>
        </el-form-item>

        <el-form-item label="验证码" prop="code" style="width: 380px">
          <el-input v-model="loginForm.code" style="width: 172px; float: left;"></el-input>
          <el-image :src="captchaImg" class="captchaImg"></el-image>
        </el-form-item>
        <div class="butt">
        <el-form-item>
          <el-button type="primary" @click="submitForm('loginForm')">登录</el-button>
          <el-button @click="resetForm('loginForm')">重置</el-button>
        </el-form-item>
        </div>
      </el-form>

      </div>
    </div>
  </div>
</template>
<script>
export default {
  name:"Login",
  data() {
    return {
      loginForm: {
        username: '',
        password: '',
        code: '',
        token:''
      },
      checked: false,
      rules: {
        username: [
          { required: true, message: '请输入用户名', trigger: 'blur' }
        ],
        password: [
          { required: true, message: '请输入密码', trigger: 'blur' }
        ],
        code: [
          { required: true, message: '请输入验证码', trigger: 'blur' },
          { min: 5, max: 5, message: '长度在5个字符', trigger: 'blur' }
        ]
      },
      captchaImg: null
    };
  },
  methods: {
    submitForm(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
            this.$axios.post('/login',this.loginForm).then(res =>{

              const  jwt =res.headers['authorization']

              this.$store.commit('SET_TOKEN',jwt)

              this.$router.push("/index")
            });
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    resetForm(formName) {
      this.$refs[formName].resetFields();
    },
    getCaptcha(){
      this.$axios.get('/captcha').then(res =>{
        console.log("/captcha")
        console.log(res)
        this.loginForm.token=res.data.data.token
        this.captchaImg=res.data.data.captchaImg
      })
    }
    //Result - code、msg、data

  },
  created() {
    this.getCaptcha()
  }

}
</script>
<style scoped>
.loginbody {
  width: 100%;
  height: 100%;
  min-width: 1000px;
  background-image: url("../assets/login2.jpg");
  background-size: 100% 100%;
  background-position: center center;
  overflow: auto;
  background-repeat: no-repeat;
  position: fixed;
  line-height: 100%;
  padding-top: 150px;
}

.logintext {
  margin-bottom: 20px;
  line-height: 50px;
  text-align: center;
  font-size: 30px;
  font-weight: bolder;
  color: white;
  text-shadow: 2px 2px 4px #000000;
}

.logindata {
  width: 400px;
  height: 300px;
  transform: translate(-50%);
  margin-left: 50%;
}


.butt {
  margin-top: 10px;
  text-align: center;
}


</style>

store下index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    token:''
  },
  getters: {
  },
  mutations: {
    SET_TOKEN:(state,token)=>{
      state.token=token
      localStorage.setItem("token",token)
    }
  },
  actions: {
  },
  modules: {
  }
})

main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import axios from 'axios'

Vue.prototype.$axios = axios
Vue.config.productionTip = false

require("./mock.js")

Vue.use(ElementUI);





new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

main.js同级mock.js

const  Mock =require('mockjs')

const Random =Mock.Random

let Result={
    code: 200,
    msg: '操作成功',
    data: null
}

Mock.mock('/captcha','get',()=>{
Result.data={
    token: Random.string(32),
    captchaImg: Random.dataImage('120x40','p7n5w')
}
return Result
})

Mock.mock('/login','post',()=>{

    //无法在header中传入jwt

    return Result
})


axios请求前后拦截处理

axios.js

import axios from "axios";
import  router from "./router";
import Element from  "element-ui";

// axios.defaults.baseURL="http://localhost:8081"

const request = axios.create({
    timeout: 5000,
    headers:{
        'Content-Type':"application/json; charset=utf-8"
    }
})

request.interceptors.request.use(config => {
    config.headers['Authorization'] =localStorage.getItem("token")
    return config
})

request.interceptors.response.use(response=>{
let res =response.data
    if (res.code===200){
        return response
    }else {
        Element.Message.error(res.msg?'系统异常':res.msg)
        return Promise.reject(response.data.msg)
    }
},error => {
    if (error.response.data){
        error.message=error.response.data.msg
    }

    if (error.response.status===401){
        router.push("/login")
        }
    Element.Message.error(error.message,{duration:3000})
    return Promise.reject(error)
    }
)

export default request

main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import axios from './axios'

Vue.prototype.$axios = axios
Vue.config.productionTip = false

require("./mock.js")

Vue.use(ElementUI);





new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

mock.js

const  Mock =require('mockjs')

const Random =Mock.Random

let Result={
    code: 200,
    msg: '操作成功',
    data: null
}

Mock.mock('/captcha','get',()=>{
Result.data={
    token: Random.string(32),
    captchaImg: Random.dataImage('120x40','p7n5w')
}
return Result
})

Mock.mock('/login','post',()=>{

    //无法在header中传入jwt
    Result.code=400
    Result.msg="验证码错误"
    return Result
})


后台整体布局、头部样式

代码如下:

views下index.vue

<template>
  <el-container class="layout-container">
    <el-aside width="200px">Aside</el-aside>
    <el-container>
      <el-header>
        <strong>通用管理平台</strong>

        <div class="header-avatar">
          <el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>

          <el-dropdown>
          <span class="el-dropdown-link">
            下拉菜单<i class="el-icon-arrow-down el-icon--right"></i>
          </span>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item>个人中心</el-dropdown-item>
              <el-dropdown-item>退出</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>

        <el-link href="https://www.yongyuankuaile.com" target="_blank">网站</el-link>
        </div>


      </el-header>
      <el-main>Main</el-main>
    </el-container>
  </el-container>
</template>

<script>
export default {
  name:"Index"
}
</script>

<style scoped>
.layout-container {
  height: 100%;
}

.header-avatar{
  float: right;
  width: 210px;
  display: flex;
  justify-content: space-around;
  align-items: center;
}

.el-dropdown-link{
  cursor: pointer;
  color: #407EFF;
}

.el-icon-arrow-down{
  font-size: 12px;
}

.el-header, .el-footer {
  background-color: #B3C0D1;
  color: #333;
  text-align: center;
  line-height: 60px;
}

.el-aside {
  background-color: #D3DCE6;
  color: #333;
  text-align: center;
  line-height: 200px;
}

.el-main {
  background-color: #E9EEF3;
  color: #333;
  text-align: center;
  line-height: 160px;
}

body > .el-container {
  margin-bottom: 40px;
}

.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
  line-height: 260px;
}

.el-container:nth-child(7) .el-aside {
  line-height: 320px;
}
</style>

在src下的assets下新建css文件包创建global.css文件

html,body,#app {
    height: 100%;
    margin: 0;
    padding: 0;
}

mian.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import axios from './axios'
import '@/assets/css/global.css'

Vue.prototype.$axios = axios
Vue.config.productionTip = false

require("./mock.js")

Vue.use(ElementUI);





new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/Home.vue'
import Index from '../views/Index'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/index',
    name: 'Index',
    component: Index
  },
  {
    path: '/login',
    name: 'login',
    component: () => import( '../views/Login.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

扩展知识

element-ui 中让el-container 高度自适应

assets文件夹中,新建一个global.css文件。

html,body,#app {
  height: 100%;
  margin: 0;
  padding: 0;
}

2、然后在main.js中引入?global.css

import '@/assets/css/global.css'

3、后续给你所有的组件设置?height:100%?就可以了。

vue中使用

 <el-container class="layout-container">
    <el-aside width="300px">
    </el-aside>
 <el-container>

css

.layout-container {
  height: 100%;
}

左侧导航菜单填充

index.vue

<template>
  <el-container class="layout-container">
    <el-aside width="200px">
      <el-menu
          default-active="2"
          class="el-menu-vertical-demo"
          @open="handleOpen"
          @close="handleClose"
          background-color="#545c64"
          text-color="#fff"
          active-text-color="#ffd04b">

        <router-link to="/index">
          <el-menu-item index="Index">
            <template slot="title">
              <i class="el-icon-s-home"></i>
              <span>首页</span>
            </template>
          </el-menu-item>
        </router-link>
        <el-submenu index="1">
          <template slot="title">
            <i class="el-icon-s-operation"></i>
            <span>系统管理</span>
          </template>
          <el-submenu index="1-1">
            <template slot="title">
              <i class="el-icon-s-custom"></i>
              <span>用户管理</span>
            </template>
            <el-menu-item index="1-2">
              <template slot="title">
                <i class="el-icon-rank"></i>
                <span>角色管理</span>
              </template>
          </el-menu-item>
            <el-menu-item index="1-3">
              <template slot="title">
                <i class="el-icon-s-tools"></i>
                <span>菜单管理</span>
              </template>
            </el-menu-item>
        </el-submenu>
        </el-submenu>

        <el-submenu index="2">
          <template slot="title">
            <i class="el-icon-s-tools"></i>
            <span>系统工具</span>
          </template>
          <el-menu-item index="2-1">
            <template slot="title">
              <i class="el-icon-s-order"></i>
              <span>数字字典</span>
            </template>
          </el-menu-item>
        </el-submenu>
      </el-menu>
    </el-aside>
    <el-container>
      <el-header>
        <strong>通用管理平台</strong>

        <div class="header-avatar">
          <el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>

          <el-dropdown>
          <span class="el-dropdown-link">
            下拉菜单<i class="el-icon-arrow-down el-icon--right"></i>
          </span>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item>个人中心</el-dropdown-item>
              <el-dropdown-item>退出</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>

        <el-link href="https://www.yongyuankuaile.com" target="_blank">网站</el-link>
        </div>


      </el-header>
      <el-main>Main</el-main>
    </el-container>
  </el-container>
</template>

<script>
export default {
  name:"Index"
}
</script>

<style scoped>
.layout-container {
  height: 100%;
}

.header-avatar{
  float: right;
  width: 210px;
  display: flex;
  justify-content: space-around;
  align-items: center;
}

.el-dropdown-link{
  cursor: pointer;
  color: #407EFF;
}

.el-icon-arrow-down{
  font-size: 12px;
}

.el-header{
  background-color: #17B3A3;
  color: #333;
  text-align: center;
  line-height: 60px;
}

.el-aside {
  background-color: #D3DCE6;
  color: #333;
  text-align: center;
  line-height: 200px;
}

.el-main {
  background-color: #E9EEF3;
  color: #333;
  text-align: center;
  line-height: 160px;
}



.el-menu-vertical-demo{
  height: 100%;
}
</style>

拆分抽取Vue组件

在views文件夹下新建inc文件夹

inc文件夹新建SideMenu.vue代码如下

<template>
  <el-menu
      default-active="2"
      class="el-menu-vertical-demo"
      @open="handleOpen"
      @close="handleClose"
      background-color="#545c64"
      text-color="#fff"
      active-text-color="#ffd04b">

    <router-link to="/index">
      <el-menu-item index="Index">
        <template slot="title">
          <i class="el-icon-s-home"></i>
          <span>首页</span>
        </template>
      </el-menu-item>
    </router-link>
    <el-submenu index="1">
      <template slot="title">
        <i class="el-icon-s-operation"></i>
        <span>系统管理</span>
      </template>
      <el-submenu index="1-1">
        <template slot="title">
          <i class="el-icon-s-custom"></i>
          <span>用户管理</span>
        </template>
        <el-menu-item index="1-2">
          <template slot="title">
            <i class="el-icon-rank"></i>
            <span>角色管理</span>
          </template>
        </el-menu-item>
        <el-menu-item index="1-3">
          <template slot="title">
            <i class="el-icon-s-tools"></i>
            <span>菜单管理</span>
          </template>
        </el-menu-item>
      </el-submenu>
    </el-submenu>

    <el-submenu index="2">
      <template slot="title">
        <i class="el-icon-s-tools"></i>
        <span>系统工具</span>
      </template>
      <el-menu-item index="2-1">
        <template slot="title">
          <i class="el-icon-s-order"></i>
          <span>数字字典</span>
        </template>
      </el-menu-item>
    </el-submenu>
  </el-menu>
</template>
<script>
export default {
  name:"SideMenu"
}
</script>
<style scoped>
.el-menu-vertical-demo{
  height: 100%;
}
</style>

修改Home.vue

<template>
  <el-container class="layout-container">
    <el-aside width="200px">
      <SideMenu></SideMenu>
    </el-aside>
    <el-container>
      <el-header>
        <strong>通用管理平台</strong>

        <div class="header-avatar">
          <el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>

          <el-dropdown>
          <span class="el-dropdown-link">
            下拉菜单<i class="el-icon-arrow-down el-icon--right"></i>
          </span>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item>个人中心</el-dropdown-item>
              <el-dropdown-item>退出</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>

          <el-link href="https://www.yongyuankuaile.com" target="_blank">网站</el-link>
        </div>


      </el-header>
      <el-main>
        <router-view></router-view>
      </el-main>
    </el-container>
  </el-container>
</template>
<script>
import SideMenu from "@/views/inc/SideMenu";
export default {
  name:"Home",
  components: {SideMenu}
}
</script>
<style scoped>
.layout-container {
  height: 100%;
}

.header-avatar{
  float: right;
  width: 210px;
  display: flex;
  justify-content: space-around;
  align-items: center;
}

.el-dropdown-link{
  cursor: pointer;
  color: #407EFF;
}

.el-icon-arrow-down{
  font-size: 12px;
}

.el-header{
  background-color: #17B3A3;
  color: #333;
  text-align: center;
  line-height: 60px;
}

.el-aside {
  background-color: #D3DCE6;
  color: #333;
  text-align: center;
  line-height: 200px;
}

.el-main {
  background-color: #E9EEF3;
  color: #333;
  text-align: center;
  line-height: 160px;
}



</style>

修改Index.vue

<template>
<div>main</div>
</template>

<script>
import SideMenu from "@/views/inc/SideMenu";
export default {
  name:"Index",
  components: {SideMenu}
}
</script>

<style scoped>


</style>

修改router路由下的index.js增加子路由

import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/Home.vue'
import Index from '../views/Index'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView,
    children:[
      {
        path: '/index',
        name: 'Index',
        component: Index
      }
    ]
  },

  {
    path: '/login',
    name: 'login',
    component: () => import( '../views/Login.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

编写导航栏的路由

在views文件包下新增sys文件包增加User.vue、Role.vue、Menu.vue

代码如下:

User.vue

<template>
<div>用户管理</div>
</template>

<script>
export default {
  name: "User"
}
</script>

<style scoped>

</style>

Role.vue

<template>
  <div>权限管理</div>
</template>

<script>
export default {
  name: "Role"
}
</script>

<style scoped>

</style>

Menu.vue

<template>
  <div>菜单管理</div>
</template>

<script>
export default {
  name: "Menu"
}
</script>

<style scoped>

</style>

在路由中增加子菜单

import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/Home.vue'
import Index from '../views/Index'
import Menu from '../views/sys/Menu'
import Role from '../views/sys/Role'
import User from '../views/sys/User'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView,
    children:[
      {
        path: '/index',
        name: 'Index',
        component: Index
      },
      {
        path: '/user',
        name: 'SysUser',
        component: User
      },
      {
        path: '/role',
        name: 'SyeRole',
        component: Role
      },
      {
        path: '/menus',
        name: 'SysMenu',
        component: Menu
      }
    ]
  },

  {
    path: '/login',
    name: 'login',
    component: () => import( '../views/Login.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

在导航

SideMenu.vue增加跳转注解

<template>
  <el-menu
      default-active="2"
      class="el-menu-vertical-demo"
      @open="handleOpen"
      @close="handleClose"
      background-color="#545c64"
      text-color="#fff"
      active-text-color="#ffd04b">

    <router-link to="/index">
      <el-menu-item index="Index">
        <template slot="title">
          <i class="el-icon-s-home"></i>
          <span>首页</span>
        </template>
      </el-menu-item>
    </router-link>

    <el-submenu index="1">
      <template slot="title">
        <i class="el-icon-s-operation"></i>
        <span>系统管理</span>
      </template>
    </el-submenu>

      <router-link to="/user">
      <el-menu-item index="1-1">
        <template slot="title">
          <i class="el-icon-s-custom"></i>
          <span>用户管理</span>
        </template>
      </el-menu-item>
        </router-link>

        <router-link to="/role">
        <el-menu-item index="1-2">
          <template slot="title">
            <i class="el-icon-rank"></i>
            <span>角色管理</span>
          </template>
        </el-menu-item>
        </router-link>

        <el-menu-item index="1-3">
          <template slot="title">
            <i class="el-icon-s-tools"></i>
            <span>菜单管理</span>
          </template>
        </el-menu-item>
      </el-submenu>
    </el-submenu>

    <el-submenu index="2">
      <template slot="title">
        <i class="el-icon-s-tools"></i>
        <span>系统工具</span>
      </template>

      <el-menu-item index="2-1">
        <template slot="title">
          <i class="el-icon-s-order"></i>
          <span>数字字典</span>
        </template>
      </el-menu-item>
    </el-submenu>
  </el-menu>
</template>
<script>
export default {
  name:"SideMenu"
}
</script>
<style scoped>
.el-menu-vertical-demo{
  height: 100%;
}
</style>

用户信息展示、修改个人密码

Home.vue

<template>
  <el-container class="layout-container">
    <el-aside width="200px">
      <SideMenu></SideMenu>
    </el-aside>
    <el-container>
      <el-header>
        <strong>通用管理平台</strong>

        <div class="header-avatar">
          <el-avatar :src="userInfo.avatar"></el-avatar>

          <el-dropdown>
          <span class="el-dropdown-link">
            {{userInfo.username}}<i class="el-icon-arrow-down el-icon--right"></i>
          </span>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item>
              <router-link :to="{name: 'userCenter'}">  个人中心</router-link>
              </el-dropdown-item>
              <el-dropdown-item>退出</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>

          <el-link href="https://www.yongyuankuaile.com" target="_blank">网站</el-link>
        </div>


      </el-header>
      <el-main>
        <router-view></router-view>
      </el-main>
    </el-container>
  </el-container>
</template>
<script>
import SideMenu from "@/views/inc/SideMenu";
export default {
  name:"Home",
  components: {SideMenu},
  data(){
  return{
    userInfo:{
      id:"",
      username:"",
      avatar:""
    }
  }
  },
  created() {
    this.getUserInfo()
  },
  methods:{
    getUserInfo(){
      this.$axios.get("/sys/userInfo").then(res=>{
        this.userInfo=res.data.data
      })
    }
  }
}
</script>
<style scoped>
.layout-container {
  height: 100%;
}

.header-avatar{
  float: right;
  width: 210px;
  display: flex;
  justify-content: space-around;
  align-items: center;
}

.el-dropdown-link{
  cursor: pointer;
  color: #407EFF;
}

.el-icon-arrow-down{
  font-size: 12px;
}

.el-header{
  background-color: #17B3A3;
  color: #333;
  text-align: center;
  line-height: 60px;
}

.el-aside {
  background-color: #D3DCE6;
  color: #333;
  text-align: center;
  line-height: 200px;
}

.el-main {
  background-color: #E9EEF3;
  color: #333;
  text-align: center;
  line-height: 160px;
}



</style>

mock.js

<template>
  <el-container class="layout-container">
    <el-aside width="200px">
      <SideMenu></SideMenu>
    </el-aside>
    <el-container>
      <el-header>
        <strong>通用管理平台</strong>

        <div class="header-avatar">
          <el-avatar :src="userInfo.avatar"></el-avatar>

          <el-dropdown>
          <span class="el-dropdown-link">
            {{userInfo.username}}<i class="el-icon-arrow-down el-icon--right"></i>
          </span>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item>
              <router-link :to="{name: 'userCenter'}">  个人中心</router-link>
              </el-dropdown-item>
              <el-dropdown-item>退出</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>

          <el-link href="https://www.yongyuankuaile.com" target="_blank">网站</el-link>
        </div>


      </el-header>
      <el-main>
        <router-view></router-view>
      </el-main>
    </el-container>
  </el-container>
</template>
<script>
import SideMenu from "@/views/inc/SideMenu";
export default {
  name:"Home",
  components: {SideMenu},
  data(){
  return{
    userInfo:{
      id:"",
      username:"",
      avatar:""
    }
  }
  },
  created() {
    this.getUserInfo()
  },
  methods:{
    getUserInfo(){
      this.$axios.get("/sys/userInfo").then(res=>{
        this.userInfo=res.data.data
      })
    }
  }
}
</script>
<style scoped>
.layout-container {
  height: 100%;
}

.header-avatar{
  float: right;
  width: 210px;
  display: flex;
  justify-content: space-around;
  align-items: center;
}

.el-dropdown-link{
  cursor: pointer;
  color: #407EFF;
}

.el-icon-arrow-down{
  font-size: 12px;
}

.el-header{
  background-color: #17B3A3;
  color: #333;
  text-align: center;
  line-height: 60px;
}

.el-aside {
  background-color: #D3DCE6;
  color: #333;
  text-align: center;
  line-height: 200px;
}

.el-main {
  background-color: #E9EEF3;
  color: #333;
  text-align: center;
  line-height: 160px;
}



</style>

index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/Home.vue'
import Index from '../views/Index'
import Menu from '../views/sys/Menu'
import Role from '../views/sys/Role'
import User from '../views/sys/User'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView,
    children:[
      {
        path: '/index',
        name: 'Index',
        component: Index
      },
      {
        path: '/userCenter',
        name: 'userCenter',
        component: () => import( '../views/userCenter.vue')
      },
      {
        path: '/sys/user',
        name: 'SysUser',
        component: User
      },
      {
        path: '/sys/role',
        name: 'SyeRole',
        component: Role
      },
      {
        path: '/sys/menus',
        name: 'SysMenu',
        component: Menu
      }
    ]
  },

  {
    path: '/login',
    name: 'login',
    component: () => import( '../views/Login.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

userCenter.vue

<template>
  <div style="text-align: center;">
    <h2>你好!{{ userInfo.username }} 同学</h2>

    <el-form :model="passForm" status-icon :rules="rules" ref="passForm" label-width="100px">
      <el-form-item label="旧密码" prop="currentPass">
        <el-input type="password" v-model="passForm.currentPass" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="新密码" prop="password">
        <el-input type="password" v-model="passForm.password" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="确认密码" prop="checkPass">
        <el-input type="password" v-model="passForm.checkPass" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm('passForm')">提交</el-button>
        <el-button @click="resetForm('passForm')">重置</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
export default {
  name: "Login",
  data() {
    var validatePass = (rule, value, callback) => {
      if (value === '') {
        callback(new Error('请再次输入密码'));
      } else if (value !== this.passForm.password) {
        callback(new Error('两次输入密码不一致!'));
      } else {
        callback();
      }
    };
    return {
      userInfo: {
      },
      passForm: {
        password: '',
        checkPass: '',
        currentPass: ''
      },
      rules: {
        password: [
          { required: true, message: '请输入新密码', trigger: 'blur' },
          { min: 6, max: 12, message: '长度在 6 到 12 个字符', trigger: 'blur' }
        ],
        checkPass: [
          { required: true, validator: validatePass, trigger: 'blur' }
        ],
        currentPass: [
          { required: true, message: '请输入当前密码', trigger: 'blur' },
        ]
      }
    }
  },
  created() {
    this.getUserInfo()
  },
  methods: {
    getUserInfo() {
      this.$axios.get("/sys/userInfo").then(res => {
        this.userInfo = res.data.data;
      })
    },
    submitForm(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          const _this = this
          this.$axios.post('/sys/user/updatePass', this.passForm).then(res => {
            _this.$alert(res.data.msg, '提示', {
              confirmButtonText: '确定',
              callback: action => {
                this.$refs[formName].resetFields();
              }
            });
          })
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    resetForm(formName) {
      this.$refs[formName].resetFields();
    }
  }
}
</script>

<style scoped>
.el-form {
  width: 420px;
  margin: 50px auto;
}
</style>

前端用户退出操作

Home.vue

<template>
  <el-container class="layout-container">
    <el-aside width="200px">
      <SideMenu></SideMenu>
    </el-aside>
    <el-container>
      <el-header>
        <strong>通用管理平台</strong>

        <div class="header-avatar">
          <el-avatar :src="userInfo.avatar"></el-avatar>

          <el-dropdown>
          <span class="el-dropdown-link">
            {{userInfo.username}}<i class="el-icon-arrow-down el-icon--right"></i>
          </span>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item>
              <router-link :to="{name: 'userCenter'}">  个人中心</router-link>
              </el-dropdown-item>
              <el-dropdown-item @click.native="logout">退出</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>

          <el-link href="https://www.yongyuankuaile.com" target="_blank">网站</el-link>
        </div>


      </el-header>
      <el-main>
        <router-view></router-view>
      </el-main>
    </el-container>
  </el-container>
</template>
<script>
import SideMenu from "@/views/inc/SideMenu";
export default {
  name:"Home",
  components: {SideMenu},
  data(){
  return{
    userInfo:{
      id:"",
      username:"",
      avatar:""
    }
  }
  },
  created() {
    this.getUserInfo()
  },
  methods:{
    getUserInfo(){
      this.$axios.get("/sys/userInfo").then(res=>{
        this.userInfo=res.data.data
      })
    },
    logout(){
      this.$axios.post("/logout").then(res => {
        localStorage.clear()
        sessionStorage.clear()
        this.$store.commit("resetState")

        this.$router.push("/login")
      })
    }
  }
}
</script>
<style scoped>
.layout-container {
  height: 100%;
}

.header-avatar{
  float: right;
  width: 210px;
  display: flex;
  justify-content: space-around;
  align-items: center;
}

.el-dropdown-link{
  cursor: pointer;
  color: #407EFF;
}

.el-icon-arrow-down{
  font-size: 12px;
}

.el-header{
  background-color: #17B3A3;
  color: #333;
  text-align: center;
  line-height: 60px;
}

.el-aside {
  background-color: #D3DCE6;
  color: #333;
  text-align: center;
  line-height: 200px;
}

.el-main {
  background-color: #E9EEF3;
  color: #333;
  text-align: center;
  line-height: 160px;
}



</style>

Mock.js

const  Mock =require('mockjs')

const Random =Mock.Random

let Result={
    code: 200,
    msg: '操作成功',
    data: null
}

Mock.mock('/captcha','get',()=>{
Result.data={
    token: Random.string(32),
    captchaImg: Random.dataImage('120x40','p7n5w')
}
return Result
})

Mock.mock('/login','post',()=>{

    //无法在header中传入jwt
    Result.code=400
    Result.msg="验证码错误"
    return Result
})

Mock.mock('/sys/userInfo','get',()=>{

    Result.data={
        id:"1",
        username:"test",
        avatar:""
    }
    return Result
})


Mock.mock('/logout','post',()=>{

    return Result
})

index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    token:''
  },
  getters: {
  },
  mutations: {
    SET_TOKEN:(state,token)=>{
      state.token=token
      localStorage.setItem("token",token)
    },

    resetState:(state) =>{
      state.token =''

    }
  },
  actions: {
  },
  modules: {
  }
})

动态导航与动态路由绑定

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-17 12:24:08  更:2022-10-17 12:27:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/11 16:53:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码