美文网首页博客
基于阿里egg框架搭建博客(7)——编辑文章

基于阿里egg框架搭建博客(7)——编辑文章

作者: 妖云小离 | 来源:发表于2019-03-20 12:02 被阅读61次

    相关文章

    基于阿里egg框架搭建博客(1)——开发准备
    基于阿里egg框架搭建博客(2)——Hello World
    基于阿里egg框架搭建博客(3)——注册与登录
    基于阿里egg框架搭建博客(4)——权限控制
    基于阿里egg框架搭建博客(5)——置顶导航条
    基于阿里egg框架搭建博客(6)——浏览、发表文章
    基于阿里egg框架搭建博客(7)——编辑文章

    git

    https://github.com/ZzzSimon/egg-example
    喜欢就点个赞吧!

    正文

    编辑文章,首先得把文章原先内容获取到,然后放在编辑页,给用户展现出一个“半成品”的状态,可以重新保存文章。

    页面设计

    我的文章页面

    编辑页面

    功能设计

    1. 我的文章页标题前显示是否保密,标题后有编辑按钮
    2. 点击编辑按钮,进入编辑页面可重新编辑文章

    前端代码

    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点:

    1. helper.formatInvisiblehelper.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];
        }
    

    结尾

    如果看完觉得有用,请给作者一个喜欢吧!谢谢啦!

    相关文章

      网友评论

        本文标题:基于阿里egg框架搭建博客(7)——编辑文章

        本文链接:https://www.haomeiwen.com/subject/qqzamqtx.html