小白误入(需要一定的vue基础 )使用node建立服务器——vue前端登录注册页面连接到数据库

news/2025/1/23 17:36:18/

第一步:首先明确需要编写的文件:

vue前端的登录页面:login.vue

vue前端的注册页面:sign.vue

vue前端的路由页面,负责vue框架内页面的跳转:index.js

node后端连接数据,建立请求文件 :app.js

node后端连接数据库文件:mysql.js

一定要确保对应文件的连接位置。

代码架构:

主目录src目录view目录login.vuesign.vuerouter目录index.jsapi目录app.jsmysql.js

第二步书写对应的文件 

login.vue

<template><div class="login-container"><div class="layer"><div class="some-space"><div class="form"><h2>大数据可视化平台</h2><div class="item"><i class="iconfont icon-user"></i><label for="username">登录</label><input autocomplete="off"type="text"class="input"v-model="form.username"placeholder="请输入用户名" /></div><div class="item"><i class="iconfont icon-password"></i><label for="password">密码</label><input autocomplete="off"type="password"class="input"v-model="form.password"maxlength="20"@keyup.enter="login"placeholder="请输入密码" /></div><!-- 添加验证码相关的输入框和显示区域 --><div class="item"><i class="iconfont icon-password"></i><label for="verificationCode">验证码</label><input autocomplete="off"type="text"class="input"v-model="form.verificationCode"placeholder="请输入验证码" /><span class="verification-code-img" @click="refreshVerificationCode">{{ verificationCodeText }}</span></div><button class="loginBtn":disabled="isLoginAble"@click.stop="login">立即登录</button><button class="registerBtn" @click="goToRegister">注册用户</button><div class="tip">默认用户名:admin ,默认密码:123456</div></div></div></div><vue-particles color="#6495ED":particleOpacity="0.7":particlesNumber="80"shapeType="circle":particleSize="4"linesColor="#6495ED":linesWidth="1":lineLinked="true":lineOpacity="0.6":linesDistance="150":moveSpeed="3":hoverEffect="true"hoverMode="grab":clickEffect="true"clickMode="push"></vue-particles><bgAnimation /></div>
</template><script>
import { userLogin } from '../api/user';
import router from '../router';
export default {name: 'Home',data() {return {form: {username: '',password: '',verificationCode: '' // 添加验证码字段},verificationCodeText: '1234' // 模拟验证码文本,实际应用中应从后端获取并更新};},methods: {login() {// 简单验证验证码是否正确(这里只是简单示例,实际要对接后端验证逻辑)if (this.form.verificationCode === this.verificationCodeText) {userLogin(this.form).then((res) => {alert(res.data.msg);router.push({path: '/traffic'});}).catch((err) => {alert(err.response.data.msg);});} else {alert('验证码错误,请重新输入');}},goToRegister() {console.log('准备跳转');router.push({path: '/about'});console.log('已执行跳转操作');},refreshVerificationCode() {// 模拟刷新验证码,这里简单修改文本,实际应从后端获取新的验证码this.verificationCodeText = Math.floor(Math.random() * 10000).toString().padStart(4, '0');}}
};
</script><style lang="scss" scoped>
.login-container {
.layer {position: absolute;height: 100%;width: 100%;background-image: url('../assets/bg-4.jpg');background-size: cover;background-repeat: no-repeat;}#particles-js {position: absolute;top: 0;left: 0;width: 100%;height: 100%;z-index: 1000;}
.some-space {color: white;font-weight: 100;letter-spacing: 2px;position: absolute;top: 50%;left: 50%;z-index: 1001;-webkit-transform: translate3d(-50%, -50%, 0);transform: translate3d(-50%, -50%, 0);-ms-animation: cloud 2s 3s ease-in infinite alternate;-moz-animation: cloud 2s 3s ease-in infinite alternate;-webkit-animation: cloud 2s 3s ease-in infinite alternate;-o-animation: cloud 2s 3s ease-in infinite alternate;animation: cloud 2s 3s ease-in infinite alternate;.form {width: 460px;height: auto;background: rgba(36, 36, 85, 0.5);margin: 0 auto;padding: 35px 30px 25px;box-shadow: 0 0 25px rgba(255, 255, 255, 0.5);border-radius: 10px;.item {display: flex;align-items: center;margin-bottom: 25px;border-bottom: 1px solid #d3d7f7;i {color: #d3d7f7;margin-right: 10px;}}h2 {text-align: center;font-weight: normal;font-size: 26px;color: #d3d7f7;padding-bottom: 35px;}.input {font-size: 16px;line-height: 30px;width: 100%;color: #d3d7f7;outline: none;border: none;background-color: rgba(0, 0, 0, 0);padding: 10px 0;}.loginBtn {width: 100%;padding: 12px 0;border: 1px solid #d3d7f7;font-size: 16px;color: #d3d7f7;cursor: pointer;background: transparent;border-radius: 4px;margin-top: 10px;&:hover {color: #fff;background: #0090ff;border-color: #0090ff;}}.registerBtn {width: 100%;padding: 12px 0;border: 1px solid #d3d7f7;font-size: 16px;color: #d3d7f7;cursor: pointer;background: transparent;border-radius: 4px;margin-top: 10px;&:hover {color: #fff;background: #0090ff;border-color: #0090ff;}}.tip {font-size: 12px;padding-top: 20px;}// 验证码显示区域样式.verification-code-img {margin-left: 10px;cursor: pointer;color: #d3d7f7;}}}
}input::-webkit-input-placeholder {color: #d3d7f7;
}
input::-moz-placeholder {/* Mozilla Firefox 19+ */color: #d3d7f7;
}
input:-moz-placeholder {/* Mozilla Firefox 4 to 18 */color: #d3d7f7;
}
input:-ms-input-placeholder {/* Internet Explorer 10-11 */color: #d3d7f7;
}@-ms-keyframes cloud {0% {-ms-transform: translate(-50%, -50%);}40% {opacity: 1;}60% {opacity: 1;}100% {-ms-transform: translate(-50%, -40%);}
}
@-moz-keyframes cloud {0% {-moz-transform: translate(-50%, -50%);}40% {opacity: 1;}60% {opacity: 1;}100% {-moz-transform: translate(-50%, -40%);}
}
@-o-keyframes cloud {0% {-o-transform: translate(-50%, -50%);}40% {opacity: 1;}60% {opacity: 1;}100% {-o-transform: translate(-50%, -40%);}
}
@-webkit-keyframes cloud {0% {-webkit-transform: translate(-50%, -50%);}40% {opacity: 1;}60% {opacity: 1;}100% {-webkit-transform: translate(-50%, -40%);}
}
@keyframes cloud {0% {transform: translate(-50%, -50%);}40% {opacity: 1;}60% {opacity: 1;}100% {transform: translate(-50%, -40%);}
}
</style>

sign.vue 

<template><div class="login-container"><div class="layer"></div><div id="particles-js"></div><div class="some-space"><div class="form"><h2>用户登录/注册</h2><div class="item"><i class="icon-user"></i><input type="text" v-model="form.username" placeholder="请输入用户名" class="input" /></div><div class="item"><i class="icon-lock"></i><input type="password" v-model="form.password" placeholder="请输入密码" class="input" /></div><div class="item"><i class="icon-lock"></i><input type="password" v-model="form.confirmPassword" placeholder="请再次输入密码" class="input" /></div><button @click="register" class="loginBtn">注册</button><button @click="getUser" class="loginBtn">登录</button><div class="tip">温馨提示:请按照要求填写信息哦~</div></div></div></div>
</template><script>
import { getUserInfo, register } from '../api/user';
export default {data() {return {form: {username: '',password: '',confirmPassword: ''},userInfo: {}};},methods: {getUser() {getUserInfo(this.form.username).then(res => {this.userInfo = res.data.data[0];}).catch((err) => {console.log(err);});},register() {if (this.form.username === '' ||this.form.password === '' ||this.form.confirmPassword === '') {alert('数据不能为空');return;}// 验证两次输入的密码是否一致if (this.form.password!== this.form.confirmPassword) {alert('两次输入的密码不一致,请重新输入');return;}register({username: this.form.username,password: this.form.password}).then((res) => {alert(res.data.msg);this.$router.push('/');}).catch((err) => {alert(err.response.data.msg);});}}
};
</script><style lang="scss" scoped>
.login-container {.layer {position: absolute;height: 100%;width: 100%;background-image: url('../assets/bg-4.jpg');background-size: cover;background-repeat: no-repeat;}#particles-js {position: absolute;top: 0;left: 0;width: 100%;height: 100%;z-index: 1000;}.some-space {color: white;font-weight: 100;letter-spacing: 2px;position: absolute;top: 50%;left: 50%;z-index: 1001;-webkit-transform: translate3d(-50%, -50%, 0);transform: translate3d(-50%, -50%, 0);-ms-animation: cloud 2s 3s ease-in infinite alternate;-moz-animation: cloud 2s 3s ease-in infinite alternate;-webkit-animation: cloud 2s 3s ease-in infinite alternate;-o-animation: cloud 2s 3s ease-in infinite alternate;animation: cloud 2s 3s ease-in infinite alternate;.form {width: 460px;height: auto;background: rgba(36, 36, 85, 0.5);margin: 0 auto;padding: 35px 30px 25px;box-shadow: 0 0 25px rgba(255, 255, 255, 0.5);border-radius: 10px;.item {display: flex;align-items: center;margin-bottom: 25px;border-bottom: 1px solid #d3d7f7;i {color: #d3d7f7;margin-right: 10px;}}h2 {text-align: center;font-weight: normal;font-size: 26px;color: #d3d7f7;padding-bottom: 35px;}.input {font-size: 16px;line-height: 30px;width: 100%;color: #d3d7f7;outline: none;border: none;background-color: rgba(0, 0, 0, 0);padding: 10px 0;}.loginBtn {width: 100%;padding: 12px 0;border: 1px solid #d3d7f7;font-size: 16px;color: #d3d7f7;cursor: pointer;background: transparent;border-radius: 4px;margin-top: 10px;&:hover {color: #fff;background: #0090ff;border-color: #0090ff;}}// 注册按钮样式,与登录按钮样式保持一致.registerBtn {width: 100%;padding: 12px 0;border: 1px solid #d3d7f7;font-size: 16px;color: #d3d7f7;cursor: pointer;background: transparent;border-radius: 4px;margin-top: 10px;&:hover {color: #fff;background: #0090ff;border-color: #0090ff;}}.tip {font-size: 12px;padding-top: 20px;}}}
}input::-webkit-input-placeholder {color: #d3d7f7;
}
input::-moz-placeholder {/* Mozilla Firefox 19+ */color: #d3d7f7;
}
input:-moz-placeholder {/* Mozilla Firefox 4 to 18 */color: #d3d7f7;
}
input:-ms-input-placeholder {/* Internet Explorer 10-11 */color: #d3d7f7;
}@-ms-keyframes cloud {0% {-ms-transform: translate(-50%, -50%);}40% {opacity: 1;}60% {opacity: 1;}100% {-ms-transform: translate(-50%, -40%);}
}
@-moz-keyframes cloud {0% {-moz-transform: translate(-50%, -50%);}40% {opacity: 1;}60% {opacity: 1;}100% {-moz-transform: translate(-50%, -40%);}
}
@-o-keyframes cloud {0% {-o-transform: translate(-50%, -50%);}40% {opacity: 1;}60% {opacity: 1;}100% {-o-transform: translate(-50%, -40%);}
}
@-webkit-keyframes cloud {0% {-webkit-transform: translate(-50%, -50%);}40% {opacity: 1;}60% {opacity: 1;}100% {-webkit-transform: translate(-50%, -40%);}
}
@keyframes cloud {0% {transform: translate(-50%, -50%);}40% {opacity: 1;}60% {opacity: 1;}100% {transform: translate(-50%, -40%);}
}
</style> 

 index.js

import Vue from 'vue'
import VueRouter from 'vue-router'Vue.use(VueRouter);const routes = [{path: '/',name: 'Home',component: () => import('@/views/Home.vue'),meta: {title: '登录界面'}},{path: '/login',redirect: '/'},{path: '/about',name: 'About',component: () => import('@/views/About.vue'),}
];const router = new VueRouter({routes,
});export default router;

app.js

const express = require('express');
const bodyParser = require('body-parser');
const multiparty = require('connect-multiparty');
const fs = require('fs');
let { conMysql } = require('./mysql');// 创建统一的返回报文对象
class Response {constructor(isSucceed, msg, code, data) {this.isSucceed = isSucceed;this.msg = msg;this.code = code;this.data = data;}
}// 创建
const app = express();// 处理 x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));// 处理 application/json
app.use(bodyParser.json());// 处理 multipart/form-data
app.use(multiparty());// 设置跨域访问
const cors = require('cors');
app.use(cors());// 测试接口能否正常调用
app.get('/info', (req, res) => {res.send('Hello shaoyahu!');
});// 测试数据库连接是否正常
app.get('/getUser', (req, res) => {let sql = 'select * from userinfo';conMysql(sql).then(result => {res.send(result);});
});// 登录
app.post('/login', (req, res) => {let sql = `select * from userinfo where username = '${req.body.username}'`;conMysql(sql).then(result => {if (result[0]?.password === req.body.password) {let response = new Response(true, '登录成功', 200, result);res.send(response);} else {let response = new Response(false, '用户名或密码错误', 400);res.status(400).send(response);}}).catch(err => {res.status(500).send('数据库连接出错!');});
});// 修改密码
app.post('/updatePassword', (req, res) => {let sql = `update userinfo set password = '${req.body.newPassword}' where username = '${req.body.username}'`;conMysql(sql).then(result => {if (result.affectedRows == 1) {let response = new Response(true, '修改成功', 200, result);res.send(response);} else {let response = new Response(false, '修改失败,请稍后重试', 400);res.status(400).send(response);}}).catch(err => {res.status(500).send('数据库连接出错!');});
});// 用户注册接口
app.post('/register', (req, res) => {const { username, password } = req.body;// 简单的合法性校验,用户名和密码都不能为空if (!username ||!password) {let response = new Response(false, '用户名和密码不能为空', 400);res.status(400).send(response);return;}// 检查用户名是否已存在let checkSql = `select * from userinfo where username = '${username}'`;conMysql(checkSql).then(existResult => {if (existResult.length > 0) {let response = new Response(false, '用户名已存在,请更换用户名', 400);res.status(400).send(response);return;}// 插入新用户信息到数据库let insertSql = `insert into userinfo (username, password) values ('${username}', '${password}')`;conMysql(insertSql).then(insertResult => {if (insertResult.affectedRows === 1) {let response = new Response(true, '注册成功', 200, insertResult);res.send(response);} else {let response = new Response(false, '注册失败,请稍后重试', 400);res.status(400).send(response);}}).catch(err => {res.status(500).send('数据库连接出错!');});}).catch(err => {res.status(500).send('数据库连接出错!');});
});// 获取当前用户信息
app.get('/getUserInfo', (req, res) => {let sql = `select * from userinfo where username = '${req.query.username}'`;conMysql(sql).then(result => {let response = new Response(true, '获取成功', 200, result);res.send(response);}).catch(err => {res.status(500).send('数据库连接出错!');});
});// 生成文件的接口
app.get('/generateFile', async (req, res) => {try {let sql = 'select * from userinfo';const result = await conMysql(sql);const dataString = JSON.stringify(result, null, 2);fs.writeFileSync('userinfo.json', dataString);let response = new Response(true, '文件生成成功', 200, null);res.send(response);} catch (err) {res.status(500).send('数据库连接出错或文件生成失败!');}
});// 启动
app.listen(3000, () => {console.log('express server running at http://127.0.0.1:' + 3000);
});

 mysql.js

let mysql = require('mysql')
const db_config = {host: 'localhost',user: 'root',password: 'mysql',port: '3306',database: 'db1'
}function conMysql(sql) {let connect = mysql.createConnection(db_config)// 开始连接数据库connect.connect(function (err) {if (err) {console.log(`mysql连接失败: ${err}!`)} else {console.log('mysql连接成功!')}})return new Promise((resolve, reject) => {connect.query(sql, (err, result) => {if (err) {reject(err)} else {let res = JSON.parse(JSON.stringify(result))closeMysql(connect)resolve(res)}})})
}
// 查询成功后关闭mysql
function closeMysql(connect) {connect.end((err) => {if (err) {console.log(`mysql关闭失败:${err}!`)} else {console.log('mysql关闭成功!')}})
}
exports.conMysql = conMysql

要注意对应版本和环境

记得添加对应下载环境包

{"name": "express","version": "1.0.0","main": "app.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"author": "","license": "ISC","dependencies": {"body-parser": "^1.20.0","connect-multiparty": "^2.2.0","cors": "^2.8.5","express": "^4.18.1","mysql": "^2.18.1"},"devDependencies": {"babel-preset-env": "^1.7.0"},"description": ""
}

第三部进pnpm命令安装和运行——效果展示 

     

 

 

 

 


http://www.ppmy.cn/news/1565541.html

相关文章

线性代数概述

矩阵与线性代数的关系 矩阵是线性代数的研究对象之一&#xff1a; 矩阵&#xff08;Matrix&#xff09;是一个按照长方阵列排列的复数或实数集合&#xff0c;是线性代数中的核心概念之一。矩阵的定义和性质构成了线性代数中矩阵理论的基础&#xff0c;而矩阵运算则简洁地表示和…

Erlang语言的网络编程

Erlang语言的网络编程探索 引言 在现代网络应用开发中&#xff0c;高并发、可扩展性以及系统容错能力是至关重要的。这些需求促使开发者寻求一种能够有效应对这些挑战的编程语言。Erlang作为一种功能强大的编程语言&#xff0c;其在电信行业的成功应用为其在网络编程领域的使…

vue3中使用render函数以及组合式写法实现一个配置化生成的表单组件

表单组件代码 import { h, computed, ref } from vue import type { PropType } from vue import { Form, Input, Radio, FormItem, Checkbox } from arco-design/web-vue//去除定义类型中 指定的key type RestrictKey<T, K extends keyof any> {[P in keyof T]: P ext…

零售业革命:改变行业的顶级物联网用例

mpro5 产品负责人Ruby Whipp表示&#xff0c;技术进步持续重塑零售业&#xff0c;其中物联网&#xff08;IoT&#xff09;正引领这一变革潮流。 研究表明&#xff0c;零售商们正在采用物联网解决方案&#xff0c;以提升运营效率并改善顾客体验。这些技术能够监控运营的各个方面…

Flink Gauss CDC:深度剖析存量与增量同步的创新设计

目录 设计思路 1.为什么不直接用FlinkCDC要重写Flink Gauss CDC 2.存量同步的逻辑是什么 2.1、单主键的切片策略是什么 2.2、​​​​​复合主键作切片,怎么保证扫描到所有的数据 3、增量同步的逻辑是什么 4、存量同步结束之后如何无缝衔接增量同步 5、下游数据如何落…

电梯系统的UML文档08

5.1.2 用例 2 –处理电梯呼叫 这个用例有二个场景:乘客进入电梯和按电梯呼叫按钮。乘客可能想要去楼上或楼下&#xff0c;与电梯当前的移动方向有关。当电梯经过乘客或当在附近的楼层徘徊时&#xff0c;乘客可以到达目的层。这二个场景可以共享同一个用例。 场景 2.1 电梯呼叫…

《探秘鸿蒙Next:非结构化数据处理与模型轻量化的完美适配》

在鸿蒙Next的人工智能应用场景中&#xff0c;处理非结构化数据并使其适配模型轻量化需求是一项关键且具有挑战性的任务。以下是一些有效的方法和策略。 数据预处理 数据清洗&#xff1a;非结构化数据中往往存在噪声、重复和错误数据。对于文本数据&#xff0c;要去除乱码、特殊…

新年好(Dijkstra+dfs/全排列)

1135. 新年好 - AcWing题库 思路&#xff1a; 1.先预处理出1,a,b,c,d,e到其他点的单源最短路&#xff0c;也就是进行6次Dijkstra 2.计算以1为起点的这6个数的全排列&#xff0c;哪种排列方式所得距离最小&#xff0c;也可以使用dfs 1.Dijkstradfs #define int long longusing …