final—前后端分离的网站
前后端分离的网站
- 后台使用 express+mysql搭建
- 前台使用vue-cli搭建
安装
cnpm install express express-static cookie-parser body-parser multer cookie-session mysql consolidate --save
目录结构
- libs:自定义的工具库
- libs/db.js: 数据库操作
- static:静态文件 css upload js
- views: ejs模板目录
- route: 路由
- route/admin: 后台路由
- route/api: 前台数据接口
- app.js: 入口文件
设置静态文件目录,用于css、js等静态文件的获取
app.use(express.static(path.join(__dirname, 'static')));
操作后信息提示功能
引入flash模块来实现页面通知功能(即成功与失败的信息显示)
-
什么是flash? 我们所说的flash即 connect-flash模块(https://github.com/jaredhanson/connect-flash),flash是一个在session中用于存储信息的特定区域。信息写入flash,下一次显示完毕后即被清除。典型的应用是结合重定向的功能,确保信息是提供给下一个被渲染的页面
-
安装模块
npm install connect-flash --save
-
在app.js中添加调用此模块
var flash = require('connect-flash'); app.use(flash());//因为flash依赖session,所以他必须放在session后面
-
在res.locals中增加成功失败信息,以便所有模板中可以使用
//用户登录数据分配 app.use(function(req,res,next){ //res.locals 属性是express模板引擎最后分配的数据对象,因为每个模板都要分配user数据,所以直接写入这个对象即可 res.locals.user = req.session.user; res.locals.success = req.flash('success').toString(); res.locals.error = req.flash('error').toString(); next(); });
-
设置flash中成功失败信息 /routes/users.js login
router.post('/login', function (req, res, next) { var user = req.body; var username = user.username; var password = utils.md5(user.password); userModel.findOne({username: username, password: password}, function (err, doc) { if (err) { reg.flash('error','登录失败'); res.redirect('back'); } else { if (doc) {//登录成功后,将数据写入session req.session.user = doc; req.flash('success','登录成功'); res.redirect('/'); } else { req.flash('error','用户名或密码错误'); res.redirect('back'); } } }); });
-
模板中显示
<% if(success){ %> <div class="alert alert-success"><%= success %></div> <% } %> <% if(error){ %> <div class="alert alert-danger"><%= error %></div> <% } %>
权限控制
- 根目录创建 middleware目录,并创建auth.js做权限控制
auth.js内容如下
//登录后才能访问
exports.checkLogin = function(req,res,next){
if(req.session.user){
next();
}else{
req.flash('error','请登录后查看');
res.redirect('/users/login');
}
}
//没登录时才能访问
exports.checkNotLogin = function(req,res,next){
if(req.session.user){
req.flash('error','您已经登录了');
res.redirect('/');
}else{
next();
}
}
-
在各个路由中根据需要引入对应的验证,如/routes/user.js
var auth = require('../middleware/auth');//引入权限验证中间件 router.get('/login',auth.checkNotLogin, function (req, res, next) { res.render('users/login', {title: '登录'}); });
md5 加密
const crypto = require('crypto');
module.exports = {
md5(str){
return crypto.createHash('md5').update(str).digest('hex');
}
}
发表文章时可以上传图片
使用方法查看 Readme.md
- 安装multer中间件,处理图片上传
npm install multer --save
-
修改 /views/article/add.html 的form, 增加 enctype="multipart/form-data".增加 type=file表单
-
修改/model/models.js 中 artilce的骨架,增加 thumb 字段
-
创建目录uploads, /public/uploads
-
修改routes/article.js
//引入multer处理上传图片 var multer = require('multer'); var storage = multer.diskStorage({ //指定上传路径 destination: function (req, file, cb) { //注意路径,位置不能写错,文件夹要存在,不然都会报错 cb(null, 'public/uploads'); }, //指定上传文件名 filename: function (req, file, cb) { cb(null, Date.now()+'.'+file.mimetype.slice(file.mimetype.indexOf('/')+1)); } }) var upload = multer({ storage: storage }); router.post('/add',auth.checkLogin,upload.single('thumb'), function (req, res, next) { var article = req.body; article.user = req.session.user._id; //如果有上传文件,那么写入模型 if(req.file){ var uploadPath = '/uploads/'+req.file.filename; article.thumb = uploadPath; } new Model('articles')(article).save(function(err,doc){ if(err){ req.flash('error','添加文章失败'); res.redirect('back'); }else{ if(doc){ req.flash('success','文章添加成功'); res.redirect('/'); } } }) });
可以将上传封装成中间件,创建 /middleware/multerUpload.js,将如下代码从article.js中移入,并修改如下。
//引入multer处理上传图片
var multer = require('multer');
var storage = multer.diskStorage({
//指定上传路径
destination: function (req, file, cb) {
//注意路径,位置不能写错,文件夹要存在,不然都会报错
cb(null, 'public/uploads');
},
//指定上传文件名
filename: function (req, file, cb) {
cb(null, Date.now()+'.'+file.mimetype.slice(file.mimetype.indexOf('/')+1));
}
})
module.exports = multer({ storage: storage });
在/routes/article.js中,引入。以后需要上传功能的地方,引入如下内容即可
var upload = require('../middleware/multerUpload');//引入封装好的上传中间件