新增了打赏积分和获取用户积分

This commit is contained in:
wucongxing8150 2025-06-12 16:53:08 +08:00
parent 73e7eb620a
commit 0e5d8effa8
16 changed files with 590 additions and 23 deletions

View File

@ -18,4 +18,7 @@ public class AppConfig {
@Value("${app.platform}")
private String platform;
@Value("${app.platformPointAccount}")
private String platformPointAccount;
}

View File

@ -23,10 +23,7 @@ import com.example.caseData.service.CaseClinicalVideoService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
@ -71,6 +68,8 @@ public class ClinicalController extends BaseController {
@Resource
private CaseClinicalVideoService caseClinicalVideoService;
/**
* 临床病例库-搜索-文章
*/
@ -120,10 +119,15 @@ public class ClinicalController extends BaseController {
}
}
// 获取视频数量
resultMap.put("page", resultPage.getCurrent());
resultMap.put("pageSize", resultPage.getSize());
resultMap.put("total", resultPage.getTotal());
resultMap.put("data", resultPage.getRecords());
resultMap.put("search_article_num", resultPage.getTotal());
resultMap.put("search_video_num", 0);
return Response.success(resultMap);
}
@ -256,4 +260,7 @@ public class ClinicalController extends BaseController {
resultMap.put("data", resultPage.getRecords());
return Response.success(resultMap);
}
}

View File

@ -0,0 +1,50 @@
package com.example.caseData.controller;
import com.example.caseData.common.Response;
import com.example.caseData.dto.T;
import com.example.caseData.exception.BusinessException;
import com.example.caseData.request.RewardPointRequest.rewardPoint;
import com.example.caseData.service.RewardPointService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("/api")
public class RewardPointController {
@Resource
private HttpServletRequest httpServletRequest;
@Resource
private RewardPointService rewardService;
/**
* 临床病例库-打赏
*/
@PostMapping("/reward")
public Response<T> RewardPoint(@Validated() @ModelAttribute rewardPoint r) {
// 判断参数
if (r.getType() != 1 && r.getType() != 2 && r.getType() != 3){
return Response.error("操作失败");
}
String userId = (String) httpServletRequest.getAttribute("userId");
try {
boolean res = rewardService.RewardPoint(userId,r);
if (!res){
return Response.error("操作失败");
}
} catch (BusinessException e) {
return Response.error(e.getMessage());
}
return Response.success();
}
}

View File

@ -3,9 +3,14 @@ package com.example.caseData.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.caseData.common.Response;
import com.example.caseData.dao.*;
import com.example.caseData.dto.T;
import com.example.caseData.dto.user.UserDto;
import com.example.caseData.exception.BusinessException;
import com.example.caseData.extend.app.UserPoint.UserPoint;
import com.example.caseData.extend.app.UserPoint.UserPointResponse;
import com.example.caseData.model.*;
import com.example.caseData.request.UserRequest.UserRequest;
import com.example.caseData.service.RewardPointService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.validation.annotation.Validated;
@ -44,6 +49,12 @@ public class UserController extends BaseController {
@Resource
private UserCaseReadDao userCaseReadDao;
@Resource
private RewardPointService rewardService;
@Resource
private UserPoint userPoint;
// // 查询所有用户
// @GetMapping("/users")
// public Response<Map<String, Object>> getUserPage(@Validated({UserRequest.Page.class}) @ModelAttribute UserRequest request) {
@ -109,6 +120,33 @@ public class UserController extends BaseController {
return Response.success(g);
}
/**
* 获取用户积分
*/
@GetMapping("/user/point")
public Response<Integer> getUserPoint() {
String userId = (String) httpServletRequest.getAttribute("userId");
// 获取当前登录用户数据
UserModel user = userDao.selectById(Long.valueOf(userId));
if (user == null) {
return Response.error();
}
Integer point = 0;
try {
UserPointResponse result = userPoint.GetUserPoint(user.getUserIden());
point = result.getData();
if (point == null) {
point = 0;
}
} catch (BusinessException e) {
return Response.error(e.getMessage());
}
return Response.success(point);
}
}

View File

@ -28,6 +28,18 @@ public interface CaseClinicalVideoDao extends BaseMapper<CaseClinicalVideoModel>
@Param("order") Map<String, String> order
);
/**
* 临床病例库-搜索-数量
* @param page 分页数据
* @param keyword 搜索关键词-标题/医生名称/标签名称
*/
Long getCaseClinicalVideoSearchCount(
Page<?> page,
@Param("keyword") String keyword,
@Param("hospitalId") String hospitalId,
@Param("doctorId") String doctorId
);
/**
* Inc 自增
* @param articleId 文章 ID

View File

@ -0,0 +1,18 @@
package com.example.caseData.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.caseData.dto.caseClinicalVideo.CaseClinicalVideoDto;
import com.example.caseData.model.CaseClinicalVideoModel;
import com.example.caseData.model.RecordRewardPointModel;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
import java.util.Map;
@Mapper
public interface RecordRewardPointDao extends BaseMapper<RecordRewardPointModel> {
}

View File

@ -0,0 +1,67 @@
package com.example.caseData.extend.app.Reward;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.example.caseData.config.AppConfig;
import com.example.caseData.exception.BusinessException;
import com.example.caseData.extend.app.Base;
import com.example.caseData.extend.app.label.GetLabelsResponse;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@Slf4j
@Component
public class Reward extends Base {
@Resource
private AppConfig appConfig;
// 打赏积分
public RewardResponse RewardPoint(String userUuid,Integer point,String authorUuid) throws BusinessException {
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
// 处理参数
Map<String, Object> requestData = new HashMap<>();
requestData.put("user_uuid", userUuid);
requestData.put("bonusPoints", point);
requestData.put("recipients", authorUuid);
requestData.put("platform", appConfig.getPlatform());
requestData.put("timestamp", timestamp);
// 生成签名
String sign = genSignature(requestData,appConfig.getSecretKey());
String url = appConfig.getApiUrl() + "/expert-api/admireBonusPoints";
String jsonBody = JSONUtil.toJsonStr(requestData);
log.info("获取app数据参数:{}",jsonBody);
try(HttpResponse response = HttpRequest.post(url)
.header("Content-Type", "application/json")
.header("sign", sign)
.body(jsonBody)
.execute()){
if (response.getStatus() != 200) {
throw new BusinessException("失败");
}
// 反序列化 JSON
RewardResponse result = JSONUtil.toBean(response.body(), RewardResponse.class);
log.info("获取app数据返回:{}",result);
if (result.getCode() != 200){
if (!Objects.equals(result.getMsg(), "")){
throw new BusinessException(result.getMsg());
}else{
throw new BusinessException("失败");
}
}
return result;
}
}
}

View File

@ -0,0 +1,23 @@
package com.example.caseData.extend.app.Reward;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
public class RewardResponse
{
/** 接口调用状态。200正常其它值调用出错 */
private int code;
/** 结果说明。如果接口调用出错,那么返回错误描述。成功则返回 ok */
private String msg;
/** 接口是否调用成功 */
private boolean success;
/** 错误信息或提示信息 */
private String message;
}

View File

@ -0,0 +1,64 @@
package com.example.caseData.extend.app.UserPoint;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.example.caseData.config.AppConfig;
import com.example.caseData.exception.BusinessException;
import com.example.caseData.extend.app.Base;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@Slf4j
@Component
public class UserPoint extends Base {
@Resource
private AppConfig appConfig;
// 获取用户积分
public UserPointResponse GetUserPoint(String uuid) throws BusinessException {
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
// 处理参数
Map<String, Object> requestData = new HashMap<>();
requestData.put("user_uuid", uuid);
requestData.put("platform", appConfig.getPlatform());
requestData.put("timestamp", timestamp);
// 生成签名
String sign = genSignature(requestData,appConfig.getSecretKey());
String url = appConfig.getApiUrl() + "/expert-api/getBonusPoints";
String jsonBody = JSONUtil.toJsonStr(requestData);
log.info("获取app数据参数:{}",jsonBody);
try(HttpResponse response = HttpRequest.post(url)
.header("Content-Type", "application/json")
.header("sign", sign)
.body(jsonBody)
.execute()){
if (response.getStatus() != 200) {
throw new BusinessException("失败");
}
// 反序列化 JSON
UserPointResponse result = JSONUtil.toBean(response.body(), UserPointResponse.class);
log.info("获取app数据返回:{}",result);
if (result.getCode() != 200){
if (!Objects.equals(result.getMsg(), "")){
throw new BusinessException(result.getMsg());
}else{
throw new BusinessException("失败");
}
}
return result;
}
}
}

View File

@ -0,0 +1,26 @@
package com.example.caseData.extend.app.UserPoint;
import com.example.caseData.extend.app.label.GetLabelsResponse;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
public class UserPointResponse
{
/** 接口调用状态。200正常其它值调用出错 */
private int code;
/** 结果说明。如果接口调用出错,那么返回错误描述。成功则返回 ok */
private String msg;
/** 接口是否调用成功 */
private boolean success;
/** 错误信息或提示信息 */
private String message;
/** 接口返回的数据 */
private Integer data;
}

View File

@ -0,0 +1,65 @@
package com.example.caseData.model;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 记录-打赏积分记录实体类
*/
@Data // Lombok注解用于自动生成getter/setter方法等
@TableName("`record_reward_point`") // 指定数据库表名
public class RecordRewardPointModel {
/**
* 主键id
*/
@TableId(type = IdType.ASSIGN_ID) // 使用MyBatis-Plus的ID生成策略
private Long rewardPointId;
/**
* 打赏人id
*/
@TableField("user_id")
private Long userId;
/**
* 作者唯一标识根据type不同对应不同
* 文章/视频case_clinical_doctor
* 病例交流user
*/
@TableField("author_iden")
private String authorIden;
/**
* 来源id根据type不同对应不同文章表
*/
@TableField("source_id")
private String sourceId;
/**
* 积分总数
*/
@TableField("point")
private Integer point;
/**
* 来源类型1:文章 2:视频 3:病例交流
*/
@TableField("source_type")
private Integer sourceType;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@JsonProperty("created_at")
private LocalDateTime createdAt;
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updatedAt;
}

View File

@ -0,0 +1,33 @@
package com.example.caseData.request.RewardPointRequest;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class rewardPoint {
/**
* 主键id根据type不同对应不同数据表
*/
@JsonProperty("id")
@NotEmpty(message = "参数错误")
private String id;
/**
* 类型1:文章 2:视频 3:病例交流
*/
@JsonProperty("type")
@NotNull(message = "参数错误")
private Integer type;
/**
* 总积分
*/
@JsonProperty("point")
@NotNull(message = "参数错误")
@Min(value = 1, message = "请最少打赏1积分")
private Integer point;
}

View File

@ -0,0 +1,138 @@
package com.example.caseData.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.caseData.config.AppConfig;
import com.example.caseData.dao.*;
import com.example.caseData.extend.app.Reward.Reward;
import com.example.caseData.middlewares.LogRequestInterceptor;
import com.example.caseData.model.*;
import com.example.caseData.request.RewardPointRequest.rewardPoint;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Service
public class RewardPointService {
@Resource
private Reward reward;
@Resource
private UserDao userDao;
@Resource
private AppConfig appConfig;
@Resource
private CaseClinicalArticleAuthorDao caseClinicalArticleAuthorDao;
@Resource
private CaseClinicalVideoAuthorDao caseClinicalVideoAuthorDao;
@Resource
private CaseClinicalDoctorDao caseClinicalDoctorDao;
@Resource
private CaseExchangeDao caseExchangeDao;
@Resource
private RecordRewardPointDao recordRewardPointDao;
private static final Logger logger = LoggerFactory.getLogger(LogRequestInterceptor.class);
@Transactional
public boolean RewardPoint(String userId, rewardPoint r){
// 获取当前登录用户数据
UserModel user = userDao.selectById(Long.valueOf(userId));
if (user == null) {
return false;
}
// 获取对应作者
List<String> authorList = new ArrayList<>();
// 文章
if (r.getType() == 1){
// 获取文章作者数据
LambdaQueryWrapper<CaseClinicalArticleAuthorModel> authorQueryWrapper = new LambdaQueryWrapper<>();
authorQueryWrapper.eq(CaseClinicalArticleAuthorModel::getArticleId, r.getId());
List<CaseClinicalArticleAuthorModel> caseClinicalArticleAuthors = caseClinicalArticleAuthorDao.selectList(authorQueryWrapper);
for (CaseClinicalArticleAuthorModel author : caseClinicalArticleAuthors) {
// 查询医生
CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectById(author.getDoctorId());
if (caseClinicalDoctor == null) {
authorList.add(appConfig.getPlatformPointAccount());
}else{
authorList.add(caseClinicalDoctor.getDoctorIden());
}
}
}
// 视频
if (r.getType() == 2){
// 获取文章作者数据
LambdaQueryWrapper<CaseClinicalVideoAuthorModel> authorQueryWrapper = new LambdaQueryWrapper<>();
authorQueryWrapper.eq(CaseClinicalVideoAuthorModel::getVideoId, r.getId());
List<CaseClinicalVideoAuthorModel> caseClinicalVideoAuthors = caseClinicalVideoAuthorDao.selectList(authorQueryWrapper);
for (CaseClinicalVideoAuthorModel author : caseClinicalVideoAuthors) {
// 查询医生
CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectById(author.getDoctorId());
if (caseClinicalDoctor == null) {
authorList.add(appConfig.getPlatformPointAccount());
}else {
authorList.add(caseClinicalDoctor.getDoctorIden());
}
}
}
// 病例交流
if (r.getType() == 3){
// 获取病例交流数据
CaseExchangeModel exchange = caseExchangeDao.selectById(r.getId());
if (exchange == null) {
return false;
}
if (exchange.getExchangeStatus() != 1){
return false;
}
// 获取病例交流用户数据
UserModel exchangeUser = userDao.selectById(exchange.getUserId());
if (exchangeUser == null) {
return false;
}
authorList.add(exchangeUser.getUserIden());
}
if (authorList.isEmpty()) {
return false;
}
String authors = String.join(",", authorList);
reward.RewardPoint(user.getUserIden(),r.getPoint(),authors);
// 添加打赏记录
RecordRewardPointModel data = new RecordRewardPointModel();
data.setUserId(Long.valueOf(userId));
data.setAuthorIden(authors);
data.setSourceId(r.getId());
data.setPoint(r.getPoint());
data.setSourceType(r.getType());
int res = recordRewardPointDao.insert(data);
if (res <= 0){
logger.info("添加打赏记录失败: {}",r);
}
return true;
}
}

View File

@ -65,3 +65,4 @@ app:
secretKey: nmBCF@hEK6eN&h03dYUin@AU3%bMf%$O
imagePrefix: https://dev-doc.igandan.com/app
platform: case-storge
platformPointAccount: GDXZadmin01

View File

@ -49,25 +49,25 @@
a.collect_num,
a.push_date
FROM (
SELECT DISTINCT a.article_id
FROM case_clinical_article a
LEFT JOIN case_clinical_article_author caa ON a.article_id = caa.article_id
LEFT JOIN case_clinical_doctor d ON caa.doctor_id = d.doctor_id
LEFT JOIN case_clinical_article_label l ON a.article_id = l.article_id
WHERE a.article_status = 1
<if test="keyword != null and keyword != ''">
AND (
a.article_title LIKE CONCAT('%', #{keyword}, '%')
OR d.doctor_name LIKE CONCAT('%', #{keyword}, '%')
OR l.label_name LIKE CONCAT('%', #{keyword}, '%')
)
</if>
<if test="hospitalId != null and hospitalId != ''">
AND d.hospital_id = ${hospitalId}
</if>
<if test="doctorId != null and doctorId != ''">
AND d.doctor_id = ${doctorId}
</if>
SELECT DISTINCT a.article_id
FROM case_clinical_article a
LEFT JOIN case_clinical_article_author caa ON a.article_id = caa.article_id
LEFT JOIN case_clinical_doctor d ON caa.doctor_id = d.doctor_id
LEFT JOIN case_clinical_article_label l ON a.article_id = l.article_id
WHERE a.article_status = 1
<if test="keyword != null and keyword != ''">
AND (
a.article_title LIKE CONCAT('%', #{keyword}, '%')
OR d.doctor_name LIKE CONCAT('%', #{keyword}, '%')
OR l.label_name LIKE CONCAT('%', #{keyword}, '%')
)
</if>
<if test="hospitalId != null and hospitalId != ''">
AND d.hospital_id = ${hospitalId}
</if>
<if test="doctorId != null and doctorId != ''">
AND d.doctor_id = ${doctorId}
</if>
) AS result
JOIN case_clinical_article a ON a.article_id = result.article_id
<if test="order != null and !order.isEmpty()">

View File

@ -43,4 +43,26 @@
</foreach>
</if>
</select>
<select id="getCaseClinicalVideoSearchCount" resultType="long">
SELECT COUNT(DISTINCT a.video_id)
FROM case_clinical_video a
LEFT JOIN case_clinical_video_author caa ON a.video_id = caa.video_id
LEFT JOIN case_clinical_doctor d ON caa.doctor_id = d.doctor_id
LEFT JOIN case_clinical_video_label l ON a.video_id = l.video_id
WHERE a.video_status = 1
<if test="keyword != null and keyword != ''">
AND (
a.video_title LIKE CONCAT('%', #{keyword}, '%')
OR d.doctor_name LIKE CONCAT('%', #{keyword}, '%')
OR l.label_name LIKE CONCAT('%', #{keyword}, '%')
)
</if>
<if test="hospitalId != null and hospitalId != ''">
AND d.hospital_id = ${hospitalId}
</if>
<if test="doctorId != null and doctorId != ''">
AND d.doctor_id = ${doctorId}
</if>
</select>
</mapper>