多人后台博客管理DAY07

(七)项目功能的实现之文章管理

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
Powered by 黑马程序员

userPage.js
  • app.locals.currentlink标识表示当前访问的是用户管理页面
  • user-edit.js同样也是不做赘述
// 标识 标识当前访问的是用户管理页面 req.app.locals.currentLink = 'user';

article.js
  • 【多人后台博客管理DAY07】文章集合创建:
    • 引入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'}}{{include './common/aside.art'}}文章 找到1篇文章 发布新文章 {{each articles.records}} {{/each}}
ID 标题 发布时间 作者 操作
{{@$value._id}} {{$value.title}} {{dateFormat($value.publishDate, 'yyyy-mm-dd')}} {{$value.author.username}}
    {{if articles.page > 1}}
  • «
  • {{/if}}{{each articles.display}}
  • {{$value}}
  • {{/each}}{{if articles.page < articles.pages}}
  • »
  • {{/if}}
{{/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是异步的,
    • 多人后台博客管理DAY07
      文章图片
  • 对图片添加Id值preview,并将文件处理的结果显示在页面当中
{{extend './common/layout.art'}}{{block 'main'}} {{include './common/header.art'}}{{include './common/aside.art'}}5b9a716cb2d2bf17706bcc0a
多人后台博客管理DAY07
文章图片
{{/block}}{{block 'script'}}{{/block}}

article-add.js
  • body-parser只能接受普通表单的数据post,不能接受二进制数据的传输所以我们应该用哪个formidable来进行 npm install formidable
    • 作用:解析表单,支持get请求参数,post请求参数、文件上传。
    • 多人后台博客管理DAY07
      文章图片
  • 引入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;

    推荐阅读