let express = require("express");
let path = require('path');
let bodyParser = require("body-parser");
let cors = require("cors");
let session = require("express-session");
var multer = require('multer');
var upload = multer({ dest: path.resolve(__dirname, 'public') });
let MongoStore = require('connect-mongo')(session);
let { dbUrl } = require('./settings');
let { md5 } = require('./utils');
let { UserModel, SliderModel, LessonModel } = require('./db');
let app = express();
app.use(express.static(path.resolve(__dirname, 'public')));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(
cors({
origin: ["http://localhost:8080", "http://localhost:8081"],
credentials: true,
allowedHeaders: "Content-Type,x-requested-with",
methods: "GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS"
})
);
app.use((req, res, next) => {
if (req.method === 'OPTIONS') {
res.sendStatus(200);
} else {
next();
}
});
app.use(
session({
secret: "zhufeng",
resave: false,
saveUninitialized: true,
store: new MongoStore({
url: dbUrl,
mongoOptions: {
useNewUrlParser: true,
useUnifiedTopology: true
}
})
})
);
app.post('/uploadAvatar', upload.single('avatar'), async function (req, res, next) {
let { userId } = req.body;
let avatar = `${req.protocol}://${req.headers.host}/${req.file.filename}`;
await UserModel.updateOne({ _id: userId }, { avatar });
setTimeout(() => {
res.send({ code: 0, data: avatar });
}, 3000);
})
app.post('/register', async (req, res) => {
let user = req.body;//username password email phone avatar
user.avatar = `https://secure.gravatar.com/avatar/${md5(user.email)}?s=48`;
user = await UserModel.create(user);
req.session.user = user;
res.json({ code: 0, user });
});
app.post('/login', async (req, res) => {
let user = await UserModel.findOne(req.body);
if (user) {
req.session.user = user;
res.json({ code: 0, data: user });
} else {
res.json({ code: 1, error: '用户未登录' });
}
});
app.get("/validate", (req, res) => {
let user = req.session.user;
if (user) {
res.json({ code: 0, data: user });
} else {
res.json({ code: 1, error: '当前用户未登录' });
}
});
app.get("/logout", (req, res) => {
req.session.user = null;
res.json({ code: 0, data: "退出登录成功" });
});
app.get('/sliders', async function (req, res) {
let sliders = await SliderModel.find();
res.json({ code: 0, data: sliders });
});
app.get('/getlesson', async function (req, res) {
let { id } = req.query;
let lessons = await LessonModel.findById(id);
res.json({ code: 0, data: lessons });
});
// http://getLessons/vue?offset=0&limit=5
app.get('/getLessons/:category', async function (req, res) {
let category = req.params.category;
let { offset, limit } = req.query;
offset = isNaN(offset) ? 0 : parseInt(offset);//偏移量
limit = isNaN(limit) ? 5 : parseInt(limit); //每页条数
let query = {};
if (category && category != 'all')
query.category = category;
let total = await LessonModel.count(query);
let list = await LessonModel.find(query).sort({ order: 1 }).skip(offset).limit(limit);
setTimeout(function () {
console.log({ list, hasMore: total > offset + limit });
res.json({ code: 0, data: { list, hasMore: total > offset + limit } });
}, 1000);
});
app.listen(8000);
server\settings.js
module.exports = {
cookieSecret: 'zhufeng',// 用于 Cookie 加密与数据库无关
dbUrl: "mongodb://127.0.0.1:27017/zhufengketang"
}
server\utils.js
function md5(val) {
return require('crypto').createHash('md5').update(val).digest('hex');
}
module.exports = {
md5
}
server\db\index.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ObjectId = Schema.Types.ObjectId;
const { dbUrl } = require('../settings');
const conn = mongoose.createConnection(dbUrl, { useNewUrlParser: true, useUnifiedTopology: true });
const UserModel = conn.model('User', new Schema({
username: { type: String, required: true },//用户名
password: { type: String, required: true },//密码
email: { type: String, required: true },//邮箱
phone: { type: String, required: true },//手机号
avatar: { type: String, required: true }//头像
}));
const SliderModel = conn.model('Slider', new Schema({
url: String
}));
const LessonModel = conn.model('Lesson', new Schema({
order: Number,//顺序
title: String,//标题
video: String,//视频
poster: String, //海报
url: String,//url地址
price: String,//价格
category: String,//分类
}));
module.exports = {
UserModel,
SliderModel,
LessonModel
}
; (async function () {
let sliderList = await SliderModel.find();
if (sliderList.length == 0) {
SliderModel.create([
{ url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/reactnative.png' },
{ url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/react.png' },
{ url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/vue.png' },
{ url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/wechat.png' },
{ url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/architect.jpg' }
]);
}
let lessonList = await LessonModel.find();
if (lessonList.length == 0) {
LessonModel.create([
{
order: 1,
title: '1.React全栈架构',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/react/img/react.jpg",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/react.png',
price: '¥100.00元',
category: 'react'
},
{
order: 2,
title: '2.React全栈架构',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/react/img/react.jpg",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/react.png',
price: '¥200.00元',
category: 'react'
},
{
order: 3,
title: '3.React全栈架构',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/react/img/react.jpg",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/react.png',
price: '¥300.00元',
category: 'react'
},
{
order: 4,
title: '4.React全栈架构',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/react/img/react.jpg",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/react.png',
price: '¥400.00元',
category: 'react'
},
{
order: 5,
title: '5.React全栈架构',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/react/img/react.jpg",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/react.png',
price: '¥500.00元',
category: 'react'
},
{
order: 6,
title: '6.Vue从入门到项目实战',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/vue/img/vue.png",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/vue.png',
price: '¥100.00元',
category: 'vue'
},
{
order: 7,
title: '7.Vue从入门到项目实战',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/vue/img/vue.png",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/vue.png',
price: '¥200.00元',
category: 'vue'
},
{
order: 8,
title: '8.Vue从入门到项目实战',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/vue/img/vue.png",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/vue.png',
price: '¥300.00元',
category: 'vue'
},
{
order: 9,
title: '9.Vue从入门到项目实战',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/vue/img/vue.png",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/vue.png',
price: '¥400.00元',
category: 'vue'
},
{
order: 10,
title: '10.Vue从入门到项目实战',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/vue/img/vue.png",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/vue.png',
price: '¥500.00元',
category: 'vue'
},
{
order: 11,
title: '11.React全栈架构',
"video": "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/react/img/react.jpg",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/react.png',
price: '¥600.00元',
category: 'react'
},
{
order: 12,
title: '12.React全栈架构',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/react/img/react.jpg",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/react.png',
price: '¥700.00元',
category: 'react'
},
{
order: 13,
title: '13.React全栈架构',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/react/img/react.jpg",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/react.png',
price: '¥800.00元',
category: 'react'
},
{
order: 14,
title: '14.React全栈架构',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/react/img/react.jpg",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/react.png',
price: '¥900.00元',
category: 'react'
},
{
order: 15,
title: '15.React全栈架构',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/react/img/react.jpg",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/react.png',
price: '¥1000.00元',
category: 'react'
},
{
order: 16,
title: '16.Vue从入门到项目实战',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/vue/img/vue.png",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/vue.png',
price: '¥600.00元',
category: 'vue'
},
{
order: 17,
title: '17.Vue从入门到项目实战',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/vue/img/vue.png",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/vue.png',
price: '¥700.00元',
category: 'vue'
},
{
order: 18,
title: '18.Vue从入门到项目实战',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/vue/img/vue.png",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/vue.png',
price: '¥800.00元',
category: 'vue'
},
{
order: 19,
title: '19.Vue从入门到项目实战',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/vue/img/vue.png",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/vue.png',
price: '¥900.00元',
category: 'vue'
},
{
order: 20,
title: '20.Vue从入门到项目实战',
video: "http://upload-markdown-images.oss-cn-beijing.aliyuncs.com/gee2.mp4",
poster: "http://www.zhufengpeixun.cn/vue/img/vue.png",
url: 'http://www.zhufengpeixun.cn/themes/jianmo2/images/vue.png',
price: '¥1000.00元',
category: 'vue'
}
]);
}
})();