用户登录+页面跳转+后台首页实现

1. 完成用户登录操作

1.1 用户登录流程
用户登录完成之后 需要将密钥进行保存. Session,Cookie
将页面跳转到系统首页.
1.2 Session和Cookie介绍

1.2.1 Session 会话机制

服务器保存用户信息的一种手段. 可以将用户登录信息通过session的方式进行保存. 当会话关闭时,Session对象销毁.
1

1.2.2 Cookie 机制
Cookie,有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息 [1] 。
概括: Cookie是客户端保存服务器信息的一种机制 可以做到永久保存

Cookie的规则:

  1. 浏览器只能查看当前网址的Cookie的记录. 相对安全
  2. Cookie可以设置共享 ,但是需要指定 xxx.com 域名
  3. Cookie可以设定失效时间 单位为秒
    (https://img-blog.csdnimg.cn/20210611085814616.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81Njc2MjcwOQ==,size_16,color_FFFFFF,t_70)

1.3 前端用户登录操作

<!-- 定义模版对象 -->
<template>
    <div class="login_container">
      <div class="login_box">
        <!-- 头像区域-->
        <div class="avatar_box">
          <img src="../assets/logo.png" alt="VUE图片" />
        </div>


        <!-- ref: form表单可以通过ref进行引用
             :model: 对整个表单进行数据的绑定
             :rules  对整个表单数据进行数据校验
        -->
        <el-form ref="loginFormRef" label-width="0"  :rules="rules"  class="login_form" :model="loginForm"
        @submit.native.prevent>
          <el-form-item prop="username">
            <el-input  prefix-icon="iconfont iconuser" v-model="loginForm.username"></el-input>
          </el-form-item>
          <el-form-item prop="password">
            <el-input  prefix-icon="iconfont iconsuo" type="password"  v-model="loginForm.password"></el-input>
          </el-form-item>
          <el-form-item class="btns">
              <el-button type="primary" @click="login"   native-type="submit">登录</el-button>
              <el-button type="info" @click="reset">重置</el-button>
          </el-form-item>
        </el-form>
      </div>
    </div>
</template>

<!-- 定义JS变量 -->
<script>
export default {
  data(){
    return {
      loginForm: {
        username: '',
        password: ''
      },
      rules: {
            username: [
              /* required 是否为必填项  message:提示信息 trigger:出发条件 */
              { required: true, message: '请输入用户名', trigger: 'blur' },
              { min: 3, max: 30, message: '长度在 3 到 30 个字符', trigger: 'blur' }
            ],
            password: [
              /* required 是否为必填项  message:提示信息 trigger:出发条件 */
              { required: true, message: '请输入密码', trigger: 'blur' },
              { min: 3, max: 30, message: '长度在 3 到 30 个字符', trigger: 'blur' }
            ]
      }
    }
  },
  methods: {
    reset(){
        //将表单数据改为空串
        /* this.loginForm.username = ''
        this.loginForm.password = '' */
        /* this:代表当前的Vue的组件对象  */
        /* $refs
            1.$从vue对象中获取数据
            2.从vue组件对象中获取全部ref标签 */
        this.$refs.loginFormRef.resetFields()
    },
    login(){
        //1.获取表单数据
        this.$refs.loginFormRef.validate(async valid => {
            //2.当程序没有通过校验时 程序终止
            if(!valid) return

            //3.发起ajax请求, 实现业务调用
            //参数1: url地址   参数2:传递的数据
            let {data: result} =
            await this.$http.post("/user/login",this.loginForm)

            //4.判断用户校验是否正常 status=200  201
            if(result.status !== 200) return this.$message.error("用户名或密码错误")

            this.$message.success("恭喜你 登录成功!")

            //如何获取token result.data
            //将用户信息保存到session中
            window.sessionStorage.setItem("token",result.data)
            //window.sessionStorage.removeItem("token") 删除单个
            //window.sessionStorage.clear() //全部删除

            //5.登录成功之后,跳转到/home页面中
            this.$router.push("/home")
        })
    }
  }

}
</script>

<!-- 防止组件冲突 -->
<style lang="less" scoped>
.login_container{
  background-color: #2b4b6b;
  height: 100%;
}

.login_box {
  width: 450px;
  height: 300px;
  background-color: #FFFFFF;
  /* 设定圆弧角*/
  border-radius: 10px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);

  .avatar_box {
    height: 130px;
    width: 130px;
    border: 1px solid #EEEEEE;
    border-radius: 50%;
    padding: 10px;
    box-shadow: 0 0 10px #DDDDDD; /* 添加阴影*/
    position: absolute;           /* 绝对定位*/
    left: 50%;                    /* 距离左侧50%*/
    transform: translate(-50%,-50%);   /*回调50%*/
    background-color: #FFFFFF;
    img {
      height: 100%;
      width: 100%;
      border-radius: 50%;
      background-color: #EEEEEE;
    }
  }

  .btns {
    display: flex;
    justify-content: flex-end;

  }

  .login_form {
    position: absolute;
    bottom: 0;
    width: 100%;
    padding: 0 20px;
    box-sizing: border-box;
  }
}
</style>


2 后台首页实现

2.1 后台首页跳转
2.1.1 配置路由规则
说明: 要求用户通过/home请求,跳转到Home.vue的页面中. 编辑router/index.js 文件

2.2.3 编辑路由导航守卫

在这里插入图片描述

 //定义路由导航守卫 考点: 拦截器
/**
 * 1.遍历的每个路由都会执行回调函数.
 * 2.参数信息: 3个
 *    2.1 to: 请求访问的地址           到哪去
 *    2.2 from: 请求从哪里跳转而来     从哪来
 *    2.3 next: 是一个函数  next() 请求放行
 *                         next("/login") 发起login请求
 */
router.beforeEach((to,from,next) => {
  //1.如果用户访问/login的请求,应该直接放行
  if(to.path === '/login')  return next()

  //2.不是访问的登录页面,所以判断用户是否登录. 判断依据token
  let token = window.sessionStorage.getItem("token")

  //3.如果!token  没有值,则执行if之后的操作
  if(!token)  return next("/login")

  //4.如果代码执行到这一行,说明用户已经登录.则放行
  next()
})


3.3标题容器布局代码

	<el-container>
		  <el-header>Header</el-header>
		  <el-container>
		    <el-aside width="200px">Aside</el-aside>
		    <el-main>Main</el-main>
		  </el-container>
	</el-container>

3.6实关于表设计自关联说明

问题: 如何设计表,实现3级菜单表?
思考: 表关联的层级不要太多, 左链接的查询会写的异常困难. 如何提高软件的扩展性. 自关联
表设计: 设定一张表 通过ID,和parentID 定义表的父子关系.
在这里插入图片描述

3.7项目中的布局结构

在这里插入图片描述
3.8 左侧菜单实现
3.8.1 左侧菜单说明
在这里插入图片描述

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

               <!-- 一级标签 -->
          	   <el-submenu index="1">
                  <template slot="title">
                    <i class="el-icon-location"></i>
                    <span>看的懂</span>
                  </template>
                  <!-- 二级标签 -->
                 <el-menu-item index="1-1">1</el-menu-item>
                 <el-menu-item index="1-2">2</el-menu-item>
                </el-submenu>
          </el-menu>

后端项目左侧菜单实现

	<template>

  <!-- 定义布局容器 -->
  <el-container class="home-container">

    <!-- 定义头标签 -->
    <el-header>
      <div>
        <img src="../assets/images/logo.png" />
        <span>京淘电商后台管理系统</span>
      </div>
      <el-button type="info" @click="logout">退出</el-button>
    </el-header>

    <!-- 定义中间区域-->
    <el-container>
      <!-- 当打开左侧菜单时 宽度为200, 当不打开时为默认值-->
      <el-aside :width="isCollapse ? '64px' : '200px' ">
        <!-- 这是左侧菜单-->
        <!--定义折叠项-->
        <div class="leftCollapse" @click="collspseClick">|||</div>

        <!--
          background-color 定义背景色
          text-color="#fff"  定义文字颜色
          active-text-color="#4094ff" 选中元素的颜色
          unique-opened 是否只保持一个子菜单的展开
          collapse      是否水平折叠收起菜单(仅在 mode 为 vertical 时可用)
          collapse-transition	是否开启折叠动画 默认不要展现
          router 是否使用 vue-router 的模式,启用该模式会在激活导航时以 index 作为 path 进行路由跳转
        -->
        <el-menu background-color="#2C3E50" text-color="#fff"
        active-text-color="#4094ff" unique-opened
        :collapse="isCollapse" :collapse-transition="isCollapseTransition"
        router  :default-active="defaultActive">

          <!-- 定义一级菜单 -->
          <el-submenu :index="menu.id+''" v-for="menu in menuList" :key="menu.id">
            <!-- 定义一级菜单模版 -->
            <template slot="title">
              <!-- 定义左侧图标-->
              <i :class="menuIcon[menu.id]"></i>
              <!-- 定义菜单名称-->
              <span>{{menu.name}}</span>
            </template>
            <!-- 定义二级菜单 -->
            <el-menu-item :index="childrenMenu.path" v-for="childrenMenu in menu.children" :key="childrenMenu.id"
            @click="defaultActiveMenu(childrenMenu.path)">
              <template slot="title">
                <i class="el-icon-menu"></i>
                <span>{{childrenMenu.name}}</span>
              </template>
            </el-menu-item>
          </el-submenu>
        </el-menu>
      </el-aside>

      <!-- 定义主页面结构-->
      <el-main>
        <!-- 定义路由展现页面-->
        <router-view></router-view>
      </el-main>
    </el-container>
  </el-container>
</template>

<script>
  export default {
    //初始化函数
    created() {
      //动态获取左侧菜单信息
      this.getMenuList()
      //设定模式选中按钮
      this.defaultActive = window.sessionStorage.getItem("activeMenu")
    },
    data() {
      return {
        //左侧菜单数据
        menuList: [],
        menuIcon: {
          '1': 'iconfont iconuser',
          '3': 'iconfont iconshangpin',
          '5': 'iconfont iconicon--copy',
          '7': 'iconfont iconquanxian',
          '8': 'iconfont iconziyuan'
        },
        //定义是否折叠
        isCollapse: false,
        //是否展现折叠动态效果
        isCollapseTransition: false,
        //定义默认高亮
        defaultActive: ''
      }
    },
    methods: {
      logout() {
        //1.删除token数据
        window.sessionStorage.clear()

        //2.跳转到用户登录页面  注意路径的写法 加/
        this.$router.push("/login")

      },
      async getMenuList() {
       const {data: result} =  await this.$http.get('/rights/getRightsList')
       if(result.status !== 200) return this.$message.error("左侧菜单查询失败")
       //如果请求正常,则将返回值结果赋值给vue的data
       this.menuList = result.data

      },
      //设定左侧折叠展开效果
      collspseClick() {
        this.isCollapse = !this.isCollapse
      },
      defaultActiveMenu(activeMenu){
        //为了实现返回之后的选中效果,应该将数据保存到第三方中sessionStory
        window.sessionStorage.setItem("activeMenu",activeMenu)
        this.defaultActive = activeMenu
      }
    }
  }
</script>

<!-- 防止样式重叠 -->
<style lang="less" scoped>
  .el-header {
    background-color: #2B4B6B;
    display: flex; //灵活的盒子容器
    justify-content: space-between; //左右对齐
    align-items: center; //文本元素居中对齐
    color: #FFFFFF; //设定字体颜色
    padding-left: 1px;

    >div {
      display: flex;
      align-items: center;

      span {
        margin-left: 15px;
        font-size: 25px; //设定字体高度
      }
    }
  }

  .el-aside {
    background-color: #2C3E50;

    .el-menu {
      border-right: none;
    }
  }

  .el-main {
    background-color: #EEEEEE;
  }

  .home-container {
    height: 100%;
    width: 100%;
  }

  .iconfont {
    margin-right: 8px;
  }

  //定义折叠项
  .leftCollapse {
    //设定背景色
    background-color: #708090;
    //定义字体大小
    font-size: 10px;
    //定义行高
    line-height: 30px;
    //定义颜色
    color: #FFFFFF;
    //设置居中
    text-align: center;
    //设定字符间距
    letter-spacing: 4px;
    //鼠标放上之后设置为小手
    cursor: pointer;
  }
</style>

3.9.2 定义路由标签

在home的main中添加路由占位符.
在这里插入图片描述

3.9.3 指定路由规则

在这里插入图片描述

  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是一个简单的示例,供您参考: 1. 安装 Vue CLI ``` npm install -g @vue/cli ``` 2. 创建一个新的 Vue 项目 ``` vue create my-project ``` 3. 安装 Element UI 和 Axios ``` npm i element-ui axios -S ``` 4. 引入 Element UI 在 `main.js` 中添加以下代码: ```js import Vue from 'vue' import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' Vue.use(ElementUI) ``` 5. 创建登录页面 在 `src/views` 目录下创建一个新的文件夹,例如 `Login`,然后在其中创建一个新的 Vue 组件,例如 `index.vue`。 6. 实现登录功能 在 `Login/index.vue` 中添加以下代码: ```html <template> <div> <el-form ref="form" :model="form" :rules="rules" label-position="left" label-width="80px" class="demo-ruleForm"> <el-form-item label="用户名" prop="username"> <el-input v-model="form.username"></el-input> </el-form-item> <el-form-item label="密码" prop="password"> <el-input type="password" v-model="form.password"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="login">登录</el-button> </el-form-item> </el-form> </div> </template> <script> export default { data() { return { form: { username: '', password: '' }, rules: { username: [ { required: true, message: '请输入用户名', trigger: 'blur' } ], password: [ { required: true, message: '请输入密码', trigger: 'blur' } ] } } }, methods: { login() { this.$refs.form.validate(valid => { if (valid) { const { username, password } = this.form // 发送登录请求 this.$axios.post('/api/login', { username, password }) .then(res => { // 登录成功后的操作 // 例如保存 token 到本地存储中 localStorage.setItem('token', res.data.token) // 跳转到主页面 this.$router.push('/') }) .catch(error => { // 处理登录失败的情况 this.$message.error('登录失败') }) } }) } } } </script> ``` 7. 创建主页面 在 `src/views` 目录下创建一个新的文件夹,例如 `Dashboard`,然后在其中创建一个新的 Vue 组件,例如 `index.vue`。 8. 添加路由 在 `src/router/index.js` 中添加以下代码: ```js import Vue from 'vue' import Router from 'vue-router' import Login from '@/views/Login/index.vue' import Dashboard from '@/views/Dashboard/index.vue' Vue.use(Router) const router = new Router({ routes: [ { path: '/', name: 'Dashboard', component: Dashboard, meta: { requiresAuth: true } }, { path: '/login', name: 'Login', component: Login } ] }) // 添加路由守卫 router.beforeEach((to, from, next) => { if (to.matched.some(record => record.meta.requiresAuth)) { // 判断用户是否已登录 const token = localStorage.getItem('token') if (!token) { next({ path: '/login', query: { redirect: to.fullPath } }) } else { next() } } else { next() } }) export default router ``` 9. 运行项目 在命令行中运行以下命令: ``` npm run serve ``` 以上是一个简单的示例,您可以根据自己的需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值