项目实战——实现注册与登录模块(结尾)

news2025/7/9 0:30:39

目录

一、整体框架

 二、前端页面授权

三、实现注册页面

 四、实现登录状态的持久化


一、整体框架

框架1

 二、前端页面授权

当我们登录网站的时候,如果没有登录,强制让用户重定向到 登录界面

在 router 目录下的 index.js 文件下实现。 router -> index.js:

import store from '../store/index'

// 把一些额外信息放到一个额外的域里面,meta信息里面存一下是否要授权,如果需要授权而且没有登录,重定向到登录页面,重定向到登录界面。
const routes = [
  {
    path: "/",
    name: "home",
    redirect: "/pk/",
    meta: {
      requestAuth: true,
    }
  },
  {
    path: "/pk/",
    name: "pk_index",
    component: PkIndexView,
    meta: {
      requestAuth: true,
    }
  },
  {
    path: "/record/",
    name: "record_index",
    component: RecordIndexView,
    meta: {
      requestAuth: true,
    }
  },
  {
    path: "/ranklist/",
    name: "ranklist_index",
    component: RanklistIndexView,
    meta: {
      requestAuth: true,
    }
  },
  {
    path: "/user/bot/",
    name: "user_bot_index",
    component: UserBotIndexView,
    meta: {
      requestAuth: true,
    }
  },
  {
    path: "/user/account/login",
    name: "user_account_login",
    component: UserAccountLoginView,
    meta: {
      requestAuth: false,
    }
  },
  {
    path: "/user/account/register",
    name: "user_account_register",
    component: UserAccountRegisterView,
    meta: {
      requestAuth: false,
    }
  },
  {
    path: "/404/",
    name: "404",
    component: NotFound,
    meta: {
      requestAuth: false,
    }
  },
  {
    path: "/:catchAll(.*)",
    redirect: "/404/",
  }
]
// to跳转到哪个页面, from表示从哪个页面跳转过去
// next的表示将页面要不要执行下一步操作,写之前首先要记录每一个未授权界面
router.beforeEach((to, from, next) => {
  if (to.meta.requestAuth && !store.state.user.is_login) {
    next({name: "user_account_login"});
  } else {
    next();
  }
})

前端页面重定向

最终效果: 如果处于未登录状态,点击 除注册之外的按钮 页面会跳转到 登录界面。

三、实现注册页面

在 view -> user -> account 下的 UserAccountRegisterView.vue 文件实现,实现方式类似于同目录下的 UserAccountLoginView.vue

可以直接把登录页面的样式复制过来再做修改

<template>
    <ContentField>
        <div class="row justify-content-md-center">
            <div class="col-3">
                <form @submit.prevent="register">
                    <div class="mb-3">
                        <label for="username" class="form-label">用户名</label>
                        <input v-model="username" type="text" class="form-control" id="username" placeholder="请输入用户名">
                    </div>
                    <div class="mb-3">
                        <label for="password" class="form-label">密码</label>
                        <input v-model="password" type="password" class="form-control" id="password" placeholder="请输入密码">
                    </div>
                    <div class="mb-3">
                        <label for="confirmedpassword" class="form-label">密码</label>
                        <input v-model="confirmedpassword" type="password" class="form-control" id="confirmedpassword" placeholder="请再次输入密码">
                    </div>
                    <div class="error-message">{{ error_message }}</div>
                    <button type="submit" class="btn btn-primary">提交</button>
                </form>
            </div>
        </div>
    </ContentField>
</template>

<script>
import ContentField from '../../../components/ContentField.vue'
import { ref } from 'vue'
import router from '../../../router/index'
import $ from 'jquery'

export default {
    components: {
        ContentField
    },
    setup() {
        let username = ref('');
        let password = ref('');
        let confirmedPassword = ref('');
        let error_message = ref('');

        const register = () => {
            $.ajax({
                url: "http://127.0.0.1:8080/user/account/register/",
                type: "post",
                data: {
                    username: username.value,
                    password: password.value,
                    confirmedPassword: confirmedPassword.value,
                },
                success(resp) {
                    // 成功直接返回登录界面
                    if (resp.error_message === "success") {
                        router.push({name: "user_account_login"});
                    } else {
                        error_message.value = resp.error_message;
                    }
                },
              });

        }

        return {
            username,
            password,
            confirmedPassword,
            error_message,
            register,
        }
    }
}
</script>

<style scoped>
button {
    width: 100%;
}
div.error-message {
    color: red;
    justify-content: center;
}
</style>

注册页面

 注册界面成功

 在测试的时候可以会遇到不输入密码也可以注册成功的 bug, 在 RegisterServiceImpl.java 下 修改一下就可以了:

bug

 四、实现登录状态的持久化

当我们的用户重定向到登陆页面的时候,我们需要把用户的 token 存储到浏览器的 local storage,这样就可以实现登录状态持久化。

首先 修改 store 目录下的 -> user.js 文件,在合适的位置添加下列两行。

localStorage.setItem("jwt_token", resp.token);

localStorage.removeItem("jwt_token");

localstorage

 其次 修改 view -> user -> account 下的 UserAccountLoginView.vue 文件

<script>
import ContentField from '../../../components/ContentField.vue'
import { useStore } from 'vuex'
import { ref } from 'vue'
import router from '../../../router/index'

export default {
    components: {
        ContentField
    },
    setup() {
        const store = useStore();
        let username = ref('');
        let password = ref('');
        let error_message = ref('');


        const jwt_token = localStorage.getItem("jwt_token");
        if (jwt_token) {
            store.commit("updateToken", jwt_token);
            store.dispatch("getinfo", {
                success() {
                    router.push({ name: "home" });
                },
                error() {
                }
            })
        }else {

        }

        const login = () => {
            error_message.value = "";
            store.dispatch("login", {
                username: username.value,
                password: password.value,
                success() {
                    store.dispatch("getinfo", {
                        success() {
                            router.push({ name: 'home' });
                            console.log(store.state.user);
                        }
                    })
                },
                error() {
                    error_message.value = "用户名或密码错误";
                }
            })
        }
        return {
            username,
            password,
            error_message,
            login,
        }
    }
}
</script>

在这里插入图片描述

优化前端
在实现前端登录状态持久化之后,刷新页面可能会存在明显的转换,所以下面对前端页面进行优化。

首先 在 store 目录下的 user.js 中添加全局变量和下拉函数。

state: {
        id: "",
        username: "",
        password: "",
        photo: "",
        token: "",
        is_login: false,
        pulling_info: true, //是否正在拉取信息
    },

 mutations: {
        updateUser(state, user) {
            state.id = user.id;
            state.username = user.username;
            state.photo = user.photo;
            state.is_login = user.is_login;
        },
        updateToken(state, token) {
            state.token = token;
        },
        logout(state) {
            state.id = "";
            state.username = "";
            state.photo = "";
            state.token = "";
            state.is_login = false;
        },
        updatePullingInfo(state, pulling_info) {
            state.pulling_info = pulling_info;
        }
    },

在这里插入图片描述

 其次 修改 UserAccountLoginView.vue

<template>
    <ContentField v-if="!$store.state.user.pulling_info">
        <div class="row justify-content-md-center">
            <div class="col-3">
                <form @submit.prevent="login">
                    <div class="mb-3">
                        <label for="username" class="form-label">用户名</label>
                        <input v-model="username" type="text" class="form-control" id="username" placeholder="请输入用户名">
                    </div>
                    <div class="mb-3">
                        <label for="password" class="form-label">密码</label>
                        <input v-model="password" type="password" class="form-control" id="password" placeholder="请输入密码">
                    </div>
                    <div class="error-message">{{ error_message }}</div>
                    <button type="submit" class="btn btn-primary">提交</button>
                </form>
            </div>
        </div>
    </ContentField>
</template>

<script>
setup() {
        const store = useStore();
        let username = ref('');
        let password = ref('');
        let error_message = ref('');


        const jwt_token = localStorage.getItem("jwt_token");
        if (jwt_token) {
            store.commit("updateToken", jwt_token);
            store.dispatch("getinfo", {
                success() {
                    router.push({ name: "home" });
                    store.commit("updatePullingInfo", false);
                },
                error() {
                    store.commit("updatePullingInfo", false);
                }
            })
        }else {
            store.commit("updatePullingInfo", false);
        }
}

</script>

在这里插入图片描述

 在这里插入图片描述

 最后还需要修改 NavBar.vue。

<ul class="navbar-nav" v-else-if="!$store.state.user.pulling_info">
  <li class="nav-item">
    <router-link class="nav-link" :to="{name: 'user_account_login' }" role="button">
      登录
    </router-link>
  </li>
  <li class="nav-item">
    <router-link class="nav-link" :to="{name: 'user_account_register'}" role="button">
      注册
    </router-link>
  </li>
</ul>

在这里插入图片描述

记得 git 维护~ 

 

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

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

相关文章

DIVFusion:首个耦合互促低光增强图像融合的框架

DIVFusion:首个耦合互促低光增强&图像融合的框架DIVFusion:首个耦合互促低光增强&图像融合的框架写在前面问题引入Motivation主要贡献网络架构实验验证融合性能目标检测性能消融实验结论写在最后DIVFusion:首个耦合互促低光增强&图像融合的框架 论文&#xff1a;h…

攻防世界Running

Running 题目描述&#xff1a;无 题目环境&#xff1a;https://download.csdn.net/download/m0_59188912/87016663 一个可执行文件&#xff0c;执行后显示error&#xff0c;尝试binwalk文件分离。 命令&#xff1a;binwalk -e run.exe浏览分离出来的文件。 末尾发现一个run.ex…

mannose-CHO|甘露糖-醛基|甘露糖-聚乙二醇-醛基|醛基-PEG-甘露糖

mannose-CHO|甘露糖-醛基|甘露糖-聚乙二醇-醛基|醛基-PEG-甘露糖 羰基中的一个共价键跟氢原子相连而组成的一价原子团&#xff0c;叫做醛基&#xff0c;醛基结构简式是-CHO&#xff0c;醛基是亲水基团&#xff0c;因此有醛基的有机物&#xff08;如乙醛等&#xff09;有一定的…

APS高级排产软件在快消品行业的应用

快消行业是指消费频率高、使用时限短、拥有广泛的消费群体、对于消费的便利性要求很高的商品销售行业。快消行业的销售渠道种类多而复杂&#xff0c;传统业态和新兴业态等多种渠道并存。快消行业集中度逐步上升&#xff0c;竞争度加大。 随着快速消费品市场的复苏&#xff0c;经…

CNN学习笔记

目录 如何理解卷积层和池化层&#xff1f; 机器视角&#xff1a;长文揭秘图像处理和卷积神经网络架构 卷积神经网络 - 基础知识 激活函数的作用是什么&#xff1f; 激活函数&#xff08;加入非线性因素&#xff09; 提高模型鲁棒性&#xff08;抗干扰能力&#xff09;&#…

时间复杂度和空间复杂度详解

文章目录 引入 一、时间复杂度的详解及例题 1、时间复杂度的概念 2、时间复杂度的例题训练 2.1 实题训练1 2.2 实题训练2 2.3 实题训练3 2.4 实题训练4 2.5 大O符号&#xff08;Big O notation)的函数绘图 二、空间复杂度的详解及例题 1、空间复杂的的概念 2、空间复杂度…

Java注解与原理分析

使用的太多&#xff0c;被忽略的理所当然&#xff1b; 一、注解基础 注解即标注与解析&#xff0c;在Java的代码工程中&#xff0c;注解的使用几乎是无处不在&#xff0c;甚至多到被忽视&#xff1b; 无论是在JDK源码或者框架组件&#xff0c;都在使用注解能力完成各种识别和…

【Vue】url拼接参数获取解析

前言&#xff1a; 前端在开发的时候有很多情况下需要提供不带参数的链接或者带参数的链接给自己使用或者给第三方系统&#xff0c;如果提供给第三方系统使用的话一般是第三方需要通过iframe/window.open/a标签打开链接进入对应的页面。 情况一&#xff1a;获取当前浏览器地址栏…

【React二】ref与事件处理与生命周期钩子函数

关于react基础及组件化编程的可以参考本篇笔记 文章目录一、 React中的事件处理1-1 例子&#xff1a; 不要过度使用ref1-2 受控组件与非受控组件1-2-1 受控组件1-2-2 非受控组件1-3 高阶函数1-3-1 函数的柯里化1-3-2 不用柯里化的写法二、生命周期2-1 引出生命周期2-2 组件生命…

TiDB 数据库架构概述

TiDB 数据库架构概述 TiDB体系架构 水平扩容或者缩容金融级高可用实时HTAP云原生的分布式数据兼容MYSQL5.7 Region&#xff1a;存储单位&#xff0c;96~144MB之间,分布式存储在TiKV中 TiKV&#xff1a;默认三副本&#xff0c;将分布式数据存储&#xff0c;并进行存储副本。…

【ARM微型电脑/IoT设备/嵌入式】树莓派安装失败sysstat,成功后还是无法使用sar,并报错:-bash:sar:command not found

1. 安装sysstat报错 安装&#xff1a; sudo apt-get install sysstat错误如下&#xff1a; dpkg: error processing package sysstat (–configure): installed sysstat package post-installation script subprocess returned error exit status 10 Errors were encountered…

1737C - Ela and Crickets

原题链接&#xff1a; Problem - 1737C - Codeforces 题目描述&#xff1a; The problem, which involves a non-standard chess pieces type that is described below, reads: given 33 white crickets on a n⋅nn⋅n board, arranged in an "L" shape next to ea…

详细讲解磁盘及文件系统管理(图例解析)

磁盘及文件系统管理详解 目前市场上主流的磁盘是机械式硬盘 u盘&#xff0c;光盘&#xff0c;软盘&#xff0c;硬盘&#xff0c;磁带 机械式硬盘 【硬盘内部由一个个同心圆组成】如下图&#xff1a; 硬盘内部所有盘片都固定在一根“轴”上&#xff0c;所以&#xff1a;所有…

Vant的List组件列表 滑动后不触底也发送请求的Bug

&#x1f4c3;目录跳转&#x1f4da;简介&#xff1a;&#x1f389;页面效果&#xff1a;&#x1f4ad;使用Float:&#x1f9d0; 问题&#xff1a;&#x1f52d;div 转为行内块 &#xff08;解决&#xff09;&#x1f3c6;总结&#xff1a;&#x1f4da;简介&#xff1a; Vant的…

docke入门基础知识

一、Docker 架构 Docker 包括三个基本概念: 镜像&#xff08;Image&#xff09;&#xff1a;Docker 镜像&#xff08;Image&#xff09;&#xff0c;就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。 容…

html前端跨域问题的解决方案

前言&#xff1a; 在前端发出Ajax请求的时候&#xff0c;有时候会产生跨域问题&#xff0c;报错如下: Access to XMLHttpRequest at ‘http://127.0.0.1/api/post’ from origin ‘null’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is pre…

WINSOFT ComPort轻松连接到各种串行端口和连接设备

WINSOFT ComPort轻松连接到各种串行端口和连接设备 WINSOFT ComPort是一个Delphi库和CBuilder&#xff0c;通过USB端口连接到输入设备。该库提供CP210x、CP2130、CDC、FTDI、PL2303和CH34x设备。这些标准包括广泛的设备和电气从设备。例如&#xff0c;除了标准输入设备之外&…

Android App开发之利用Glide实现图片的三级缓存Cache讲解及实战(附源码 超详细必看 简单易懂)

需要图片集和源码请点赞关注收藏后评论区留言~~~ 一、利用Glide实现图片的三级缓存 图片加载框架之所以高效&#xff0c;是因为它不但封装了访问网络的步骤&#xff0c;而且引入了三级缓存的机制。具体来说&#xff0c;是先到内存中查找图片&#xff0c;找到了就直接显示内存图…

国内访问Github超级慢?那是你没有用我这个脚本。直接起飞。

导语 之前很多朋友咨询过国内访问Github较慢的问题&#xff0c;然后我一般让他们自己去知乎上找攻略&#xff0c;但今天我才发现网上竟然没有一个一键配置的脚本&#xff0c;一般都需要我们跟着教程一步步地去做才行。这也太麻烦了&#xff0c;于是自己动手写了个脚本&#xf…

2-1 C++类的转换函数与禁止隐士转换(explicit)

1. 转换函数与explicit关键字 1.1 转换函数 下述代码的第5行operator double()即是一个转换函数&#xff0c;通过这个函数&#xff0c;编译器可以在需要的情况下&#xff0c;直接将Fraction类型的对象转换为double类型。这个函数有两个特点&#xff1a;首先因为转换函数的返回…