zoukankan      html  css  js  c++  java
  • Vue管理系统前端系列三登录页和首页及`vuex`管理登录状态


    登录页面设计

    该节记录了登录界面的设计,以及 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
                        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="100%;">
                        <el-button type="primary" style="   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%;
         100%;
        background: url(../../assets/img/loginbg.jpg) no-repeat center center;
        background-size: 100% 100%;
        overflow: hidden;
    }
    .loginBox {
        height: 455px;
         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;
        height: $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;
         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;
         100%;
        background: #4b5f6e;
        color: #fff;
        .logo {
            float: left;
            height: 60px;
            padding: 0;
            margin: 0;
        }
        .logo-width {
             230px;
        }
        .logo-collapse-width {
             65px;
        }
    
        .tools {
            padding-left: 10px;
            padding-right: 10px;
            text-align: center;
             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 {
                     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

  • 相关阅读:
    把redhat5.4-linux2.6.18内核升级到2.6.24 vmware虚拟机中
    webdeploy 使用总结(二)
    System.Web.UI.Page 详解(转)
    Dapper常用方法总结
    webdeploy 使用总结(一)
    Log4Net 详解(转)
    C# 日志工具汇总(转)
    Global.asax 详解(转)
    Transfer与Redirect区别(转)
    web.config配置节system.webServer的子元素详细介绍
  • 原文地址:https://www.cnblogs.com/levywang/p/13537717.html
Copyright © 2011-2022 走看看