关于前端:多人后台博客管理DAY07

2次阅读

共计 7659 个字符,预计需要花费 20 分钟才能阅读完成。

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

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;
正文完
 0