修改了搜索,增加了部分评论模块接口

This commit is contained in:
wucongxing8150 2025-05-21 16:06:00 +08:00
parent bbc66da590
commit c106bce7e2
12 changed files with 489 additions and 76 deletions

View File

@ -0,0 +1,127 @@
package com.example.caseData.controller;
import com.example.caseData.common.Response;
import com.example.caseData.dao.*;
import com.example.caseData.dto.T;
import com.example.caseData.exception.BusinessException;
import com.example.caseData.request.CaseClinicalArticleCommentRequest.addClinicalArticleComment;
import com.example.caseData.service.CaseClinicalArticleCommentService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class CaseClinicalArticleCommentController {
@Resource
private CaseClinicalArticleDao caseClinicalArticleDao;
@Resource
private CaseClinicalArticleAuthorDao caseClinicalArticleAuthorDao;
@Resource
private StatsCaseClinicalDoctorDao statsCaseClinicalDoctorDao;
@Resource
private CaseClinicalDoctorDao caseClinicalDoctorDao;
@Resource
private BasicHospitalDao basicHospitalDao;
@Resource
private HttpServletRequest httpServletRequest;
@Resource
private CaseClinicalArticleCommentService caseClinicalArticleCommentService;
/**
* 临床病例库-文章-评论
*/
@PostMapping("/clinical/article/comment/{article_id}")
public Response<T> AddClinicalArticleComment(
@PathVariable("article_id") String articleId,
@Validated()
@RequestBody addClinicalArticleComment request
) {
String userId = (String) httpServletRequest.getAttribute("userId");
if (userId == null) {
return Response.error("操作失败");
}
try {
boolean res = caseClinicalArticleCommentService.AddClinicalArticleComment(articleId,userId,request);
if (!res){
return Response.error("操作失败");
}
} catch (BusinessException e) {
return Response.error(e.getMessage());
}
return Response.success();
}
/**
* 临床病例库-文章-评论-删除
*/
@DeleteMapping("/clinical/article/comment/{comment_id}")
public Response<T> DeleteClinicalArticleComment(
@PathVariable("comment_id") String commentId
) {
String userId = (String) httpServletRequest.getAttribute("userId");
if (userId == null) {
return Response.error("操作失败");
}
try {
boolean res = caseClinicalArticleCommentService.DeleteClinicalArticleComment(commentId,userId);
if (!res){
return Response.error("操作失败");
}
} catch (BusinessException e) {
return Response.error(e.getMessage());
}
return Response.success();
}
/**
* 临床病例库-文章-评论-置顶
*/
@PutMapping("/clinical/article/comment/top/{article_id}")
public Response<T> AddTopClinicalArticleComment(
@PathVariable("article_id") String articleId
) {
String userId = (String) httpServletRequest.getAttribute("userId");
if (userId == null) {
return Response.error("操作失败");
}
return Response.success();
}
/**
* 临床病例库-文章-评论-取消置顶
*/
@DeleteMapping("/clinical/article/comment/top/{article_id}")
public Response<T> deleteTopClinicalArticleComment(
@PathVariable("article_id") String articleId
) {
String userId = (String) httpServletRequest.getAttribute("userId");
if (userId == null) {
return Response.error("操作失败");
}
return Response.success();
}
// 临床病例库-文章-评论-列表
}

View File

@ -1,29 +1,17 @@
package com.example.caseData.controller; package com.example.caseData.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.caseData.common.Response; import com.example.caseData.common.Response;
import com.example.caseData.dao.*; import com.example.caseData.dao.*;
import com.example.caseData.dto.T; import com.example.caseData.dto.T;
import com.example.caseData.dto.basicHospital.BasicHospitalDto;
import com.example.caseData.dto.caseClinicalArticle.CaseClinicalArticleDto; import com.example.caseData.dto.caseClinicalArticle.CaseClinicalArticleDto;
import com.example.caseData.dto.statsCaseClinicalHospital.StatsCaseClinicalHospitalDto;
import com.example.caseData.exception.BusinessException;
import com.example.caseData.model.*; import com.example.caseData.model.*;
import com.example.caseData.request.UserRequest;
import com.example.caseData.request.clinicalRequest.addClinicalArticleComment;
import com.example.caseData.request.clinicalRequest.getClinicalHospitalSearchPage;
import com.example.caseData.service.CaseClinicalArticleService; import com.example.caseData.service.CaseClinicalArticleService;
import com.example.caseData.service.UserService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
@RestController @RestController
@RequestMapping("/api") @RequestMapping("/api")
@ -141,27 +129,4 @@ public class CaseClinicalArticleController {
return Response.success(); return Response.success();
} }
/**
* 临床病例库-文章-评论
*/
@PostMapping("/clinical/article/comment/{article_id}")
public Response<T> AddClinicalArticleComment(
@PathVariable("article_id") String articleId,
@Validated() addClinicalArticleComment request
) {
String userId = (String) httpServletRequest.getAttribute("userId");
if (userId == null) {
return Response.error("操作失败");
}
boolean res = caseClinicalArticleService.AddClinicalArticleComment(articleId,userId,request.getComment());
if (!res){
return Response.error("操作失败");
}
return Response.success();
}
} }

View File

@ -20,12 +20,6 @@ public class BasicSensitiveWordModel {
@TableField("word") @TableField("word")
private String word; private String word;
/**
* 状态0:禁用 1:正常
*/
@TableField("status")
private Integer status;
/** /**
* 创建时间 * 创建时间
*/ */

View File

@ -51,10 +51,10 @@ public class UserCommentClinicalArticleModel {
private Integer isSensitive; private Integer isSensitive;
/** /**
* 是否优质留言0: 1: * 是否置顶0: 1:
*/ */
@TableField("is_high_quality") @TableField("is_top")
private Integer isHighQuality; private Integer isTop;
/** /**
* 点赞数量 * 点赞数量
@ -74,6 +74,12 @@ public class UserCommentClinicalArticleModel {
@TableField("content_word") @TableField("content_word")
private String contentWord; private String contentWord;
/**
* 评论图片
*/
@TableField("comment_image")
private String commentImage;
/** /**
* 创建时间 * 创建时间
*/ */

View File

@ -51,10 +51,10 @@ public class UserCommentClinicalVideoModel {
private Integer isSensitive; private Integer isSensitive;
/** /**
* 是否优质留言0: 1: * 是否置顶0: 1:
*/ */
@TableField("is_high_quality") @TableField("is_top")
private Integer isHighQuality; private Integer isTop;
/** /**
* 点赞数量 * 点赞数量
@ -74,6 +74,12 @@ public class UserCommentClinicalVideoModel {
@TableField("content_word") @TableField("content_word")
private String contentWord; private String contentWord;
/**
* 评论图片
*/
@TableField("comment_image")
private String commentImage;
/** /**
* 创建时间 * 创建时间
*/ */

View File

@ -0,0 +1,25 @@
package com.example.caseData.request.CaseClinicalArticleCommentRequest;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
@Data
public class addClinicalArticleComment {
// 父级 次级评论此字段必须存在
@JsonProperty("parent_id")
private String parentId;
// 根评论标识 次级评论此字段必须存在
@JsonProperty("root_id")
private String rootId;
// 评论内容
@JsonProperty("content")
@NotEmpty(message = "请输入评论内容")
private String content;
// 评论图片
@JsonProperty("comment_image")
private String commentImage;
}

View File

@ -1,11 +0,0 @@
package com.example.caseData.request.clinicalRequest;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class addClinicalArticleComment {
// 评论内容
@JsonProperty("comment")
private String comment;
}

View File

@ -41,8 +41,13 @@ public class getClinicalArticleSearchPage {
*/ */
@Data @Data
public static class OrderRequest { public static class OrderRequest {
@JsonProperty("created_at")
private String createdAt; // 创建时间 private String createdAt; // 创建时间
@JsonProperty("read_num")
private String readNum; // 阅读量 private String readNum; // 阅读量
@JsonProperty("push_date")
private String pushDate; // 发表时间 private String pushDate; // 发表时间
public Map<String, String> toMap() { public Map<String, String> toMap() {

View File

@ -41,8 +41,13 @@ public class getClinicalVideoSearchPage {
*/ */
@Data @Data
public static class OrderRequest { public static class OrderRequest {
@JsonProperty("created_at")
private String createdAt; // 创建时间 private String createdAt; // 创建时间
@JsonProperty("read_num")
private String readNum; // 阅读量 private String readNum; // 阅读量
@JsonProperty("push_date")
private String pushDate; // 发表时间 private String pushDate; // 发表时间
public Map<String, String> toMap() { public Map<String, String> toMap() {

View File

@ -0,0 +1,133 @@
package com.example.caseData.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.caseData.dao.BasicSensitiveWordDao;
import com.example.caseData.model.BasicSensitiveWordModel;
import com.example.caseData.model.CaseClinicalArticleModel;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.type.TypeReference;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Service
public class BasicSensitiveWordService {
private static final String REDIS_SENSITIVE_WORD_KEY = "sensitive:word:list";
private static final long REDIS_EXPIRE_MINUTES = 30;
@Resource
private RedisTemplate<String, String> redisTemplate;
@Resource
private BasicSensitiveWordDao basicSensitiveWordDao; // 假设你有这个 DAO
private final ObjectMapper objectMapper = new ObjectMapper();
// 主过滤方法
public FilterResult filter(String comment) {
List<String> wordList = loadSensitiveWords();
if (wordList == null || wordList.isEmpty()) {
return new FilterResult(comment, 0);
}
TrieNode root = buildTrie(wordList);
return doFilter(comment, root);
}
// 加载敏感词可替换为数据库查询
private List<String> loadSensitiveWords() {
List<String> wordList = new ArrayList<>();
// 尝试从 Redis 获取
String wordJson = redisTemplate.opsForValue().get(REDIS_SENSITIVE_WORD_KEY);
if (wordJson != null && !wordJson.isEmpty()) {
try {
// 反序列化 JSON 字符串为 List<String>
wordList = objectMapper.readValue(wordJson, new TypeReference<List<String>>() {});
} catch (Exception e) {
return wordList;
}
}else{
// Redis 无数据则查询 DB
LambdaQueryWrapper<BasicSensitiveWordModel> queryWrapper = new LambdaQueryWrapper<>();
List<BasicSensitiveWordModel> basicSensitiveWords = basicSensitiveWordDao.selectList(queryWrapper); // 你自己的 DAO 方法
if (basicSensitiveWords != null && !basicSensitiveWords.isEmpty()) {
wordList = basicSensitiveWords.stream()
.map(BasicSensitiveWordModel::getWord)
.filter(Objects::nonNull)
.collect(Collectors.toList());
try {
String wordListJson = objectMapper.writeValueAsString(wordList);
redisTemplate.opsForValue().set(REDIS_SENSITIVE_WORD_KEY, wordListJson, Duration.ofMinutes(REDIS_EXPIRE_MINUTES));
} catch (Exception e) {
return wordList;
}
}
}
return wordList;
}
// 构建字典树
private TrieNode buildTrie(List<String> words) {
TrieNode root = new TrieNode();
for (String word : words) {
TrieNode node = root;
for (char ch : word.toCharArray()) {
node.children.putIfAbsent(ch, new TrieNode());
node = node.children.get(ch);
}
node.isEnd = true;
}
return root;
}
// 实际过滤逻辑
private FilterResult doFilter(String comment, TrieNode root) {
char[] chars = comment.toCharArray();
int isSensitive = 0;
for (int i = 0; i < chars.length; i++) {
TrieNode node = root;
int j = i;
while (j < chars.length && node.children.containsKey(chars[j])) {
node = node.children.get(chars[j]);
if (node.isEnd) {
for (int k = i; k <= j; k++) {
chars[k] = '*';
}
isSensitive = 1;
break;
}
j++;
}
}
return new FilterResult(new String(chars), isSensitive);
}
// Trie 节点内部类
private static class TrieNode {
boolean isEnd = false;
Map<Character, TrieNode> children = new HashMap<>();
}
// 返回结果封装
public static class FilterResult {
public final String comment;
public final int hasSensitive;
public FilterResult(String comment, int hasSensitive) {
this.comment = comment;
this.hasSensitive = hasSensitive;
}
}
}

View File

@ -0,0 +1,160 @@
package com.example.caseData.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.caseData.dao.*;
import com.example.caseData.exception.BusinessException;
import com.example.caseData.model.*;
import com.example.caseData.request.CaseClinicalArticleCommentRequest.addClinicalArticleComment;
import com.example.caseData.utils.Replace;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import java.util.List;
import java.util.Objects;
@Service
public class CaseClinicalArticleCommentService {
@Resource
private UserCollectClinicalArticleDao userCollectClinicalArticleDao;
@Resource
private CaseClinicalArticleDao caseClinicalArticleDao;
@Resource
private StatsCaseClinicalDao statsCaseClinicalDao;
@Resource
private StatsCaseClinicalHospitalDao statsCaseClinicalHospitalDao;
@Resource
private StatsCaseClinicalDoctorDao statsCaseClinicalDoctorDao;
@Resource
private CaseClinicalArticleAuthorDao caseClinicalArticleAuthorDao;
@Resource
private CaseClinicalDoctorDao caseClinicalDoctorDao;
@Resource
private BasicSensitiveWordService basicSensitiveWordService;
@Resource
private UserCommentClinicalArticleDao userCommentClinicalArticleDao;
@Resource
private UserDao userDao;
/**
* 新增评论-临床病例库-文章
* @param articleId 文章id
* @param userId 用户id
* @return bool
*/
@Transactional
public boolean AddClinicalArticleComment(String articleId, String userId, addClinicalArticleComment request){
// 获取文章数据
CaseClinicalArticleModel article = caseClinicalArticleDao.selectById(articleId);
if (article == null) {
throw new BusinessException("非法文章");
}
if (article.getArticleStatus() != 1){
throw new BusinessException("非法文章");
}
// 处理评论内容
BasicSensitiveWordService.FilterResult result = basicSensitiveWordService.filter(request.getContent());
// 新增评论
UserCommentClinicalArticleModel userCommentClinicalArticleData = new UserCommentClinicalArticleModel();
userCommentClinicalArticleData.setUserId(Long.valueOf(userId));
userCommentClinicalArticleData.setArticleId(Long.valueOf(articleId));
userCommentClinicalArticleData.setStatus(1);
userCommentClinicalArticleData.setIsSensitive(result.hasSensitive);
userCommentClinicalArticleData.setContent(result.comment);
userCommentClinicalArticleData.setCommentImage(Replace.addOssDomain(request.getCommentImage()));
if (result.hasSensitive == 1){
userCommentClinicalArticleData.setContentWord(request.getContent());
}
// 评论根id
if (request.getRootId() != null) {
userCommentClinicalArticleData.setRootId(Long.valueOf(request.getRootId()));
}
// 评论父级id
if (request.getParentId() != null) {
userCommentClinicalArticleData.setParentId(Long.valueOf(request.getParentId()));
}
int res = userCommentClinicalArticleDao.insert(userCommentClinicalArticleData);
return res > 0;
}
/**
* 删除评论-临床病例库-文章
* @param commentId 评论id
* @param userId 用户id
* @return bool
*/
@Transactional
public boolean DeleteClinicalArticleComment(String commentId, String userId){
// 获取评论数据
UserCommentClinicalArticleModel comment = userCommentClinicalArticleDao.selectById(commentId);
if (comment == null) {
return true;
}
// 获取当前登录用户数据
UserModel user = userDao.selectById(Long.valueOf(userId));
if (user == null) {
throw new BusinessException("错误");
}
// 获取文章数据
CaseClinicalArticleModel article = caseClinicalArticleDao.selectById(comment.getArticleId());
if (article == null) {
throw new BusinessException("删除失败");
}
if (article.getArticleStatus() != 1){
throw new BusinessException("删除失败");
}
// 当前用户是否是作者之一
boolean isAuthor = false;
// 获取文章作者数据
LambdaQueryWrapper<CaseClinicalArticleAuthorModel> authorQueryWrapper = new LambdaQueryWrapper<>();
authorQueryWrapper.eq(CaseClinicalArticleAuthorModel::getArticleId, article.getArticleId());
List<CaseClinicalArticleAuthorModel> caseClinicalArticleAuthors = caseClinicalArticleAuthorDao.selectList(authorQueryWrapper);
for (CaseClinicalArticleAuthorModel author : caseClinicalArticleAuthors) {
// 查询医生
CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectById(author.getDoctorId());
if (caseClinicalDoctor == null) {
throw new BusinessException("错误");
}
if (Objects.equals(caseClinicalDoctor.getDoctorIden(), user.getUserIden())){
isAuthor = true;
}
}
if (!isAuthor) {
throw new BusinessException("不可删除");
}
// 删除评论
int res = userCommentClinicalArticleDao.deleteById(comment.getCommentId());
if (res <= 0){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return false;
}
return true;
}
}

View File

@ -2,10 +2,10 @@ package com.example.caseData.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.caseData.dao.*; import com.example.caseData.dao.*;
import com.example.caseData.model.CaseClinicalArticleAuthorModel; import com.example.caseData.exception.BusinessException;
import com.example.caseData.model.CaseClinicalDoctorModel; import com.example.caseData.model.*;
import com.example.caseData.model.UserCollectClinicalArticleModel; import com.example.caseData.request.CaseClinicalArticleCommentRequest.addClinicalArticleComment;
import com.example.caseData.model.UserModel; import com.example.caseData.utils.Replace;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -28,9 +28,6 @@ public class CaseClinicalArticleService {
@Resource @Resource
private StatsCaseClinicalDao statsCaseClinicalDao; private StatsCaseClinicalDao statsCaseClinicalDao;
@Resource
private UserDao userDao;
@Resource @Resource
private StatsCaseClinicalHospitalDao statsCaseClinicalHospitalDao; private StatsCaseClinicalHospitalDao statsCaseClinicalHospitalDao;
@ -43,6 +40,12 @@ public class CaseClinicalArticleService {
@Resource @Resource
private CaseClinicalDoctorDao caseClinicalDoctorDao; private CaseClinicalDoctorDao caseClinicalDoctorDao;
@Resource
private BasicSensitiveWordService basicSensitiveWordService;
@Resource
private UserCommentClinicalArticleDao userCommentClinicalArticleDao;
/** /**
* 新增收藏-临床病例库-文章 * 新增收藏-临床病例库-文章
@ -52,6 +55,12 @@ public class CaseClinicalArticleService {
*/ */
@Transactional @Transactional
public boolean AddClinicalArticleCollect(String articleId,String userId){ public boolean AddClinicalArticleCollect(String articleId,String userId){
// 获取文章数据
CaseClinicalArticleModel article = caseClinicalArticleDao.selectById(articleId);
if (article == null) {
return false;
}
// 检测用户是否已收藏过 // 检测用户是否已收藏过
UserCollectClinicalArticleModel userCollectClinicalArticle = getUserCollectClinicalArticleStatus(articleId,userId); UserCollectClinicalArticleModel userCollectClinicalArticle = getUserCollectClinicalArticleStatus(articleId,userId);
if (userCollectClinicalArticle != null) { if (userCollectClinicalArticle != null) {
@ -136,17 +145,6 @@ public class CaseClinicalArticleService {
return true; return true;
} }
/**
* 新增评论-临床病例库-文章
* @param articleId 文章id
* @param userId 用户id
* @return bool
*/
@Transactional
public boolean AddClinicalArticleComment(String articleId,String userId,String comment){
return true;
}
/** /**
* 获取用户收藏数据 * 获取用户收藏数据
* @param articleId 文章id * @param articleId 文章id