摘要:以上就是對評論模塊的設(shè)計(jì)與功能實(shí)現(xiàn),歡迎各位大佬提出代碼優(yōu)化建議,共同成長代碼出自開源項(xiàng)目,致力于打造全平臺型全棧精品開源項(xiàng)目。
評論模塊在很多系統(tǒng)中都有,CodeRiver河碼 作為類似程序員客棧的溝通協(xié)作平臺自然也不會少。
前端界面是參考了簡書的評論模塊,專門寫了一篇文章介紹實(shí)現(xiàn)步驟:
vue + element-ui + scss 仿簡書評論模塊
感興趣的可以看看。
項(xiàng)目地址:https://github.com/cachecats/...
代碼在 根目錄/java/comments-service
文章將分三部分介紹:
前端界面分析
數(shù)據(jù)庫設(shè)計(jì)
功能實(shí)現(xiàn)
一、前端界面分析先看看前端界面長什么樣,知道了前端需要什么數(shù)據(jù),就知道數(shù)據(jù)庫該怎么設(shè)計(jì)了。
首先評論的主體可以是人、項(xiàng)目、資源,所以要有一個(gè) type 字段標(biāo)明這條評論的類型。
以項(xiàng)目為例,一個(gè)項(xiàng)目下面可能會有多條評論。每條評論其實(shí)分為兩種,一種是直接對項(xiàng)目的評論,稱之為父評論吧;另一種是對已有評論的評論,稱為子評論。
梳理一下關(guān)系,每個(gè)項(xiàng)目可能有多個(gè)父評論,每個(gè)父評論可能有多個(gè)子評論。項(xiàng)目與父評論,父評論與子評論,都是一對多的關(guān)系。
由此可知數(shù)據(jù)庫應(yīng)該分為兩個(gè)表,一個(gè)存儲父評論,一個(gè)存儲子評論。
再看都需要什么字段,先分析主評論。必須要有的是項(xiàng)目id,得知道是對誰評論的,叫 ownerId 吧。還有評論者的頭像、昵稱、id,還有評論時(shí)間、內(nèi)容、點(diǎn)贊個(gè)數(shù)等。
子評論跟父評論的字段差不多,只是不要點(diǎn)贊數(shù)量。
二、數(shù)據(jù)庫設(shè)計(jì)分析了界面,知道需要什么字段,就開始設(shè)計(jì)數(shù)據(jù)庫吧。
評論主表(父評論表)
CREATE TABLE `comments_info` ( `id` varchar(32) NOT NULL COMMENT "評論主鍵id", `type` tinyint(1) NOT NULL COMMENT "評論類型:對人評論,對項(xiàng)目評論,對資源評論", `owner_id` varchar(32) NOT NULL COMMENT "被評論者id,可以是人、項(xiàng)目、資源", `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 "點(diǎn)贊的數(shù)量", `content` varchar(512) DEFAULT NULL COMMENT "評論內(nèi)容", `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT "創(chuàng)建時(shí)間", `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT "修改時(shí)間", PRIMARY KEY (`id`), KEY `owner_id` (`owner_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT="評論主表";
評論回復(fù)表(子評論表)
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 "評論內(nèi)容", `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT "創(chuàng)建時(shí)間", `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT "修改時(shí)間", PRIMARY KEY (`id`), KEY `comment_id` (`comment_id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT="評論回復(fù)表";三、功能實(shí)現(xiàn)
項(xiàng)目采用 SpringCloud 微服務(wù)架構(gòu),評論模塊跟其他模塊的關(guān)聯(lián)性不強(qiáng),可以抽出為一個(gè)多帶帶的服務(wù) comments-service 。
數(shù)據(jù)實(shí)體對象數(shù)據(jù)實(shí)體對象 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項(xiàng)目評論,3資源評論 private Integer type; //被評論者的id private String ownerId; //評論者id private String fromId; //評論者名字 private String fromName; //評論者頭像 private String fromAvatar; //獲得點(diǎn)贊的數(shù)量 private Integer likeNum; //評論內(nèi)容 private String content; //創(chuàng)建時(shí)間 private Date createTime; //更新時(shí)間 private Date updateTime; }
數(shù)據(jù)實(shí)體對象 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; /** * 評論回復(fù)表 */ @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; //評論內(nèi)容 private String content; //創(chuàng)建時(shí)間 private Date createTime; //更新時(shí)間 private Date updateTime; }數(shù)據(jù)庫操作倉庫 repository
操作數(shù)據(jù)庫暫時(shí)用的是 Jpa ,后期可能會增加一份 mybatis 的實(shí)現(xiàn)。
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); }
為了代碼更健壯,要把數(shù)據(jù)庫的操作封裝一下
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); /** * 根據(jù)被評論者的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 { /** * 保存評論回復(fù) * @param reply * @return */ CommentsReply save(CommentsReply reply); /** * 根據(jù)評論id查詢回復(fù) * @param commentId * @return */ ListfindByCommentId(String commentId); }
接口的實(shí)現(xiàn)類
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 層分發(fā)請求,并返回前端需要的數(shù)據(jù)
package com.solo.coderiver.comments.controller; @RestController @Api(description = "評論相關(guān)接口") 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 里的數(shù)據(jù)拷貝到 CommentsInfo CommentsInfo info = new CommentsInfo(); BeanUtils.copyProperties(form, info); // 生成并設(shè)置評論的主鍵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("根據(jù) ownerId 查詢評論") @ApiImplicitParam(name = "ownerId", value = "被評論者id") public ResultVO getCommentsByOwnerId(@PathVariable("ownerId") String ownerId) { ListinfoList = infoService.findByOwnerId(ownerId); //將 CommentsInfo 轉(zhuǎn)換為 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("保存評論回復(fù)") @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獲取評論回復(fù)") public ResultVO getReplyByCommentId(@PathVariable("commentId") String commentId) { List replyList = replyService.findByCommentId(commentId); //將 CommentsReply 轉(zhuǎn)換為 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 上查看源碼。
以上就是對評論模塊的設(shè)計(jì)與功能實(shí)現(xiàn),歡迎各位大佬提出代碼優(yōu)化建議,共同成長~
代碼出自開源項(xiàng)目 CodeRiver,致力于打造全平臺型全棧精品開源項(xiàng)目。
coderiver 中文名 河碼,是一個(gè)為程序員和設(shè)計(jì)師提供項(xiàng)目協(xié)作的平臺。無論你是前端、后端、移動端開發(fā)人員,或是設(shè)計(jì)師、產(chǎn)品經(jīng)理,都可以在平臺上發(fā)布項(xiàng)目,與志同道合的小伙伴一起協(xié)作完成項(xiàng)目。
coderiver河碼 類似程序員客棧,但主要目的是方便各細(xì)分領(lǐng)域人才之間技術(shù)交流,共同成長,多人協(xié)作完成項(xiàng)目。暫不涉及金錢交易。
計(jì)劃做成包含 pc端(Vue、React)、移動H5(Vue、React)、ReactNative混合開發(fā)、Android原生、微信小程序、java后端的全平臺型全棧項(xiàng)目,歡迎關(guān)注。
項(xiàng)目地址:https://github.com/cachecats/...
您的鼓勵(lì)是我前行最大的動力,歡迎點(diǎn)贊,歡迎送小星星? ~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/17825.html
摘要:無論你是前端后端移動端開發(fā)人員,或是設(shè)計(jì)師產(chǎn)品經(jīng)理,都可以在平臺上發(fā)布項(xiàng)目,與志同道合的小伙伴一起協(xié)作完成項(xiàng)目。 全平臺全棧開源項(xiàng)目 coderiver 今天終于開始前后端聯(lián)調(diào)了~ 首先感謝大家的支持,coderiver 在 GitHub 上開源兩周,獲得了 54 個(gè) Star,9 個(gè) Fork,5 個(gè) Watch。 這些鼓勵(lì)和認(rèn)可也更加堅(jiān)定了我繼續(xù)寫下去的決心~ 再次感謝各位大佬! ...
摘要:前段時(shí)間設(shè)計(jì)了系統(tǒng)的評論模塊,并寫了篇文章評論模塊后端數(shù)據(jù)庫設(shè)計(jì)及功能實(shí)現(xiàn)講解。下面就對評論模塊進(jìn)行優(yōu)化改造,首先更改表結(jié)構(gòu),合成一張表。評論表不存用戶頭像的話,需要從用戶服務(wù)獲取。用戶服務(wù)提供獲取頭像的接口,兩個(gè)服務(wù)間通過通信。 前段時(shí)間設(shè)計(jì)了系統(tǒng)的評論模塊,并寫了篇文章 評論模塊 - 后端數(shù)據(jù)庫設(shè)計(jì)及功能實(shí)現(xiàn) 講解。 大佬們在評論區(qū)提出了些優(yōu)化建議,總結(jié)一下: 之前評論一共分...
摘要:個(gè)人認(rèn)為單頁面應(yīng)用的優(yōu)勢相當(dāng)明顯前后端職責(zé)分離,架構(gòu)清晰前端進(jìn)行交互邏輯,后端負(fù)責(zé)數(shù)據(jù)處理。上面的這種單頁面應(yīng)用也有其相應(yīng)的一種開發(fā)工作流,當(dāng)然這種工作流也適合非單頁面應(yīng)用進(jìn)行產(chǎn)品功能原型設(shè)計(jì)。 未經(jīng)允許,請勿轉(zhuǎn)載。本文同時(shí)也發(fā)布在我的博客。 (如果對SPA概念不清楚的同學(xué)可以先自行了解相關(guān)概念) 平時(shí)喜歡做點(diǎn)小頁面來玩玩,并且一直采用單頁面應(yīng)用(Single Page Appl...
閱讀 3024·2021-09-22 15:52
閱讀 2903·2019-08-30 15:55
閱讀 2700·2019-08-30 15:53
閱讀 2454·2019-08-30 13:21
閱讀 1621·2019-08-30 13:10
閱讀 2481·2019-08-26 12:09
閱讀 2564·2019-08-26 10:33
閱讀 1802·2019-08-23 18:06