node.js+Koa框架+MySQL实现注册登录

news2024/9/20 17:32:06

完整视频展示:https://item.taobao.com/item.htm?ft=t&id=831092436619&spm=a21dvs.23580594.0.0.52de2c1bg9gTfM

效果展示:


一、项目介绍

本项目是基于node.js+Koa+mysql的注册登录的项目,主要是给才学习node.js和Koa框架的萌新才写的。


二、项目目录

```

server.js

public

    index.html

    CSS

    JS

    img

node_modules

```


三、实现逻辑

<1>登录和注册页面

登录和注册前端界面代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录注册</title>
    <link rel="stylesheet" href="css/login and sign.css">
    <link rel="stylesheet" href="../component/loading/loading.css">
</head>
<body>
    <div class="container">
        <!-- loading -->
    <div class="loader"></div>
        <!-- Registration form -->
        <div class="form registration-form" style="display: none;">
            <h2>注册</h2>
            <input type="text" placeholder="😎 昵称" class="input" id="nickname" />
            <input type="password" placeholder="🔒 密码" class="input" id="password" />
            <input type="email" placeholder="📮 邮箱" class="input" id="email" />
            <button class="btn" id="register">注册</button>
            <a class="link" id="loginLink">已有账号,去登录</a>
        </div>
        <!-- Login form -->
        <div class="form login-form">
            <h2>登录</h2>
            <input type="text" placeholder="😎 账号" class="input" id="loginUsername" />
            <input type="password" placeholder="🔒 密码" class="input" id="loginPassword" />
            <button class="btn" id="login">登录</button>
            <a class="link" id="registerLink">没有账号,去注册</a>
        </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script src="js/login and sign.js"></script>
    <script src="../component/loading/loading.js"></script>
</body>
</html>

CSS如下:

body {
    background: linear-gradient(135deg, rgba(179, 217, 230, 0.8), rgba(0, 153, 204, 0.8));
    display: grid;
    height: 100vh;
    place-items: center;
    margin: 0;
    font-family: 'Arial', sans-serif;
    overflow: hidden; /* 防止滚动条出现 */
}

.container {
    border-radius: 1rem;
    width: 90%;
    max-width: 400px;
    height: auto;
    overflow: hidden;
    padding: 2rem;
    transition: all 0.3s ease, transform 0.3s ease; /* 添加变换效果 */
    backdrop-filter: blur(10px); /* 添加模糊背景效果 */
}

.container:hover {
    transform: scale(1.02); /* 鼠标悬停时轻微放大效果 */
}

.form {
    align-items: stretch;
    background: rgba(255, 255, 255, 0.9); /* 半透明白色背景 */
    border-radius: 1rem;
    box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
    display: flex;
    flex-direction: column;
    padding: 2rem;
    animation: fadeIn 0.5s ease; /* 添加淡入动画 */
}

@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(10px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

input {
    border: 1px solid #c4c4c4;
    border-radius: 0.25rem;
    font-size: 1rem;
    margin: 0.5rem 0;
    padding: 0.6rem;
    width: 95%;
    transition: border-color 0.3s ease, box-shadow 0.3s ease;
}

input::placeholder {
    color: #999; /* 更加明显的占位符颜色 */
}

input:focus {
    border-color: #00bfff;
    outline: none;
    box-shadow: 0 0 5px rgba(0, 191, 255, 0.5); /* 添加聚焦阴影效果 */
}

.btn {
    background: linear-gradient(135deg, #00bfff, #0099cc);
    border: none;
    color: #fff;
    cursor: pointer;
    font-size: 1.1rem;
    margin-top: 1.5rem;
    padding: 0.6rem;
    width: 100%;
    border-radius: 0.25rem;
    transition: background-color 0.3s ease, transform 0.1s ease, box-shadow 0.3s ease; /* 添加阴影效果 */
}

.btn:hover {
    background: linear-gradient(135deg, #0099cc, #00bfff);
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); /* 鼠标悬停时添加阴影 */
}

.btn:active {
    transform: scale(0.95); /* 改变按下时的缩放比例 */
}

.link {
    color: #00bfff;
    cursor: pointer;
    font-size: 0.9rem;
    text-align: center;
    text-decoration: none;
    transition: color 0.3s ease; /* 添加颜色过渡效果 */
}

.link:hover {
    text-decoration: underline;
    color: #0099cc; /* 悬停时颜色变化 */
}

h2 {
    color: #0099cc;
    margin-bottom: 2rem;
    text-align: center; /* 中心对齐标题 */
}


.form .link {
    display: block;
    text-align: center;
    margin-top: 10px; /* Adjust the margin as needed for spacing */
}

JS逻辑如下:

document.addEventListener('DOMContentLoaded', function() {
    // 获取页面上的元素
    const loginLink = document.getElementById('loginLink'); // 登录链接
    const registerLink = document.getElementById('registerLink'); // 注册链接
    const registrationForm = document.querySelector('.registration-form'); // 注册表单
    const loginForm = document.querySelector('.login-form'); // 登录表单

    // 设置点击登录链接时的事件处理函数
    loginLink.addEventListener('click', () => {
        registrationForm.style.display = 'none'; // 隐藏注册表单
        loginForm.style.display = 'block'; // 显示登录表单
    });

    // 设置点击注册链接时的事件处理函数
    registerLink.addEventListener('click', () => {
        registrationForm.style.display = 'block'; // 显示注册表单
        loginForm.style.display = 'none'; // 隐藏登录表单
    });

    // 获取注册按钮元素
    const registerBtn = document.getElementById('register');
    // 设置点击注册按钮时的事件处理函数
    registerBtn.addEventListener('click', async () => {
        // 获取注册表单中的值
        const nickname = document.getElementById('nickname').value;
        const email = document.getElementById('email').value;
        const password = document.getElementById('password').value;

        // 检查所有字段是否都已填写
        if (!nickname || !email || !password) {
            alert('所有字段均不能为空!'); // 提示用户所有字段必须填写
            return;
        }

        // 密码强度验证:至少8个字符,包括字母和数字
        const passwordPattern = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/;
        if (!passwordPattern.test(password)) {
            alert('密码必须至少包含8个字符,包括字母和数字!'); // 提示用户密码要求
            return;
        }

        try {
            // 向服务器发送注册请求
            const response = await axios.post('/register', { nickname, email, password });
            alert(response.data); // 显示服务器返回的消息
            
            // 切换到登录表单
            registrationForm.style.display = 'none';
            loginForm.style.display = 'block';
        } catch (error) {
            alert(error.response.data); // 显示服务器返回的错误信息
        }
    });

    // 获取登录按钮元素
    const loginBtn = document.getElementById('login');
    // 设置点击登录按钮时的事件处理函数
    loginBtn.addEventListener('click', async () => {
        // 获取登录表单中的值
        const username = document.getElementById('loginUsername').value;
        const password = document.getElementById('loginPassword').value;

        // 检查所有字段是否都已填写
        if (!username || !password) {
            alert('所有字段均不能为空!'); // 提示用户所有字段必须填写
            return;
        }

        try {
            // 向服务器发送登录请求
            const response = await axios.post('/login', { username, password });
            if (response.data === '登录成功!') {
                alert(response.data); // 显示登录成功的消息
                
                // 存储昵称到 sessionStorage
                sessionStorage.setItem('nickname', username); // 使用登录时的用户名作为昵称
                
                // 重定向到新页面
                setTimeout(() => {
                    window.location.href = 'after.html';
                }, 900); // 延迟900毫秒后重定向
            } else {
                alert(response.data); // 显示登录失败的消息
            }
        } catch (error) {
            alert(error.response.data); // 显示服务器返回的错误信息
        }
    });
});

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

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

相关文章

java数据结构----图

图的存储结构: 代码实现 public class Graph {// 标记顶点数目private int V;// 标记边数目private int E;// 邻接表private Queue<Integer>[] adj;public Graph(int v) {V v;this.E 0;this.adj new Queue[v];for (int i 0; i < adj.length; i) {adj[i] new Queu…

C++的类与对象中(主讲默认成员函数)

目录 1.类的默认成员函数 2.构造函数 1.全缺省构造函数 2.第7点中的对自定义类型的成员变量构造&#xff08;调用编译器自动生成的默认构造函数&#xff09; 3.析构函数 4.拷贝构造函数 5.运算符重载 1.概念 2.赋值运算符重载 6.const成员函数 1.类的默认成员函数 默…

微服务——网关路由(Spring Cloud Gateway)

网关路由 1.什么是网关 网关又称网间连接器、协议转换器&#xff0c;是在网络层以上实现网络互连的复杂设备&#xff0c;主要用于两个高层协议不同的网络之间的互连。网关就是网络的关口。数据在网络间传输&#xff0c;从一个网络传输到另一网络时就需要经过网关来做数据的路由…

【深度智能】:迈向高级时代的人工智能全景指南

​ ​ 前几天偶然发现了一个超棒的人工智能学习网站&#xff0c;内容通俗易懂&#xff0c;讲解风趣幽默&#xff0c;简直让人欲罢不能。忍不住分享给大家&#xff0c;人工智能立刻跳转&#xff0c;开启你的AI学习之旅吧&#xff01; 第一阶段&#xff1a;基础知识 1. 计算机科…

人脸防伪检测系统源码分享

人脸防伪检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

【Python基础】Python 装饰器(优雅的代码增强工具)

本文收录于 《Python编程入门》专栏&#xff0c;从零基础开始&#xff0c;分享一些Python编程基础知识&#xff0c;欢迎关注&#xff0c;谢谢&#xff01; 文章目录 一、前言二、装饰器基础三、语法糖 四、带参数的装饰器五、多层装饰器六、总结 一、前言 在Python编程的世界里…

【手撕】快排-分治

1. 颜色分类 . - 力扣&#xff08;LeetCode&#xff09;. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/sort-colors/description/ 代码 class Solution {public…

Neo4j入门案例:三星堆

创建一个关于三星堆的知识图谱可以是一个非常有趣的项目&#xff0c;它可以帮助理解如何使用Neo4j来存储和查询复杂的关系数据。三星堆文化以其独特的青铜器、金器和其他文物而闻名&#xff0c;这为我们提供了一个丰富的历史背景来构建知识图谱。 数据模型定义 实体类型&#…

数据安全查询-—SAAS本地化及未来之窗行业应用跨平台架构

一、数据库安全查询 默认数据库查询是不区分大小写的&#xff0c;这样无法区分Mm&#xff0c;Admin&#xff0c;admin 二、thinkphp 区分大小写 $condition "binary appdhj_sn {$应用sn}"; 三、原始mysql select * from TableA where binary columnA aaa; 四、…

mtk7628 网口灯问题

板子上电插入网线到网口&#xff0c;只有wan口灯会亮&#xff0c;插入lan口灯不会亮。对比了ok的代码&#xff0c;先对比设备树&#xff0c;未看到网口相关的GPIO。 mt7628an_WMD-7688A-12816.dts mt7628an_hilink_hlk-7628n.dts 继续查看网口相关代码&#xff0c;加打印&…

Android应用程序启动源码分析

文章目录 Android应用程序启动源码分析一、启动流程二、Launcher通知AndroidOS(用户点击图标)2.1 Activity.java2.2 Instrumentation.java2.3 ActivityTaskManagerService.java2.4 ActivityStarter.java2.5 RootWindowContainer.java2.5.1 Task.java2.5.2 TaskFragment.java 2.…

基于python+django+vue的个性化餐饮管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于pythondjangovueMySQL的视…

勇于尝试,永远行动 - 《洛克菲勒写给儿子的38封信》读书笔记

两倍速听过好几遍的书&#xff0c;洛克菲勒的思想和志向&#xff0c;配得上他的成就。 “在尝试中寻找突破&#xff0c;在行动中成就自我。”这是洛克菲勒写给儿子的箴言&#xff0c;也是他一生的真实写照。在这38封信中&#xff0c;他不仅分享了自己的工作心得&#xff0c;更…

Docker安装mysql安装nginx安装Redis

Docker安装mysql 下载镜像 docker pull mysql:8.0注意,使用此方法安装镜像需要提前配置镜像源,详情看之前的文章 安装 docker run -d -p 3306:3306 \ --name mysql \ --restartalways \ --privilegedtrue \ -e TZAsia/Shanghai \ -e MYSQL_ROOT_PASSWORDroot \ mysql:8.0进…

【重学 MySQL】二十九、函数的理解

【重学 MySQL】二十九、函数的理解 什么是函数不同 DBMS 函数的差异函数名称和参数功能实现数据类型支持性能和优化兼容性和可移植性 MySQL 的内置函数及分类单行函数多行函数&#xff08;聚合函数&#xff09;使用注意事项 什么是函数 函数&#xff08;Function&#xff09;在…

【PHP代码审计】 PHP环境搭建

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 安装phpstudy 泥菩萨-CSDN博客 安装vscode 直接去官网下载安装包&#xff0c;然后双击安装即可。官网地址&#xff1a;htt…

24/9/15 kaggle数字识别器

这次做的是数字识别器&#xff0c;借鉴了大佬的文章Kaggle竞赛实战系列&#xff08;一&#xff09;&#xff1a;手写数字识别器&#xff08;Digit Recognizer&#xff09;得分99.53&#xff05;、99.91%和100%_手写数字识别实现 digist-CSDN博客 加入了自己对大佬里面步骤的解…

多模态大语言模型综述(中)-算法实用指南

本文是Multimodal Large Language Models: A Survey的译文之算法实用指南部分。 上&#xff1a;摘要、概念与技术要点实用指南中&#xff1a;算法实用指南(本文)下: 任务的实用指南(应用)、挑战等 原始信息 标题: Multimodal Large Language Models: A Survey译文: 多模态大…

Conda和pip 清空缓存

conda clean --all然后选y&#xff0c;如下图&#xff1a; pip cache purge # 清除所有缓存

视频工具EasyDarwin将本地视频生成RTSP给WVP拉流列表

效果 ffmpeg生成rtsp流 EasyDarwin的rtsp端口默认的是10054, 使用ffmpeg将本地视频转到EasyDarwin的rtsp。 F:\rtsp\ffmpeg-7.0.2-essentials_build\bin>ffmpeg -re -i F:\rtsp\123.mp4 -rtsp_transport tcp -vcodec h264 -f rtsp rtsp://127.0.0.1:10054/video11 它的直播…