【项目实战】登录与注册业务的实现(前端+后端+数据库)

news2025/1/22 16:15:23

        本示例基于Vue.js和mint UI实现。


目录

一、数据库的创建

二、后端接口与数据库的连接

三、前端代码实现

1.注册页相关代码

2.注册页效果

3.登录页相关代码

4.登录页效果

四、注册登录演示

五、项目文件结构


一、数据库的创建

        此处以Navicat软件进行创建,新建数据库reg_log.sql与数据表reg_log; 

        为了实现注册业务,我们在数据库中设计ID、用户名、密码、邮箱、电话号5个字段。

        创建结束后保存,便可以在数据库中找到我们刚刚创建的数据库和空表。这样就可以在项目中进行连接了。

二、后端接口与数据库的连接

server文件夹 -> app.js 

// 加载Express模块
const express = require('express');

// 加载MySQL模块
const mysql = require('mysql');

// 加载bodyParser模块
const bodyParser = require('body-parser');

// 加载MD5模块
const md5 = require('md5');

// 创建MySQL连接池
const pool = mysql.createPool({
  host: '127.0.0.1', //MySQL服务器地址
  port: 3306, //MySQL服务器端口号
  user: 'root', //数据库用户的用户名
  password: '', //数据库用户密码
  database: 'reg_log', //数据库名称
  connectionLimit: 20, //最大连接数
  charset: 'utf8' //数据库服务器的编码方式
});

// 创建服务器对象
const server = express();

server.use(bodyParser.urlencoded({
  extended: false
}));


// 加载CORS模块
const cors = require('cors');

// 使用CORS中间件
server.use(cors({
  origin: ['http://localhost:8080', 'http://127.0.0.1:8080']
}));

//用户注册接口
server.post('/register', (req, res) => {
  //console.log(md5('12345678'));
  // 获取用户名和密码信息
  let username = req.body.username;
  let password = req.body.password;
  //以username为条件进行查找操作,以保证用户名的唯一性
  let sql = 'SELECT COUNT(id) AS count FROM reg_log WHERE username=?';
  pool.query(sql, [username], (error, results) => {
    if (error) throw error;
    let count = results[0].count;
    if (count == 0) {
      // 将用户的相关信息插入到数据表
      sql = 'INSERT reg_log(username,password) VALUES(?,MD5(?))';
      pool.query(sql, [username, password], (error, results) => {
        if (error) throw error;
        res.send({
          message: 'ok',
          code: 200
        });
      })
    } else {
      res.send({
        message: 'user exists',
        code: 201
      });
    }
  });
});

// 用户登录接口
server.post('/login', (req, res) => {
  //获取用户名和密码信息
  let username = req.body.username;
  let password = req.body.password;
  // SQL语句
  let sql = 'SELECT id,username FROM reg_log WHERE username=? AND password=MD5(?)';
  pool.query(sql, [username, password], (error, results) => {
    if (error) throw error;
    if (results.length == 0) { //登录失败
      res.send({
        message: 'login failed',
        code: 201
      });
    } else { //登录成功
      res.send({
        message: 'ok',
        code: 200,
        result: results[0]
      });
    }
  });

});

// 指定服务器对象监听的端口号
server.listen(3000, () => {
  console.log('server is running...');
});

三、前端代码实现

1.注册页相关代码

项目文件夹 -> Register.vue

<template>
<!-- 注册页面 -->
  <div class="reg">
    <mt-header title="用户注册">
      <router-link slot="left" to="/"> 返回首页 </router-link>
      <router-link to="/login" slot="right">去登录</router-link>
    </mt-header>
    <mt-field
      type="text"
      label="用户名"
      placeholder="请输入用户名"
      v-model="name"
      :state="nameState"
      @blur.native.capture="checkName"></mt-field>
      <!-- @blur失焦,输入框在输入完成、移到其他地方时进行验证 -->
    <mt-field
      type="password"
      label="密码"
      placeholder="请输入密码"
      v-model="pwd"
      :state="pwdState"
      @blur.native.capture="checkPwd"></mt-field>
    <mt-field
      type="password"
      label="确认密码"
      placeholder="再次输入密码"
      v-model="repwd"
      :state="repwdState"
      @blur.native.capture="checkrePwd"></mt-field>
    <mt-field
      label="邮箱"
      placeholder="请输入邮箱"
      type="email"
      v-model="email"
      :state="emailState"
      @blur.native.capture="checkEmail"></mt-field>
    <mt-field
      label="手机号"
      placeholder="请输入手机号"
      type="tel"
      v-model="phone"
      :state="phoneState"
      @blur.native.capture="checkPhone"></mt-field>
    <mt-field
      label="生日"
      placeholder="请输入生日"
      type="date"
      v-model="birthday"></mt-field>
    <mt-button class="btn" type="primary" size="large" @click="checkForm">注册</mt-button>
  </div>
</template>

<style scope>
.reg .btn {
  background-color: #d86931;
  width: 190px;
  border-radius: 0;
  border: 0;
  margin: auto;
}
.reg .mint-cell-wrapper {
  line-height: 80px;
}
.reg {
  margin-top: 14%;
}

.reg .mint-header {
  background-color: #d86931;
}
.reg .btn {
  background-color: #d86931;
}
</style>

<script>
export default {
  data() {
    return {
      name: "", //双向数据绑定 用户名输入框
      nameState: "", //处理用户名输入框的动态更新
      pwd: "",
      pwdState: "",
      repwd: "",
      repwdState: "",
      email: "",
      emailState: "",
      phone: "",
      phoneState: "",
      birthday: "",
    };
  },
  methods: {
    // 封装各个字段的验证方法:
    // 1.验证用户名
    checkName() {
      //事件处理函数:处理点击按钮验证表单
      let reg = /^[a-zA-Z0-9\u4E00-\u9FA5]{2,6}$/;
      if (reg.test(this.name)) {
        this.nameState = "success";
        return true;
      } else {
        this.nameState = "error";
        return false;
      }
    },
    // 2.验证密码
    checkPwd() {
      let reg = /^\d{6}$/;
      if (reg.test(this.pwd)) {
        this.pwdState = "success";
        return true;
      } else {
        this.pwdState = "error";
        return false;
      }
    },
    // 3.重复输入密码
    checkrePwd() {
      let reg = /^\d{6}$/;
      if (reg.test(this.repwd) && this.pwd == this.repwd) {
        this.repwdState = "success";
        return true;
      } else {
        this.repwdState = "error";
        return false;
      }
    },
    // 4.验证邮箱格式
    checkEmail() {
      let reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
      if (reg.test(this.email)) {
        this.emailState = "success";
        return true;
      } else {
        this.emailState = "error";
        return false;
      }
    },
    // 5.验证手机号
    checkPhone() {
      let reg = /^1[3|5|7|8][0-9]\d{8}$/;
      if (reg.test(this.phone)) {
        this.phoneState = "success";
        return true;
      } else {
        this.phoneState = "error";
        return false;
      }
    },

    checkForm() {
      // 点击注册按钮后调用此方法,验证用户名、密码、二次密码是否均正确,正确则发送axios请求
      if (this.checkName() && this.checkPwd() && this.checkrePwd()) {
        console.log(`验证成功,执行注册业务......`);
        // 发送注册(post)请求
        this.axios
          .post("/register", `username=${this.name}&password=${this.pwd}`)
          .then((result) => {
            console.log(result);
            if (result.data.code == 200) {
              // 弹窗提示注册成功
              this.$toast({
                message: "注册成功",
                position: "bottom",
                duration: 3000,
              });
              // 注册成功后直接跳转到登录页
              this.$router.push("/login");
            } else if (result.data.code == 201) {
              this.$toast({
                message: "用户已存在,请重新注册",
                position: "bottom",
                duration: 3000,
              });
            }
          });
      }
    },
  },
};
</script>

2.注册页效果

3.登录页相关代码

项目文件夹 -> Login.vue 

<template>
<!-- 登录页面 -->
  <div class="log">
    <span class="login">请登录</span>
    <span class="reg">
      <router-link to="/register">先去注册</router-link>
    </span>
    <!-- mint ui的表单组件 -->
    <mt-field
      type="text"
      label="用户名"
      placeholder="请输入用户名"
      v-model="name"
      :state="nameState"
      @blur.native.capture="checkName"></mt-field>
    <mt-field
      type="password"
      label="密码"
      placeholder="请输入密码"
      v-model="pwd"
      :state="pwdState"
      @blur.native.capture="checkPwd"></mt-field>
    <hr style="width: 85%" />
    <mt-button class="btn" type="primary" size="large" @click="checkForm">登录</mt-button>
  </div>
</template>

<style scoped>
.log .reg {
  font-size: 18px;
}
.log .login {
  font-size: 24px;
  font-family: "楷体";
  font-weight: 700;
  margin-left: 5px;
  margin-right: 210px;
  line-height: 80px;
}
.log {
  margin-top: 20%;
}
.log .btn {
  background-color: #d86931;
  width: 190px;
  border-radius: 0;
  border: 0;
  margin: auto;
}
.log .btn1 {
  background-color: white;
  border: 2px solid #d86931;
  color: #d86931;
  width: 190px;
  margin: auto;
  margin-top: 30px;
}
</style>>

<script>
export default {
  namespaced: true,
  data() {
    return {
      name: "", //双向数据绑定 用户名输入框
      nameState: "", //处理用户名输入框的动态更新
      pwd: "",
      pwdState: "",
    };
  },
  methods: {
    // 封装验证方法:
    // 1.验证用户名
    checkName() {
      //事件处理函数:处理点击按钮验证表单
      let reg = /^[a-zA-Z0-9\u4E00-\u9FA5]{2,6}$/; //2-6位的数字、字母、汉字
      if (reg.test(this.name)) {
        this.nameState = "success";
        return true;
      } else {
        this.nameState = "error";
        return false;
      }
    },
    // 2.验证密码
    checkPwd() {
      let reg = /^\d{6}$/;
      if (reg.test(this.pwd)) {
        this.pwdState = "success";
        return true;
      } else {
        this.pwdState = "error";
        return false;
      }
    },

    checkForm() {
      // 点击登录按钮后调用此方法,同时验证用户名和密码
      if (this.checkName() && this.checkPwd()) {
        // 发送登录(post)请求
        this.axios
          .post("/login", `username=${this.name}&password=${this.pwd}`)
          .then((result) => {
            console.log(result);
            if (result.data.code == 200) {
              // 弹窗提示登录成功
              this.$toast({
                message: `欢迎您 ${this.name}`,
                position: "bottom",
                duration: 3000,
              });
              // 修改vuex中用户登录状态
              this.$store.commit("loginok", this.name);
              // 将islogin与username存入sessionStorage
              sessionStorage.setItem("islogin", true);
              sessionStorage.setItem("username", this.name);
              // 登录成功后直接跳转到首页
              this.$router.push("/club");
            } else {
              this.$toast({
                message: "登录失败,请检查您的用户名和密码",
                position: "bottom",
                duration: 3000,
              });
            }
          });
      }
    },
  },
};
</script>

4.登录页效果

四、注册登录演示

        按正则要求输入用户信息。

        注册成功后弹窗显示并且跳转至登录页。 进行登录:

        登录成功。

五、项目文件结构

        因为登陆注册业务需要使用到接口并调用数据库,所以需要两个文件夹,一个是项目文件夹,作为前端;一个是server文件夹,作为后端,且这两个文件夹都需要下载 node_modules 包并单独启动;

各模块的加载、连接池的创建以及接口写于 server 下的 app.js 文件,启动时使用命令 node app.js; 

 而前端的页面就正常在你的项目文件夹中书写,启动时使用命令 npm run serve;

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

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

相关文章

刚去公司,发现node版本过高,如何将node版本降低?

我们可以安装nvm&#xff0c;node版本管理器来实现。 1、nvm是什么&#xff1f; nvm&#xff08;node.js version management&#xff09;&#xff0c;是一个nodejs的版本管理工具。nvm和n都是node.js版本管理工具&#xff0c;为了解决node.js各种版本存在不兼容现象可以通过…

uniapp自动更新

一uniapp自动更新流程逻辑 实现检测版本更新并下载新版本&#xff1a;通过后台返回更新版本的版本号和当前版本号做比较&#xff0c;不同则提示有新版本需要更新&#xff0c;下载地址又后台返回 uniapp自动更新设计思路 在服务端配置一个最新的应用版本号&#xff1b; 并将打包…

【jQuery从入门到精通】

文章目录jQuery简介jQuery下载与安装下载版本说明优点安装jQuery核心DOM对象和Jquery包装集对象dom对象的获取获取一个不存在的dom对象jQuery对象的获取获取一个不存在的jQuery对象DOM对象与jQuery对象的转换dom对象转jQuery对象jQuery对象转dom对象jQuery选择器基础选择器层次…

【ES6丨前端进阶基础 】二,ES6rest参数,Symbol第七种数据类型

CSDN话题挑战赛第2期 参赛话题&#xff1a;面试宝典 目录​​​​​​​ 前言 一&#xff0c;函数参数的默认值设置 二&#xff0c;rest参数 三&#xff0c;扩展运算符 扩展运算符应用 1.合并数组 2.数组的克隆 3.伪数组转化成真正的数组 四&#xff0c;Symbol第7种数…

vue脚手架(2022年9月份nodejs16.17.0版本)

vue脚手架(2022年9月份nodejs16.17.0版本) 目录 vue脚手架(2022年9月份nodejs16.17.0版本) 下载地址 环境变量设置 全局文件夹与缓存文件夹设置 修改国内的【阿里】镜像 查看vue信息 更新npm 新增环境变量 安装vue与router 安装vue脚手架 Vue项目创建 项目层级 …

GitHub Copilot的下载使用方法(2022最新)

流程 1.去官网提交申请 填写邮件 2.等待几天收到邮件 3.点击邮件链接下载copilot-docs-main 4.打开vsCode&#xff0c;在扩展商店搜索下载github copilot 5.安装完成之后会在vsCode右下角提示登录github以及允许copilot 6.如果你有资格那么vsCode右下角就会出现copilot的…

Window.location用法

Window.location 详细介绍 本文翻译自 samanthaming 发表于 dev.to 的博文 原文地址 window.location Cheatsheet - DEV Community &#x1f469;‍&#x1f4bb;&#x1f468;‍&#x1f4bb; 如果你需要获取网站的 URL 信息&#xff0c;那么 window.location 对象就是为你准备…

【vue2可视化开发】新手会遇到的问题——大屏自适应

简要描述 开发可视化大屏第一步&#xff0c;必须要考虑适配不同屏幕的问题&#xff0c;在网络上查看资料&#xff0c;总结了一个目前最适合可视化开发的自适应方案——v-scale-screen组件 1. 安装 注&#xff1a;vue2使用v-scale-screen1.0.0版本&#xff0c;vue3使用v-scal…

Qt 下拉复选框(MultiSelectComboBox)(一) 实现下拉框多选,搜索下拉框内容

文章目录本系列目录前言一、QCombobox的组成二、MultiSelectComboBox实现1. 总体实现2. QLineEdit部分3. QListWidget部分1. 搜索框部分2. 选项部分4. 对外接口定义5. 代码实现总结本系列目录 Qt 下拉复选框&#xff08;MultiSelectComboBox&#xff09;(一) 实现下拉框多选&a…

vue3中使用ref语法糖

自从引入组合式 API 的概念以来&#xff0c;一个主要的未解决的问题就是 ref 和响应式对象到底用哪个。响应式对象存在解构丢失响应性的问题&#xff0c;而 ref 需要到处使用 .value 则感觉很繁琐&#xff0c;并且在没有类型系统的帮助时很容易漏掉 .value 以上是官方原话,大概…

webrtc streamer前端页面js播放摄像头rtsp流

webrtc streamer 大致的了解了一下&#xff0c;就是使用js来播放rtsp视频流的一个技术。目前实现的厂家有很多&#xff0c;但是要收费。我这里是找了一个开源免费的项目&#xff0c;使用起来有一定的局限性&#xff0c;需要根据自己的业务自己去实现逻辑&#xff0c;目前我只做…

盘点那些神级uniapp插件,总有一款让你事半功倍

自从有了uniapp&#xff0c;各位做小程序&#xff0c;app是不是感觉快起飞了&#xff0c;如果你想快速推出自己的移动端&#xff08;各平台小程序&#xff0c;安卓、苹果&#xff09;&#xff0c;那么uniapp还是很不错的&#xff0c;至少时间和研发成本可以帮你降低很多很多。 …

VUE+BPMN.JS右侧属性栏自定义功能

博主最近项目需求要实现BPMNVUE实现流程自定义, 在完成基础功能后,要求右侧属性栏内的一些属性需要根据后端返回内容进行动态渲染, 这时候,用原来的属性栏明显就不满足需求,我找到的大部分博客包括官方都是建议你根据项目需求来全部重写一个属性栏.但是项目时间紧的情况下这种…

React基础-JSX的本质-虚拟DOM的创建过程

文章目录JSX的本质虚拟DOM的创建过程JSX的本质 实际上&#xff0c;jsx仅仅只是 React.createElement(component, props, ...children) 这个函数的语法糖。 所有的jsx最终都会被转换成React.createElement的函数调用。 createElement需要传递三个参数: 参数一:type 当前元素的…

Error in render: “TypeError: Cannot read properties of undefined (reading ‘length‘)“,深层次数据处理报错????

vue中出现很烦人的红色报错&#xff0c;例如&#xff0c;如下图&#xff1a; 1. 2. Error in render: “TypeError: Cannot read properties of undefined (reading ‘name‘)“ 一般这样的length读取出现的报错&#xff0c;往往很令人苦恼&#xff0c;vue虽然正常渲染&#x…

炫酷登录注册 完整功能版【本地存储+JS+HTML+CSS+jQuery】

一&#xff1a;源码获取 &#x1f50d;说明&#xff1a; 这篇文章是完整功能的登录注册&#xff0c;包含了基于本地存储的注册&#xff0c;登录&#xff0c;以及密码修改功能&#xff0c;登录包含错误三次冻结账户1000s等细微功能&#xff0c;适合新入门前端的小伙伴拿来学习使…

前端页面显示的时间格式为:2022-03-18T01:46:08.000+00:00 如何转换为:年-月-日 时:分:秒 ?

解决办法&#xff1a; 第一种办法&#xff1a;后端格式处理&#xff0c;在后端转数据格式为字符串类型 第二种办法&#xff1a;前端格式处理&#xff0c; ElementUI 中 Table-column Attributes 列属性中有一个 formatter参数 &#xff0c;用来格式化内容 &#xff0c; 里面可…

SpringBoot+Vue实现文件上传下载功能

前言 本文主要实现了以下功能&#xff1a; 1、 单文件上传以及多文件上传功能 2、 输入文件名下载文件功能 3、 输入音频文件名在线播放音频功能 一、项目基础部分搭建 1.1 前端项目搭建 1.1.1 新建前端项目 打开命令行输入以下命令&#xff0c;使用Vue CLI创建前端项目&a…

浏览器同源策略导致跨域问题 No ‘Access-Control-Allow-Origin‘ header 原因及解决方式--(后端、nginx、前端)

目录 现象 原因 浏览器同源策略 导致结果&#xff1a; 解决方案 跨源资源共享&#xff08;CORS&#xff09; 各个端解决方法&#xff1a; 后端&#xff1a; 方式1&#xff1a;重载WebMvcConfigurer方法 方式2&#xff1a;配置监听CorsFilter 方式3&#xff1a;相关类…

微信小程序--》你真的了解小程序组件的使用吗?

&#x1f3cd;️作者简介&#xff1a;大家好&#xff0c;我是亦世凡华、渴望知识储备自己的一名在校大学生 &#x1f6f5;个人主页&#xff1a;亦世凡华、 &#x1f6fa;系列专栏&#xff1a;微信小程序 &#x1f6b2;座右铭&#xff1a;人生亦可燃烧&#xff0c;亦可腐败&…