您的位置:首页 > Web前端 > Vue.js

Vue管理系统前端系列三登录页和首页及`vuex`管理登录状态

2020-08-21 15:23 816 查看

目录

  • 首页相关代码
  • 登录页面设计

    该节记录了登录界面的设计,以及 vuex 的简单实用,然后将首页简单搭建完成。

    先看最终效果图

    先在 views 文件夹下 新建 login/index.vue 文件。用于登录首页

    vuex 对应 用户模块

    vuex
    相关介绍可参考另一篇博文,链接

    新建

    store/modules/user.js
    ,将登录状态及内容保存到状态管理器中,内容如下:

    import router from '@/router'
    
    export default {
    state: {
    userInfo: null, //用户信息
    token: null,
    },
    getters: {
    userInfo: (state) => {
    if (state.userInfo == null) {
    let sessionUser = sessionStorage.getItem('user')
    if (sessionUser != null) {
    state.userInfo = JSON.parse(sessionUser)
    return sessionUser
    } else {
    let localeUser = localStorage.getItem('user')
    if (localeUser != null) {
    state.userInfo = JSON.parse(localeUser)
    }
    return localeUser
    }
    }
    return state.userInfo
    },
    token: (state) => {
    if (state.token == null) {
    let sessionToken = sessionStorage.getItem('token')
    if (sessionToken != null) {
    state.token = sessionToken
    
    1b1c
    return sessionToken
    } else {
    let localeToken = localStorage.getItem('token')
    state.token = localeToken
    return localeToken
    }
    }
    return state.token
    },
    },
    mutations: {
    setToken(state, token, flag = true) {
    if (flag) {
    localStorage.setItem('token', token)
    } else {
    sessionStorage.setItem('token', token)
    }
    },
    setUserInfo(state, userInfo, flag = true) {
    state.userInfo = userInfo
    state.token = userInfo.token
    if (flag) {
    localStorage.setItem('user', JSON.stringify(userInfo))
    } else {
    sessionStorage.setItem('user', JSON.stringify(userInfo))
    }
    this.commit('setToken', userInfo.token, flag)
    },
    logout(state) {
    state.userInfo = null
    state.token = null
    localStorage.removeItem('token')
    localStorage.removeItem('user')
    sessionStorage.removeItem('token')
    sessionStorage.removeItem('user')
    router.push('/login')
    },
    },
    actions: {},
    }

    然后再在

    store/index.js
    中将 user 模块引入进来,代码如下:

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    import user from './modules/user'
    
    const store = new Vuex.Store({
    modules: {
    user: user,
    },
    })
    export default store

    丰富界面

    使用

    element
    的 from 组件,进行设计登录界面。界面代码如下:

    <template>
    <div class="loginContain">
    <div class="loginBox">
    <h2 class="loginH2"><strong>Vue</strong> 后台管理系统</h2>
    <el-form :model="loginForm" :rules="loginFormRules" ref="loginForm" label-position="left" label-width="0px" class="login-form">
    <el-form-item prop="username">
    <el-input type="text" v-model="loginForm.username" auto-complete="off" placeholder="请输入账号">
    <i slot="prefix" class="el-input__icon el-icon-user-solid"></i>
    </el-input>
    </el-form-item>
    <el-form-item prop="password">
    <el-input type="password" v-model="loginForm.password" auto-complete="off" placeholder="密码">
    <i slot="prefix" class="el-input__icon el-icon-lock"></i>
    </el-input>
    </el-form-item>
    <el-form-item style="width:100%;">
    <el-button type="primary" style="  width: 100%; background: #19b9e7;" @click.native.prevent="login" :loading="logining">登 录</el-button>
    </el-form-item>
    </el-form>
    </div>
    </div>
    </template>

    登录相关 脚本 代码如下:

    <script>
    export default {
    data() {
    return {
    logining: false,
    loginForm: {
    username: 'admin',
    password: '123456',
    },
    notifyObj: null,
    loginFormRules: {
    username: [{ required: true, message: '请输入账号', trigger: 'blur' }],
    password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
    },
    }
    },
    //引入组件
    components: {},
    // 方法
    methods: {
    login() {
    this.logining = true
    let userInfo = { username: this.loginForm.username, password: this.loginForm.password }
    this.$api.login(userInfo).then((res) => {
    if (res.success) {
    this.$store.commit('setUserInfo', res.data)
    this.$message({
    type: 'success',
    message: '登录成功',
    duration: 800,
    })
    
    let redirect = '/'
    if (this.$route.query.redirect !== undefined) {
    redirect = this.$route.query.redirect
    }
    setTimeout(() => {
    this.logining = false
    this.$router.push(redirect)
    if (this.notifyObj) {
    this.notifyObj.close()
    }
    this.notifyObj = null
    }, 800)
    } else {
    this.logining = false
    this.$message({
    type: 'error',
    message: '账号或密码错误',
    })
    }
    })
    },
    },
    // 计算属性
    computed: {},
    //未挂载DOM,不能访问ref为空数组
    //可在这结束loading,还做一些初始化,实现函数自执行,
    //可以对data数据进行操作,可进行一些请求,请求不易过多,避免白屏时间太长。
    created() {},
    //可在这发起后端请求,拿回数据,配合路由钩子做一些事情;可对DOM 进行操作
    mounted() {
    this.notifyObj = this.$notify({
    title: '提示',
    message: '管理员,账号分别为:admin,密码都为:123456',
    duration: 4000,
    iconClass: 'el-icon-s-opportunity',
    })
    },
    }
    </script>

    对界面进行 简单的样式调整,设置背景等,代码如下:

    <style lang="scss" scoped>
    $inputHeight: 48px;
    
    .loginContain {
    height: 100%;
    width: 100%;
    background: url(../../assets/img/loginbg.jpg) no-repeat center center;
    background-size: 100% 100%;
    overflow: hidden;
    }
    .loginBox {
    height: 455px;
    width: 550px;
    margin: 0 auto;
    position: relative;
    top: 20%;
    }
    .loginH2 {
    font-size: 28px;
    color: #fff;
    text-align: center;
    }
    
    .el-input {
    background-color: transparent;
    border-radius: 20px;
    height: $inputHeight;
    color: #ffffff !important;
    border: rgba(255, 255, 255, 0.2) 2px solid !important;
    }
    ::v-deep .el-input__inner {
    padding-left: 30px;
    background-color: transparent !important;
    border: none !important;
    he
    3909
    ight: $inputHeight !important;
    color: #ffffff !important;
    }
    .login-form {
    -webkit-border-radius: 5px;
    border-radius: 5px;
    -moz-border-radius: 5px;
    background-clip: padding-box;
    margin: 10px auto;
    width: 380px;
    padding: 35px 35px 15px 35px;
    }
    </style>

    相关接口上一篇文章中有写,这里就不再赘述了。

    mock 接口截图如下,

    既然涉及到登录,那肯定需要进行权限判断,所以我们使用 路由前置守卫进行控制,

    const WhiteListRouter = ['/login', '/notfound'] // 路由白名单
    //导航守卫  路由开始前
    router.beforeEach((to, from, next) => {
    let user = store.getters.userInfo
    let token = store.getters.token
    var hasAuth = user !== null && token !== null && user !== undefined && token !== undefined
    if (to.path == '/login') {
    if (hasAuth) {
    next({ path: '/' })
    } else {
    next()
    }
    } else {
    if (!hasAuth) {
    //没登录的情况下  访问的是否是白名单
    if (WhiteListRouter.indexOf(to.path) !== -1) {
    next()
    } else {
    next({
    path: '/login',
    })
    }
    } else {
    next()
    }
    }
    })

    路由相关代码

    const routes = [
    {
    path: '/',
    name: 'home',
    component: () => import('@/views/home'),
    children: [
    {
    path: '',
    name: '首页',
    component: () => import('@/views/home/defaultPage'),
    },
    ],
    },
    {
    path: '/login',
    name: 'login',
    component: login,
    },
    {
    path: '/notfound',
    name: 'notfound',
    component: () => import('@/views/notfound'),
    },
    {
    path: '*',
    redirect: '/notfound',
    name: 'notfound',
    component: () => import('@/views/notfound'),
    },
    ]

    其中涉及到的相关页面,就只有自己建了。

    首页相关代码

    完整代码:

    <!-- 首页 -->
    <template>
    <el-container>
    <el-header class="header">
    <!-- logo -->
    <div class="logo" :class="isCollapse ? 'logo-collapse-width' : 'logo-width'">
    <img v-if="isCollapse" src="@assets/logo6065.png" />
    <img v-else src="@assets/logo.png" />
    </div>
    <!-- 折叠按钮 -->
    <div class="tools" @click.prevent="collapse">
    <i class="el-icon-menu"></i>
    </div>
    <!-- 头部导航栏 -->
    <div class="heardNavBar">
    <el-menu default-active="1" class="el-menu-demo" background-color="#4b5f6e" text-color="#fff" active-text-color="#ffd04b" mode="horizontal">
    <el-menu-item index="1" @click="$router.push('/')">首页</el-menu-item>
    <el-menu-item index="2" @click="openUrl('#')">使用文档</el-menu-item>
    <el-menu-item index="3" @click="openUrl('https://github.com/levy-w-wang/lion-ui')">GitHub</el-menu-item>
    </el-menu>
    </div>
    <!-- 右侧信息 -->
    <div style="float:right">
    <!-- 全屏 -->
    <div style="float:left;line-height: 60px; padding: 0 10px;">
    <i class="el-icon-full-screen" @click="toggleFull"></i>
    </div>
    <!-- 个人信息 -->
    <div class="userinfo">
    <el-dropdown trigger="hover">
    <span class="el-dropdown-link userinfo-inner">
    <img src="@assets/img/user.jpg" />
    {{ userName }}<i class="el-icon-caret-bottom"></i>
    </span>
    <el-dropdown-menu slot="dropdown">
    <el-dropdown-item>
    <router-link to="/"><i class="el-icon-s-home"></i>首页</router-link>
    </el-dropdown-item>
    <el-dropdown-item>
    <router-link to="/"><i class="el-icon-s-custom"></i>我的主页</router-link>
    </el-dropdown-item>
    <el-dropdown-item divided>
    <a @click="loginOut()"><i class="el-icon-switch-button"></i>登出</a>
    </el-dropdown-item>
    </el-dropdown-menu>
    </el-dropdown>
    </div>
    </div>
    </el-header>
    <el-container>
    <el-aside class="aside">
    <!--导航菜单  default-active="1-1"-->
    <el-menu class="el-menu-vertical-demo" :collapse="isCollapse">
    <el-submenu index="1">
    <template slot="title">
    <i class="el-icon-setting"></i>
    <span slot="title">系统管理</span>
    </template>
    <el-menu-item index="1-1" @click="$router.push('usermanage')">用户管理</el-menu-item>
    <el-menu-item index="1-2" @click="$router.push('menumanage')">菜单管理</el-menu-item>
    </el-submenu>
    <el-menu-item index="2" disabled>
    <i class="el-icon-magic-stick"></i>
    <span slot="title">导航一</span>
    </el-menu-item>
    <el-menu-item index="3" disabled>
    <i class="el-icon-reading"></i>
    <span slot="title">导航二</span>
    </el-menu-item>
    </el-menu>
    </el-aside>
    <el-main>
    <router-view></router-view>
    </el-main>
    </el-container>
    </el-container>
    </template>
    
    <script>
    import screenfull from 'screenfull'
    export default {
    data() {
    return {
    isCollapse: false,
    userName: 'Levy',
    }
    },
    //引入组件
    components: {},
    // 方法
    methods: {
    openUrl(url) {
    window.open(url)
    },
    //折叠导航栏
    collapse: function() {
    this.isCollapse = !this.isCollapse
    },
    loginOut() {
    this.$confirm('确认退出吗?', '提示', {
    type: 'warning',
    })
    .then(() => {
    this.$store.commit('logout')
    })
    .catch(() => {})
    },
    toggleFull() {
    if (!screenfull.isEnabled) {
    this.$message({
    type: 'warning',
    message: 'you browser can not work',
    })
    return false
    }
    screenfull.toggle()
    },
    },
    // 计算属性
    computed: {},
    //未挂载DOM,不能访问ref为空数组
    //可在这结束loading,还做一些初始化,实现函数自执行,
    //可以对data数据进行操作,可进行一些请求,请求不易过多,避免白屏时间太长。
    created() {},
    //可在这发起后端请求,拿回数据,配合路由钩子做一些事情;可对DOM 进行操作
    mounted() {},
    }
    </script>
    
    <style lang="scss" scoped>
    .aside {
    flex: 0 0 230px;
    height: 100%;
    .el-menu {
    height: 100%;
    text-align: left;
    }
    }
    .header {
    padding-left: 0px !important;
    height: 60px;
    line-height: 60px;
    width: 100%;
    background: #4b5f6e;
    color: #fff;
    .logo {
    float: left;
    height: 60px;
    padding: 0;
    margin: 0;
    }
    .logo-width {
    width: 230px;
    }
    .logo-collapse-width {
    width: 65px;
    }
    
    .tools {
    padding-left: 10px;
    padding-right: 10px;
    text-align: center;
    width: 40px;
    height: 60px;
    line-height: 60px;
    float: left;
    cursor: pointer;
    }
    .heardNavBar {
    float: left;
    background: #4b5f6e;
    padding: 0px 0px;
    height: 60px;
    line-height: 60px;
    font-size: 28px;
    cursor: pointer;
    }
    
    .userinfo {
    text-align: right;
    padding-right: 24px;
    float: right;
    padding: 0 10px;
    .userinfo-inner {
    font-size: 20px;
    cursor: pointer;
    color: #fff;
    img {
    width: 40px;
    height: 40px;
    border-radius: 10px;
    margin: 10px 0px 10px 10px;
    float: right;
    }
    }
    }
    }
    </style>

    其中设计到了 全屏按钮 的使用,

    需要执行以下安装命令:

    npm install sreenfull --save

    原文地址:http://book.levy.net.cn/doc/frontend/uiframe/login_home.html

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: