相关文章
基于阿里egg框架搭建博客(1)——开发准备
基于阿里egg框架搭建博客(2)——Hello World
基于阿里egg框架搭建博客(3)——注册与登录
基于阿里egg框架搭建博客(4)——权限控制
基于阿里egg框架搭建博客(5)——置顶导航条
基于阿里egg框架搭建博客(6)——浏览、发表文章
基于阿里egg框架搭建博客(7)——编辑文章
git
https://github.com/ZzzSimon/egg-example
喜欢就点个赞吧!
正文
编辑文章,首先得把文章原先内容获取到,然后放在编辑页,给用户展现出一个“半成品”的状态,可以重新保存文章。
页面设计
我的文章页面
编辑页面
功能设计
- 我的文章页标题前显示是否保密,标题后有编辑按钮
- 点击编辑按钮,进入编辑页面可重新编辑文章
前端代码
myarticle.tpl 我的文章页
我们创建/app/view/article/myarticle.tpl
页面:
{% extends "parent.tpl" %}
{% block head %}
<!--注意:模板中已添加bootstrap相关head-->
<title>我的文章</title>
{% endblock %}
{% block content %}
<h1>我的文章</h1>
<ul class="article-view view">
{% for item in list %}
<li class="item">
<dl>
<dt>
<small style="color: red">{{helper.formatInvisible(item.invisible)}}</small>
<a href="{{ item.url }}">{{ item.title }}</a>
<a class="btn btn-link" href='/modify/{{item.id}}.htm'>编辑</a>
</dt>
<dd><small>{{item.author}}</small> 最后更新于 {{helper.formatTime(item.update_time)}} </dd>
<dd></dd>
</dl>
</li>
{% endfor %}
</ul>
{% endblock %}
此处需要注意1点:
-
helper.formatInvisible
与helper.formatTime
两个方法的作用是格式化后端返回的参数。当然,你也可以在后端代码执行这些逻辑,不过我更倾向于后端代码尽量精简。格式化应当归属于前端范畴。如果说模板的渲染属于后端逻辑,那当我没说= =。
关于helper用法:https://eggjs.org/zh-cn/basics/objects.html#helper
helper.js
const moment = require('moment');
//时间格式化
exports.formatTime = time => moment(time).format('YYYY-MM-DD HH:mm:ss');
exports.formatInvisible = invisible => invisible===1 ? '保密':'';
modify.tpl 编辑文章页
我们创建/app/view/article/modify.tpl
页面:
{% extends "parent.tpl" %}
{% block head %}
<title>编辑文章</title>
<link rel="stylesheet" href="/public/editormd/editormd.css">
<script type="text/javascript" src="/public/editormd/editormd.js"></script>
{% endblock %}
{% block content %}
<div class="row">
<div class="form-group">
<label for="title">文章标题:</label>
<input id="title" type="text" class="form-control" value="{{article.title}}">
</div>
<div class="checkbox ">
<label>
<input id="invisible" type="checkbox" >保密(勾选后将<strong style="color: red">不显示</strong>在文章列表)
</label>
</div>
<div id="detail" style="visibility: hidden">{{article.detail}}</div>
<div class="form-group pull-right">
<button id="save" class="btn btn-success ">保存</button>
</div>
</div>
<div class="row">
<div id="layout">
<div id="test-editormd"></div>
</div>
</div>
{% endblock %}
{% block script %}
<script type="text/javascript">
$('#invisible').prop('checked','{{article.invisible}}' === '1' ? 'checked':'');
const markdown = $('#detail').text();
let testEditor = editormd("test-editormd", {
width: "100%",
height: 740,
path: '/public/editormd/lib/',
markdown: markdown,
codeFold: true,
saveHTMLToTextarea: true, // 保存 HTML 到 Textarea
searchReplace: true,
htmlDecode: "style,script,iframe|on*", // 开启 HTML 标签解析,为了安全性,默认不开启
emoji: true,
taskList: true,
tocm: true, // Using [TOCM]
tex: true, // 开启科学公式TeX语言支持,默认关闭
flowChart: true, // 开启流程图支持,默认关闭
sequenceDiagram: true, // 开启时序/序列图支持,默认关闭,
imageUpload: true,
imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
imageUploadURL: "/edit/uploadPic?_csrf={{ ctx.csrf | safe }}",
onload: function () {
console.log('onload', this);
}
});
$('#save').bind('click', function () {
data = {
article: {
id: '{{article.id}}',
title: $('#title').val(),
detail: testEditor.getMarkdown(),
invisible: $('#invisible').prop('checked') ? 1:0
}
};
$.post('/edit/modify?_csrf={{ ctx.csrf | safe }}', data, function (resp) {
if (resp.flag === '1') {
window.location.href = resp.url;
}else {
alert(resp)
}
})
})
</script>
{% endblock %}
后端代码
ArticleController
我们添加以下内容:
async myarticle(){
const ctx = this.ctx;
const articleList = await ctx.service.article.getArticleByAuthor(ctx.session.user.username);
await ctx.render('article/myarticle.tpl', { list: articleList });
}
EditController
我们添加以下内容:
async modifyHtm(){
const {ctx, service} = this;
const article = await service.article.getArticleById(ctx.params.id);
await ctx.render('article/modify.tpl',{article:article})
}
async modify(){
const {ctx, service} = this;
const article = ctx.request.body.article;
const nowTime = new Date();
article.update_time = nowTime;
const result = await service.article.modify(article);
if (result) {
ctx.body = {flag:'1',msg:'保存成功',url:'/article/'+article.id+'.htm'}
}else {
ctx.body = {flag:'0',msg:'保存失败'}
}
}
ArticleService
我们添加以下内容:
async modify(article = {}){
const res = await this.app.mysql.update('article',article);
return res.affectedRows === 1;
}
async getArticleByAuthor(author){
const sql = "SELECT id,url,title,author,update_time,invisible FROM article WHERE author = ?";
const list =await this.app.mysql.query(sql, [author]);
return list;
}
async getArticleById(id){
const sql = "SELECT id,title,detail,invisible FROM article WHERE id = ?";
const list =await this.app.mysql.query(sql, [id]);
return list[0];
}
结尾
如果看完觉得有用,请给作者一个喜欢吧!谢谢啦!
网友评论