(七)我的项目性能的实现之文章治理
BLOG -- 源码目录 └── model -- 数据库操作 └──article.js 文章规定 ├── public -- 动态资源 └── route -- 路由 └── admin --博客治理 ├── article.js --文章列表页 ├── article-add.js --新增文章 ├── userPage.js --用户列表页 ├── user-edit.js --用户治理页 └── article-edit.js --文章治理页 └── admin.js --博客治理页面路由 └── views -- 模板 └── admin --博客治理页面art模板 └── common --公共模板 └── aside.art --侧边栏 ├── article.art --文章列表模板 └── article-edit.art --文章治理模板 └── app.js -- 创立网站服务
admin.js
- 增加文章列表页面和文章编辑页面的路由
- 增加实现文章增加性能的路由
// 文章列表页面路由admin.get('/article', require('./admin/article'));// 文章编辑页面路由admin.get('/article-edit', require('./admin/article-edit'));// 实现文章增加性能的路由admin.post('/article-add', require('./admin/article-add'))
article.js
- 渲染article.art的模板文件
- app.locals.currentlink标识示意以后拜访的是文章列表治理页面
- files中存储了cover就是所有上传的门路
- 将文章汇合构造函数导入,查问所有文章数据
- 进行多汇合联结查问,populate()办法,查问到了作者的全副办法作为对象,所以能够通过.username来批改作者的格局为登录用户而不是id值
// 将文章汇合的构造函数导入到以后文件中const { Article } = require('../../model/article');module.exports = async (req, res) => { // 标识 标识以后拜访的是文章列表页面 req.app.locals.currentLink = 'article'; // 查问所有文章数据 let articles = await Article.find().populate('author'); // res.send(articles); // 渲染文章列表页面模板 res.render('admin/article.art', { articles: articles });}
article-edit.js
- 渲染article-edit.art的模板文件
- app.locals.currentlink标识示意以后拜访的是文章治理页面
module.exports = (req, res) => { // 标识 标识以后拜访的是文章治理页面 req.app.locals.currentLink = 'article'; res.render('admin/article-edit.art');}
aside.art
- 为用户治理和文章治理增加对应的用户跳转herf
- 对于item前面是否增加active进行判断,判断条件是是否是选中的是currentlink是article还是user
<!-- 侧边栏 --><div class="aside fl"> <ul class="menu list-unstyled"> <li> <a class="item {{currentLink == 'user' ? 'active' : ''}}" href="/admin/user"> <span class="glyphicon glyphicon-user"></span> 用户治理 </a> </li> <li> <a class="item {{currentLink == 'article' ? 'active' : ''}}" href="/admin/article"> <span class="glyphicon glyphicon-th-list"></span> 文章治理 </a> </li> </ul> <div class="cprt"> Powered by <a href="http://www.itheima.com/" target="_blank">黑马程序员</a> </div></div><!-- 侧边栏 -->
userPage.js
- app.locals.currentlink标识示意以后拜访的是用户治理页面
- user-edit.js同样也是不做赘述
// 标识 标识以后拜访的是用户治理页面 req.app.locals.currentLink = 'user';
article.js
文章汇合创立:
- 引入mongoose模块
- 创立文章汇合规定 articleSchema
- 依据规定发明汇合mongoose.model
- 将汇合规定作为模块成员进行导出
// 1.引入mongoose模块const mongoose = require('mongoose');// 2.创立文章汇合规定const articleSchema = new mongoose.Schema({ title: { type: String, maxlength: 20, minlength: 4, required: [true, '请填写文章题目'] }, author: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: [true, '请传递作者'] }, publishDate: { type: Date, default: Date.now }, cover: { type: String, default: null }, content: { type: String }});// 3.依据规定创立汇合const Article = mongoose.model('Article', articleSchema);// 4.将汇合做为模块成员进行导出module.exports = { Article}
article.art
- 对于公布新文章按钮进行调准href到article-edit
- 去掉所有的tr标签,进行循环each articles使得变为动态数据,对于Id进行原文输入@
- 对于公布工夫的格局进行解决
{{extend './common/layout.art'}}{{block 'main'}} {{include './common/header.art'}} <!-- 主体内容 --> <div class="content"> {{include './common/aside.art'}} <div class="main"> <!-- 分类题目 --> <div class="title"> <h4>文章</h4> <span>找到1篇文章</span> <a href="/admin/article-edit" class="btn btn-primary new">公布新文章</a> </div> <!-- /分类题目 --> <!-- 内容列表 --> <table class="table table-striped table-bordered table-hover custom-table"> <thead> <tr> <th>ID</th> <th>题目</th> <th>公布工夫</th> <th>作者</th> <th>操作</th> </tr> </thead> <tbody> {{each articles.records}} <tr> <td>{{@$value._id}}</td> <td>{{$value.title}}</td> <td>{{dateFormat($value.publishDate, 'yyyy-mm-dd')}}</td> <td>{{$value.author.username}}</td> <td> <a href="article-edit.html" class="glyphicon glyphicon-edit"></a> <i class="glyphicon glyphicon-remove" data-toggle="modal" data-target=".confirm-modal"></i> </td> </tr> {{/each}} </tbody> </table> <!-- /内容列表 --> <!-- 分页 --> <ul class="pagination"> {{if articles.page > 1}} <li> <a href="/admin/article?page={{articles.page - 1}}"> <span>«</span> </a> </li> {{/if}} {{each articles.display}} <li><a href="/admin/article?page={{$value}}">{{$value}}</a></li> {{/each}} {{if articles.page < articles.pages}} <li> <a href="/admin/article?page={{articles.page - 0 + 1}}"> <span>»</span> </a> </li> {{/if}} </ul> <!-- /分页 --> </div> </div> <!-- /主体内容 --> <!-- 删除确认弹出框 --> <div class="modal fade confirm-modal"> <div class="modal-dialog modal-lg"> <form class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal"><span>×</span></button> <h4 class="modal-title">请确认</h4> </div> <div class="modal-body"> <p>您确定要删除这篇文章吗?</p> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">勾销</button> <input type="submit" class="btn btn-primary"> </div> </form> </div> </div>{{/block}}
article-edit.art
- 为表单增加申请形式method和申请地址action到article-add
- 对于题目、作者、公布工夫、文章封面都增加对应的name属性
文件上传必须是二进制,enctype是指定表单数据的编码类型
- enctype 指定表单数据的编码类型
application/x-www-form-urlencoded
name=zhangsan&age=20
multipart/form-data 将表单数据编码成二进制类型
- enctype 指定表单数据的编码类型
在文章封面增加id值,如果想要一次性能抉择多个在Input 前面能够增加mutiple则就能够一次抉择多个了。为其增加onchange事件,抉择文件上传空间,抉择完之后进行文件的读取,用FileReader,因为readAsDataURL是异步的,
- 对图片增加Id值preview,并将文件解决的结果显示在页面当中
{{extend './common/layout.art'}}{{block 'main'}} {{include './common/header.art'}} <!-- 主体内容 --> <div class="content"> {{include './common/aside.art'}} <div class="main"> <!-- 分类题目 --> <div class="title"> <h4>5b9a716cb2d2bf17706bcc0a</h4> </div> <!-- enctype 指定表单数据的编码类型 application/x-www-form-urlencoded name=zhangsan&age=20 multipart/form-data 将表单数据编码成二进制类型 --> <!-- /分类题目 --> <form class="form-container" action="/admin/article-add" method="post" enctype="multipart/form-data"> <div class="form-group"> <label>题目</label> <input type="text" class="form-control" placeholder="请输出文章题目" name="title"> </div> <div class="form-group"> <label>作者</label> <input name="author" type="text" class="form-control" readonly value="{{@userInfo._id}}"> </div> <div class="form-group"> <label>公布工夫</label> <input name="publishDate" type="date" class="form-control"> </div> <div class="form-group"> <label for="exampleInputFile">文章封面</label> <!-- multiple 容许用户一次性抉择多个文件 --> <input type="file" name="cover" id="file" > <div class="thumbnail-waper"> <img class="img-thumbnail" src="" id="preview"> </div> </div> <div class="form-group"> <label>内容</label> <textarea name="content" class="form-control" id="editor"></textarea> </div> <div class="buttons"> <input type="submit" class="btn btn-primary"> </div> </form> </div> </div> <!-- /主体内容 -->{{/block}}{{block 'script'}} <script type="text/javascript"> // 抉择文件上传控件 var file = document.querySelector('#file'); var preview = document.querySelector('#preview'); // 当用户抉择完文件当前 file.onchange = function () { // 1 创立文件读取对象 var reader = new FileReader(); // 用户抉择的文件列表 // console.log(this.files[0]) // 2 读取文件 reader.readAsDataURL(this.files[0]); // 3 监听onload事件 reader.onload = function () { console.log(reader.result) // 将文件读取的结果显示在页面中 preview.src = reader.result; } } </script>{{/block}}
article-add.js
body-parser只能承受一般表单的数据post,不能承受二进制数据的传输所以咱们应该用哪个formidable来进行
npm install formidable
- 作用:解析表单,反对get申请参数,post申请参数、文件上传。
- 引入fomidable模块,创立表单解析对象,配置文件上传门路到public/uploads,写绝对路径,所以还要导入path模块
- 同时要保留上传文件的后缀,默认是不保留keepExtensions
- 对表单进行解析
- 对文件门路进行截取,uploads即前面的门路以public进行切割,利用split办法
- 引入文章汇合的构造函数,利用Article.create办法来发明这些对象,是异步的
- 文章内容增加胜利之后重定向文章列表页面
// 引入formidable第三方模块const formidable = require('formidable');const path = require('path');const { Article } = require('../../model/article')module.exports = (req, res) => { // 1.创立表单解析对象 const form = new formidable.IncomingForm(); // 2.配置上传文件的寄存地位 form.uploadDir = path.join(__dirname, '../', '../', 'public', 'uploads'); // 3.保留上传文件的后缀 form.keepExtensions = true; // 4.解析表单 form.parse(req, async (err, fields, files) => { // 1.err谬误对象 如果表单解析失败 err外面存储错误信息 如果表单解析胜利 err将会是null // 2.fields 对象类型 保留一般表单数据 // 3.files 对象类型 保留了和上传文件相干的数据 // res.send(files.cover.path.split('public')[1]) await Article.create({ title: fields.title, author: fields.author, publishDate: fields.publishDate, cover: files.cover.path.split('public')[1], content: fields.content, }); // 将页面重定向到文章列表页面 res.redirect('/admin/article'); }) // res.send('ok');}
app.js
- 引入dataFormat来进行日期的解决
同时引入art-template向模板中导入内部变量dataFormat,咱们就能够在其余模板中调用这个办法了
// 导入dateformat第三方模块const dateFormat = require('dateformat');// 导入art-tempate模板引擎const template = require('art-template');// 向模板外部导入dateFormate变量template.defaults.imports.dateFormat = dateFormat;