mirror of https://github.com/halo-dev/halo
				
				
				
			🍎 新增评论盖楼,管理员回复评论可使用表情。
							parent
							
								
									e31b6d9d24
								
							
						
					
					
						commit
						005a7e4f96
					
				| 
						 | 
				
			
			@ -6,6 +6,7 @@ import lombok.Data;
 | 
			
		|||
import javax.persistence.*;
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * <pre>
 | 
			
		||||
| 
						 | 
				
			
			@ -93,4 +94,10 @@ public class Comment implements Serializable {
 | 
			
		|||
     * 是否是博主的评论 0:不是 1:是
 | 
			
		||||
     */
 | 
			
		||||
    private Integer isAdmin;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 当前评论下的所有子评论
 | 
			
		||||
     */
 | 
			
		||||
    @Transient
 | 
			
		||||
    private List<Comment> childComments;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,61 @@
 | 
			
		|||
package cc.ryanc.halo.utils;
 | 
			
		||||
 | 
			
		||||
import cc.ryanc.halo.model.domain.Comment;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author : RYAN0UP
 | 
			
		||||
 * @date : 2018/7/12
 | 
			
		||||
 */
 | 
			
		||||
public class CommentUtil {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取组装好的评论
 | 
			
		||||
     *
 | 
			
		||||
     * @param commentsRoot commentsRoot
 | 
			
		||||
     * @return List
 | 
			
		||||
     */
 | 
			
		||||
    public static List<Comment> getComments(List<Comment> commentsRoot) {
 | 
			
		||||
        List<Comment> commentsResult = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < commentsRoot.size(); i++) {
 | 
			
		||||
            if (commentsRoot.get(i).getCommentParent() == 0) {
 | 
			
		||||
                commentsResult.add(commentsRoot.get(i));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (Comment comment : commentsResult) {
 | 
			
		||||
            comment.setChildComments(getChild(comment.getCommentId(), commentsRoot));
 | 
			
		||||
        }
 | 
			
		||||
        return commentsResult;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取评论的子评论
 | 
			
		||||
     *
 | 
			
		||||
     * @param id           评论编号
 | 
			
		||||
     * @param commentsRoot commentsRoot
 | 
			
		||||
     * @return List
 | 
			
		||||
     */
 | 
			
		||||
    private static List<Comment> getChild(Long id, List<Comment> commentsRoot) {
 | 
			
		||||
        List<Comment> commentsChild = new ArrayList<>();
 | 
			
		||||
        for (Comment comment : commentsRoot) {
 | 
			
		||||
            if (comment.getCommentParent() != 0) {
 | 
			
		||||
                if (comment.getCommentParent().equals(id)) {
 | 
			
		||||
                    commentsChild.add(comment);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        for (Comment comment : commentsChild) {
 | 
			
		||||
            if (comment.getCommentParent() != 0) {
 | 
			
		||||
                comment.setChildComments(getChild(comment.getCommentId(), commentsRoot));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (commentsChild.size() == 0) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        return commentsChild;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ import cc.ryanc.halo.service.CommentService;
 | 
			
		|||
import cc.ryanc.halo.service.MailService;
 | 
			
		||||
import cc.ryanc.halo.service.PostService;
 | 
			
		||||
import cc.ryanc.halo.service.UserService;
 | 
			
		||||
import cc.ryanc.halo.utils.OwoUtil;
 | 
			
		||||
import cc.ryanc.halo.web.controller.core.BaseController;
 | 
			
		||||
import cn.hutool.core.date.DateUtil;
 | 
			
		||||
import cn.hutool.core.lang.Validator;
 | 
			
		||||
| 
						 | 
				
			
			@ -196,8 +197,8 @@ public class CommentController extends BaseController {
 | 
			
		|||
            comment.setCommentAuthorIp(ServletUtil.getClientIP(request));
 | 
			
		||||
            comment.setCommentAuthorAvatarMd5(SecureUtil.md5(user.getUserEmail()));
 | 
			
		||||
            comment.setCommentDate(DateUtil.date());
 | 
			
		||||
            String lastContent = " //<a href='#comment-id-" + lastComment.getCommentId() + "'>@" + lastComment.getCommentAuthor() + "</a>:" + lastComment.getCommentContent();
 | 
			
		||||
            comment.setCommentContent(commentContent + lastContent);
 | 
			
		||||
            String lastContent = "<a href='#comment-id-" + lastComment.getCommentId() + "'>@" + lastComment.getCommentAuthor() + "</a> ";
 | 
			
		||||
            comment.setCommentContent(lastContent + OwoUtil.markToImg(commentContent));
 | 
			
		||||
            comment.setCommentAgent(userAgent);
 | 
			
		||||
            comment.setCommentParent(commentId);
 | 
			
		||||
            comment.setCommentStatus(0);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ import cc.ryanc.halo.model.domain.Post;
 | 
			
		|||
import cc.ryanc.halo.model.enums.PostType;
 | 
			
		||||
import cc.ryanc.halo.service.CommentService;
 | 
			
		||||
import cc.ryanc.halo.service.PostService;
 | 
			
		||||
import cc.ryanc.halo.utils.CommentUtil;
 | 
			
		||||
import cc.ryanc.halo.web.controller.core.BaseController;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
| 
						 | 
				
			
			@ -119,7 +120,7 @@ public class FrontArchiveController extends BaseController {
 | 
			
		|||
        Pageable pageable = PageRequest.of(0,999,sort);
 | 
			
		||||
        Page<Comment> comments = commentService.findCommentsByPostAndCommentStatus(post,pageable,0);
 | 
			
		||||
        model.addAttribute("post", post);
 | 
			
		||||
        model.addAttribute("comments",comments);
 | 
			
		||||
        model.addAttribute("comments", CommentUtil.getComments(comments.getContent()));
 | 
			
		||||
        postService.updatePostView(post);
 | 
			
		||||
        return this.render("post");
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ import cc.ryanc.halo.service.CommentService;
 | 
			
		|||
import cc.ryanc.halo.service.MailService;
 | 
			
		||||
import cc.ryanc.halo.service.PostService;
 | 
			
		||||
import cc.ryanc.halo.service.UserService;
 | 
			
		||||
import cc.ryanc.halo.utils.CommentUtil;
 | 
			
		||||
import cc.ryanc.halo.utils.OwoUtil;
 | 
			
		||||
import cn.hutool.core.date.DateUtil;
 | 
			
		||||
import cn.hutool.core.lang.Validator;
 | 
			
		||||
| 
						 | 
				
			
			@ -30,8 +31,6 @@ import java.util.HashMap;
 | 
			
		|||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import java.util.regex.Matcher;
 | 
			
		||||
import java.util.regex.Pattern;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author : RYAN0UP
 | 
			
		||||
| 
						 | 
				
			
			@ -64,12 +63,12 @@ public class FrontCommentController {
 | 
			
		|||
    public List<Comment> getComment(@PathVariable Long postId) {
 | 
			
		||||
        Optional<Post> post = postService.findByPostId(postId);
 | 
			
		||||
        Sort sort = new Sort(Sort.Direction.DESC, "commentDate");
 | 
			
		||||
        Pageable pageable = PageRequest.of(0, 10, sort);
 | 
			
		||||
        List<Comment> comments = commentService.findCommentsByPostAndCommentStatus(post.get(), pageable, 2).getContent();
 | 
			
		||||
        Pageable pageable = PageRequest.of(0, 999, sort);
 | 
			
		||||
        List<Comment> comments = commentService.findCommentsByPostAndCommentStatus(post.get(), pageable, 0).getContent();
 | 
			
		||||
        if (null == comments) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        return comments;
 | 
			
		||||
        return CommentUtil.getComments(comments);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -113,8 +112,8 @@ public class FrontCommentController {
 | 
			
		|||
            comment.setCommentAuthor(HtmlUtil.encode(comment.getCommentAuthor()));
 | 
			
		||||
            if(comment.getCommentParent()>0){
 | 
			
		||||
                lastComment = commentService.findCommentById(comment.getCommentParent()).get();
 | 
			
		||||
                String lastContent = " //<a href='#comment-id-"+lastComment.getCommentId()+"'>@"+lastComment.getCommentAuthor()+"</a>:"+lastComment.getCommentContent();
 | 
			
		||||
                comment.setCommentContent(StringUtils.substringAfter(OwoUtil.markToImg(HtmlUtil.encode(comment.getCommentContent())),":")+lastContent);
 | 
			
		||||
                String lastContent = "<a href='#comment-id-" + lastComment.getCommentId() + "'>@" + lastComment.getCommentAuthor() + "</a>";
 | 
			
		||||
                comment.setCommentContent(lastContent + StringUtils.substringAfter(OwoUtil.markToImg(HtmlUtil.encode(comment.getCommentContent())), ":"));
 | 
			
		||||
            }else{
 | 
			
		||||
                //将评论内容的字符专为安全字符
 | 
			
		||||
                comment.setCommentContent(OwoUtil.markToImg(HtmlUtil.encode(comment.getCommentContent())));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ import cc.ryanc.halo.model.enums.PostType;
 | 
			
		|||
import cc.ryanc.halo.service.CommentService;
 | 
			
		||||
import cc.ryanc.halo.service.GalleryService;
 | 
			
		||||
import cc.ryanc.halo.service.PostService;
 | 
			
		||||
import cc.ryanc.halo.utils.CommentUtil;
 | 
			
		||||
import cc.ryanc.halo.web.controller.core.BaseController;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.data.domain.Page;
 | 
			
		||||
| 
						 | 
				
			
			@ -75,7 +76,7 @@ public class FrontPageController extends BaseController {
 | 
			
		|||
        if(null==post){
 | 
			
		||||
            return this.renderNotFound();
 | 
			
		||||
        }
 | 
			
		||||
        model.addAttribute("comments",comments);
 | 
			
		||||
        model.addAttribute("comments", CommentUtil.getComments(comments.getContent()));
 | 
			
		||||
        model.addAttribute("post", post);
 | 
			
		||||
        postService.updatePostView(post);
 | 
			
		||||
        return this.render("page");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -130,7 +130,8 @@
 | 
			
		|||
                    </div>
 | 
			
		||||
                    <form method="post" action="/admin/comments/reply">
 | 
			
		||||
                        <div class="modal-body">
 | 
			
		||||
                            <textarea class="form-control" rows="5" id="commentContent" name="commentContent" style="resize: none"></textarea>
 | 
			
		||||
                            <textarea class="form-control comment-input-content" rows="5" id="commentContent" name="commentContent" style="resize: none"></textarea>
 | 
			
		||||
                            <div class="OwO"></div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div class="modal-footer">
 | 
			
		||||
                            <input type="hidden" id="commentId" name="commentId" value=""/>
 | 
			
		||||
| 
						 | 
				
			
			@ -144,6 +145,14 @@
 | 
			
		|||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <script>
 | 
			
		||||
            var s = new OwO({
 | 
			
		||||
                container: document.getElementsByClassName('OwO')[0],
 | 
			
		||||
                target: document.getElementsByClassName('comment-input-content')[0],
 | 
			
		||||
                position: 'down',
 | 
			
		||||
                width: '100%',
 | 
			
		||||
                maxHeight: '210px',
 | 
			
		||||
                api:"/static/plugins/OwO/OwO.min.json"
 | 
			
		||||
            });
 | 
			
		||||
            function modelShow(url,message) {
 | 
			
		||||
                $('#url').val(url);
 | 
			
		||||
                $('#message').html(message);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,12 +15,14 @@
 | 
			
		|||
    <link rel="stylesheet" href="/static/css/loader.css">
 | 
			
		||||
    <link rel="stylesheet" href="/static/plugins/toast/css/jquery.toast.min.css">
 | 
			
		||||
    <link rel="stylesheet" href="/static/plugins/fileinput/fileinput.min.css">
 | 
			
		||||
    <link type="text/css" rel="stylesheet" href="/static/plugins/OwO/OwO.min.css">
 | 
			
		||||
    <!--[if lt IE 9]>
 | 
			
		||||
    <script src="//oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
 | 
			
		||||
    <script src="//oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
 | 
			
		||||
    <![endif]-->
 | 
			
		||||
    <script src="/static/plugins/jquery/jquery.min.js"></script>
 | 
			
		||||
    <script src="/static/plugins/bootstrap/js/bootstrap.min.js"></script>
 | 
			
		||||
    <script src="/static/plugins/OwO/OwO.min.js"></script>
 | 
			
		||||
</head>
 | 
			
		||||
<body class="hold-transition sidebar-mini ${options.admin_theme?default('skin-blue')} ${options.admin_layout?default('')} ${options.sidebar_style?default('')}">
 | 
			
		||||
<#if options.admin_loading?default("false") == "true">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -223,6 +223,12 @@
 | 
			
		|||
        .comment-input-who, .comment-input-email, .comment-input-website {
 | 
			
		||||
            width: 100% !important;
 | 
			
		||||
        }
 | 
			
		||||
        .ua{
 | 
			
		||||
            display: none!important;
 | 
			
		||||
        }
 | 
			
		||||
        .native-list{
 | 
			
		||||
            margin-left: 5px!important;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
</style>
 | 
			
		||||
<div class="native-comment">
 | 
			
		||||
| 
						 | 
				
			
			@ -248,11 +254,12 @@
 | 
			
		|||
    </div>
 | 
			
		||||
    <div class="native-message" style="text-align: center;padding: 20px;display: none"></div>
 | 
			
		||||
    <div class="native-info">
 | 
			
		||||
        <span id="native-info-total" style="font-weight: 600">${comments.getTotalElements()}</span>评论
 | 
			
		||||
        <#--<span id="native-info-total" style="font-weight: 600">${comments.getTotalElements()}</span>评论-->
 | 
			
		||||
    </div>
 | 
			
		||||
    <ul class="native-list">
 | 
			
		||||
        <#if comments.content?? && comments.content?size gt 0>
 | 
			
		||||
            <#list comments.content as comment>
 | 
			
		||||
    <#macro childComments comments>
 | 
			
		||||
        <ul class="native-list" style="margin-left: 20px; border-left: 1px solid #f1f1f1">
 | 
			
		||||
        <#if comments?? && comments?size gt 0>
 | 
			
		||||
            <#list comments as comment>
 | 
			
		||||
                <li class="native-list-one" id="comment-id-${comment.commentId?c}">
 | 
			
		||||
                    <img class="native-list-one-img" src="//www.gravatar.com/avatar/${comment.commentAuthorAvatarMd5?if_exists}?s=256&d=${options.native_comment_avatar?default('mm')}">
 | 
			
		||||
                    <section>
 | 
			
		||||
| 
						 | 
				
			
			@ -271,6 +278,38 @@
 | 
			
		|||
                            <span at="${comment.commentId?c}" class="native-list-one-footer-reback">回复</span>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </section>
 | 
			
		||||
                <#if comment.childComments?? && comment.childComments?size gt 0>
 | 
			
		||||
                    <@childComments comment.childComments></@childComments>
 | 
			
		||||
                </#if>
 | 
			
		||||
                </li>
 | 
			
		||||
            </#list>
 | 
			
		||||
        </#if>
 | 
			
		||||
        </ul>
 | 
			
		||||
    </#macro>
 | 
			
		||||
    <ul class="native-list">
 | 
			
		||||
        <#if comments?? && comments?size gt 0>
 | 
			
		||||
            <#list comments as comment>
 | 
			
		||||
                <li class="native-list-one" id="comment-id-${comment.commentId?c}">
 | 
			
		||||
                    <img class="native-list-one-img" src="//www.gravatar.com/avatar/${comment.commentAuthorAvatarMd5?if_exists}?s=256&d=${options.native_comment_avatar?default('mm')}">
 | 
			
		||||
                    <section>
 | 
			
		||||
                        <div class="native-list-one-head">
 | 
			
		||||
                            <a class="native-list-one-head-name" rel="nofollow" href="${comment.commentAuthorUrl?if_exists}">${comment.commentAuthor?if_exists}</a>
 | 
			
		||||
                            <span class="native-comment-ua-info" style="display: none">${comment.commentAgent?if_exists}</span>
 | 
			
		||||
                            <#if comment.isAdmin==1>
 | 
			
		||||
                                <label class="native-list-one-head-admin">博主</label>
 | 
			
		||||
                            </#if>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div class="native-list-one-content">
 | 
			
		||||
                            <p>${comment.commentContent?if_exists}</p>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div class="native-list-one-footer">
 | 
			
		||||
                            <span class="native-list-one-footer-time">${comment.commentDate?string("yyyy-MM-dd HH:mm")}</span>
 | 
			
		||||
                            <span at="${comment.commentId?c}" class="native-list-one-footer-reback">回复</span>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </section>
 | 
			
		||||
                <#if comment.childComments?? && comment.childComments?size gt 0>
 | 
			
		||||
                    <@childComments comment.childComments></@childComments>
 | 
			
		||||
                </#if>
 | 
			
		||||
                </li>
 | 
			
		||||
            </#list>
 | 
			
		||||
        </#if>
 | 
			
		||||
| 
						 | 
				
			
			@ -376,4 +415,4 @@
 | 
			
		|||
        return '<span class="ua">'+browser+'</span><span class="ua">'+os+'</span>';
 | 
			
		||||
    }
 | 
			
		||||
</script>
 | 
			
		||||
</@compress>
 | 
			
		||||
</@compress>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue