【wiki知识库】08.添加用户登录功能--前端Vue部分修改

news2024/9/24 23:32:11

🍊 编程有易不绕弯,成长之路不孤单!

目录

🍊 编程有易不绕弯,成长之路不孤单!

一、今日目标

二、前端Vue模块的修改

2.1 the-header组件

2.2 store工具

2.3 router路由配置修改


一、今日目标

上篇文章链接:【wiki知识库】07.用户管理前端模块的添加-前端部分-CSDN博客

之前的一篇文章带大家实现了用户管理的功能,网站内我们并未提供注册功能,而是在一开始就初始化了一个管理员账号,只有登录管理员的账号后才能对用户进行增删改查功能。这次我们要开发网站的登录功能。

下方的图片能够看到,这是没有登录的情况,导航栏中的菜单并没有展示一些操作功能。



当我们登录账号后就会展示对应的功能。



 这个事情不难,说的简单一些呢就是前端会从你的本地浏览器的存储空间中找出有没有一个可以证明你登陆过的token,如果有这个token就会展示对应的功能选项,否则的话就不会展示。这个token就是在我们登录之后返回给前端的,并且由前端来将其保存到本地浏览器的一个存储空间当中。

二、前端Vue模块的修改

在之前我们修改过the-header组件,今天我们还要修改,为其添加上用户登录的一些代码。

2.1 the-header组件

这个代码我自己弄了半天,因为这个布局总是展示错误,就是<a-menu>标签后边

不能去加登录按钮,需要在之前加。

<template>
  <a-layout-header class="header">
    <div class="logo">熊哈哈</div>
    <div> 
      <a-popconfirm
        title="确认退出登录?"
        ok-text="是"
        cancel-text="否"
        @confirm="logout()"
      >
        <a class="login-menu" v-show="user.id">
          <span>退出登录</span>
        </a>
      </a-popconfirm>
      <a class="login-menu" v-show="user.id">
        <span>您好:{{user.name}}</span>
      </a>
      <a class="login-menu" v-show="!user.id" @click="showLoginModal">
        <span>登录</span>
      </a>
    </div>
    <a-menu
      theme="dark"
      mode="horizontal"
      :style="{ lineHeight: '64px' }"
    >
      <a-menu-item key="/">
        <router-link to="/">首页</router-link>
      </a-menu-item>
      <a-menu-item key="/about">
        <router-link to="/about">关于我们</router-link>
      </a-menu-item>
      <a-menu-item key="/admin/user" :style="user.id? {} : {display:'none'}">
        <router-link to="/admin/user">用户管理</router-link>
      </a-menu-item>
      <a-menu-item key="/admin/ebook" :style="user.id? {} : {display:'none'}">
        <router-link to="/admin/ebook">电子书管理</router-link>
      </a-menu-item>
      <a-menu-item key="/admin/category" :style="user.id? {} : {display:'none'}">
        <router-link to="/admin/category">分类管理</router-link>
      </a-menu-item>
    </a-menu>

    <a-modal
      title="登录"
      v-model:visible="loginModalVisible"
      :confirm-loading="loginModalLoading"
      @ok="login"
    >
      <a-form :model="loginUser" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
        <a-form-item label="登录名">
          <a-input v-model:value="loginUser.loginName" />
        </a-form-item>
        <a-form-item label="密码">
          <a-input v-model:value="loginUser.password" type="password" />
        </a-form-item>
      </a-form>
    </a-modal>
  </a-layout-header>
</template>

然后就是script部分的代码。

<script lang="ts">
  import { defineComponent, ref, computed } from 'vue';
  import axios from 'axios';
  import { message } from 'ant-design-vue';
  import store from "@/store";


  export default defineComponent({
    name: 'the-header',
    setup () {
      // 登录后保存
      const user = computed(() => store.state.user);

      // 用来登录
      const loginUser = ref({
        loginName: "",
        password: ""
      });
      const loginModalVisible = ref(false);
      const loginModalLoading = ref(false);
      const showLoginModal = () => {
        loginModalVisible.value = true;
      };

      // 登录
      const login = () => {
        console.log("开始登录");
        loginModalLoading.value = true;
        axios.post('/user/login', loginUser.value).then((response) => {
          loginModalLoading.value = false;
          const data = response.data;
          if (data.success) {
            loginModalVisible.value = false;
            message.success("登录成功!");

            store.commit("setUser", data.content);
          } else {
            message.error(data.message);
          }
        });
      };

      // 退出登录
      const logout = () => {
        console.log("退出登录开始");
        axios.get('/user/logout/' + user.value.token).then((response) => {
          const data = response.data;
          if (data.success) {
            message.success("退出登录成功!");
            store.commit("setUser", {});
          } else {
            message.error(data.message);
          }
        });
      };

      return {
        loginModalVisible,
        loginModalLoading,
        showLoginModal,
        loginUser,
        login,
        user,
        logout
      }
    }
  });
</script>

最后是style部分的代码。

<style scoped> 
  .logo {
    width: 120px;
    height: 31px;
    float: left;
    color: white;
    font-size: 18px;
  }
  .login-menu {
    float: right;
    color: white;
    padding-left: 10px;
  }
</style>

2.2 store工具

在上方的代码中你会看到这句话。

  import store from "@/store";

store是vue中的状态管理模式,用来存储和管理vue中的状态信息。说白了就是可以存储一些你需要的全局性质的信息。具体的内容还要大家自己去了解。我忘记了这段代码之前有没有提供了,所以我索性在提供一次。

看一下下方的代码,用到了一个变量SessionStorage,这个变量用来将你登陆后的token保存在浏览器中。其中的state保存了user数据,这个数据就是从SessionStorage中获取的,或者是在你登陆后自动设置的。

import {createStore} from 'vuex'

declare let SessionStorage: any;
const USER = "USER";

const store = createStore({
    state: {
        user: SessionStorage.get(USER) || {}
    },
    mutations: {
        setUser(state, user) {
            console.log("store user:", user);
            state.user = user;
            SessionStorage.set(USER, user);
        }
    },
    actions: {},
    modules: {}
});

export default store;

再看看下方的代码。菜单标签的属性上加上了判断条件,判断的就是当前的SessionStorage中是否有user被存储,如果没有那么就不会展示菜单。

    <a-menu
      theme="dark"
      mode="horizontal"
      :style="{ lineHeight: '64px' }"
    >
      <a-menu-item key="/">
        <router-link to="/">首页</router-link>
      </a-menu-item>
      <a-menu-item key="/about">
        <router-link to="/about">关于我们</router-link>
      </a-menu-item>
      <a-menu-item key="/admin/user" :style="user.id? {} : {display:'none'}">
        <router-link to="/admin/user">用户管理</router-link>
      </a-menu-item>
      <a-menu-item key="/admin/ebook" :style="user.id? {} : {display:'none'}">
        <router-link to="/admin/ebook">电子书管理</router-link>
      </a-menu-item>
      <a-menu-item key="/admin/category" :style="user.id? {} : {display:'none'}">
        <router-link to="/admin/category">分类管理</router-link>
      </a-menu-item>
    </a-menu>

2.3 router路由配置修改

有了上方的代码我们就能够在用户不登陆的状态下隐藏这些功能菜单,但是这样只能隐藏菜单,而不是彻底的屏蔽掉没有登陆的用户去访问这些组件。用户还是可以通过路由的路径访问到对应的组件。所以我们还要在路由配置中配置一些信息来防止这样的行为。

{
    path: '/admin/user',
    name: 'AdminUser',
    component: AdminUser,
    meta: {
      loginRequire: true
  }

以用户管理为例,我们要在这个用户管理的组件上加上一些信息。加上下边这个配置项后,就意味着这个组件是需要登陆后访问的。这样我们就可以进行后续操作,来组织用户在不登陆的状态下访问组件。注意:所有需要登陆才能访问的组件都要加上这个配置信息。

接下来要配置的是路由拦截,顾名思义,在我们访问路由的时候进行拦截,在拦截方法中判断组件是否需要登陆访问,并且判断用户是否登录。如果组件需要登陆访问并且用户没有登陆的话就会跳到主页去。这样就防止了用户在不登陆的情况下通过路径访问路由了。

router.beforeEach((to, from, next) => {
  // 要不要对meta.loginRequire属性做监控拦截
  if (to.matched.some(function (item) {
      console.log(item, "是否需要登录校验:", item.meta.loginRequire);
      return item.meta.loginRequire
  })) {
      const loginUser = store.state.user;
      if (Tool.isEmpty(loginUser)) {
          console.log("用户未登录!");
          next('/');
      } else {
          next();
      }
  } else {
      next();
  }
});

2.4 添加axios拦截

在我们每次向后端发送请求的时候,需要携带上当前登录用户的token,用于用户身份的校验,这里先不多说。

这个拦截器会让你的axios请求每一次请求后端之前先做一些事情,这里仅仅是携带上了用户的token,其实还可以做很多的事情。

/**
 * axios拦截器
 */
axios.interceptors.request.use(function (config) {
    console.log('请求参数:', config);
    const token = store.state.user.token;
    if (Tool.isNotEmpty(token)) {
        config.headers.token = token;
        console.log("请求headers增加token:", token);
    }
    return config;
}, error => {
    return Promise.reject(error);
});
axios.interceptors.response.use(function (response) {
    console.log('返回结果:', response);
    return response;
}, error => {
    console.log('返回错误:', error);
    const response = error.response;
    const status = response.status;
    if (status === 401) {
        // 判断状态码是401 跳转到首页或登录页
        console.log("未登录,跳到首页");
        store.commit("setUser", {});
        message.error("未登录或登录超时");
        router.push('/');
    }
    return Promise.reject(error);
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1993162.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

河南萌新联赛2024第(四)场:河南理工大学

河南萌新联赛2024第&#xff08;四&#xff09;场&#xff1a;河南理工大学 2024.8.7 13:00————17:00 过题数5/12 补题数8/12 该出奇兵了 小雷的神奇电脑 岗位分配 简单的素数 AND 小雷的算式 循环字符串 聪明且狡猾的恶魔 马拉松 尖塔第四强的高手 比赛 抓字符 B - 小雷…

企业如何选择靠谱的第三方软件测试机构?

第三方软件测试机构是专门提供软件测试服务的第三方检测机构&#xff0c;旨在对软件的功能、性能、安全性等方面进行系统评估&#xff0c;确保其满足设定的标准和需求。这些机构通常拥有丰富的行业经验和专业资质&#xff0c;可以为企业提供包括项目验收测试、软件确认测试、安…

贪吃蛇之地图的绘制

首先我们要知道地图位置大体是怎么样的 绘出一个大概的地图 设置了2020的方格 源码在这里 #include<curses.h>void initNcurse() {initscr();keypad(stdscr,1); }void gamePic() {int hang;int lie;for(hang0;hang<20;hang){if(hang0){for(lie0;lie<20;lie){pr…

开通期权分仓账户需要多少资金?

在金融衍生品市场&#xff0c;期权分仓账户犹如一艘精巧的帆船&#xff0c;承载着投资者的智慧与梦想&#xff0c;驶向财富的彼岸。然而&#xff0c;每一艘帆船的启航&#xff0c;都需备足风帆与给养&#xff0c;即那开启航程所必需的资金之舟&#xff0c;下文为大家介绍开通期…

【C语言基础习题】C语言练习题——bite 寒假班作业(6)【未完成】

编程小白如何成为大神?大学新生的最佳入门攻略 编程已成为当代大学生的必备技能,但面对众多编程语言和学习资源,新生们常常感到迷茫。如何选择适合自己的编程语言?如何制定有效的学习计划?如何避免常见的学习陷阱?让我们一起探讨大学新生入门编程的最佳路径,为你的大学…

【进阶篇-Day14:JAVA中IO流之转换流、序列化流、打印流、Properties集合的介绍】

目录 1、转换流1.1 转换流分类&#xff1a;1.2 转换流的作用&#xff08;1&#xff09;按照指定的字符编码读写操作&#xff1a;&#xff08;2&#xff09;将字节流转换为字符流进行操作&#xff1a; 2、序列化流2.1 序列化的基本使用&#xff1a;2.2 序列化的操作流程&#xf…

《Token-Label Alignment for Vision Transformers》ICCV2023

摘要 这篇论文探讨了数据混合策略&#xff08;例如CutMix&#xff09;在提高卷积神经网络&#xff08;CNNs&#xff09;性能方面的有效性&#xff0c;并指出这些策略在视觉Transformer&#xff08;ViTs&#xff09;上同样有效。然而&#xff0c;发现了一个“token fluctuation…

mp3音频怎么压缩小一点?音频压缩的6个简单方法

在日常的数字生活中&#xff0c;MP3音频文件凭借其广泛的兼容性和相对较高的音质&#xff0c;已然成为了连接音乐创作者与听众之间不可或缺的桥梁。从个人音乐收藏到社交媒体分享&#xff0c;再到专业音频项目的交付&#xff0c;MP3格式以其便捷性占据了重要地位。然而&#xf…

MLP:全连接神经网络的并行执行

目录 MLP:全连接神经网络的并行执行 假设 代码解释 注意事项 MLP:全连接神经网络的并行执行 为了继续解释这段代码,我们需要做一些假设和补充,因为原始代码片段中DummyModel、Shard和mx.array的具体实现没有给出。不过,基于常见的编程模式和深度学习框架的惯例,我们…

【Linux网络】Linux网络初探:开启网络世界的大门

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; 前言&#xff1a;我们已经系统的学习了Linux的基本操作、进程、线程、文件、通信等待&#xff0c;但是在如今社会没有网络通信方式是万万不行的&#xff0c;今天我们就走进网络中&#xff0c;系统的学习一下有关Linux网…

电脑外接设备管理软件有哪些(三款USB外设管理软件推荐)

“小张&#xff0c;你上次用U盘拷贝资料时&#xff0c;有没有担心过数据安全问题&#xff1f;” “是啊&#xff0c;李姐&#xff0c;我总感觉用U盘传文件不太放心&#xff0c;万一数据被误删或者泄露就麻烦了。” 正是这样的担忧&#xff0c;促使了电脑外接设备管理软件的出现…

让模型从Pytorch到NCNN——Pytorch模型向NCNN框架部署的小白向详细流程(PNNX模型转换、Linux模型使用)

参考文章和项目地址&#xff1a; [1] Tencent/ncnn: ncnn is a high-performance neural network inference framework optimized for the mobile platform (github.com) [2] pnnx/pnnx: PyTorch Neural Network eXchange (github.com) [3] 使用pnnx把pytorch模型转ncnn模型-CS…

重塑购车体验,实时云渲染赋能东风日产探路云看车新体验

在科技日新月异的今天&#xff0c;汽车行业正经历着前所未有的深刻变革。随着互联网、大数据、人工智能等新兴技术的深度融合&#xff0c;汽车营销策略也迎来了从传统展示到数字化体验的跨越。 消费者的购车习惯逐渐倾向于线上互动与深度体验&#xff0c;希望在线上获得线下同…

【docker】docker数据卷与网络部署服务

Docker 网络模式 选择网络模式 Host Mode (主机模式) 特点: 容器与宿主机共享网络命名空间操作: docker run --nethost ... Container Mode (容器模式) 特点: 容器与指定容器共享网络命名空间操作: docker run --netcontainer:<container-id-or-name> ... None Mode (无…

XP服务器-远程桌面连接不上

今天遇到个很奇怪的事&#xff0c;xp服务器突然远程桌面连接不上了&#xff0c;根据上网百度的结果&#xff0c;防火墙关了&#xff0c;也允许远程连接了。我之前修改过服务器的默认端口号3389&#xff0c;改为了新端口号A&#xff0c;但是当时修改完是可以正常登陆的。而且新端…

004集——静态常量和动态常量——C#学习笔记

首先普及一个小白使用的小技巧&#xff1a;tab键可以自动输出系统显示的引导字符。 常量是使用 const 关键字来定义的 。定义一个常量的语法如下&#xff1a; const <data_type> <constant_name> value; 下面的代码演示了如何在程序中定义和使用常量&#xff1…

win服务器cmd执行exe文件失败

问题场景 场景&#xff1a;用python打包的exe文件&#xff0c;在cmd下执行是没问题的&#xff0c;放到定时任务就不执行。。。动di脚本调试没问题&#xff0c;打包成exe可执行程序也能正常运行。就是放到定时任务有问题。 解决&#xff1a; 解决方案 1.打开计划任务创建计划任…

OpenGL3.3_C++_Windows(34)

demo 1 Fresnel-Schlick PBR直接光源 顾名思义&#xff1a;直接光源指有光源直接照射到点p 的辐射强度&#xff0c;由于一个光源只会有一个光线wi影响点p&#xff0c;所以和之前的计算没什么差异对于影响p的光源&#xff0c;并不需要积分计算半球形辐照度&#xff0c;遍历每个…

71 为对象定义类

① 类定义对象的特征和行为。 ② 一个 Python 类使用变量存储数据域&#xff0c;定义方法来完成动作。类就是一份契约&#xff08;有时也称之为模板或蓝本&#xff09;&#xff0c;它定义对象的数据域和方法。 ③ 对象是类的一个实例&#xff0c;可以创建一个类的多个对象。创建…

【Linux】yum软件包管理器(使用、生态、yum源切换)

目录 1.yum-软件包管理器&#x1f638;1.1yum使用方法1.2什么是yum&#xff1f;&#x1f638;1.3yum的周边生态1.4yum源切换1.4.1 查看系统本身yum源1.4.2 软件源1.4.3yum源配置 1.yum-软件包管理器 以下操作需要联网的情况下进行 &#x1f638;1.1yum使用方法 安装软件时由于需…