app接口。新增了两个接口

This commit is contained in:
wucongxing8150 2025-07-25 14:34:57 +08:00
parent cb6717e3fa
commit 262e576192
13 changed files with 417 additions and 19 deletions

View File

@ -392,4 +392,26 @@ public class CaseClinicalVideoController {
resultMap.put("data", resultPage.getRecords());
return Response.success(resultMap);
}
/**
* 临床病例库-视频-同步app视频
*/
@PostMapping("/app/clinical/video")
public Response<T> AddClinicalVideoComment(
@Validated()
@RequestBody addClinicalVideoComment request
) {
//
// try {
// boolean res = caseClinicalVideoService.AddClinicalVideoComment(userId,request);
// if (!res){
// return Response.error("操作失败");
// }
// } catch (BusinessException e) {
// return Response.error(e.getMessage());
// }
return Response.success();
}
}

View File

@ -367,6 +367,60 @@ public class CaseExchangeController {
return Response.success();
}
/**
* 病例交流-修改
*/
@PutMapping("/exchange/{exchange_id}")
public Response<T> UpdateCaseExchange(
@Validated()
@RequestBody updateCaseExchange request,
@PathVariable("exchange_id") String exchangeId
) {
String userId = (String) httpServletRequest.getAttribute("userId");
if (userId == null) {
return Response.error("操作失败");
}
try {
boolean res = caseExchangeService.UpdateCaseExchange(userId,exchangeId,request);
if (!res){
return Response.error("操作失败");
}
} catch (BusinessException e) {
return Response.error(e.getMessage());
}
return Response.success();
}
/**
* 病例交流-删除
*/
@DeleteMapping("/exchange/{exchange_id}")
public Response<T> DeleteCaseExchange(
@PathVariable("exchange_id") String exchangeId
) {
String userId = (String) httpServletRequest.getAttribute("userId");
if (userId == null) {
return Response.error("操作失败");
}
try {
boolean res = caseExchangeService.DeleteCaseExchange(exchangeId,userId);
if (!res){
return Response.error("操作失败");
}
} catch (BusinessException e) {
return Response.error(e.getMessage());
}
return Response.success();
}
/**
* 病例交流-收藏
*/

View File

@ -70,8 +70,6 @@ public class ClinicalController extends BaseController {
@Resource
private StatsCaseClinicalLabelDao statsCaseClinicalLabelDao;
/**
* 临床病例库-搜索-文章
*/

View File

@ -2,9 +2,13 @@ package com.example.caseData.extend.app;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.example.caseData.exception.BusinessException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
@ -119,4 +123,45 @@ public class Base {
return response.body();
}
}
/**
* 校验签名
* @param request 请求对象
* @param secretKey 密钥
* @param mapper ObjectMapper 实例用于 JSON 反序列化
*/
public static void checkSign(HttpServletRequest request, String secretKey, ObjectMapper mapper) {
try {
String appId = request.getHeader("appId");
String sign = request.getHeader("sign");
if (appId == null || appId.isEmpty()) {
throw new BusinessException("-1", "请求未授权");
}
if (sign == null || sign.isEmpty()) {
throw new BusinessException("-1", "缺少签名");
}
// 读取请求体
String body = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);
if (body == null || body.isEmpty()) {
throw new BusinessException("-1", "请求体为空");
}
// 使用 TypeReference 明确泛型类型避免警告
Map<String, Object> params = mapper.readValue(body, new TypeReference<Map<String, Object>>() {});
// 生成签名
String serverSign = Base.genSignature(params, secretKey);
if (!sign.equals(serverSign)) {
throw new BusinessException("-1", "签名错误");
}
} catch (BusinessException e) {
throw e;
} catch (Exception e) {
throw new BusinessException("-1", "签名校验失败:" + e.getMessage());
}
}
}

View File

@ -3,10 +3,21 @@ package com.example.caseData.middlewares;
import com.example.caseData.dao.UserDao;
import com.example.caseData.exception.BusinessException;
import com.example.caseData.model.UserModel;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.codec.digest.HmacUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedReader;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
@Component
public class AuthInterceptor extends BaseInterceptor {
@ -20,7 +31,6 @@ public class AuthInterceptor extends BaseInterceptor {
public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {
// 放行白名单路径
if (isWhiteListed(request)) {
// 在白名单
return true;
}
@ -46,4 +56,6 @@ public class AuthInterceptor extends BaseInterceptor {
return true; // 如果权限验证通过则继续处理请求
}
}

View File

@ -16,7 +16,8 @@ public abstract class BaseInterceptor implements HandlerInterceptor {
"GET:/api/index/clinical", // 首页-临床病例库
"POST:/api/login/mobile", // 登陆
"POST:/api/code/phone", // 获取验证码
"POST:/api/login/hcp" // 登陆-hcp
"POST:/api/login/hcp", // 登陆-hcp
"POST:/api/app/clinical/video" // 视频同步
);
/**

View File

@ -25,6 +25,12 @@ public class CaseClinicalArticleModel {
@TableField("article_status")
private Integer articleStatus;
/**
* 删除状态0: 1:
*/
@TableField("delete_status")
private Integer deleteStatus;
/**
* 阅读量
*/

View File

@ -28,6 +28,12 @@ public class CaseClinicalVideoModel {
@TableField("video_status")
private Integer videoStatus;
/**
* 删除状态0: 1:
*/
@TableField("delete_status")
private Integer deleteStatus;
/**
* 阅读量
*/

View File

@ -37,6 +37,12 @@ public class CaseExchangeModel {
@TableField("exchange_status")
private Integer exchangeStatus;
/**
* 删除状态0: 1:
*/
@TableField("delete_status")
private Integer deleteStatus;
/**
* 是否被精选0: 1:
*/

View File

@ -0,0 +1,86 @@
package com.example.caseData.request.caseExchangeRequest;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.util.List;
@JsonIgnoreProperties(ignoreUnknown = true)
@Data
public class updateCaseExchange {
/**
* 标题
*/
@NotEmpty(message = "请输入标题")
@JsonProperty("exchange_title")
private String exchangeTitle;
/**
* 内容
*/
@NotEmpty(message = "请输入内容")
@JsonProperty("exchange_content")
private String exchangeContent;
/**
* 总结
*/
@JsonProperty("exchange_summary")
private String exchangeSummary;
/**
* 投票
*/
@JsonProperty("case_exchange_vote")
private CaseExchangeVoteRequest caseExchangeVote;
/**
* 标签
*/
@JsonProperty("case_exchange_label")
private List<CaseExchangeLabelRequest> caseExchangeLabel;
/**
* 投票
*/
@JsonIgnoreProperties(ignoreUnknown = true)
@Data
public static class CaseExchangeVoteRequest {
@JsonProperty("vote_title")
@NotEmpty(message = "请输入投票标题")
private String voteTitle; // 选项标题
@JsonProperty("valid_day")
@Size(min = 1, max = 20, message = "有效期在1-20天内")
private Integer validDay; // 投票有效期天数
@JsonProperty("case_exchange_vote_option")
private List<CaseExchangeVoteOptionRequest> caseExchangeVoteOption;
}
/**
* 投票选项
*/
@JsonIgnoreProperties(ignoreUnknown = true)
@Data
public static class CaseExchangeVoteOptionRequest {
@JsonProperty("option_value")
private String optionValue; // 选项
}
/**
* 标签
*/
@JsonIgnoreProperties(ignoreUnknown = true)
@Data
public static class CaseExchangeLabelRequest {
@JsonProperty("app_iden")
private String appIden; // app唯一标识
@JsonProperty("label_name")
private String labelName; // 标签名称
}
}

View File

@ -3,16 +3,21 @@ 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.extend.app.Base;
import com.example.caseData.model.*;
import com.example.caseData.model.UserCollectClinicalVideoModel;
import com.example.caseData.request.CaseClinicalVideoRequest.addClinicalVideoComment;
import com.example.caseData.utils.Replace;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Objects;
//import static com.baomidou.mybatisplus.extension.toolkit.Db.removeById;

View File

@ -6,6 +6,7 @@ import com.example.caseData.exception.BusinessException;
import com.example.caseData.model.*;
import com.example.caseData.request.caseExchangeRequest.addCaseExchange;
import com.example.caseData.request.caseExchangeRequest.addCaseExchangeComment;
import com.example.caseData.request.caseExchangeRequest.updateCaseExchange;
import com.example.caseData.utils.JwtUtil;
import com.example.caseData.utils.RegularUtil;
import com.example.caseData.utils.Replace;
@ -199,6 +200,153 @@ public class CaseExchangeService {
return true;
}
/**
* 修改-病例交流
* @param userId 用户id
* @param exchangeId 病例交流id
* @return bool
*/
@Transactional
public boolean UpdateCaseExchange(String userId,String exchangeId, updateCaseExchange r){
// 获取病例交流数据
CaseExchangeModel caseExchange = caseExchangeDao.selectById(exchangeId);
if (caseExchange == null){
throw new BusinessException("非法操作");
}
if (!Objects.equals(caseExchange.getUserId(), Long.valueOf(userId))){
throw new BusinessException("非法操作");
}
// 标签
if (r.getCaseExchangeLabel() != null && !r.getCaseExchangeLabel().isEmpty()){
for (updateCaseExchange.CaseExchangeLabelRequest caseExchangeLabelRequest : r.getCaseExchangeLabel()){
if (caseExchangeLabelRequest.getAppIden() == null){
throw new BusinessException("操作失败");
}
if (caseExchangeLabelRequest.getLabelName() == null){
throw new BusinessException("操作失败");
}
}
}
// 处理违法内容
BasicSensitiveWordService.FilterResult result = basicSensitiveWordService.filter(r.getExchangeContent());
if (result.hasSensitive == 1){
throw new BusinessException("内容中存在敏感词,请修改后提交");
}
if (r.getExchangeSummary() != null){
result = basicSensitiveWordService.filter(r.getExchangeSummary());
if (result.hasSensitive == 1){
throw new BusinessException("总结中存在敏感词,请修改后提交");
}
}
// 匹配预览视频
List<String> videoUrls = regularUtil.extractOssVideosUrls(r.getExchangeContent());
videoUrls.replaceAll(Replace::removeOssDomain);
String exchangeContentVideo = String.join(",", videoUrls);
String exchangeContentImage = "";
if (exchangeContentVideo.isEmpty()){
// 匹配预览图片
List<String> imageUrls = regularUtil.extractOssImageUrls(r.getExchangeContent());
imageUrls.replaceAll(Replace::removeOssDomain);
exchangeContentImage = String.join(",", imageUrls);
}else{
exchangeContentImage = "";
}
// 修改病例交流
caseExchange.setExchangeTitle(r.getExchangeTitle());
caseExchange.setExchangeStatus(1);
caseExchange.setExchangeContent(r.getExchangeContent());
caseExchange.setExchangeSummary(r.getExchangeSummary());
caseExchange.setExchangeContentVideo(exchangeContentVideo);
caseExchange.setExchangeContentImage(exchangeContentImage);
caseExchangeDao.updateById(caseExchange);
// 删除标签
LambdaQueryWrapper<CaseExchangeLabelModel> labelQueryWrapper = new LambdaQueryWrapper<>();
labelQueryWrapper.eq(CaseExchangeLabelModel::getExchangeId, exchangeId);
int res = caseExchangeLabelDao.delete(labelQueryWrapper);
if (res <= 0){
throw new BusinessException("操作失败");
}
// 新增标签
if (r.getCaseExchangeLabel() != null && !r.getCaseExchangeLabel().isEmpty()){
// 验证标签数据-暂时无法验证病例库不存标签库
List<updateCaseExchange.CaseExchangeLabelRequest> caseExchangeLabel = r.getCaseExchangeLabel();
for (updateCaseExchange.CaseExchangeLabelRequest label : caseExchangeLabel ){
CaseExchangeLabelModel caseExchangeLabelData = new CaseExchangeLabelModel();
caseExchangeLabelData.setExchangeId(caseExchange.getExchangeId());
caseExchangeLabelData.setAppIden(label.getAppIden());
caseExchangeLabelData.setLabelName(label.getLabelName());
res = caseExchangeLabelDao.insert(caseExchangeLabelData);
if (res <= 0){
throw new BusinessException("操作失败");
}
}
}
return true;
}
/**
* 删除-病例交流
* @param exchangeId 病例交流id
* @param userId 用户id
* @return bool
*/
@Transactional
public boolean DeleteCaseExchange(String exchangeId, String userId){
// 获取病例交流数据
CaseExchangeModel caseExchange = caseExchangeDao.selectById(exchangeId);
if (caseExchange == null) {
return false;
}
if (!Objects.equals(caseExchange.getUserId(), Long.valueOf(userId))){
throw new BusinessException("非法操作");
}
// 修改病例交流删除状态
caseExchange.setDeleteStatus(1);
caseExchangeDao.updateById(caseExchange);
// 处理统计数据
boolean r = DecCaseExchangeStats(exchangeId,4,1);
if (!r){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return false;
}
r = DecCaseExchangeStats(exchangeId,1,caseExchange.getReadNum());
if (!r){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return false;
}
r = DecCaseExchangeStats(exchangeId,2,caseExchange.getCollectNum());
if (!r){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return false;
}
r = DecCaseExchangeStats(exchangeId,3,caseExchange.getCommentNum());
if (!r){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return false;
}
return true;
}
/**
* 新增收藏-病例交流
* @param exchangeId 病例交流id
@ -260,7 +408,7 @@ public class CaseExchangeService {
}
// 减少文章的统计字段
boolean r = DecCaseExchangeStats(exchangeId,2);
boolean r = DecCaseExchangeStats(exchangeId,2,1);
if (!r){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return false;
@ -364,7 +512,7 @@ public class CaseExchangeService {
}
// 减少统计字段
boolean r = DecCaseExchangeStats(String.valueOf(comment.getExchangeId()),2);
boolean r = DecCaseExchangeStats(String.valueOf(comment.getExchangeId()),1,1);
if (!r){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return false;
@ -580,10 +728,10 @@ public class CaseExchangeService {
/**
* 减少病例交流统计字段
* @param exchangeId 病例id
* @param type 类型1:阅读量 2收藏量 3:评论数
* @param type 类型1:阅读量 2收藏量 3:评论数 4:数量
*/
@Transactional
public boolean DecCaseExchangeStats(String exchangeId,Integer type){
public boolean DecCaseExchangeStats(String exchangeId,Integer type,Integer num){
try {
// 获取病例数据
CaseExchangeModel caseExchange = caseExchangeDao.selectById(exchangeId);
@ -601,37 +749,46 @@ public class CaseExchangeService {
// 阅读量
if (type == 1){
//
statsCaseExchangeDao.dec(1L,"exchange_read_num",1);
statsCaseExchangeDao.dec(1L,"exchange_read_num",num);
//
caseExchangeDao.dec(Long.valueOf(exchangeId),"read_num",1);
caseExchangeDao.dec(Long.valueOf(exchangeId),"read_num",num);
// 用户
statsCaseExchangeUserDao.dec(statsCaseExchangeUser.getUserId(),"exchange_read_num",1);
statsCaseExchangeUserDao.dec(statsCaseExchangeUser.getUserId(),"exchange_read_num",num);
}
// 收藏量
if (type == 2){
//
statsCaseExchangeDao.dec(1L,"exchange_collect_num",1);
statsCaseExchangeDao.dec(1L,"exchange_collect_num",num);
//
caseExchangeDao.dec(Long.valueOf(exchangeId),"collect_num",1);
caseExchangeDao.dec(Long.valueOf(exchangeId),"collect_num",num);
// 用户
statsCaseExchangeUserDao.dec(statsCaseExchangeUser.getUserId(),"exchange_collect_num",1);
statsCaseExchangeUserDao.dec(statsCaseExchangeUser.getUserId(),"exchange_collect_num",num);
}
// 评论数
if (type == 3){
//
statsCaseExchangeDao.dec(1L,"exchange_comment_num",1);
statsCaseExchangeDao.dec(1L,"exchange_comment_num",num);
//
caseExchangeDao.dec(Long.valueOf(exchangeId),"comment_num",1);
caseExchangeDao.dec(Long.valueOf(exchangeId),"comment_num",num);
// 用户
statsCaseExchangeUserDao.dec(statsCaseExchangeUser.getUserId(),"exchange_comment_num",1);
statsCaseExchangeUserDao.dec(statsCaseExchangeUser.getUserId(),"exchange_comment_num",num);
}
// 数量
if (type == 4){
//
statsCaseExchangeDao.dec(1L,"exchange_num",num);
// 用户
statsCaseExchangeUserDao.dec(statsCaseExchangeUser.getUserId(),"exchange_num",num);
}
return true;

View File

@ -85,7 +85,7 @@ public class IndexService {
caseClinicalArticleQueryWrapper = new LambdaQueryWrapper<>();
caseClinicalArticleQueryWrapper.eq(CaseClinicalArticleModel::getArticleStatus, 1) // 上线状态
.orderByDesc(CaseClinicalArticleModel::getReadNum) // 按阅读量倒序
.last("LIMIT 2"); // 只取2条记录
.last("LIMIT 3"); // 只取2条记录
List<CaseClinicalArticleModel> mostReadArticles = caseClinicalArticleDao.selectList(caseClinicalArticleQueryWrapper);
for (CaseClinicalArticleModel article : mostReadArticles) {
// 根据文章ID查找作者
@ -118,7 +118,7 @@ public class IndexService {
// 医院病例库推荐-2条
LambdaQueryWrapper<StatsCaseClinicalHospitalModel> statsCaseClinicalHospitalModelQueryWrapper = new LambdaQueryWrapper<>();
statsCaseClinicalHospitalModelQueryWrapper.orderByDesc(StatsCaseClinicalHospitalModel::getArticleNum) // 按文章数量倒序
.last("LIMIT 2"); // 只取2条记录
.last("LIMIT 3"); // 只取2条记录
List<StatsCaseClinicalHospitalModel> statsCaseClinicalHospitals = statsCaseClinicalHospitalDao.selectList(statsCaseClinicalHospitalModelQueryWrapper);
for (StatsCaseClinicalHospitalModel hospital : statsCaseClinicalHospitals) {
// 查询医院基础数据