需要引入的模块和框架:JQ,monogoDB,mongoose模块,express模块,nodemailer模块,cors模块,multer模块,body-parser模块。
文件夹(大致)结构如下:
css:主页样式;
get_pic: 临时文件存放;
img:默认头像路径;
js:首页的js;
main:入口server文件(终端执行的);
node_moudules:下载的模块和框架;
savePic:保存静态文件;
set:注册,登录,mongoose初始,邮件发送等模块;
index:主页;
首先,主页的Html,Css,Js文件:
Html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<script src="./jquery.js"></script>
<link rel="stylesheet" href="./css/main.css">
</head>
<body>
<ul id="list">
<li id="regChange">注册</li>
<li id="loginChange">登录</li>
</ul>
<div id="reg">
<input type="file" name="img" id="fileData">
<button id="send">上传头像</button>
<img id="headImg" src="">
<input type="text" placeholder="邮箱" id="user" />
<input type="text" placeholder="密码" id="psd" />
<input type="text" placeholder="验证码" id="sendmail" />
<button id="email">发送验证码</button>
<button id="btn">注册</button>
</div>
<div id="login">
<input type="text" placeholder="用户名" id="loguser" />
<input type="text" placeholder="密码" id="logpsd" />
<button id="logbtn">登录</button>
</div>
<script src="./js/main.js"></script>
</body>
</html>
Css
* {
margin: 0;
padding: 0;
}
div:nth-child(3) {
display: none;
}
input {
display: block;
height: 40px;
width: 200px;
margin: 20px auto;
}
button:not(#email) {
display: block;
height: 30px;
width: 70px;
background: lightcoral;
border: none;
margin: 0 auto;
}
#send{
display: inline-block;
}
#headImg{
display: block;
margin: 0 auto;
}
#email {
display: block;
height: 30px;
width: 100px;
margin: 0 auto;
}
ul {
height: 50px;
width: 200px;
background: lightblue;
margin: 0 auto;
list-style: none;
}
li {
height: 50px;
width: 100px;
float: left;
text-align: center;
line-height: 50px;
}
li:hover {
background: lightgreen;
cursor: pointer;
}
table{
margin: 50px auto 0;
}
td{
text-align: center;
border: 1px solid lightcoral;
}
td img{
vertical-align: top;
}
Js
//主页js文件
//增加监听事件
btn.addEventListener("click", clickHandler); //注册
logbtn.addEventListener("click", clickHandler); //登录
email.addEventListener("click", sendHandler); //发送验证码
regChange.addEventListener("click", changeHandler); //切换登录注册
loginChange.addEventListener("click", changeHandler);
$('#send').on('click', sendHead);
webAdd = 'http://localhost:1024/main';
var table; //新建登陆成功后的表格
function sendHead(e) { //上传文件
var picData = new FormData(); //实例化文件对象
picData.append("sendImg", $("#fileData")[0].files[0]); //将上传文件的添加到文件中
$.ajax({ //ajax方式上传至后台
url: webAdd + '/head',
type: 'POST',
data: picData,
cache: false,
contentType: false,
processData: false,
success: function (data) {
if (!data.error) {
alert('Success');
headImg.src = data.data; //成功时将图片显示
headImg.style.width = '100px';
}
},
error: function () {
alert('Error');
}
});
}
function clickHandler(e) {
if (this.textContent === "注册") {
//若为空时跳出
if (!user.value || !psd.value || !sendmail.value) {
alert("输入不能为空");
return;
}
var AllData = {
email: user.value,
password: psd.value,
mailnum: sendmail.value,
headPic: headImg.src
};
//点击注册时将邮箱号,密码,验证码,头像传送至后台
$.post(webAdd + '/reg', AllData,
function (res) {
//后台返回的对象,若hasUser为真,说明已有用户名,否则注册成功
if (res.hasUser) {
// location.reload();
alert("注册失败");
return;
} else {
alert("注册成功~");
}
//成功后隐藏注册,显示登录
reg.style.display = "none";
login.style.display = "block";
}
);
} else if (this.textContent === "登录") {
// 同注册,不能为空
if (!loguser.value || !logpsd.value) {
alert("不能为空");
return;
}
//点击登录时将邮箱号,密码传送至后台
$.post(webAdd + '/login', {
email: loguser.value,
password: logpsd.value
},
function (res) {
//后台返回的对象,若isUser为真,说明正确,并跳转至欢迎页,否则失败
if (res.isUser) {
alert("登录成功");
login.style.display = "none";
list.style.display = 'none';
createTab(document.body, res.data[0]); //若登陆成功,创建用户表格
} else {
alert("用户名或密码不正确");
return;
}
}
);
}
}
function sendHandler(e) {
// 点击获取验证码后将验证码发送到后端进行比对
$.post(webAdd + '/sendmail', {
email: user.value
});
}
function changeHandler(e) {
// 点击上方的注册登录切换
if (e.target.textContent === "注册") {
reg.style.display = "block";
login.style.display = "none";
} else {
reg.style.display = "none";
login.style.display = "block";
}
}
function createTab(parent, data) {//新建表格函数
if (table) {
table.remove();//若表格存在,删除表格
}
table = document.createElement('table');
for (var str in data) {//根据遍历数据创建表格
var tr = document.createElement('tr');
var td = document.createElement('td');
if (str === 'head') {
td.textContent = '头像:'
var img = new Image();
img.src = data[str];
td.appendChild(img);
} else {
td.textContent = str + ':' + data[str];
}
tr.appendChild(td);
table.appendChild(tr);
}
parent.appendChild(table);
}
之后是其他模块:
mongoose的Schema:
const mongoose = require('./main'); //引入main模块
const Schema = mongoose.Schema; //新建schema对象
let userSchema = new Schema({
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
head: {
type: String,
required: true
}
}); //实例化对象
let userModel = mongoose.model('allUser', userSchema); //新建数据库
module.exports = userModel; //抛出模块
mongoose数据库连接:
const mongoose = require('mongoose');//引入mongoose
mongoose.connect('mongodb://localhost:27017/UserList', {
useNewUrlParser: true
});//连接数据库
let db = mongoose.connection;
db.on("error", function (error) {
console.log("错误:" + error);
});
db.on("open", function () {
console.log("连接成功");
});
db.on('disconnected', function () {
console.log('连接断开');
});
module.exports = mongoose;//抛出mongose对象
电子邮件验证模块:
const nodemailer = require("nodemailer");
let obj = {
transporter: nodemailer.createTransport({
service: "qq", // 运营商 qq邮箱 网易//
port: 465,
secure: true,
auth: {
user: "********@qq.com", //发送方的邮箱
pass: "**********" // pop3 授权码
}
}),
send: function(mail, content,callback) {
mailOptions = {
from: '"Hello World~" <**********@qq.com>',
to: mail,
subject: content,
text: content,
html: "<h1>" + content + "</h1>"
};
this.transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
console.log("Message sent: %s", info.messageId);
callback();
});
}
};
module.exports = obj;
头像上传:
const express = require('express');
const router = express.Router(); //新建路由
var multer = require('multer'); //文件获取储存的第三方模块
const fs = require('fs');
const path = require('path');
var upload = multer({
dest: '../get_pic/'
}); //将头像临时文件夹
router.post('/head', upload.single('sendImg'), (req, res) => { //路由地址
//读取传输的头像
fs.readFile(req.file.path, (err, data) => {
if (err) {
throw ('Load_Err');
}
let type = req.file.mimetype.split('/')[1]; //获取文件类型名
let name = new Date().getTime() + parseInt(Math.random() * Math.random() * 1000000); //使用时间戳和随机数生成随机名,并且连成完整的文件名
//保存文件至savePic文件夹
let filename = name + '.' + type;
fs.writeFile(path.join(__dirname, '../savePic/' + filename), data, (err) => {
// 返回信息给前端
if (err) {
res.send({
err: 1,
msg: '上传失败'
});
//保存图片后删除临时文件
fs.unlink(req.file.path, (err) => {
if (err) {
console.log('删除失败');
}
});
return;
}
res.send({
err: 0,
msg: '上传成功',
data: 'savePic/' + filename
});
//保存图片后删除临时文件
fs.unlink(req.file.path, (err) => {
if (err) {
console.log('删除失败');
}
});
});
});
});
module.exports = router;
注册:
const express = require('express');
const router = express.Router(); //新建路由
const Model = require('./mod'); //传入数据库对象
const fs = require('fs');
const path = require('path');
const sendMail = require('./send'); //传入邮件发送的模块对象
var count = ""; //新建一个空字符存放验证码,可供全局调用
//用post方法传输数据
router.post('/reg', (req, res) => {
//保存前端传来的数据
var mail = req.body.email;
var psd = req.body.password;
var mailnum = req.body.mailnum;
var headUrl = req.body.headPic;
//使用Model对象连接数据库
Model.find({ // 查询邮箱
'email': mail
}).then((data) => {
//若返回的邮箱找到或验证码不对,则抛错
if (data.length >= 1 || mailnum !== count) {
res.send({
hasUser: true
});
return;
}
res.send({
hasUser: false
});
//若前端传了图片,则保存上传的图片,否则使用默认图片
if (headUrl==='http://localhost:1024/') {
headUrl = 'http://localhost:1024/img/cat.gif';
}
Model.insertMany({ //反之将邮箱插入到数据库
'email': mail,
'password': psd,
'head':headUrl
}).then((result) => {
console.log(result);
})
}).catch((err) => {
console.log(err);
});
});
//邮箱验证接口
router.post("/sendmail", (req, res) => {
count = ""; //初始化验证码容器
var mail = req.body.email; //获取前端传来的邮箱号
for (let i = 0; i < 4; i++) {
count += Math.floor(Math.random() * 10); //生成4个随机数
}
var callback = () => {
console.log("发送成功");
};
sendMail.send(mail, count, callback); //调用邮件发送模块
res.send('send');
});
module.exports = router;
登录:
const express = require('express');
const router = express.Router();//新建路由
const Model = require('./mod');//获取数据库对象
router.post('/login', (req, res) => {//路由地址
//保存前端传来的数据
var mail = req.body.email;
var psd = req.body.password;
Model.find({
// 查询是否有该用户,若用户邮箱和密码符合,则抛出正确,否则抛出错误对象
'email': mail,
'password': psd
}).then((data) => {
if (data.length >= 1) {
res.send({
isUser: true,
data:data
});
} else {
res.send({
isUser: false
});
}
}).catch((err) => {
console.log(err);
});
});
module.exports = router;
最后server.js
const express = require('express');
const app = express();
const cors = require("cors"); //引入cors模块(解决跨域问题)
const path = require('path');
var bodyParser = require('body-parser');
app.use(cors());
// 下面的类似于http请求的头文件(另一篇文章有写到http请求,也是注册登录)
app.all("*", function (req, res, next) {
//设置允许跨域的域名,*代表允许任意域名跨域
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "content-type"); //允许的header类型
res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS"); //跨域允许的请求方式
next(); //是否继续向下执行
});
//创建静态文件目录
app.use(express.static(path.join(__dirname, '../../user_info')));
//解决post传输的数据格式问题
app.use(bodyParser.urlencoded({
extended: false
}))
app.use(bodyParser.json())
// 路由选择导入注册
const reg = require('../set/reg.js');
app.use('/main', reg);
// 路由选择导入登录
const login = require('../set/login.js');
app.use('/main', login);
// 路由选择上传图片模块
const head = require('../set/sendhead.js');
app.use('/main', head);
// 开启监听
app.listen(1024, () => {
console.log('Server Start~');
});