需要引入的模塊和框架: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~');
});