From 02fb81912036b80d11680c1f7921356410493f68 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <1179705413@qq.com> Date: Sat, 12 Jul 2025 11:15:35 +0800 Subject: [PATCH] =?UTF-8?q?feat(novel-front):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E8=AF=84=E8=AE=BA=E5=9B=9E=E5=A4=8D=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/sql/20250712.sql | 13 ++ doc/sql/novel_plus.sql | 15 ++ .../novel/controller/BookController.java | 34 +++- .../novel/controller/page/PageController.java | 10 ++ .../novel/mapper/FrontBookCommentMapper.java | 1 + .../mapper/FrontBookCommentReplyMapper.java | 16 ++ .../java2nb/novel/service/BookService.java | 16 +- .../novel/service/impl/BookServiceImpl.java | 29 ++- .../java2nb/novel/vo/BookCommentReplyVO.java | 30 ++++ .../mybatis/mapping/BookCommentMapper.xml | 7 + .../mapping/BookCommentReplyMapper.xml | 23 +++ .../src/main/resources/static/css/base.css | 10 ++ .../resources/static/javascript/bookdetail.js | 46 +++++ .../templates/book/book_comment.html | 11 +- .../templates/book/book_comment_reply.html | 165 ++++++++++++++++++ .../resources/templates/book/book_detail.html | 86 ++++++--- 16 files changed, 465 insertions(+), 47 deletions(-) create mode 100644 doc/sql/20250712.sql create mode 100644 novel-front/src/main/java/com/java2nb/novel/mapper/FrontBookCommentReplyMapper.java create mode 100644 novel-front/src/main/java/com/java2nb/novel/vo/BookCommentReplyVO.java create mode 100644 novel-front/src/main/resources/mybatis/mapping/BookCommentReplyMapper.xml create mode 100644 novel-front/src/main/resources/templates/book/book_comment_reply.html diff --git a/doc/sql/20250712.sql b/doc/sql/20250712.sql new file mode 100644 index 0000000..d2eb17a --- /dev/null +++ b/doc/sql/20250712.sql @@ -0,0 +1,13 @@ +DROP TABLE IF EXISTS `book_comment_reply`; +CREATE TABLE `book_comment_reply` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', + `comment_id` bigint(20) DEFAULT NULL COMMENT '评论ID', + `reply_content` varchar(512) DEFAULT NULL COMMENT '回复内容', + `location` varchar(50) DEFAULT NULL COMMENT '地理位置', + `audit_status` tinyint(1) DEFAULT '0' COMMENT '审核状态,0:待审核,1:审核通过,2:审核不通过', + `create_time` datetime DEFAULT NULL COMMENT '回复用户ID', + `create_user_id` bigint(20) DEFAULT NULL COMMENT '回复时间', + PRIMARY KEY (`id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 COMMENT ='小说评论回复表'; \ No newline at end of file diff --git a/doc/sql/novel_plus.sql b/doc/sql/novel_plus.sql index 53bc41e..577d3fd 100644 --- a/doc/sql/novel_plus.sql +++ b/doc/sql/novel_plus.sql @@ -3160,3 +3160,18 @@ alter table book_comment add column location varchar(50) DEFAULT NULL COMMENT ' alter table crawl_single_task add column crawl_chapters int DEFAULT 0 COMMENT '采集章节数量' after exc_count ; + + +DROP TABLE IF EXISTS `book_comment_reply`; +CREATE TABLE `book_comment_reply` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', + `comment_id` bigint(20) DEFAULT NULL COMMENT '评论ID', + `reply_content` varchar(512) DEFAULT NULL COMMENT '回复内容', + `location` varchar(50) DEFAULT NULL COMMENT '地理位置', + `audit_status` tinyint(1) DEFAULT '0' COMMENT '审核状态,0:待审核,1:审核通过,2:审核不通过', + `create_time` datetime DEFAULT NULL COMMENT '回复用户ID', + `create_user_id` bigint(20) DEFAULT NULL COMMENT '回复时间', + PRIMARY KEY (`id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 COMMENT ='小说评论回复表'; \ No newline at end of file diff --git a/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java b/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java index 65dcf97..3eea52e 100644 --- a/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java +++ b/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java @@ -3,17 +3,11 @@ package com.java2nb.novel.controller; import com.java2nb.novel.core.bean.UserDetails; import com.java2nb.novel.core.enums.ResponseStatus; import com.java2nb.novel.core.utils.IpUtil; -import com.java2nb.novel.entity.Book; -import com.java2nb.novel.entity.BookCategory; -import com.java2nb.novel.entity.BookComment; -import com.java2nb.novel.entity.BookIndex; +import com.java2nb.novel.entity.*; import com.java2nb.novel.service.BookContentService; import com.java2nb.novel.service.BookService; import com.java2nb.novel.service.IpLocationService; -import com.java2nb.novel.vo.BookCommentVO; -import com.java2nb.novel.vo.BookSettingVO; -import com.java2nb.novel.vo.BookSpVO; -import com.java2nb.novel.vo.BookVO; +import com.java2nb.novel.vo.*; import io.github.xxyopen.model.page.PageBean; import io.github.xxyopen.model.page.builder.pagehelper.PageBuilder; import io.github.xxyopen.model.resp.RestResult; @@ -153,6 +147,16 @@ public class BookController extends BaseController { return RestResult.ok(bookService.listCommentByPage(null, bookId, page, pageSize)); } + /** + * 分页查询评论回复列表 + */ + @GetMapping("listCommentReplyByPage") + public RestResult> listCommentReplyByPage(@RequestParam("commentId") Long commentId, + @RequestParam(value = "curr", defaultValue = "1") int page, + @RequestParam(value = "limit", defaultValue = "5") int pageSize) { + return RestResult.ok(bookService.listCommentReplyByPage(null, commentId, page, pageSize)); + } + /** * 新增评价 */ @@ -167,6 +171,20 @@ public class BookController extends BaseController { return RestResult.ok(); } + /** + * 新增回复 + */ + @PostMapping("addCommentReply") + public RestResult addCommentReply(BookCommentReply commentReply, HttpServletRequest request) { + UserDetails userDetails = getUserDetails(request); + if (userDetails == null) { + return RestResult.fail(ResponseStatus.NO_LOGIN); + } + commentReply.setLocation(ipLocationService.getLocation(IpUtil.getRealIp(request))); + bookService.addBookCommentReply(userDetails.getId(), commentReply); + return RestResult.ok(); + } + /** * 根据小说ID查询小说前十条最新更新目录集合 */ diff --git a/novel-front/src/main/java/com/java2nb/novel/controller/page/PageController.java b/novel-front/src/main/java/com/java2nb/novel/controller/page/PageController.java index 765b07e..11b9e14 100644 --- a/novel-front/src/main/java/com/java2nb/novel/controller/page/PageController.java +++ b/novel-front/src/main/java/com/java2nb/novel/controller/page/PageController.java @@ -313,6 +313,16 @@ public class PageController extends BaseController { return "book/book_comment"; } + /** + * 评论回复页面 + */ + @RequestMapping("/book/reply-{commentId}.html") + public String commentReplyList(@PathVariable("commentId") Long commentId, Model model) { + model.addAttribute("commentId", commentId); + model.addAttribute("commentContent", bookService.getBookComment(commentId).getCommentContent()); + return "book/book_comment_reply"; + } + /** * 新闻内容页面 */ diff --git a/novel-front/src/main/java/com/java2nb/novel/mapper/FrontBookCommentMapper.java b/novel-front/src/main/java/com/java2nb/novel/mapper/FrontBookCommentMapper.java index 920a73f..8c82df0 100644 --- a/novel-front/src/main/java/com/java2nb/novel/mapper/FrontBookCommentMapper.java +++ b/novel-front/src/main/java/com/java2nb/novel/mapper/FrontBookCommentMapper.java @@ -12,4 +12,5 @@ public interface FrontBookCommentMapper extends BookCommentMapper { List listCommentByPage(@Param("userId") Long userId, @Param("bookId") Long bookId); + void addReplyCount(@Param("commentId") Long commentId); } diff --git a/novel-front/src/main/java/com/java2nb/novel/mapper/FrontBookCommentReplyMapper.java b/novel-front/src/main/java/com/java2nb/novel/mapper/FrontBookCommentReplyMapper.java new file mode 100644 index 0000000..bbcce79 --- /dev/null +++ b/novel-front/src/main/java/com/java2nb/novel/mapper/FrontBookCommentReplyMapper.java @@ -0,0 +1,16 @@ +package com.java2nb.novel.mapper; + +import com.java2nb.novel.vo.BookCommentReplyVO; +import com.java2nb.novel.vo.BookCommentVO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * @author Administrator + */ +public interface FrontBookCommentReplyMapper extends BookCommentReplyMapper { + + List listCommentReplyByPage(@Param("userId") Long userId, @Param("commentId") Long commentId); + +} diff --git a/novel-front/src/main/java/com/java2nb/novel/service/BookService.java b/novel-front/src/main/java/com/java2nb/novel/service/BookService.java index eff1a61..900ebca 100644 --- a/novel-front/src/main/java/com/java2nb/novel/service/BookService.java +++ b/novel-front/src/main/java/com/java2nb/novel/service/BookService.java @@ -1,12 +1,9 @@ package com.java2nb.novel.service; +import com.java2nb.novel.vo.*; import io.github.xxyopen.model.page.PageBean; import com.java2nb.novel.entity.*; -import com.java2nb.novel.vo.BookCommentVO; -import com.java2nb.novel.vo.BookSettingVO; -import com.java2nb.novel.vo.BookSpVO; -import com.java2nb.novel.vo.BookVO; import java.util.Date; import java.util.List; @@ -295,4 +292,15 @@ public interface BookService { * 查询AI生成图片 */ String queryAiGenPic(Long bookId); + + /** + * 新增回复 + * @param userId 用户ID + * @param commentReply 回复内容 + * */ + void addBookCommentReply(Long userId, BookCommentReply commentReply); + + PageBean listCommentReplyByPage(Long userId, Long commentId, int page, int pageSize); + + BookComment getBookComment(Long commentId); } diff --git a/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java b/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java index f899bc0..1dc3c80 100644 --- a/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java +++ b/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java @@ -15,10 +15,7 @@ import com.java2nb.novel.mapper.*; import com.java2nb.novel.service.AuthorService; import com.java2nb.novel.service.BookService; import com.java2nb.novel.service.FileService; -import com.java2nb.novel.vo.BookCommentVO; -import com.java2nb.novel.vo.BookSettingVO; -import com.java2nb.novel.vo.BookSpVO; -import com.java2nb.novel.vo.BookVO; +import com.java2nb.novel.vo.*; import io.github.xxyopen.model.page.PageBean; import io.github.xxyopen.model.page.builder.pagehelper.PageBuilder; import io.github.xxyopen.util.IdWorker; @@ -87,6 +84,8 @@ public class BookServiceImpl implements BookService { private final FrontBookCommentMapper bookCommentMapper; + private final FrontBookCommentReplyMapper bookCommentReplyMapper; + private final BookAuthorMapper bookAuthorMapper; private final CacheService cacheService; @@ -888,5 +887,27 @@ public class BookServiceImpl implements BookService { return cacheService.get(CacheKey.AI_GEN_PIC + bookId); } + @Transactional(rollbackFor = Exception.class) + @Override + public void addBookCommentReply(Long userId, BookCommentReply commentReply) { + //增加回复 + commentReply.setCreateUserId(userId); + commentReply.setCreateTime(new Date()); + bookCommentReplyMapper.insertSelective(commentReply); + //增加评论回复数 + bookCommentMapper.addReplyCount(commentReply.getCommentId()); + } + + @Override + public PageBean listCommentReplyByPage(Long userId, Long commentId, int page, int pageSize) { + PageHelper.startPage(page, pageSize); + return PageBuilder.build(bookCommentReplyMapper.listCommentReplyByPage(userId, commentId)); + } + + @Override + public BookComment getBookComment(Long commentId) { + return bookCommentMapper.selectByPrimaryKey(commentId).orElse(null); + } + } \ No newline at end of file diff --git a/novel-front/src/main/java/com/java2nb/novel/vo/BookCommentReplyVO.java b/novel-front/src/main/java/com/java2nb/novel/vo/BookCommentReplyVO.java new file mode 100644 index 0000000..8ff7890 --- /dev/null +++ b/novel-front/src/main/java/com/java2nb/novel/vo/BookCommentReplyVO.java @@ -0,0 +1,30 @@ +package com.java2nb.novel.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.java2nb.novel.core.serialize.CommentUserNameSerialize; +import com.java2nb.novel.entity.BookComment; +import com.java2nb.novel.entity.BookCommentReply; +import lombok.Data; + +import java.util.Date; + +/** + * @author 11797 + */ +@Data +public class BookCommentReplyVO extends BookCommentReply { + + @JsonSerialize(using = CommentUserNameSerialize.class) + private String createUserName; + + private String createUserPhoto; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + @Override + public String toString() { + return super.toString(); + } +} diff --git a/novel-front/src/main/resources/mybatis/mapping/BookCommentMapper.xml b/novel-front/src/main/resources/mybatis/mapping/BookCommentMapper.xml index eaa0fe9..0720d05 100644 --- a/novel-front/src/main/resources/mybatis/mapping/BookCommentMapper.xml +++ b/novel-front/src/main/resources/mybatis/mapping/BookCommentMapper.xml @@ -19,5 +19,12 @@ + + update book_comment + set reply_count = reply_count + 1 + where id = #{commentId} + + + \ No newline at end of file diff --git a/novel-front/src/main/resources/mybatis/mapping/BookCommentReplyMapper.xml b/novel-front/src/main/resources/mybatis/mapping/BookCommentReplyMapper.xml new file mode 100644 index 0000000..43624c7 --- /dev/null +++ b/novel-front/src/main/resources/mybatis/mapping/BookCommentReplyMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + + + \ No newline at end of file diff --git a/novel-front/src/main/resources/static/css/base.css b/novel-front/src/main/resources/static/css/base.css index 1246d57..a340870 100644 --- a/novel-front/src/main/resources/static/css/base.css +++ b/novel-front/src/main/resources/static/css/base.css @@ -964,4 +964,14 @@ i.vip_b { .userBox { margin: 0 auto +} + + +.layui-elem-quote { + margin-bottom: 10px; + padding: 15px; + line-height: 1.8; + border-left: 5px solid #16b777; + border-radius: 0 2px 2px 0; + background-color: #fafafa; } \ No newline at end of file diff --git a/novel-front/src/main/resources/static/javascript/bookdetail.js b/novel-front/src/main/resources/static/javascript/bookdetail.js index 7e78c68..a0bf95c 100644 --- a/novel-front/src/main/resources/static/javascript/bookdetail.js +++ b/novel-front/src/main/resources/static/javascript/bookdetail.js @@ -133,6 +133,52 @@ }) + }, + + SaveCommentReply: function (cmtBId, cmtCId, cmtDetail) { + if (!isLogin) { + layer.alert('请先登陆'); + return; + } + var cmtDetailTemp = cmtDetail.replace(/(^\s*)/g, ""); + if (cmtDetailTemp == '') { + layer.alert('回复内容必须填写'); + return; + } + if (cmtDetailTemp.length < 5) { + layer.alert('回复内容必须大于5个字'); + return; + } + if (cmtDetail.length < 5) { + layer.alert('回复内容必须大于5个字'); + return; + } + $.ajax({ + type: "POST", + url: "/book/addCommentReply", + data: {'commentId': $("#commentId").val(), 'replyContent': cmtDetail}, + dataType: "json", + success: function (data) { + if (data.code == 200) { + $('#txtComment').val("") + layer.alert('回复成功!'); + loadCommentList(1, 20); + + } else if (data.code == 1001) { + //未登录 + location.href = '/user/login.html?originUrl=' + encodeURIComponent(location.href); + + } else { + layer.alert(data.msg); + } + + }, + error: function () { + layer.alert('网络异常'); + } + }) + + }, GetFavoritesBook: function (BId) { }, diff --git a/novel-front/src/main/resources/templates/book/book_comment.html b/novel-front/src/main/resources/templates/book/book_comment.html index 22647f4..3ab30d2 100644 --- a/novel-front/src/main/resources/templates/book/book_comment.html +++ b/novel-front/src/main/resources/templates/book/book_comment.html @@ -114,9 +114,9 @@ $('#txtComment').val($('#txtComment').val().substring(0, 1000)); } }); - searchComments(1, 20); + loadCommentList(1, 20); - function searchComments(curr, limit) { + function loadCommentList(curr, limit) { $.ajax({ type: "get", @@ -139,8 +139,11 @@ comment.commentContent+ "
  • " + ""+comment.createTime+"" + - "(0)" + - "
  • \t\t\t"); + "(0)" + + "(0)" + + "回复("+comment.replyCount+ + ")" + + "\t\t\t"); } $("#commentPanel").html(commentListHtml); diff --git a/novel-front/src/main/resources/templates/book/book_comment_reply.html b/novel-front/src/main/resources/templates/book/book_comment_reply.html new file mode 100644 index 0000000..d8c1d9c --- /dev/null +++ b/novel-front/src/main/resources/templates/book/book_comment_reply.html @@ -0,0 +1,165 @@ + + + + + + + + + + + +
    +
    + +
    +
    + +
    +
    +
    + +
    +
    +
    +

    评论回复区

    (0条) +
    + 发表回复 +
    +
    +
    + +
    + +
    +
    +
    + +
    +
    + 发表回复 + + +
    + +
    + 0/1000 + 发表 +
    +
    +
    + +
    +
    +
    + + + + + +
    +
    + +
    +
    +
    + + + + diff --git a/novel-front/src/main/resources/templates/book/book_detail.html b/novel-front/src/main/resources/templates/book/book_detail.html index c9c9452..a6a335d 100644 --- a/novel-front/src/main/resources/templates/book/book_detail.html +++ b/novel-front/src/main/resources/templates/book/book_detail.html @@ -22,21 +22,23 @@
    + th:attr="alt=${book.bookName}"/>

    + th:utext="${book.authorName}+' 著'">
    • 类别: - 状态:连载中已完结 + 状态:连载中已完结 总点击: 总字数:
    @@ -70,7 +72,9 @@
    • - +
    • @@ -86,21 +90,46 @@
      -

      作品评论区

      +

      作品评论区

      发表评论
      -
      +
      暂无评论
      -
      -
      + -
      + @@ -109,7 +138,7 @@ 发表评论
      @@ -175,10 +204,12 @@
    • - +
      - + @@ -210,7 +241,7 @@ var bookId = pathname.substring(pathname.lastIndexOf("/") + 1, pathname.lastIndexOf(".")) //查询章节信息 var lastBookIndexId = $("#lastBookIndexId").val(); - if(lastBookIndexId){ + if (lastBookIndexId) { $.ajax({ type: "get", url: "/book/queryBookIndexAbout", @@ -232,7 +263,7 @@ layer.alert('网络异常'); } }) - }else{ + } else { $("#optBtn").remove(); } @@ -264,9 +295,6 @@ }) - - - var currentBId = 37, spmymoney = 0; var relationStep = 0; var authorUId = 8; @@ -283,7 +311,6 @@ }); - $("#AuthorOtherNovel li").unbind("mouseover"); $('#txtComment').on('input propertychange', function () { @@ -301,7 +328,7 @@ }); - function loadCommentList(){ + function loadCommentList() { $.ajax({ type: "get", url: "/book/listCommentByPage", @@ -311,20 +338,25 @@ if (data.code == 200) { var commentList = data.data.list; if (commentList.length > 0) { - $("#bookCommentTotal").html("("+data.data.total+"条)"); + $("#bookCommentTotal").html("(" + data.data.total + "条)"); var commentListHtml = ""; for (var i = 0; i < commentList.length; i++) { var comment = commentList[i]; commentListHtml += ("
      " + "
      " + - "\"\"" + + "\"\"" + "见习
      " + - "
        \t\t\t
      • "+(comment.createUserName)+""+(comment.location ? comment.location + "读者" : '')+"
      • " + - comment.commentContent+ + "
          \t\t\t
        • " + (comment.createUserName) + "" + (comment.location ? comment.location + "读者" : '') + "
        • " + + comment.commentContent + "
        • " + - ""+comment.createTime+"" + - "(0)" + - "
        • \t\t
        \t
      "); + "" + comment.createTime + "" + + "(0)" + + "(0)" + + "回复("+comment.replyCount+ + ")" + + "
    • \t\t
    \t
    " + ) + ; } $("#commentPanel").html(commentListHtml); $("#noCommentPanel").hide();