摘要:以上就是對評論模塊的設計與功能實現,歡迎各位大佬提出代碼優化建議,共同成長代碼出自開源項目,致力于打造全平臺型全棧精品開源項目。
評論模塊在很多系統中都有,CodeRiver河碼 作為類似程序員客棧的溝通協作平臺自然也不會少。
前端界面是參考了簡書的評論模塊,專門寫了一篇文章介紹實現步驟:
vue + element-ui + scss 仿簡書評論模塊
感興趣的可以看看。
項目地址:https://github.com/cachecats/...
代碼在 根目錄/java/comments-service
文章將分三部分介紹:
前端界面分析
數據庫設計
功能實現
一、前端界面分析先看看前端界面長什么樣,知道了前端需要什么數據,就知道數據庫該怎么設計了。
首先評論的主體可以是人、項目、資源,所以要有一個 type 字段標明這條評論的類型。
以項目為例,一個項目下面可能會有多條評論。每條評論其實分為兩種,一種是直接對項目的評論,稱之為父評論吧;另一種是對已有評論的評論,稱為子評論。
梳理一下關系,每個項目可能有多個父評論,每個父評論可能有多個子評論。項目與父評論,父評論與子評論,都是一對多的關系。
由此可知數據庫應該分為兩個表,一個存儲父評論,一個存儲子評論。
再看都需要什么字段,先分析主評論。必須要有的是項目id,得知道是對誰評論的,叫 ownerId 吧。還有評論者的頭像、昵稱、id,還有評論時間、內容、點贊個數等。
子評論跟父評論的字段差不多,只是不要點贊數量。
二、數據庫設計分析了界面,知道需要什么字段,就開始設計數據庫吧。
評論主表(父評論表)
CREATE TABLE `comments_info` ( `id` varchar(32) NOT NULL COMMENT "評論主鍵id", `type` tinyint(1) NOT NULL COMMENT "評論類型:對人評論,對項目評論,對資源評論", `owner_id` varchar(32) NOT NULL COMMENT "被評論者id,可以是人、項目、資源", `from_id` varchar(32) NOT NULL COMMENT "評論者id", `from_name` varchar(32) NOT NULL COMMENT "評論者名字", `from_avatar` varchar(512) DEFAULT "" COMMENT "評論者頭像", `like_num` int(11) DEFAULT "0" COMMENT "點贊的數量", `content` varchar(512) DEFAULT NULL COMMENT "評論內容", `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT "創建時間", `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT "修改時間", PRIMARY KEY (`id`), KEY `owner_id` (`owner_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT="評論主表";
評論回復表(子評論表)
CREATE TABLE `comments_reply` ( `id` int(11) NOT NULL AUTO_INCREMENT, `comment_id` varchar(32) NOT NULL COMMENT "評論主表id", `from_id` varchar(32) NOT NULL COMMENT "評論者id", `from_name` varchar(32) NOT NULL COMMENT "評論者名字", `from_avatar` varchar(512) DEFAULT "" COMMENT "評論者頭像", `to_id` varchar(32) NOT NULL COMMENT "被評論者id", `to_name` varchar(32) NOT NULL COMMENT "被評論者名字", `to_avatar` varchar(512) DEFAULT "" COMMENT "被評論者頭像", `content` varchar(512) DEFAULT NULL COMMENT "評論內容", `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT "創建時間", `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT "修改時間", PRIMARY KEY (`id`), KEY `comment_id` (`comment_id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT="評論回復表";三、功能實現
項目采用 SpringCloud 微服務架構,評論模塊跟其他模塊的關聯性不強,可以抽出為一個多帶帶的服務 comments-service 。
數據實體對象數據實體對象 CommentsInfo
package com.solo.coderiver.comments.dataobject; import lombok.Data; import org.hibernate.annotations.DynamicUpdate; import javax.persistence.Entity; import javax.persistence.Id; import java.util.Date; /** * 評論表主表 */ @Entity @Data @DynamicUpdate public class CommentsInfo { //評論主鍵id @Id private String id; //評論類型。1用戶評論,2項目評論,3資源評論 private Integer type; //被評論者的id private String ownerId; //評論者id private String fromId; //評論者名字 private String fromName; //評論者頭像 private String fromAvatar; //獲得點贊的數量 private Integer likeNum; //評論內容 private String content; //創建時間 private Date createTime; //更新時間 private Date updateTime; }
數據實體對象 CommentsReply
package com.solo.coderiver.comments.dataobject; import lombok.Data; import org.hibernate.annotations.DynamicUpdate; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import java.util.Date; /** * 評論回復表 */ @Entity @Data @DynamicUpdate public class CommentsReply { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; //評論主表id private String commentId; //評論者id private String fromId; //評論者名字 private String fromName; //評論者頭像 private String fromAvatar; //被評論者id private String toId; //被評論者名字 private String toName; //被評論者頭像 private String toAvatar; //評論內容 private String content; //創建時間 private Date createTime; //更新時間 private Date updateTime; }數據庫操作倉庫 repository
操作數據庫暫時用的是 Jpa ,后期可能會增加一份 mybatis 的實現。
CommentsInfoRepository
package com.solo.coderiver.comments.repository; import com.solo.coderiver.comments.dataobject.CommentsInfo; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; public interface CommentsInfoRepository extends JpaRepository{ List findByOwnerId(String ownerId); }
CommentsReplyRepository
package com.solo.coderiver.comments.repository; import com.solo.coderiver.comments.dataobject.CommentsReply; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; public interface CommentsReplyRepository extends JpaRepositoryService 接口封裝{ List findByCommentId(String commentId); }
為了代碼更健壯,要把數據庫的操作封裝一下
CommentsInfoService
package com.solo.coderiver.comments.service; import com.solo.coderiver.comments.dataobject.CommentsInfo; import java.util.List; public interface CommentsInfoService { /** * 保存評論 * @param info * @return */ CommentsInfo save(CommentsInfo info); /** * 根據被評論者的id查詢評論列表 * @param ownerId * @return */ ListfindByOwnerId(String ownerId); }
CommentsReplyService
package com.solo.coderiver.comments.service; import com.solo.coderiver.comments.dataobject.CommentsReply; import java.util.List; public interface CommentsReplyService { /** * 保存評論回復 * @param reply * @return */ CommentsReply save(CommentsReply reply); /** * 根據評論id查詢回復 * @param commentId * @return */ ListfindByCommentId(String commentId); }
接口的實現類
CommentsInfoServiceImpl
package com.solo.coderiver.comments.service.impl; import com.solo.coderiver.comments.dataobject.CommentsInfo; import com.solo.coderiver.comments.repository.CommentsInfoRepository; import com.solo.coderiver.comments.service.CommentsInfoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class CommentsInfoServiceImpl implements CommentsInfoService { @Autowired CommentsInfoRepository repository; @Override public CommentsInfo save(CommentsInfo info) { return repository.save(info); } @Override public ListfindByOwnerId(String ownerId) { return repository.findByOwnerId(ownerId); } }
CommentsReplyServiceImpl
package com.solo.coderiver.comments.service.impl; import com.solo.coderiver.comments.dataobject.CommentsReply; import com.solo.coderiver.comments.repository.CommentsReplyRepository; import com.solo.coderiver.comments.service.CommentsReplyService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class CommentsReplyServiceImpl implements CommentsReplyService { @Autowired CommentsReplyRepository repository; @Override public CommentsReply save(CommentsReply reply) { return repository.save(reply); } @Override public List控制層 ControllerfindByCommentId(String commentId) { return repository.findByCommentId(commentId); } }
Controller 層分發請求,并返回前端需要的數據
package com.solo.coderiver.comments.controller; @RestController @Api(description = "評論相關接口") public class CommentsController { @Autowired CommentsInfoService infoService; @Autowired CommentsReplyService replyService; @PostMapping("/save") @ApiOperation("保存評論") @Transactional public ResultVO saveComments(@Valid CommentsInfoForm form, BindingResult bindingResult) { if (bindingResult.hasErrors()) { throw new CommentsException(ResultEnums.PARAMS_ERROR.getCode(), bindingResult.getFieldError().getDefaultMessage()); } //將 CommentsInfoForm 里的數據拷貝到 CommentsInfo CommentsInfo info = new CommentsInfo(); BeanUtils.copyProperties(form, info); // 生成并設置評論的主鍵id info.setId(KeyUtils.genUniqueKey()); CommentsInfo result = infoService.save(info); if (result == null) { throw new CommentsException(ResultEnums.SAVE_COMMENTS_FAIL); } return ResultVOUtils.success(); } @GetMapping("/get/{ownerId}") @ApiOperation("根據 ownerId 查詢評論") @ApiImplicitParam(name = "ownerId", value = "被評論者id") public ResultVO getCommentsByOwnerId(@PathVariable("ownerId") String ownerId) { ListinfoList = infoService.findByOwnerId(ownerId); //將 CommentsInfo 轉換為 CommentsInfoDTO List infoDTOS = infoList.stream().map(info -> { CommentsInfoDTO dto = new CommentsInfoDTO(); BeanUtils.copyProperties(info, dto); return dto; }).collect(Collectors.toList()); return ResultVOUtils.success(infoDTOS); } @PostMapping("/save-reply") @ApiOperation("保存評論回復") @Transactional public ResultVO saveReply(@Valid CommentsReplyForm form, BindingResult bindingResult) { if (bindingResult.hasErrors()) { throw new CommentsException(ResultEnums.PARAMS_ERROR.getCode(), bindingResult.getFieldError().getDefaultMessage()); } CommentsReply reply = new CommentsReply(); BeanUtils.copyProperties(form, reply); CommentsReply result = replyService.save(reply); if (result == null) { throw new CommentsException(ResultEnums.SAVE_COMMENTS_FAIL); } return ResultVOUtils.success(); } @GetMapping("/get-reply/{commentId}") @ApiOperation("通過commentId獲取評論回復") public ResultVO getReplyByCommentId(@PathVariable("commentId") String commentId) { List replyList = replyService.findByCommentId(commentId); //將 CommentsReply 轉換為 CommentsReplyDTO List replyDTOS = replyList.stream().map(reply -> { CommentsReplyDTO dto = new CommentsReplyDTO(); BeanUtils.copyProperties(reply, dto); return dto; }).collect(Collectors.toList()); return ResultVOUtils.success(replyDTOS); } }
代碼中工具類和枚舉類請到 github 上查看源碼。
以上就是對評論模塊的設計與功能實現,歡迎各位大佬提出代碼優化建議,共同成長~
代碼出自開源項目 CodeRiver,致力于打造全平臺型全棧精品開源項目。
coderiver 中文名 河碼,是一個為程序員和設計師提供項目協作的平臺。無論你是前端、后端、移動端開發人員,或是設計師、產品經理,都可以在平臺上發布項目,與志同道合的小伙伴一起協作完成項目。
coderiver河碼 類似程序員客棧,但主要目的是方便各細分領域人才之間技術交流,共同成長,多人協作完成項目。暫不涉及金錢交易。
計劃做成包含 pc端(Vue、React)、移動H5(Vue、React)、ReactNative混合開發、Android原生、微信小程序、java后端的全平臺型全棧項目,歡迎關注。
項目地址:https://github.com/cachecats/...
您的鼓勵是我前行最大的動力,歡迎點贊,歡迎送小星星? ~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/17825.html
摘要:無論你是前端后端移動端開發人員,或是設計師產品經理,都可以在平臺上發布項目,與志同道合的小伙伴一起協作完成項目。 全平臺全棧開源項目 coderiver 今天終于開始前后端聯調了~ 首先感謝大家的支持,coderiver 在 GitHub 上開源兩周,獲得了 54 個 Star,9 個 Fork,5 個 Watch。 這些鼓勵和認可也更加堅定了我繼續寫下去的決心~ 再次感謝各位大佬! ...
摘要:前段時間設計了系統的評論模塊,并寫了篇文章評論模塊后端數據庫設計及功能實現講解。下面就對評論模塊進行優化改造,首先更改表結構,合成一張表。評論表不存用戶頭像的話,需要從用戶服務獲取。用戶服務提供獲取頭像的接口,兩個服務間通過通信。 前段時間設計了系統的評論模塊,并寫了篇文章 評論模塊 - 后端數據庫設計及功能實現 講解。 大佬們在評論區提出了些優化建議,總結一下: 之前評論一共分...
摘要:個人認為單頁面應用的優勢相當明顯前后端職責分離,架構清晰前端進行交互邏輯,后端負責數據處理。上面的這種單頁面應用也有其相應的一種開發工作流,當然這種工作流也適合非單頁面應用進行產品功能原型設計。 未經允許,請勿轉載。本文同時也發布在我的博客。 (如果對SPA概念不清楚的同學可以先自行了解相關概念) 平時喜歡做點小頁面來玩玩,并且一直采用單頁面應用(Single Page Appl...
閱讀 3049·2021-09-22 15:52
閱讀 2914·2019-08-30 15:55
閱讀 2708·2019-08-30 15:53
閱讀 2461·2019-08-30 13:21
閱讀 1630·2019-08-30 13:10
閱讀 2488·2019-08-26 12:09
閱讀 2575·2019-08-26 10:33
閱讀 1810·2019-08-23 18:06