添加帖子是否展示的功能(一)数据保存和修改

应对可以通过路径访问,但是不在列表中展示,和机要贴有区别。
包含如下几部分

数据库

帖子表(article)添加字段帖子是否展示 articleDisplayable, 默认展示

修改 repository.json

        {
          "name": "articleDisplayable",
          "type": "int",
          "description": "帖子是否展示,0不展示,1展示"
        }

已存在的数据库手动添加列

alter table symphony_article add articleDisplayable int(11) NOT NULL DEFAULT 1 COMMENT '帖子是否展示,0不展示,1展示';

实体类

Article.java实体类添加属性

    /**
     * Key of article dispalyable.
     */
    public static final String ARTICLE_DISPLAYABLE = "articleDisplayable";

    // articleDisplayable constants
    /**
     * create by: qiankunpingtai
     * create time: 2019/5/14 22:42
     * website:https://qiankunpingtai.cn
     * description:
     * 不展示false
     * 展示true
     */
    public static final Integer ARTICLE_DISPLAYABLE_NOT =0 ;
    public static final Integer ARTICLE_DISPLAYABLE_YES = 1;
    // articleDisplayable es and algolia constants
    /**
     * create by: qiankunpingtai
     * create time: 2019/5/14 22:42
     * website:https://qiankunpingtai.cn
     * description:
     * 0 删除
     * 1 创建
     * 2 更新
     * 3 不操作
     */
    public static final String ARTICLE_DISPLAYABLE_INDEX_OPT="articleDisplayableIndexOpt";
    public static final String ARTICLE_DISPLAYABLE_INDEX_OPT_DELETE = "0";
    public static final String ARTICLE_DISPLAYABLE_INDEX_OPT_ADD = "1";
    public static final String ARTICLE_DISPLAYABLE_INDEX_OPT_UPDATE = "2";
    public static final String ARTICLE_DISPLAYABLE_INDEX_OPT_NOTHING = "3";

页面显示文本配置

lang_zh_CN.properties 添加

displayableLabel=允许展示

lang_en_US.properties 添加

displayableLabel=Allow to display

页面

管理员界面

./skins/classic/admin/article.ftl
<div class="fn__flex">
    <label>
        <div>${qnaOfferPointLabel}</div>
        <input type="text" name="articleQnAOfferPoint" value="${article.articleQnAOfferPoint?c}"/>
    </label>
    <#--添加是否列表展示的控制-->
    <label class="mid">
        <div>${displayableLabel}</div>
        <select id="articleDisplayable" name="articleDisplayable">
            <option value="1"<#if 1==article.articleDisplayable> selected</#if>>${yesLabel}</option>
            <option value="0"<#if 0==article.articleDisplayable> selected</#if>>${noLabel}</option>
        </select>
    </label>
</div>
./skins/mobile/admin/article.ftl
<label for="articleId">${pushLabel} Email  ${sortLabel}</label>
<input type="number" id="articlePushOrder" name="articlePushOrder" value="${article.articlePushOrder}" />
<#--添加是否列表展示的控制-->
<label>${displayableLabel}</label>
<select id="articleDisplayable" name="articleDisplayable">
    <option value="1"<#if 1==article.articleDisplayable> selected</#if>>${yesLabel}</option>
    <option value="0"<#if 0==article.articleDisplayable> selected</#if>>${noLabel}</option>
</select>

发帖界面

./skins/classic/home/post.ftl
<#if permissions["commonAddArticleAnonymous"].permissionGrant && articleType != 2 && articleType != 5>
<label class="article-anonymous">${anonymousLabel}<input<#if requisite> readonly disabled</#if>
        <#if article??> disabled="disabled"<#if 1 == article.articleAnonymous> checked</#if></#if>
        type="checkbox" id="articleAnonymous"></label>
</#if>
<#--添加是否列表展示的控制-->
<label class="article-anonymous">&nbsp;  ${displayableLabel}<input
        <#if (article?? && (1==article.articleDisplayable)) || !article??> checked="checked"</#if> type="checkbox" id="articleDisplayable"></label>
./skins/mobile/home/post.ftl
<#if permissions["commonAddArticleAnonymous"].permissionGrant && articleType != 2 && articleType != 5>
    <label class="article-anonymous">&nbsp;  ${anonymousLabel}<input
        <#if article??> disabled="disabled"<#if 1 == article.articleAnonymous> checked</#if></#if>
        type="checkbox" id="articleAnonymous"></label>
</#if>
<#--添加是否列表展示的控制-->
<label class="article-anonymous">&nbsp;  ${displayableLabel}<input
        <#if (article?? && (1==article.articleDisplayable)) || !article??> checked="checked"</#if>
                        type="checkbox" id="articleDisplayable"></label>
add-article.js
add: function (csrfToken, it) {
......

       /**
         * create by: qiankunpingtai
         * create time: 2019/5/14 18:11
         * website:https://qiankunpingtai.cn
         * description:
         * 添加是否在列表中展示项
         */
      var requestJSONObject = {
        articleTitle: $('#articleTitle').val().replace(/(^\s*)|(\s*$)/g, ''),
        articleContent: this.editor.getValue(),
        articleTags: articleTags,
        articleCommentable: $('#articleCommentable').prop('checked'),
        articleNotifyFollowers: $('#articleNotifyFollowers').prop('checked'),
        articleType: articleType,
        articleDisplayable: Boolean($('#articleDisplayable').prop('checked'))?1:0
      }

......
}
add-article.min.js
add: function (e, a) {
......
            var r = {
                articleTitle: $("#articleTitle").val().replace(/(^\s*)|(\s*$)/g, ""),
                articleContent: this.editor.getValue(),
                articleTags: i,
                articleCommentable: $("#articleCommentable").prop("checked"),
                articleNotifyFollowers: $("#articleNotifyFollowers").prop("checked"),
                articleType: t,
                articleDisplayable: Boolean($('#articleDisplayable').prop('checked'))?1:0
            };
......
}

后台处理

保存

/admin/article/

修改AdminProcessor.java
保存方法,从 json 中获取数据

    @RequestProcessing(value = "/admin/article/{articleId}", method = HttpMethod.POST)
    @Before({StopwatchStartAdvice.class, PermissionCheck.class})
    @After({PermissionGrant.class, StopwatchEndAdvice.class})
    public void updateArticle(final RequestContext context) {
        final String articleId = context.pathVar("articleId");
        final HttpServletRequest request = context.getRequest();

        final AbstractFreeMarkerRenderer renderer = new SkinRenderer(context, "admin/article.ftl");
        final Map<String, Object> dataModel = renderer.getDataModel();

        JSONObject article = articleQueryService.getArticle(articleId);

        final Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            final String name = parameterNames.nextElement();
            final String value = context.param(name);
            /**
             * create by: qiankunpingtai
             * create time: 2019/5/14 22:45
             * website:https://qiankunpingtai.cn
             * description:
             * int类型,值由字符串更新为int
             */
            if (name.equals(Article.ARTICLE_REWARD_POINT)
                    || name.equals(Article.ARTICLE_QNA_OFFER_POINT)
                    || name.equals(Article.ARTICLE_STATUS)
                    || name.equals(Article.ARTICLE_TYPE)
                    || name.equals(Article.ARTICLE_THANK_CNT)
                    || name.equals(Article.ARTICLE_GOOD_CNT)
                    || name.equals(Article.ARTICLE_BAD_CNT)
                    || name.equals(Article.ARTICLE_PERFECT)
                    || name.equals(Article.ARTICLE_ANONYMOUS_VIEW)
                    || name.equals(Article.ARTICLE_PUSH_ORDER)
                    ||name.equals(Article.ARTICLE_DISPLAYABLE)) {
                article.put(name, Integer.valueOf(value));
            } else {
                article.put(name, value);
            }
        }

        final String articleTags = Tag.formatTags(article.optString(Article.ARTICLE_TAGS));
        article.put(Article.ARTICLE_TAGS, articleTags);

        articleMgmtService.updateArticleByAdmin(articleId, article);
        operationMgmtService.addOperation(Operation.newOperation(request, Operation.OPERATION_CODE_C_UPDATE_ARTICLE, articleId));

        article = articleQueryService.getArticle(articleId);
        String title = article.optString(Article.ARTICLE_TITLE);
        title = Escapes.escapeHTML(title);
        article.put(Article.ARTICLE_TITLE, title);
        dataModel.put(Article.ARTICLE, article);
        /**
         * create by: qiankunpingtai
         * create time: 2019/5/15 10:45
         * website:https://qiankunpingtai.cn
         * description:
         * 如果是不在列表中显示的帖子,直接跳过
         */
        final Integer articleDisplayable = article.optInt(Article.ARTICLE_DISPLAYABLE);
        if(Article.ARTICLE_DISPLAYABLE_YES.equals(articleDisplayable)){
            updateArticleSearchIndex(article);
        }

        dataModelService.fillHeaderAndFooter(context, dataModel);
    }
/article

修改ArticleProcessor.java

    @RequestProcessing(value = "/article", method = HttpMethod.POST)
    @Before({StopwatchStartAdvice.class, LoginCheck.class, CSRFCheck.class, ArticleAddValidation.class, PermissionCheck.class})
    @After(StopwatchEndAdvice.class)
    public void addArticle(final RequestContext context) {
        context.renderJSON();

        final HttpServletRequest request = context.getRequest();
        final JSONObject requestJSONObject = context.requestJSON();
        final String articleTitle = requestJSONObject.optString(Article.ARTICLE_TITLE);
        String articleTags = requestJSONObject.optString(Article.ARTICLE_TAGS);
        final String articleContent = requestJSONObject.optString(Article.ARTICLE_CONTENT);
        final boolean articleCommentable = requestJSONObject.optBoolean(Article.ARTICLE_COMMENTABLE, true);
        final int articleType = requestJSONObject.optInt(Article.ARTICLE_TYPE, Article.ARTICLE_TYPE_C_NORMAL);
        final String articleRewardContent = requestJSONObject.optString(Article.ARTICLE_REWARD_CONTENT);
        final int articleRewardPoint = requestJSONObject.optInt(Article.ARTICLE_REWARD_POINT);
        final int articleQnAOfferPoint = requestJSONObject.optInt(Article.ARTICLE_QNA_OFFER_POINT);
        final String ip = Requests.getRemoteAddr(request);
        final String ua = Headers.getHeader(request, Common.USER_AGENT, "");
        final boolean isAnonymous = requestJSONObject.optBoolean(Article.ARTICLE_ANONYMOUS, false);
        final int articleAnonymous = isAnonymous ? Article.ARTICLE_ANONYMOUS_C_ANONYMOUS : Article.ARTICLE_ANONYMOUS_C_PUBLIC;
        final boolean articleNotifyFollowers = requestJSONObject.optBoolean(Article.ARTICLE_T_NOTIFY_FOLLOWERS);
        /**
         * create by: qiankunpingtai
         * create time: 2019/5/14 18:11
         * website:https://qiankunpingtai.cn
         * description:
         * 添加是否在列表中展示项
         */
        final Integer articleDisplayable = requestJSONObject.optInt(Article.ARTICLE_DISPLAYABLE,Article.ARTICLE_DISPLAYABLE_YES);

        final JSONObject article = new JSONObject();
        article.put(Article.ARTICLE_TITLE, articleTitle);
        article.put(Article.ARTICLE_CONTENT, articleContent);
        article.put(Article.ARTICLE_EDITOR_TYPE, 0);
        article.put(Article.ARTICLE_COMMENTABLE, articleCommentable);
        article.put(Article.ARTICLE_TYPE, articleType);
        article.put(Article.ARTICLE_REWARD_CONTENT, articleRewardContent);
        article.put(Article.ARTICLE_REWARD_POINT, articleRewardPoint);
        article.put(Article.ARTICLE_QNA_OFFER_POINT, articleQnAOfferPoint);
        article.put(Article.ARTICLE_IP, "");
        if (StringUtils.isNotBlank(ip)) {
            article.put(Article.ARTICLE_IP, ip);
        }
        article.put(Article.ARTICLE_UA, ua);
        article.put(Article.ARTICLE_ANONYMOUS, articleAnonymous);
        article.put(Article.ARTICLE_T_NOTIFY_FOLLOWERS, articleNotifyFollowers);
        /**
         * create by: qiankunpingtai
         * create time: 2019/5/14 18:11
         * website:https://qiankunpingtai.cn
         * description:
         * 添加是否在列表中展示项
         */
        article.put(Article.ARTICLE_DISPLAYABLE, articleDisplayable);

        try {
            final JSONObject currentUser = Sessions.getUser();

            article.put(Article.ARTICLE_AUTHOR_ID, currentUser.optString(Keys.OBJECT_ID));

            if (!Role.ROLE_ID_C_ADMIN.equals(currentUser.optString(User.USER_ROLE))) {
                articleTags = articleMgmtService.filterReservedTags(articleTags);
            }

            if (Article.ARTICLE_TYPE_C_DISCUSSION == articleType && StringUtils.isBlank(articleTags)) {
                articleTags = "机要";
            }

            if (Article.ARTICLE_TYPE_C_THOUGHT == articleType && StringUtils.isBlank(articleTags)) {
                articleTags = "思绪";
            }

            article.put(Article.ARTICLE_TAGS, articleTags);

            final String articleId = articleMgmtService.addArticle(article);

            context.renderJSONValue(Keys.STATUS_CODE, StatusCodes.SUCC);
            context.renderJSONValue(Article.ARTICLE_T_ID, articleId);
        } catch (final ServiceException e) {
            final String msg = e.getMessage();
            LOGGER.log(Level.ERROR, "Adds article [title=" + articleTitle + "] failed: {0}", e.getMessage());

            context.renderMsg(msg);
            context.renderJSONValue(Keys.STATUS_CODE, StatusCodes.ERR);
        }
    }

/article/{id}

修改ArticleProcessor.java

    @RequestProcessing(value = "/article/{id}", method = HttpMethod.PUT)
    @Before({StopwatchStartAdvice.class, LoginCheck.class, CSRFCheck.class, ArticleUpdateValidation.class, PermissionCheck.class})
    @After(StopwatchEndAdvice.class)
    public void updateArticle(final RequestContext context) {
        final String id = context.pathVar("id");
        final HttpServletRequest request = context.getRequest();
        if (StringUtils.isBlank(id)) {
            context.sendError(HttpServletResponse.SC_NOT_FOUND);

            return;
        }

        final JSONObject oldArticle = articleQueryService.getArticleById(id);
        if (null == oldArticle) {
            context.sendError(HttpServletResponse.SC_NOT_FOUND);

            return;
        }

        context.renderJSON();

        if (Article.ARTICLE_STATUS_C_VALID != oldArticle.optInt(Article.ARTICLE_STATUS)) {
            context.renderMsg(langPropsService.get("articleLockedLabel"));
            context.renderJSONValue(Keys.STATUS_CODE, StatusCodes.ERR);

            return;
        }



        final JSONObject requestJSONObject = context.requestJSON();
        final String articleTitle = requestJSONObject.optString(Article.ARTICLE_TITLE);
        String articleTags = requestJSONObject.optString(Article.ARTICLE_TAGS);
        final String articleContent = requestJSONObject.optString(Article.ARTICLE_CONTENT);
        final boolean articleCommentable = requestJSONObject.optBoolean(Article.ARTICLE_COMMENTABLE, true);
        final int articleType = requestJSONObject.optInt(Article.ARTICLE_TYPE, Article.ARTICLE_TYPE_C_NORMAL);
        final String articleRewardContent = requestJSONObject.optString(Article.ARTICLE_REWARD_CONTENT);
        final int articleRewardPoint = requestJSONObject.optInt(Article.ARTICLE_REWARD_POINT);
        final int articleQnAOfferPoint = requestJSONObject.optInt(Article.ARTICLE_QNA_OFFER_POINT);
        final String ip = Requests.getRemoteAddr(request);
        final String ua = Headers.getHeader(request, Common.USER_AGENT, "");
        final boolean articleNotifyFollowers = requestJSONObject.optBoolean(Article.ARTICLE_T_NOTIFY_FOLLOWERS);
        /**
         * create by: qiankunpingtai
         * create time: 2019/5/14 18:11
         * website:https://qiankunpingtai.cn
         * description:
         * 添加是否在列表中展示项
         */
        final Integer articleDisplayable = requestJSONObject.optInt(Article.ARTICLE_DISPLAYABLE,Article.ARTICLE_DISPLAYABLE_YES);
        final JSONObject article = new JSONObject();
        /**
         * create by: qiankunpingtai
         * create time: 2019/5/15 11:10
         * website:https://qiankunpingtai.cn
         * description:
         * 获取文章原始是否在列表中展示标记
         * 如果原始是在列表展示,现在修改为不在列表中展示,需要删除es和algolia索引
         *
         */
        if(Article.ARTICLE_DISPLAYABLE_YES.equals(oldArticle.optInt(Article.ARTICLE_DISPLAYABLE))){
            if(Article.ARTICLE_DISPLAYABLE_YES.equals(articleDisplayable)){
                //以前在列表展示,现在也在列表展示,更新索引
                article.put(Article.ARTICLE_DISPLAYABLE_INDEX_OPT,Article.ARTICLE_DISPLAYABLE_INDEX_OPT_UPDATE);
            }else{
                //以前在列表展示,现在不在列表展示,删除索引
                article.put(Article.ARTICLE_DISPLAYABLE_INDEX_OPT,Article.ARTICLE_DISPLAYABLE_INDEX_OPT_DELETE);

            }
        }else{
            if(Article.ARTICLE_DISPLAYABLE_YES.equals(articleDisplayable)){
                //以前不在列表展示,现在在列表展示,新建索引
                article.put(Article.ARTICLE_DISPLAYABLE_INDEX_OPT,Article.ARTICLE_DISPLAYABLE_INDEX_OPT_ADD);
            }else{
                //以前不在列表展示,现在也不在列表展示,不操作索引
                article.put(Article.ARTICLE_DISPLAYABLE_INDEX_OPT,Article.ARTICLE_DISPLAYABLE_INDEX_OPT_NOTHING);
            }
        }
        article.put(Keys.OBJECT_ID, id);
        article.put(Article.ARTICLE_TITLE, articleTitle);
        article.put(Article.ARTICLE_CONTENT, articleContent);
        article.put(Article.ARTICLE_EDITOR_TYPE, 0);
        article.put(Article.ARTICLE_COMMENTABLE, articleCommentable);
        article.put(Article.ARTICLE_TYPE, articleType);
        article.put(Article.ARTICLE_REWARD_CONTENT, articleRewardContent);
        article.put(Article.ARTICLE_REWARD_POINT, articleRewardPoint);
        article.put(Article.ARTICLE_QNA_OFFER_POINT, articleQnAOfferPoint);
        article.put(Article.ARTICLE_IP, "");
        if (StringUtils.isNotBlank(ip)) {
            article.put(Article.ARTICLE_IP, ip);
        }
        article.put(Article.ARTICLE_UA, ua);
        article.put(Article.ARTICLE_T_NOTIFY_FOLLOWERS, articleNotifyFollowers);
        /**
         * create by: qiankunpingtai
         * create time: 2019/5/14 18:11
         * website:https://qiankunpingtai.cn
         * description:
         * 添加是否在列表中展示项
         */
        article.put(Article.ARTICLE_DISPLAYABLE, articleDisplayable);
        final JSONObject currentUser = Sessions.getUser();
        if (null == currentUser
                || !currentUser.optString(Keys.OBJECT_ID).equals(oldArticle.optString(Article.ARTICLE_AUTHOR_ID))) {
            context.sendError(HttpServletResponse.SC_FORBIDDEN);

            return;
        }

        article.put(Article.ARTICLE_AUTHOR_ID, currentUser.optString(Keys.OBJECT_ID));

        if (!Role.ROLE_ID_C_ADMIN.equals(currentUser.optString(User.USER_ROLE))) {
            articleTags = articleMgmtService.filterReservedTags(articleTags);
        }

        if (Article.ARTICLE_TYPE_C_DISCUSSION == articleType && StringUtils.isBlank(articleTags)) {
            articleTags = "机要";
        }

        if (Article.ARTICLE_TYPE_C_THOUGHT == articleType && StringUtils.isBlank(articleTags)) {
            articleTags = "思绪";
        }

        article.put(Article.ARTICLE_TAGS, articleTags);

        try {
            articleMgmtService.updateArticle(article);

            context.renderJSONValue(Keys.STATUS_CODE, StatusCodes.SUCC);
            context.renderJSONValue(Article.ARTICLE_T_ID, id);
        } catch (final ServiceException e) {
            final String msg = e.getMessage();
            LOGGER.log(Level.ERROR, "Adds article [title=" + articleTitle + "] failed: {0}", e.getMessage());

            context.renderMsg(msg);
            context.renderJSONValue(Keys.STATUS_CODE, StatusCodes.ERR);
        }
    }

ArticleMgmtService.java

    public synchronized void updateArticle(final JSONObject requestJSONObject) throws ServiceException {
        String articleTitle = requestJSONObject.optString(Article.ARTICLE_TITLE);

        String articleId;
        JSONObject articleToUpdate;
        JSONObject oldArticle;
        String authorId;
        JSONObject author;
        int updatePointSum;
        int articleAnonymous;

        try {
            // check if admin allow to add article
            final JSONObject option = optionRepository.get(Option.ID_C_MISC_ALLOW_ADD_ARTICLE);

            if (!"0".equals(option.optString(Option.OPTION_VALUE))) {
                throw new ServiceException(langPropsService.get("notAllowAddArticleLabel"));
            }

            articleId = requestJSONObject.optString(Keys.OBJECT_ID);
            articleToUpdate = articleRepository.get(articleId);
            oldArticle = JSONs.clone(articleToUpdate);
            authorId = articleToUpdate.optString(Article.ARTICLE_AUTHOR_ID);
            author = userRepository.get(authorId);
            if (UserExt.USER_STATUS_C_VALID != author.optInt(UserExt.USER_STATUS)) {
                throw new ServiceException(langPropsService.get("userStatusInvalidLabel"));
            }

            final long followerCnt = followQueryService.getFollowerCount(authorId, Follow.FOLLOWING_TYPE_C_USER);
            int addition = (int) Math.round(Math.sqrt(followerCnt));
            final long collectCnt = followQueryService.getFollowerCount(articleId, Follow.FOLLOWING_TYPE_C_ARTICLE);
            final long watchCnt = followQueryService.getFollowerCount(articleId, Follow.FOLLOWING_TYPE_C_ARTICLE_WATCH);
            addition += (collectCnt + watchCnt) * 2;
            updatePointSum = Pointtransfer.TRANSFER_SUM_C_UPDATE_ARTICLE + addition;

            articleAnonymous = articleToUpdate.optInt(Article.ARTICLE_ANONYMOUS);

            if (Article.ARTICLE_ANONYMOUS_C_PUBLIC == articleAnonymous) {
                final int balance = author.optInt(UserExt.USER_POINT);
                if (balance - updatePointSum < 0) {
                    throw new ServiceException(langPropsService.get("insufficientBalanceLabel"));
                }
            }

            final JSONObject maybeExist = articleRepository.getByTitle(articleTitle);
            if (null != maybeExist) {
                if (!articleToUpdate.optString(Article.ARTICLE_TITLE).equals(articleTitle)) {
                    final String existArticleAuthorId = maybeExist.optString(Article.ARTICLE_AUTHOR_ID);
                    String msg;
                    if (existArticleAuthorId.equals(authorId)) {
                        msg = langPropsService.get("duplicatedArticleTitleSelfLabel");
                        msg = msg.replace("{article}", "<a target='_blank' href='/article/" + maybeExist.optString(Keys.OBJECT_ID)
                                + "'>" + articleTitle + "</a>");
                    } else {
                        final JSONObject existArticleAuthor = userRepository.get(existArticleAuthorId);
                        final String userName = existArticleAuthor.optString(User.USER_NAME);
                        msg = langPropsService.get("duplicatedArticleTitleLabel");
                        msg = msg.replace("{user}", "<a target='_blank' href='/member/" + userName + "'>" + userName + "</a>");
                        msg = msg.replace("{article}", "<a target='_blank' href='/article/" + maybeExist.optString(Keys.OBJECT_ID)
                                + "'>" + articleTitle + "</a>");
                    }

                    throw new ServiceException(msg);
                }
            }
        } catch (final RepositoryException e) {
            throw new ServiceException(e);
        }

        final int qnaOfferPoint = requestJSONObject.optInt(Article.ARTICLE_QNA_OFFER_POINT, 0);
        if (qnaOfferPoint < articleToUpdate.optInt(Article.ARTICLE_QNA_OFFER_POINT)) { // Increase only to prevent lowering points when adopting answer
            throw new ServiceException(langPropsService.get("qnaOfferPointMustMoreThanOldLabel"));
        }
        articleToUpdate.put(Article.ARTICLE_QNA_OFFER_POINT, qnaOfferPoint);

        final int articleType = requestJSONObject.optInt(Article.ARTICLE_TYPE, Article.ARTICLE_TYPE_C_NORMAL);

        final Transaction transaction = articleRepository.beginTransaction();

        try {
            requestJSONObject.put(Article.ARTICLE_ANONYMOUS, articleAnonymous);
            processTagsForArticleUpdate(articleToUpdate, requestJSONObject, author);
            userRepository.update(author.optString(Keys.OBJECT_ID), author);

            articleTitle = Emotions.toAliases(articleTitle);
            articleTitle = Pangu.spacingText(articleTitle);

            final String oldTitle = articleToUpdate.optString(Article.ARTICLE_TITLE);
            articleToUpdate.put(Article.ARTICLE_TITLE, articleTitle);

            articleToUpdate.put(Article.ARTICLE_TAGS, requestJSONObject.optString(Article.ARTICLE_TAGS));
            articleToUpdate.put(Article.ARTICLE_COMMENTABLE, requestJSONObject.optBoolean(Article.ARTICLE_COMMENTABLE, true));
            articleToUpdate.put(Article.ARTICLE_TYPE, articleType);
            /**
             * create by: qiankunpingtai
             * create time: 2019/5/14 22:45
             * website:https://qiankunpingtai.cn
             * description:
             * 添加帖子是否展示字段
             */
            articleToUpdate.put(Article.ARTICLE_DISPLAYABLE,requestJSONObject.optInt(Article.ARTICLE_DISPLAYABLE, Article.ARTICLE_DISPLAYABLE_YES));
            String articleContent = requestJSONObject.optString(Article.ARTICLE_CONTENT);
            articleContent = Emotions.toAliases(articleContent);
            //articleContent = StringUtils.trim(articleContent) + " "; https://github.com/b3log/symphony/issues/389
            articleContent = articleContent.replace(langPropsService.get("uploadingLabel", Locale.SIMPLIFIED_CHINESE), "");
            articleContent = articleContent.replace(langPropsService.get("uploadingLabel", Locale.US), "");
            if (Article.ARTICLE_TYPE_C_THOUGHT != articleType) {
                articleContent = Runes.removeControlChars(articleContent);
            }

            final String oldContent = articleToUpdate.optString(Article.ARTICLE_CONTENT);
            articleToUpdate.put(Article.ARTICLE_CONTENT, articleContent);

            final long currentTimeMillis = System.currentTimeMillis();
            final long createTime = articleToUpdate.optLong(Keys.OBJECT_ID);
            final boolean notIn5m = currentTimeMillis - createTime > 1000 * 60 * 5;

            articleToUpdate.put(Article.ARTICLE_UPDATE_TIME, currentTimeMillis);

            final int rewardPoint = requestJSONObject.optInt(Article.ARTICLE_REWARD_POINT, 0);
            boolean enableReward = false;
            if (0 < rewardPoint) {
                if (1 > articleToUpdate.optInt(Article.ARTICLE_REWARD_POINT)) {
                    enableReward = true;
                }

                String rewardContent = requestJSONObject.optString(Article.ARTICLE_REWARD_CONTENT);
                rewardContent = Emotions.toAliases(rewardContent);
                rewardContent = Runes.removeControlChars(rewardContent);
                articleToUpdate.put(Article.ARTICLE_REWARD_CONTENT, rewardContent);
                articleToUpdate.put(Article.ARTICLE_REWARD_POINT, rewardPoint);
            }

            final String ip = requestJSONObject.optString(Article.ARTICLE_IP);
            articleToUpdate.put(Article.ARTICLE_IP, ip);

            String ua = requestJSONObject.optString(Article.ARTICLE_UA);
            if (StringUtils.length(ua) > Common.MAX_LENGTH_UA) {
                ua = StringUtils.substring(ua, 0, Common.MAX_LENGTH_UA);
            }
            articleToUpdate.put(Article.ARTICLE_UA, ua);
            articleToUpdate.put(Article.ARTICLE_AUDIO_URL, ""); // 小薇语音预览更新 https://github.com/b3log/symphony/issues/791

            articleRepository.update(articleId, articleToUpdate);

            final boolean titleChanged = !oldTitle.replaceAll("\\s+", "").equals(articleTitle.replaceAll("\\s+", ""));
            final boolean contentChanged = !oldContent.replaceAll("\\s+", "").equals(articleContent.replaceAll("\\s+", ""));
            if (notIn5m && Article.ARTICLE_TYPE_C_THOUGHT != articleType
                    && (titleChanged || contentChanged)) {
                final JSONObject revision = new JSONObject();
                revision.put(Revision.REVISION_AUTHOR_ID, authorId);
                final JSONObject revisionData = new JSONObject();
                revisionData.put(Article.ARTICLE_TITLE, articleTitle);
                revisionData.put(Article.ARTICLE_CONTENT, articleContent);
                revision.put(Revision.REVISION_DATA, revisionData.toString());
                revision.put(Revision.REVISION_DATA_ID, articleId);
                revision.put(Revision.REVISION_DATA_TYPE, Revision.DATA_TYPE_C_ARTICLE);
                revisionRepository.add(revision);
            }

            transaction.commit();

            try {
                Thread.sleep(50); // wait for db write to avoid article duplication
            } catch (final Exception e) {
            }

            if (Article.ARTICLE_ANONYMOUS_C_PUBLIC == articleAnonymous) {
                if (notIn5m) {
                    pointtransferMgmtService.transfer(authorId, Pointtransfer.ID_C_SYS,
                            Pointtransfer.TRANSFER_TYPE_C_UPDATE_ARTICLE,
                            updatePointSum, articleId, System.currentTimeMillis(), "");
                }

                if (enableReward) {
                    pointtransferMgmtService.transfer(authorId, Pointtransfer.ID_C_SYS,
                            Pointtransfer.TRANSFER_TYPE_C_ADD_ARTICLE_REWARD,
                            Pointtransfer.TRANSFER_SUM_C_ADD_ARTICLE_REWARD, articleId, System.currentTimeMillis(), "");
                }
            }
            final JSONObject eventData = new JSONObject();
            /**
             * create by: qiankunpingtai
             * create time: 2019/5/15 11:34
             * website:https://qiankunpingtai.cn
             * description: 
             * 这里根据之前的判断,选择调用新建、删除、更新还是不操作索引
             */
            String opt=requestJSONObject.optString(Article.ARTICLE_DISPLAYABLE_INDEX_OPT);
            if(Article.ARTICLE_DISPLAYABLE_INDEX_OPT_DELETE.equals(opt)){
                //删除
                if (Symphonys.ALGOLIA_ENABLED) {
                    searchMgmtService.removeAlgoliaDocument(articleToUpdate);
                }

                if (Symphonys.ES_ENABLED) {
                    searchMgmtService.removeESDocument(articleToUpdate, Article.ARTICLE);
                }
            }else if(Article.ARTICLE_DISPLAYABLE_INDEX_OPT_ADD.equals(opt)){
                //新建
                eventData.put(Article.ARTICLE, articleToUpdate);
                eventData.put(Article.ARTICLE_T_NOTIFY_FOLLOWERS, requestJSONObject.optBoolean(Article.ARTICLE_T_NOTIFY_FOLLOWERS));
                eventManager.fireEventAsynchronously(new Event<>(EventTypes.ADD_ARTICLE, eventData));
            }else if(Article.ARTICLE_DISPLAYABLE_INDEX_OPT_UPDATE.equals(opt)){
                //更新
                eventData.put(Article.ARTICLE, articleToUpdate);
                eventData.put(Common.OLD_ARTICLE, oldArticle);
                eventData.put(Article.ARTICLE_T_NOTIFY_FOLLOWERS, requestJSONObject.optBoolean(Article.ARTICLE_T_NOTIFY_FOLLOWERS));
                eventManager.fireEventAsynchronously(new Event<>(EventTypes.UPDATE_ARTICLE, eventData));
            }else{
                //不操作
                return;
            }

        } catch (final Exception e) {
            if (transaction.isActive()) {
                transaction.rollback();
            }

            LOGGER.log(Level.ERROR, "Updates an article failed", e);
            throw new ServiceException(e);
        }
    }

管理员添加帖子

/admin/add-article

管理员添加的帖子默认在列表中展示,如果不需要在列表中展示,可以在帖子修改页面进行修改。

    @RequestProcessing(value = "/admin/add-article", method = HttpMethod.POST)
    @Before({StopwatchStartAdvice.class, PermissionCheck.class})
    @After({PermissionGrant.class, StopwatchEndAdvice.class})
    public void addArticle(final RequestContext context) {
        final HttpServletRequest request = context.getRequest();

        final String userName = context.param(User.USER_NAME);
        final JSONObject author = userQueryService.getUserByName(userName);
        if (null == author) {
            final AbstractFreeMarkerRenderer renderer = new SkinRenderer(context, "admin/error.ftl");
            final Map<String, Object> dataModel = renderer.getDataModel();
            dataModel.put(Keys.MSG, langPropsService.get("notFoundUserLabel"));
            dataModelService.fillHeaderAndFooter(context, dataModel);

            return;
        }

        final String timeStr = context.param(Common.TIME);
        final String articleTitle = context.param(Article.ARTICLE_TITLE);
        final String articleTags = context.param(Article.ARTICLE_TAGS);
        final String articleContent = context.param(Article.ARTICLE_CONTENT);
        String rewardContent = context.param(Article.ARTICLE_REWARD_CONTENT);
        final String rewardPoint = context.param(Article.ARTICLE_REWARD_POINT);
        /**
         * create by: qiankunpingtai
         * create time: 2019/5/14 18:11
         * website:https://qiankunpingtai.cn
         * description:
         * 添加是否在列表中展示项
         * 管理员添加的帖子默认在列表中展示,如果不需要在列表中展示,可以在帖子修改页面进行修改。
         */
        final Integer articleDisplayable = Article.ARTICLE_DISPLAYABLE_YES;

        long time = System.currentTimeMillis();

        try {
            final Date date = DateUtils.parseDate(timeStr, new String[]{"yyyy-MM-dd'T'HH:mm"});

            time = date.getTime();
            final int random = RandomUtils.nextInt(9999);
            time += random;
        } catch (final ParseException e) {
            LOGGER.log(Level.ERROR, "Parse time failed, using current time instead");
        }

        final JSONObject article = new JSONObject();
        article.put(Article.ARTICLE_TITLE, articleTitle);
        article.put(Article.ARTICLE_TAGS, articleTags);
        article.put(Article.ARTICLE_CONTENT, articleContent);
        article.put(Article.ARTICLE_REWARD_CONTENT, rewardContent);
        article.put(Article.ARTICLE_REWARD_POINT, Integer.valueOf(rewardPoint));
        article.put(User.USER_NAME, userName);
        article.put(Common.TIME, time);
        article.put(Article.ARTICLE_DISPLAYABLE,articleDisplayable);

        try {
            final String articleId = articleMgmtService.addArticleByAdmin(article);
            operationMgmtService.addOperation(Operation.newOperation(request, Operation.OPERATION_CODE_C_ADD_ARTICLE, articleId));
        } catch (final ServiceException e) {
            final AbstractFreeMarkerRenderer renderer = new SkinRenderer(context, "admin/error.ftl");
            final Map<String, Object> dataModel = renderer.getDataModel();
            dataModel.put(Keys.MSG, e.getMessage());
            dataModelService.fillHeaderAndFooter(context, dataModel);

            return;
        }

        context.sendRedirect(Latkes.getServePath() + "/admin/articles");
    }

下一篇 添加帖子是否展示的功能(二)查询最新帖、领域贴、问答帖