Przeglądaj źródła

add
研究队列手术问卷历史记录

lifang 2 miesięcy temu
rodzic
commit
ad26d63123

+ 1 - 12
tr-modules/tr-module-smartFollowUp/src/main/java/cn/tr/module/smart/common/config/RabbitMQConfig.java

@@ -75,17 +75,6 @@ public class RabbitMQConfig {
 
 
     /***************************研究队列推送配置***************************/
-
-    /**
-     * 创建延迟消息交换机
-     * @return TopicExchange 交换机实例
-     */
-    @Bean
-    public CustomExchange reasearchExchange() {
-        Map<String, Object> args = new HashMap<>();
-        args.put("x-delayed-type", "topic");
-        return new CustomExchange(RabbitMQConstant.TOPIC_EXCHANGE_REASEARCH_NAME, "x-delayed-message", true, false, args);
-    }
     /**
      * 创建服务号推送队列
      * @return Queue 队列实例
@@ -101,7 +90,7 @@ public class RabbitMQConfig {
      */
     @Bean
     public Binding reasearchBinding() {
-        return BindingBuilder.bind(mpPushQueue())
+        return BindingBuilder.bind(reasearchQueue())
                 .to(mpDelayExchange())
                 .with(RabbitMQConstant.ROUTING_KEY_REASEARCH_PUSH)
                 .noargs();

+ 4 - 2
tr-modules/tr-module-smartFollowUp/src/main/java/cn/tr/module/smart/common/controller/vo/BizReasearchQueuePushVO.java

@@ -1,6 +1,5 @@
 package cn.tr.module.smart.common.controller.vo;
 
-import cn.tr.module.smart.common.entity.BizReasearchPushPointEntity;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.ToString;
@@ -34,8 +33,11 @@ public class BizReasearchQueuePushVO implements Serializable {
     private  List<Long> timePointsFormat;
 
     /** 上次的推送时间间隔 */
-    private Integer lastPushInterval;
+    private Long lastPushInterval;
 
     /** 手术结束时间 */
     private Date clinicEndTime;
+
+    @ApiModelProperty("微信openId")
+    private String wxMpOpenId;
 }

+ 0 - 2
tr-modules/tr-module-smartFollowUp/src/main/java/cn/tr/module/smart/common/enums/RabbitMQConstant.java

@@ -17,8 +17,6 @@ public interface RabbitMQConstant {
     String QUEUE_MP_PUSH = "patient.mp.push";
 
     //研究队列
-    String TOPIC_EXCHANGE_REASEARCH_NAME = "reasearch.exchange";
-
     String ROUTING_KEY_REASEARCH_PUSH = "reasearch.queue.push";
 
     String QUEUE_REASEARCH_PUSH = "reasearch.queue.push";

+ 1 - 1
tr-modules/tr-module-smartFollowUp/src/main/java/cn/tr/module/smart/common/po/BizReasearchQueuePO.java

@@ -47,7 +47,7 @@ public class BizReasearchQueuePO extends TenantPO {
     @TableField(typeHandler = JsonbReasearchPushPointListTypeHandler.class)
     private List<BizReasearchPushPointEntity> timePoints;
 
-    /** 推送时间点格式化 */
+    /** 推送时间点格式化 (毫秒)*/
     @ApiModelProperty(value = "推送时间点格式化", position = 6)
     @TableField(typeHandler = JsonbLongListTypeHandler.class)
     private  List<Long> timePointsFormat;

+ 6 - 2
tr-modules/tr-module-smartFollowUp/src/main/java/cn/tr/module/smart/common/register/WxSendTemplateMsgRegister.java

@@ -56,15 +56,16 @@ public class WxSendTemplateMsgRegister implements BeanPostProcessor {
      * 发送模板消
      */
     public <T extends WxTemplateDTO> String sendMessage(String openId, T msg,String tenantId,String clinicId) throws WxErrorException {
-        return sendMessage(openId,null,msg,tenantId,clinicId);
+        return sendMessage(openId,null,msg,tenantId,clinicId,null);
     }
 
+
     @SuppressWarnings("unchecked")
     /**
      * 发送模板消息
      * @param wxMpService
      */
-    public <T extends WxTemplateDTO> String sendMessage( String openId, String url, T msg,String tenantId,String clinicId) throws WxErrorException {
+    public <T extends WxTemplateDTO> String sendMessage( String openId, String url, T msg,String tenantId,String clinicId,String queueId) throws WxErrorException {
         if (msg == null) {
             throw new ServiceException(TRExcCode.SYSTEM_ERROR_B0001, "参数对象msg不能为空");
         }
@@ -87,6 +88,9 @@ public class WxSendTemplateMsgRegister implements BeanPostProcessor {
             if(StrUtil.isNotEmpty(clinicId)){
                 pagePath=pagePath+"&clinicId="+clinicId;
             }
+            if(StrUtil.isNotEmpty(queueId)){
+                pagePath=pagePath+"&queueId="+queueId;
+            }
         }
         Boolean haveApplet=StrUtil.isNotBlank(pagePath);
         if(haveApplet&&wxMpService==null){

+ 4 - 0
tr-modules/tr-module-smartFollowUp/src/main/java/cn/tr/module/smart/common/repository/BizReasearchQueueClinicRepository.java

@@ -5,6 +5,7 @@ import cn.tr.module.smart.common.controller.vo.BizReasearchQueuePushVO;
 import cn.tr.module.smart.common.controller.vo.BizReasearchQueueQuestionAnswerVO;
 import cn.tr.module.smart.common.dto.BizReasearchQueueClinicQueryDTO;
 import cn.tr.module.smart.common.dto.BizReasearchQueueClinicQuestionAnswerRecordQueryDTO;
+import cn.tr.module.smart.wx.dto.BizMpPublishInfoDTO;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -24,5 +25,8 @@ import java.util.List;
 public interface BizReasearchQueueClinicRepository extends BaseMapper<BizReasearchQueueClinicPO> {
     List<BizReasearchQueueClinicVO> stdSelectBizReasearchQueueClinicList(@Param("query") BizReasearchQueueClinicQueryDTO query);
 
+
+    BizMpPublishInfoDTO selectPushInfo(@Param("id") String id);
+
     BizReasearchQueuePushVO stdSelectBizReasearchQueueClinicById(@Param("id") String id);
 }

+ 0 - 15
tr-modules/tr-module-smartFollowUp/src/main/java/cn/tr/module/smart/common/service/impl/BizMpPublishTaskServiceImpl.java

@@ -100,21 +100,6 @@ public class BizMpPublishTaskServiceImpl implements IBizMpPublishTaskService {
         }
         BizMpPublishTaskPO mpPublishTask = BizClinicRoomHelper.getMpPublishTask(clinicId, clinicEndTime,
                 bizQuestionGroupPO.getInterval(), bizQuestionGroupPO.getFrequency(),  ClinicUndoType.questionGroup);
-//        List<SysJobDTO> jobQuestion = BizClinicRoomHelper.getJobQuestion(mpPublishTask.getId(), mpPublishTask.getCron());
-//        List<JobKey> jobKeys  = new ArrayList<>();
-//        for (SysJobDTO job:jobQuestion  ){
-//            JobDetail scheduleJob = ScheduleUtils.createScheduleJob(scheduler, job);
-//            jobKeys.add(scheduleJob.getKey());
-//        }
-//        List<JobKeyEntity> collect = jobKeys.stream()
-//                .map(jobKey -> {
-//                    JobKeyEntity jobKeyEntity = new JobKeyEntity();
-//                    jobKeyEntity.setName(jobKey.getName());
-//                    jobKeyEntity.setGroup(jobKey.getGroup());
-//                    return jobKeyEntity;
-//                })
-//                .collect(Collectors.toList());
-//        mpPublishTask.setCronJob(collect);
         baseRepository.insert(mpPublishTask);
         //推送到消息队列
         sendDelayMessage(mpPublishTask);

+ 119 - 13
tr-modules/tr-module-smartFollowUp/src/main/java/cn/tr/module/smart/common/service/impl/BizReasearchQueueClinicServiceImpl.java

@@ -1,5 +1,6 @@
 package cn.tr.module.smart.common.service.impl;
 
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.tr.core.annotation.TenantIgnore;
@@ -9,25 +10,26 @@ import cn.tr.module.smart.common.controller.vo.BizReasearchQueuePushVO;
 import cn.tr.module.smart.common.controller.vo.BizReasearchQueueQuestionAnswerVO;
 import cn.tr.module.smart.common.dto.BizReasearchQueueAddClinicDTO;
 import cn.tr.module.smart.common.dto.BizReasearchQueueClinicQuestionAnswerRecordQueryDTO;
+import cn.tr.module.smart.common.enums.MpPublishTaskTypeEnums;
+import cn.tr.module.smart.common.enums.RabbitMQConstant;
 import cn.tr.module.smart.common.mapper.BizQuestionAnswerMapper;
-import cn.tr.module.smart.common.po.BizClinicRoomPO;
-import cn.tr.module.smart.common.po.BizQuestionAnswerPO;
-import cn.tr.module.smart.common.po.BizReasearchQueuePO;
-import cn.tr.module.smart.common.repository.BizClinicRoomRepository;
-import cn.tr.module.smart.common.repository.BizQuestionAnswerRepository;
-import cn.tr.module.smart.common.repository.BizReasearchQueueRepository;
+import cn.tr.module.smart.common.po.*;
+import cn.tr.module.smart.common.repository.*;
+import cn.tr.module.smart.wx.config.WxTemplateSendHelper;
+import cn.tr.module.smart.wx.dto.BizMpPublishInfoDTO;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import cn.hutool.core.collection.CollectionUtil;
 import org.springframework.transaction.annotation.Transactional;
 import cn.tr.core.exception.ServiceException;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import cn.tr.module.smart.common.repository.BizReasearchQueueClinicRepository;
-import cn.tr.module.smart.common.po.BizReasearchQueueClinicPO;
 import cn.tr.module.smart.common.dto.BizReasearchQueueClinicQueryDTO;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 import cn.tr.module.smart.common.service.IBizReasearchQueueClinicService;
@@ -38,6 +40,7 @@ import cn.tr.module.smart.common.service.IBizReasearchQueueClinicService;
  * @date  2025/10/15 08:27
  **/
 @Service
+@Slf4j
 public class BizReasearchQueueClinicServiceImpl extends ServiceImpl<BizReasearchQueueClinicRepository,BizReasearchQueueClinicPO> implements IBizReasearchQueueClinicService {
     @Autowired
     private BizQuestionAnswerRepository questionAnswerRepository;
@@ -45,6 +48,12 @@ public class BizReasearchQueueClinicServiceImpl extends ServiceImpl<BizReasearch
     private BizReasearchQueueRepository reasearchQueueRepository;
     @Autowired
     private BizClinicRoomRepository clinicRoomRepository;
+    @Autowired
+    private RabbitTemplate rabbitTemplate;
+    @Autowired
+    private WxTemplateSendHelper wxTemplateSendHelper;
+    @Autowired
+    private BizMpPublishTaskRepository bizMpPublishTaskRepository;
     /**
      * 根据条件查询队列-临床手术关联表
      * @param    query 查询参数
@@ -126,16 +135,113 @@ public class BizReasearchQueueClinicServiceImpl extends ServiceImpl<BizReasearch
 
     @Override
     @TenantIgnore
+    @Transactional(rollbackFor = Exception.class)
     public void pushReasearchQueueQuestion(String id){
-        if(StrUtil.isBlank(id)){
+        // 添加日志记录
+        log.info("开始处理研究队列推送任务,ID: {}", id);
+
+        // 查询研究队列信息
+        BizReasearchQueuePushVO reasearchQueuePushVO = this.baseMapper.stdSelectBizReasearchQueueClinicById(id);
+        if (ObjectUtil.isNull(reasearchQueuePushVO)) {
+            log.warn("未找到对应的研究队列信息,ID: {}", id);
             return;
         }
-        BizReasearchQueuePushVO reasearchQueuePushVO=this.baseMapper.stdSelectBizReasearchQueueClinicById(id);
-        if(ObjectUtil.isNull(reasearchQueuePushVO)){
+        // 获取当前时间和手术结束时间
+        Date now = new Date();
+        Date clinicEndTime = reasearchQueuePushVO.getClinicEndTime();
+        log.info("当前时间: {}, 手术结束时间: {}", now, clinicEndTime);
+
+        if (ObjectUtil.isNull(clinicEndTime)) {
+            log.info("手术尚未结束,24小时后再次判断,ID: {}", id);
+            sendDelayMessage(id, TimeUnit.DAYS.toMillis(1));
             return;
         }
-        //先判断当前时间与手术结束时间的时间间隔是否满足研究队列的最小时间间隔要求
 
+        // 计算时间差
+        long timeDiffMillion = now.getTime() - clinicEndTime.getTime();
+        log.info("当前时间与手术结束时间的差值(毫秒): {}", timeDiffMillion);
+
+        // 获取上次推送间隔和时间点配置
+        Long lastPushInterval = ObjectUtil.isNull(reasearchQueuePushVO.getLastPushInterval()) ? 0 : reasearchQueuePushVO.getLastPushInterval();
+        List<Long> timePointsFormat = reasearchQueuePushVO.getTimePointsFormat();
+        log.debug("上次推送间隔: {} 毫秒", lastPushInterval);
+        log.debug("推送时间点配置: {}", timePointsFormat);
+
+        // 过滤出大于上次推送间隔的时间点
+        timePointsFormat = timePointsFormat.stream()
+                .filter(timeInterval -> timeInterval > lastPushInterval)
+                .collect(Collectors.toList());
+        log.debug("过滤后的推送时间点: {}", timePointsFormat);
+
+        // 确定下一个推送间隔
+        Long nextPushInterval = CollectionUtil.getFirst(timePointsFormat);
+        if (CollectionUtil.size(timePointsFormat) == 1) {
+            nextPushInterval = CollectionUtil.getFirst(timePointsFormat);
+        }
+        log.debug("确定的下一个推送间隔: {} 毫秒", nextPushInterval);
+
+        // 如果时间点数量大于1,查找相邻时间点
+        if (CollectionUtil.isNotEmpty(timePointsFormat) && timePointsFormat.size() > 1) {
+            List<Long> sortedTimePoints = timePointsFormat.stream().sorted().collect(Collectors.toList());
+            Long nextPoint = sortedTimePoints.stream()
+                    .filter(point -> point > timeDiffMillion)
+                    .findFirst()
+                    .orElse(null);
+            Long prevPoint = sortedTimePoints.stream()
+                    .filter(point -> point < timeDiffMillion)
+                    .max(Long::compareTo)
+                    .orElse(null);
 
+            log.debug("与当前时间差值相邻的两个时间点: prevPoint={}, nextPoint={}", prevPoint, nextPoint);
+
+            if (prevPoint != null) {
+                log.info("发现已过期的推送时间点,立即执行推送: {}", prevPoint);
+                sendMessage(reasearchQueuePushVO, prevPoint);
+            }
+            if (nextPoint != null) {
+                nextPushInterval = nextPoint;
+                log.debug("更新下一个推送间隔为: {} 毫秒", nextPushInterval);
+            }
+        }
+        // 判断是否需要立即推送或延迟推送
+        if (nextPushInterval < timeDiffMillion) {
+            log.info("已超过推送时间,立即推送消息,ID: {}", id);
+            sendMessage(reasearchQueuePushVO, nextPushInterval);
+        } else {
+            long waitMillion = nextPushInterval - timeDiffMillion;
+            log.info("未满足推送条件,需等待 {} 毫秒后推送,ID: {}", waitMillion, id);
+            sendDelayMessage(id, waitMillion);
+        }
+    }
+
+
+    //执行推送逻辑
+    private void sendMessage(BizReasearchQueuePushVO source,long nextPushInterval){
+        String sql =String.format("last_push_interval = %d  and push_count = push_count + 1 and last_push_time = %s",nextPushInterval,DateUtil.now());
+        baseMapper.update(null,new LambdaUpdateWrapper<BizReasearchQueueClinicPO>()
+                .eq(BizReasearchQueueClinicPO::getId,source.getId())
+                .setSql(sql));
+        try {
+            BizMpPublishInfoDTO publishInfo = baseMapper.selectPushInfo(source.getId());
+            wxTemplateSendHelper.sendMsg(publishInfo, MpPublishTaskTypeEnums.AFTER_QUESTION.getType());
+        }catch (Exception e){
+
+        }
+    }
+
+    /**
+     * 发送延迟消息到RabbitMQ
+     */
+    private void sendDelayMessage(String id,long delayTime) {
+        // 发送延迟消息
+        rabbitTemplate.convertAndSend(
+                RabbitMQConstant.TOPIC_EXCHANGE_MP_NAME,
+                RabbitMQConstant.ROUTING_KEY_MP_PUSH,
+                id,
+                message -> {
+                    message.getMessageProperties().getHeaders().put("x-delay", delayTime);
+                    return message;
+                }
+        );
     }
-}
+}

+ 5 - 3
tr-modules/tr-module-smartFollowUp/src/main/java/cn/tr/module/smart/wx/config/WxTemplateSendHelper.java

@@ -45,14 +45,16 @@ public class WxTemplateSendHelper {
     }
 
     public  <T extends WxTemplateDTO> void  sendMsg(String openId,T source) throws WxErrorException {
-        sendMsg(openId,source,null,null);
+        sendMsg(openId,source,null,null,null);
     }
 
-    public  <T extends WxTemplateDTO> void  sendMsg(String openId,T source,String tenantId,String clinicId) throws WxErrorException {
+    public  <T extends WxTemplateDTO> void  sendMsg(String openId,T source,String tenantId,String clinicId,String queueId) throws WxErrorException {
         wxSendTemplateMsgRegister.sendMessage(
                 openId,
+                null,
                 source,
                 tenantId,
-                clinicId);
+                clinicId,
+                queueId);
     }
 }

+ 8 - 0
tr-modules/tr-module-smartFollowUp/src/main/java/cn/tr/module/smart/wx/dto/BizMpPublishInfoDTO.java

@@ -1,11 +1,17 @@
 package cn.tr.module.smart.wx.dto;
 
 import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import java.util.Date;
 
 @Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
 public class BizMpPublishInfoDTO {
     @ApiModelProperty(value = "服务号用户唯一标识", position = 0)
     private String openId;
@@ -25,4 +31,6 @@ public class BizMpPublishInfoDTO {
     private String tenantName;
     @ApiModelProperty("手术状态")
     private String clinicStatus;
+    @ApiModelProperty("研究队列id")
+    private String queueId;
 }

+ 17 - 0
tr-modules/tr-module-smartFollowUp/src/main/resources/mapper/smart/BizReasearchQueueClinicMapper.xml

@@ -36,6 +36,19 @@
         <result property="clinicEndTime" column="clinic_end_time"/>
     </resultMap>
 
+    <resultMap id="pushInfo" type="cn.tr.module.smart.wx.dto.BizMpPublishInfoDTO">
+        <result property="openId" column="open_id" />
+        <result property="clinicId" column="clinic_id" />
+        <result property="clinicName" column="clinic_name" />
+        <result property="patientName" column="patient_name" />
+        <result property="patientCode" column="patient_code" />
+        <result property="clinicStartTime" column="clinic_start_time" />
+        <result property="tenantId" column="tenant_id" />
+        <result property="tenantName" column="tenant_name" />
+        <result property="clinicStatus" column="clinic_status" />
+        <result property="queueId" column="queue_id" />
+    </resultMap>
+
     <select id="stdSelectBizReasearchQueueClinicList" resultMap="stdResult">
         SELECT
         brqc.id,
@@ -61,4 +74,8 @@
     </select>
 
 
+    <select id="selectPushInfo" resultMap="pushInfo">
+
+
+    </select>
 </mapper>

+ 1 - 1
tr-modules/tr-module-smartFollowUp/src/main/resources/mapper/smart/BizReasearchQueueMapper.xml

@@ -19,7 +19,7 @@
         SELECT
         brq.id as id,
         brq.name as  name,
-        brq.question_group_name as question_group_name,
+        brq.name as question_group_name,
         brq.time_points_show as time_points_show,
         brq.clinic_count as clinic_count,
         brq.create_time as create_time,