零基础快速开发Vue图书管理系统—登录注册篇(一)

news2024/10/7 14:26:48

零基础快速开发Vue图书管理系统—登录注册篇(一)

一、图书管理系统项目功能

在这里插入图片描述

二、项目技术选型

  • 前端主要采用:Vue3.x (vuex/vue-router)、Ant Design Vue、Axios
  • 服务端主要采用:Node.js、Koa、Mongoose
  • 数据库主要采用:MongoDB

在这里插入图片描述

三、使用vue-cli3创建项目

如何搭建环境看我之前写的文章:五分钟教你使用vue-cli3创建项目(三种创建方式,小白入门必看)

在这里插入图片描述

四、搭建所需的文件

在view的目录下新建Auth文件夹,里面分别放以下三个文件

在这里插入图片描述

前端UI框架主要采用Ant Design Vue

在这里插入图片描述
在这里插入图片描述

😛index.vue内容如下

<template>
    <div class="auth">
        <div class="bg"></div>
        <div class="title-info">
            <img src="https://ncstatic.clewm.net/rsrc/2020/1016/02/4757e4910cb527fc040d019a93ded74f.png?x-oss-process=image/resize,w_750/format,gif/sharpen,100/quality,Q_80/interlace,1/auto-orient,1"
                alt="">
            <h2 class="title">图书后台管理系统</h2>
        </div>
        <div class="form">
            <a-tabs>
                <a-tab-pane key="1" tab="登录">
                    <div class="item">
                        <a-input size="large" placeholder="账户">
                            <template v-slot:prefix>
                                <UserOutlined />
                            </template>
                        </a-input>

                    </div>

                    <div class="item">
                        <a-input size="large" placeholder="密码">
                            <template v-slot:prefix>
                                <LockOutlined />
                            </template>
                        </a-input>
                    </div>
                    <div class="item">
                        <a href="">忘记密码</a>
                    </div>

                    <div class="item">
                        <a-button size="large" type="primary">
                            登录
                        </a-button>
                    </div>
                </a-tab-pane>
                <a-tab-pane key="2" tab="注册">
                    <div class="item">
                        <a-input size="large" placeholder="账户">
                            <template v-slot:prefix>
                                <UserOutlined />
                            </template>
                        </a-input>
                    </div>

                    <div class="item">
                        <a-input size="large" placeholder="密码">
                            <template v-slot:prefix>
                                <LockOutlined />
                            </template>

                        </a-input>
                    </div>
                    <div class="item">
                        <a-input size="large" placeholder="邀请码">
                            <template v-slot:prefix>
                                <MailOutlined />
                            </template>

                        </a-input>
                    </div>
                    <div class="item">
                        <a-button size="large" type="primary">
                            注册
                        </a-button>
                    </div>
                </a-tab-pane>
            </a-tabs>
        </div>
    </div>
</template>
<script src="./index.js">
</script>
<style lang="scss" scoped>
    @import './index.scss'
</style>

😅index.scss内容如下:

.bg {
    position: fixed;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    background-image: url("https://gw.alipayobjects.com/zos/rmsportal/TVYTbAXWheQpRcWDaDMu.svg");
    background-repeat: no-repeat;
    background-size: cover;
    background-position: center center;
}

.auth {
    .title-info {
        display: flex;
        margin-top: 100px;
        text-align: center;
        align-items: center;
        justify-content: center;
        margin-bottom: 32px;
        img {
            width: 60px;
            height: 60px;
        }
        h2 {
            margin: 0;
            margin-left: 18px;
        }
    }
    .form {
        width: 400px;
        margin: 0 auto;
        .item {
            margin-bottom: 16px;
            button {
                width: 100%;
            }
        }
    }
}

🤣index.js内容如下:

 import { defineComponent } from 'vue';
 import { UserOutlined, LockOutlined, MailOutlined } from '@ant-design/icons-vue';

 export default defineComponent({
     components: {
         UserOutlined,
         LockOutlined,
         MailOutlined
     },
     setup() {

     }

 });

五、服务端开发

执行以下命令安装koa

npm i @koa/router

服务端文件结构如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

六、nodemon使用

编写调试Node的时候,项目代码做了修改,需要频繁手动停止,在重新启动,非常繁琐,使用nodemon能够监听项目文件的变动,当代码被修改后,nodemon会自动重启项目,极大方便了开发和调试

在终端中,运行如下命令,即可将nodemon安装为全局可用的工具:

npm install -g nodemon
  • 传统的方式是运行node app.js命令启动项目,需要手动重启
  • 现在将node命令替换为nodemon命令,使用nodemon app.js启动项目,会自动重启

七、使用JWT和Session实现登录注册

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

📢📢📢登录部分(服务端)

在这里插入图片描述
在这里插入图片描述
核心代码如下:

const Router = require('@koa/router');
const mongoose = require('mongoose');
const { getBody } = require('../../helpers/utils')
const jwt = require('jsonwebtoken');

const User = mongoose.model('User');

const router = new Router({
    prefix: '/auth',
});


router.post('/register', async(ctx) => {
    // console.log(ctx.request.body);
    const {
        account,
        password,
    } = getBody(ctx);

    const one = await User.findOne({
        account,
    }).exec();

    if (one) {
        ctx.body = {
            code: 0,
            msg: '已存在该用户',
            data: null,
        }
        return;

    }
    const user = new User({
        account,
        password

    });
    const res = await user.save();
    ctx.body = {
        code: 1,
        msg: '注册成功',
        data: res,
    }
});
router.post('/login', async(ctx) => {
    const {
        account,
        password,
    } = getBody(ctx);

    const one = await User.findOne({
        account,
    }).exec();

    if (!one) {
        ctx.body = {
            code: 0,
            msg: '用户名或者密码错误',
            data: null,
        }
        return;
    }
    const user = {
        account: one.account,
        _id: one._id,
    }
    if (one.password === password) {
        ctx.body = {
            code: 1,
            msg: '登录成功',
            data: {
                user,
                token: jwt.sign(user, 'manage')
            },

        }
        return;
    }
    ctx.body = {
        code: 0,
        msg: '用户名或密码错误',
        data: null,
    }
});

module.exports = router;

📢📢📢登录部分(前端)

在这里插入图片描述

在这里插入图片描述
核心代码:

 import { defineComponent, reactive } from 'vue';
 import { UserOutlined, LockOutlined, MailOutlined } from '@ant-design/icons-vue';
 import { auth } from '@/service';
 export default defineComponent({
     components: {
         UserOutlined,
         LockOutlined,
         MailOutlined,
     },
     setup() {
         //注册相关的逻辑
         const regForm = reactive({
                 account: '',
                 password: '',
             })
             //注册逻辑
         const register = () => {
                 auth.register(regForm.account, regForm.password)
             }
             //登录相关的逻辑
         const loginForm = reactive({
             account: '',
             password: '',
         });
         //登录逻辑
         const login = () => {
             auth.login(loginForm.account, loginForm.password)
         }
         return {
             //注册相关的数据
             register,
             regForm,
             //登录相关的数据
             login,
             loginForm,
         }
     }

 });

index.vue

在这里插入图片描述

<template>
    <div class="auth">
        <div class="bg"></div>
        <div class="title-info">
            <img src="https://ncstatic.clewm.net/rsrc/2020/1016/02/4757e4910cb527fc040d019a93ded74f.png?x-oss-process=image/resize,w_750/format,gif/sharpen,100/quality,Q_80/interlace,1/auto-orient,1"
                alt="">
            <h2 class="title">图书后台管理系统</h2>
        </div>
        <div class="form">
            <a-tabs>
                <a-tab-pane key="1" tab="登录">
                    <div class="item">
                        <a-input 
                        v-model:value="loginForm.account"
                        size="large" 
                        placeholder="账户">
                            <template v-slot:prefix>
                                <UserOutlined />
                            </template>
                        </a-input>

                    </div>

                    <div class="item">
                        <a-input 
                        v-model:value="loginForm.password"
                        size="large" 
                        placeholder="密码">
                            <template v-slot:prefix>
                                <LockOutlined />
                            </template>
                        </a-input>
                    </div>
                    <div class="item">
                        <a href="">忘记密码</a>
                    </div>

                    <div class="item">
                        <a-button 
                        @click="login"
                        size="large" 
                        type="primary">
                            登录
                        </a-button>
                    </div>
                </a-tab-pane>
                <a-tab-pane key="2" tab="注册">
                    <div class="item">
                        <a-input 
                        size="large"
                        placeholder="账户"
                        v-model:value="regForm.account"
                        >
                            <template v-slot:prefix>
                                <UserOutlined />
                            </template>
                        </a-input>
                    </div>

                    <div class="item">
                        <a-input 
                        size="large" 
                        placeholder="密码"
                        v-model:value="regForm.password"
                        >
                            <template v-slot:prefix>
                                <LockOutlined />
                            </template>

                        </a-input>
                    </div>
                    <div class="item">
                        <a-input size="large" placeholder="邀请码">
                            <template v-slot:prefix>
                                <MailOutlined />
                            </template>

                        </a-input>
                    </div>
                    <div class="item">
                        <a-button 
                        size="large" 
                        type="primary"
                        @click="register">
                            注册
                        </a-button>
                    </div>
                </a-tab-pane>
            </a-tabs>
        </div>
    </div>
</template>
<script src="./index.js">
</script>
<style lang="scss" scoped>
    @import './index.scss'
</style>

八、交互优化、表单校验、处理请求结果优化

登录注册逻辑校验

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

九、邀请码实现,完善注册流程

在这里插入图片描述
在这里插入图片描述

const Router = require('@koa/router');
const mongoose = require('mongoose');
const { getBody } = require('../../helpers/utils')
const jwt = require('jsonwebtoken');

const User = mongoose.model('User');
const InviteCode = mongoose.model('InviteCode');
const router = new Router({
    prefix: '/auth',
});


router.post('/register', async(ctx) => {

    const {
        account,
        password,
        inviteCode,
    } = getBody(ctx);
    //表单校验
    if (account === '' || password === '' || inviteCode === '') {
        ctx.body = {
            code: 0,
            msg: '字段不能为空',
            data: null,
        }
        return;
    }
    //找是否有邀请码
    const findCode = await InviteCode.findOne({
        code: inviteCode,
    }).exec();
    //如果没有找到邀请码
    if ((!findCode) || findCode.user) {
        ctx.body = {
            code: 0,
            msg: '邀请码不正确',
            data: null,
        }
        return;
    }

    //去找account为传递上来的account的用户
    const findUser = await User.findOne({
        account,
    }).exec();
    //判断是否有用户
    if (findUser) {
        //如果有表示已经存在
        ctx.body = {
            code: 0,
            msg: '已存在该用户',
            data: null,
        }
        return;

    }
    //创建用户
    const user = new User({
        account,
        password

    });
    //把创建的用户同步到mongdb
    const res = await user.save();

    findCode.user = res._id;
    findCode.meta.updatedAt = new Date().getTime();
    await findCode.save();
    //响应成功
    ctx.body = {
        code: 1,
        msg: '注册成功',
        data: res,
    }
});
router.post('/login', async(ctx) => {
    const {
        account,
        password,
    } = getBody(ctx);

    if (account === '' || password === '') {
        ctx.body = {
            code: 0,
            msg: '字段不能为空',
            data: null,
        }
        return;
    }

    const one = await User.findOne({
        account,
    }).exec();

    if (!one) {
        ctx.body = {
            code: 0,
            msg: '用户名或者密码错误',
            data: null,
        }
        return;
    }
    const user = {
        account: one.account,
        _id: one._id,
    }
    if (one.password === password) {
        ctx.body = {
            code: 1,
            msg: '登录成功',
            data: {
                user,
                token: jwt.sign(user, 'manage')
            },

        }
        return;
    }
    ctx.body = {
        code: 0,
        msg: '用户名或密码错误',
        data: null,
    }
});

module.exports = router;

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

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

相关文章

Docker安装Redis集群失败经历汇总

在程序员的开发过程中&#xff0c;Redis可以说基本上是必不可少的缓存中间件。不管是二进制包还是docker安装Redis的文章在网上都是数不胜数。我之前自己玩Redis的时候基本不是二进制包安装就是docker安装&#xff0c;也没有尝试过集群方式。每次需要的时候&#xff0c;网上百度…

DataFrame转化为json的方法教程

网络上有好多的教程&#xff0c;讲得不太清楚和明白&#xff0c;我用实际的例子说明了一下内容&#xff0c;附档代码&#xff0c;方便理解和使用 DataFrame.to_json(path_or_bufNone, orientNone, date_formatNone, double_precision10, force_asciiTrue, date_unitms, defau…

考研数据结构大题整合_组一(ZYL组)

考研数据结构大题整合 目录考研数据结构大题整合一、ZYL组ZYL组一ZYL组二ZYL组三ZYL组四ZYL组五ZYL组六ZYL组七ZYL组八一、ZYL组 ZYL组一 1.一棵树有度为i的结点ni 个(i1,2,3,…m), 求叶结点的个数.&#xff08;10分&#xff09; 2、已知带权连通图G(V,E)的邻接表如图所示&am…

rubbitmq 图形界面使用 常用六种通信模式 Simple-Work-fanout-direct-topic-headers

阿里云服务器添加rubbitmq需要开启端口:rabbitmq阿里云服务器开放端口号 Rubbitmq地址: 服务器地址:15672 1.简单模式Simple 一个生产者、一个消费者&#xff0c;不需要设置交换机&#xff08;使用默认的交换机&#xff09; 2.工作队列模式Work Queue 一个生产者、多个消费者&a…

windows操作系统双网卡问题处理办法

windows操作系统双网卡问题处理办法&#xff08;详解&#xff09;一、命令说明二、处理办法1.设置外网网关为默认网关2.查看当前路由表3.删除缺省路由4.添加访问外网的缺省路由5.添加访问内网的路由信息一、命令说明 显示 IP 路由表的信息 route print显示 IP 路由表中以 192…

3.7.3、ARP协议(网际层)

地址解析协议 ARP 1、工作原理 在共享总线型的以太网中 为了简单起见&#xff1a;只有各主机所配置的 IP 地址和其网卡上固化的 MAC 地址 假设主机 B 要给主机 C 发送数据包 主机 B 知道主机 C 的 IP 地址&#xff0c;但是不知道 C 的 MAC 地址 因此&#xff0c;主机 B 的…

使用 Bytebase 管理 Rainbond 上的应用数据库

在应用的发布过程中数据库的结构变更一直是最复杂也是风险最大的环节&#xff0c;而 Bytebase 可以对这一过程进行全生命周期的管理。在 Rainbond 中安装 Bytebase&#xff0c;轻松管理部署在 Rainbond 上的所有数据库。 Bytebase 是什么&#xff1f; Bytebase 是一个开源的数…

linux驱动 usb转串口ch344 改变读取缓冲区大小

开发环境 核心板&#xff1a;IMX6 内核版本&#xff1a;linux4.1.5 问题 通过USB扩展出来的串口接收数据会出现截断现象&#xff0c;而且每次截断的大小都一样。而核心板提供的串口UART就没有这个现象。 核心板自带串口正常的现象&#xff1a; 扩展串口异常现象&#xff1a…

【软件测试】8年资深测试说出来我们的心声......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 执着于手动的功能测…

VLAN划分-----计算机网络

拓扑图 LSW1与LSW2都是三层交换机&#xff0c;现在两台交换机分别连着两台pc。 其中&#xff1a; LSW1的0/0/1端口连着pc1&#xff0c;0/0/2连着pc2&#xff0c;0/0/3端口连着lsw2。 LSW2的0/0/1端口连着pc3&#xff0c;0/0/2连着pc4&#xff0c;0/0/3端口连着lsw1。 不同vlan…

pycharm opencv无法自动补全

我的环境 python 3.6.9opencv-python 4.4.0.42opencv-contrib-python 4.6.66ubuntu 18.04 LTSpycharm 2020.3.2 解决方案 首先找到cv2的site-packagespip3 show opencv-python进入到该目录, 复制so结尾文件至上级目录: cp cv2.cpython-36m-x86_64-linux-gnu.so ../等待pych…

基于粒子群算法和遗传算法优化的高速列车横向悬挂

目录 前言 1.高速列车模型 2.优化算法优化模糊PID流程 3.普通PID、优化算法模糊PID仿真对比 3.1 模糊控制器设计 3.2 仿真结果 3.2.1粒子群优化PID 3.2.2粒子群优化模糊PID 3.2.3遗传算法优化模糊PID 4.总结 前言 高速列车&#xff0c;是指最高行驶速度在200km/h 及以…

二、【React-Router5】路由的基本使用

文章目录1、写在前面的总结2、效果图3、项目结构4、CODE4.1、index.js4.2、App.js4.3、About.jsx4.4、Home.jsx5、Result6、路由组件与一般组件7、Link 升级 NavLink8、封装NavLink8.1、MyNavLink.jsx8.2、修改上面4.2部分代码1、写在前面的总结 明确好界面中的导航区、展示区…

火山引擎数智平台:CDP产品要能与多方联动

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 CDP&#xff08;Customer Data Platform&#xff0c;客户数据平台&#xff09;市场将迎来新一轮的高速增长。 国际数据公司&#xff08;以下简称“IDC”&#xff0…

[附源码]Python计算机毕业设计SSM流浪猫狗救助站(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

ofxTimeMeasurements——OpenFrameworks插件,可以轻松测量C++代码任何部分的执行时间

一、简介 ofxTimeMeasurements是一款用于OpenFrameworks 开源C框架的插件&#xff0c;可以让使用者轻松测量C代码任何部分的执行时间。其优势在于以图形化的方式显示代码执行时间。效果如下&#xff1a; 只是它必须依赖OpenFrameworks&#xff0c;所以如果你不用这个框架&…

《Head First HTML5 javascript》第10章 自定义对象

2022.11.23 第10章 自定义对象 面向对象OOP(Object Oriented Programming) 对象是一个包含相关数据和方法的集合&#xff08;通常由一些变量和函数组成&#xff0c;我们称之为对象里面的属性和方法&#xff09;对象是存储在单个分组中的相关功能的集合。在 JavaScript 中&…

第二证券|多只公募基金损失惨重;储能板块低开高走

今天早盘&#xff0c;A股大幅低开&#xff0c;上证50指数直接跳空跌破2500点&#xff0c;最多跌逾3%&#xff0c;创业板指亦跌破2300点整数关口。 盘面上&#xff0c;酒店餐饮、旅游、储能、ST等板块逆势活跃&#xff0c;酿酒、工程机械、互联网、证券等板块跌幅居前。北上资金…

【LeetCode每日一题:1758. 生成交替二进制字符串的最少操作数~~~模拟+遍历+计数】

题目描述 给你一个仅由字符 ‘0’ 和 ‘1’ 组成的字符串 s 。一步操作中&#xff0c;你可以将任一 ‘0’ 变成 ‘1’ &#xff0c;或者将 ‘1’ 变成 ‘0’ 。 交替字符串 定义为&#xff1a;如果字符串中不存在相邻两个字符相等的情况&#xff0c;那么该字符串就是交替字符…

KVM虚拟机热扩容

创建一个虚拟机用于练习在线扩容 virt-install --name centos8-3 --memory 4096,currentMemory1024 --vcpus 2,maxvcpus8 --disk /var/lib/libvirt/images/centos8-3.qcow2,busvirtio,formatqcow2 --import --os-variant rhel8.0 --graphics vnc --network networkdefault…