(七)我的项目性能的实现之文章治理

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>&laquo;</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>&raquo;</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>&times;</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 将表单数据编码成二进制类型
  • 在文章封面增加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;