基於阿里egg框架搭建博客(7)——編輯文章

相關文章

基於阿里egg框架搭建博客(1)——開發準備
基於阿里egg框架搭建博客(2)——Hello World
基於阿里egg框架搭建博客(3)——註冊與登陸
基於阿里egg框架搭建博客(4)——權限控制
基於阿里egg框架搭建博客(5)——置頂導航條
基於阿里egg框架搭建博客(6)——瀏覽、發表文章
基於阿里egg框架搭建博客(7)——編輯文章javascript

git

https://github.com/ZzzSimon/e...
喜歡就點個贊吧!css

正文

編輯文章,首先得把文章原先內容獲取到,而後放在編輯頁,給用戶展示出一個「半成品」的狀態,能夠從新保存文章。html

頁面設計

個人文章頁面

編輯頁面

功能設計

  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點:java

  1. helper.formatInvisiblehelper.formatTime兩個方法的做用是格式化後端返回的參數。固然,你也能夠在後端代碼執行這些邏輯,不過我更傾向於後端代碼儘可能精簡。格式化應當歸屬於前端範疇。若是說模板的渲染屬於後端邏輯,那當我沒說= =。
關於helper用法: https://eggjs.org/zh-cn/basic...

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頁面:mysql

{% 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

咱們添加如下內容:git

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

咱們添加如下內容:github

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

咱們添加如下內容:web

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];
    }

結尾

若是看完以爲有用,請給做者一個喜歡吧!謝謝啦!sql

相關文章
相關標籤/搜索