Procházet zdrojové kódy

Merge remote-tracking branch 'origin/openIm' into bjcz_his_scrm

# Conflicts:
#	fs-company/src/main/java/com/fs/company/controller/common/Test.java
#	fs-service/src/main/java/com/fs/hisStore/param/FsStoreOrderPayParam.java
#	fs-user-app/src/main/java/com/fs/app/controller/PatientController.java
#	fs-user-app/src/main/java/com/fs/app/controller/store/StoreOrderScrmController.java
yjwang před 1 měsícem
rodič
revize
09cac3b332
100 změnil soubory, kde provedl 3703 přidání a 233 odebrání
  1. 4 0
      fs-admin/pom.xml
  2. 2 2
      fs-admin/src/main/java/com/fs/his/controller/FsInquiryOrderController.java
  3. 4 0
      fs-admin/src/main/java/com/fs/his/controller/FsUserAddressController.java
  4. 7 24
      fs-admin/src/main/java/com/fs/his/controller/FsUserController.java
  5. 75 0
      fs-admin/src/main/java/com/fs/his/task/Task.java
  6. 79 4
      fs-admin/src/main/java/com/fs/web/controller/common/CommonController.java
  7. 103 0
      fs-admin/src/test/java/com/fs/course/controller/OpenIMServiceTest.java
  8. 8 0
      fs-company-app/src/main/java/com/fs/app/controller/CompanyUserController.java
  9. 1 0
      fs-company-app/src/main/java/com/fs/app/controller/FsUserController.java
  10. 107 12
      fs-company-app/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java
  11. 4 0
      fs-company-app/src/main/java/com/fs/core/config/RedisConfig.java
  12. 3 3
      fs-company/src/main/java/com/fs/company/controller/company/CompanyUserController.java
  13. 1 1
      fs-company/src/main/java/com/fs/framework/config/SecurityConfig.java
  14. 26 0
      fs-company/src/main/java/com/fs/user/FsUserAdminController.java
  15. 19 6
      fs-doctor-app/src/main/java/com/fs/app/controller/CommonController.java
  16. 5 0
      fs-doctor-app/src/main/java/com/fs/app/controller/DiagnosisController.java
  17. 7 3
      fs-doctor-app/src/main/java/com/fs/app/controller/DoctorController.java
  18. 17 5
      fs-doctor-app/src/main/java/com/fs/app/controller/DrugReportController.java
  19. 35 15
      fs-doctor-app/src/main/java/com/fs/app/controller/InquiryOrderController.java
  20. 67 5
      fs-doctor-app/src/main/java/com/fs/app/controller/PrescribeController.java
  21. 1 1
      fs-qwhook/src/main/resources/application.yml
  22. 1 2
      fs-service/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java
  23. 1 1
      fs-service/src/main/java/com/fs/company/vo/CompanyUserImportVO.java
  24. 5 0
      fs-service/src/main/java/com/fs/course/config/CourseConfig.java
  25. 2 0
      fs-service/src/main/java/com/fs/course/domain/FsCourseWatchLog.java
  26. 33 0
      fs-service/src/main/java/com/fs/course/dto/BatchSendCourseAllDTO.java
  27. 81 0
      fs-service/src/main/java/com/fs/course/dto/BatchSendCourseDTO.java
  28. 32 0
      fs-service/src/main/java/com/fs/course/dto/BatchUrgeCourseDTO.java
  29. 4 0
      fs-service/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java
  30. 2 0
      fs-service/src/main/java/com/fs/course/mapper/FsUserCompanyUserMapper.java
  31. 9 0
      fs-service/src/main/java/com/fs/course/param/DiagnosisConfirmParam.java
  32. 1 1
      fs-service/src/main/java/com/fs/course/param/FsCourseSendRewardUParam.java
  33. 5 3
      fs-service/src/main/java/com/fs/course/param/FsCourseWatchLogListParam.java
  34. 1 0
      fs-service/src/main/java/com/fs/course/param/FsUserCourseOrderDoPayParam.java
  35. 1 0
      fs-service/src/main/java/com/fs/course/param/FsUserVipOrderPayUParam.java
  36. 31 0
      fs-service/src/main/java/com/fs/course/param/newfs/FsCourseWatchAppParam.java
  37. 2 0
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseService.java
  38. 1 0
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseProductOrderServiceImpl.java
  39. 32 4
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java
  40. 4 3
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseOrderServiceImpl.java
  41. 38 0
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java
  42. 6 1
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  43. 3 2
      fs-service/src/main/java/com/fs/course/service/impl/FsUserVipOrderServiceImpl.java
  44. 5 0
      fs-service/src/main/java/com/fs/course/vo/FsCourseWatchLogListVO.java
  45. 52 0
      fs-service/src/main/java/com/fs/course/vo/newfs/FsImSendLogVO.java
  46. 1 1
      fs-service/src/main/java/com/fs/erp/http/JstErpHttpServiceImpl.java
  47. 1 1
      fs-service/src/main/java/com/fs/erp/service/impl/FsJstAftersalePushServiceImpl.java
  48. 1 0
      fs-service/src/main/java/com/fs/gtPush/service/impl/uniPush2ServiceImpl.java
  49. 7 0
      fs-service/src/main/java/com/fs/his/config/FsSysConfig.java
  50. 1 0
      fs-service/src/main/java/com/fs/his/domain/FsInquiryOrderMsg.java
  51. 4 2
      fs-service/src/main/java/com/fs/his/dto/PayloadDTO.java
  52. 1 0
      fs-service/src/main/java/com/fs/his/mapper/FsDoctorMapper.java
  53. 1 0
      fs-service/src/main/java/com/fs/his/mapper/FsFirstDiagnosisMapper.java
  54. 4 0
      fs-service/src/main/java/com/fs/his/mapper/FsHfpayConfigMapper.java
  55. 1 1
      fs-service/src/main/java/com/fs/his/mapper/FsInquiryPatientInfoMapper.java
  56. 5 0
      fs-service/src/main/java/com/fs/his/param/FsDiagnosisListDParam.java
  57. 1 1
      fs-service/src/main/java/com/fs/his/param/FsInquiryOrderPayParam.java
  58. 2 1
      fs-service/src/main/java/com/fs/his/service/IFsFirstDiagnosisService.java
  59. 3 1
      fs-service/src/main/java/com/fs/his/service/IFsFollowService.java
  60. 6 0
      fs-service/src/main/java/com/fs/his/service/IFsInquiryOrderMsgService.java
  61. 6 5
      fs-service/src/main/java/com/fs/his/service/IFsInquiryOrderService.java
  62. 45 8
      fs-service/src/main/java/com/fs/his/service/impl/FsDoctorServiceImpl.java
  63. 7 5
      fs-service/src/main/java/com/fs/his/service/impl/FsFirstDiagnosisServiceImpl.java
  64. 4 2
      fs-service/src/main/java/com/fs/his/service/impl/FsFollowReportServiceImpl.java
  65. 53 10
      fs-service/src/main/java/com/fs/his/service/impl/FsFollowServiceImpl.java
  66. 277 4
      fs-service/src/main/java/com/fs/his/service/impl/FsInquiryOrderMsgServiceImpl.java
  67. 115 22
      fs-service/src/main/java/com/fs/his/service/impl/FsInquiryOrderServiceImpl.java
  68. 53 8
      fs-service/src/main/java/com/fs/his/service/impl/FsPackageOrderServiceImpl.java
  69. 1 0
      fs-service/src/main/java/com/fs/his/service/impl/FsPrescribeServiceImpl.java
  70. 9 3
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreOrderServiceImpl.java
  71. 17 6
      fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java
  72. 2 0
      fs-service/src/main/java/com/fs/hisStore/param/FsStorePaymentPayParam.java
  73. 33 1
      fs-service/src/main/java/com/fs/huifuPay/service/impl/HuiFuServiceImpl.java
  74. 31 0
      fs-service/src/main/java/com/fs/im/config/IMConfig.java
  75. 72 0
      fs-service/src/main/java/com/fs/im/domain/FsImMsgSendDetail.java
  76. 106 0
      fs-service/src/main/java/com/fs/im/domain/FsImMsgSendLog.java
  77. 67 0
      fs-service/src/main/java/com/fs/im/domain/ImSendLog.java
  78. 53 0
      fs-service/src/main/java/com/fs/im/dto/OpenImBatchMsgDTO.java
  79. 31 0
      fs-service/src/main/java/com/fs/im/dto/OpenImBatchResponseDataDTO.java
  80. 12 0
      fs-service/src/main/java/com/fs/im/dto/OpenImMsgCallBackResponse.java
  81. 11 0
      fs-service/src/main/java/com/fs/im/dto/OpenImResponseDataDTO.java
  82. 65 0
      fs-service/src/main/java/com/fs/im/mapper/FsImMsgSendDetailMapper.java
  83. 75 0
      fs-service/src/main/java/com/fs/im/mapper/FsImMsgSendLogMapper.java
  84. 70 0
      fs-service/src/main/java/com/fs/im/mapper/ImSendLogMapper.java
  85. 61 0
      fs-service/src/main/java/com/fs/im/service/IFsImMsgSendDetailService.java
  86. 94 0
      fs-service/src/main/java/com/fs/im/service/IFsImMsgSendLogService.java
  87. 61 0
      fs-service/src/main/java/com/fs/im/service/IImSendLogService.java
  88. 51 1
      fs-service/src/main/java/com/fs/im/service/OpenIMService.java
  89. 93 0
      fs-service/src/main/java/com/fs/im/service/impl/FsImMsgSendDetailServiceImpl.java
  90. 193 0
      fs-service/src/main/java/com/fs/im/service/impl/FsImMsgSendLogServiceImpl.java
  91. 92 0
      fs-service/src/main/java/com/fs/im/service/impl/ImSendLogServiceImpl.java
  92. 679 47
      fs-service/src/main/java/com/fs/im/service/impl/OpenIMServiceImpl.java
  93. 46 0
      fs-service/src/main/java/com/fs/im/vo/FsImMsgSendDetailVO.java
  94. 70 0
      fs-service/src/main/java/com/fs/im/vo/FsImMsgSendLogVO.java
  95. 2 0
      fs-service/src/main/java/com/fs/qw/domain/QwExternalContactInfo.java
  96. 6 5
      fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactMapper.java
  97. 9 0
      fs-service/src/main/java/com/fs/qw/service/IQwExternalContactInfoService.java
  98. 1 0
      fs-service/src/main/java/com/fs/qw/service/impl/AsyncSopTestService.java
  99. 60 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactInfoServiceImpl.java
  100. 4 0
      fs-service/src/main/java/com/fs/store/param/h5/FsUserPageListParam.java

+ 4 - 0
fs-admin/pom.xml

@@ -94,6 +94,10 @@
             <artifactId>clickhouse-jdbc</artifactId>
             <version>0.4.6</version>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+        </dependency>
 
     </dependencies>
 

+ 2 - 2
fs-admin/src/main/java/com/fs/his/controller/FsInquiryOrderController.java

@@ -1,6 +1,7 @@
 package com.fs.his.controller;
 
 import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fs.common.annotation.Log;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.controller.BaseController;
@@ -155,8 +156,7 @@ public class FsInquiryOrderController extends BaseController
 
     @PreAuthorize("@ss.hasPermi('his:inquiryOrder:sendMsg')")
     @GetMapping(value = "/sendMsg/{orderId}")
-    public AjaxResult sendMsg(@PathVariable("orderId") Long orderId)
-    {
+    public AjaxResult sendMsg(@PathVariable("orderId") Long orderId) throws JsonProcessingException {
 
         return AjaxResult.success(fsInquiryOrderService.sendStartMsg(orderId));
     }

+ 4 - 0
fs-admin/src/main/java/com/fs/his/controller/FsUserAddressController.java

@@ -99,6 +99,10 @@ public class FsUserAddressController extends BaseController
         String kdnAddress = fsUserAddressService.getKdnAddress(address);
         AddressInfoDTO addressInfoDTO = JSON.parseObject(kdnAddress, AddressInfoDTO.class);
         AddressInfoDTO.AddressData data = addressInfoDTO.getData();
+        logger.info("快递鸟返回:"+kdnAddress);
+        if (data==null){
+            return AjaxResult.error("解析地址失败请输入正确地址");
+        }
         String provinceName = data.getProvinceName();
         if (!provinceName.contains("省") && !provinceName.contains("区")){
             data.setProvinceName(data.getProvinceName()+"市");

+ 7 - 24
fs-admin/src/main/java/com/fs/his/controller/FsUserController.java

@@ -4,7 +4,7 @@ import java.util.*;
 import java.util.stream.Collectors;
 
 import com.alibaba.fastjson.JSON;
-import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.core.domain.entity.SysRole;
@@ -13,9 +13,10 @@ import com.fs.common.exception.CustomException;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.SecurityUtils;
 import com.fs.common.utils.StringUtils;
-import com.fs.course.domain.FsUserWatchStatistics;
-import com.fs.course.mapper.FsUserWatchStatisticsMapper;
+import com.fs.course.dto.BatchSendCourseDTO;
+import com.fs.course.param.FsCourseLinkCreateParam;
 import com.fs.course.service.IFsUserCompanyUserService;
+import com.fs.course.service.IFsUserCourseService;
 import com.fs.his.domain.FsUserAddress;
 import com.fs.his.enums.FsUserIntegralLogTypeEnum;
 import com.fs.his.mapper.FsUserMapper;
@@ -27,6 +28,8 @@ import com.fs.his.utils.PhoneUtil;
 import com.fs.his.vo.FsUserExportListVO;
 import com.fs.his.vo.FsUserVO;
 import com.fs.his.vo.UserVo;
+import com.fs.im.dto.OpenImResponseDTO;
+import com.fs.im.service.OpenIMService;
 import com.fs.qw.dto.UserProjectDTO;
 import com.fs.store.param.h5.FsUserPageListParam;
 import com.fs.store.vo.h5.FsUserPageListVO;
@@ -39,6 +42,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.ibatis.session.ExecutorType;
 import org.apache.ibatis.session.SqlSession;
 import org.apache.ibatis.session.SqlSessionFactory;
+import org.springframework.beans.BeanUtils;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -384,26 +388,5 @@ public class FsUserController extends BaseController
         return userIntegralLogsService.addIntegralTemplate(integralTemplateParam);
     }
 
-//    @PutMapping("/encryptPhoneTemp")
-//    @ApiOperation("临时接口")
-//    public void encryptPhoneTemp(){
-//        FsUser fsUser = new FsUser();
-//        List<FsUser> list = fsUserService.selectFsUserList(fsUser);
-//        List<FsUser> fsUserList = list.stream().peek(v -> v.setPhone(encryptPhone(v.getPhone()))).collect(Collectors.toList());
-//
-//        // 分批次处理,一次提交500条
-//        List<List<FsUser>> batches = Lists.partition(fsUserList, 500);
-//        batches.forEach(batch -> {
-//            SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
-//            try {
-//                FsUserMapper mapper = sqlSession.getMapper(FsUserMapper.class);
-//                batch.forEach(mapper::updateFsUser);
-//                sqlSession.commit();
-//            } finally {
-//                sqlSession.close();
-//            }
-//        });
-//
-//    }
 
 }

+ 75 - 0
fs-admin/src/main/java/com/fs/his/task/Task.java

@@ -15,6 +15,7 @@ import com.fs.company.service.ICompanyService;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.company.vo.QwIpadTotalVo;
 import com.fs.company.vo.RedPacketMoneyVO;
+import com.fs.course.dto.BatchSendCourseAllDTO;
 import com.fs.course.mapper.FsCourseRedPacketLogMapper;
 import com.fs.course.service.IFsCourseWatchLogService;
 import com.fs.course.service.ITencentCloudCosService;
@@ -49,6 +50,7 @@ import com.fs.his.vo.FsSubOrderResultVO;
 import com.fs.hisStore.service.IFsStoreOrderScrmService;
 import com.fs.im.dto.*;
 import com.fs.im.service.IImService;
+import com.fs.im.service.OpenIMService;
 import com.fs.qw.domain.QwCompany;
 import com.fs.qw.service.*;
 import com.fs.qwApi.service.QwApiService;
@@ -60,9 +62,11 @@ import org.apache.commons.lang3.StringUtils;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Component;
 
 import java.util.*;
+import java.util.stream.Collectors;
 
 @Slf4j
 @Component("task")
@@ -158,6 +162,10 @@ public class Task {
     private IQwCompanyService qwCompanyService;
     @Autowired
     private IQwUserService qwUserService;
+    @Autowired
+    private OpenIMService openIMService;
+    @Autowired
+    public RedisTemplate redisTemplate;
 
     @Autowired
     private ICompanyUserService userService;
@@ -1319,4 +1327,71 @@ public class Task {
         }
         return null;
     }
+
+
+    /**
+     * 定时任务-im会员定时发课,每一分钟执行一次
+     */
+    public void sendOpenImCourse(){
+        String redisKey = "openIm:batchSendMsg:sendCourse";
+        Map<String, BatchSendCourseAllDTO> cacheMap = redisCache.getCacheMap(redisKey);
+        if(cacheMap == null || cacheMap.isEmpty()){
+            logger.info("=====================会员IM定时发课,不存在对应的redisKey==================");
+            return;
+        }
+        List<Map.Entry<String, BatchSendCourseAllDTO>> toSendMap = cacheMap.entrySet().parallelStream().filter((v) -> {
+            String[] split = v.getKey().split(":");
+            long timestamp = Long.parseLong(split[2]);
+            return timestamp < System.currentTimeMillis();
+        }).collect(Collectors.toList());
+
+        if(toSendMap.isEmpty()){
+            logger.info("=====================会员IM定时发课,不存在可执行的发课任务==================");
+            return;
+        }
+        for (Map.Entry<String, BatchSendCourseAllDTO> entry : toSendMap) {
+            //执行发送消息任务
+            BatchSendCourseAllDTO batchSendCourseAllDTO = entry.getValue();
+            openIMService.batchSendCourseTask(batchSendCourseAllDTO.getBatchSendCourseDTO(), batchSendCourseAllDTO.getOpenImBatchMsgDTO(), batchSendCourseAllDTO.getProject(), batchSendCourseAllDTO.getImMsgSendDetailList());
+
+            // 执行结束,删除
+            this.redisTemplate.<String, BatchSendCourseAllDTO>opsForHash().delete(redisKey, entry.getKey());
+
+        }
+
+    }
+
+
+    /**
+     * 定时任务-im 会员催课,每一分钟执行一次
+     */
+    public void urgeOpenImCourse(){
+        String redisKey = "openIm:batchSendMsg:urgeCourse";
+        Map<String, BatchSendCourseAllDTO> cacheMap = redisCache.getCacheMap(redisKey);
+        if(cacheMap == null || cacheMap.isEmpty()){
+            logger.info("===================== 会员-IM发消息催课,不存在对应的redisKey==================");
+            return;
+        }
+        List<Map.Entry<String, BatchSendCourseAllDTO>> toSendMap = cacheMap.entrySet().parallelStream().filter((v) -> {
+            String[] split = v.getKey().split(":");
+            long timestamp = Long.parseLong(split[2]);
+            return timestamp < System.currentTimeMillis();
+        }).collect(Collectors.toList());
+
+        if(toSendMap.isEmpty()){
+            logger.info("===================== 会员-IM发消息催课,不存在可发送的消息==================");
+            return;
+        }
+        for (Map.Entry<String, BatchSendCourseAllDTO> entry : toSendMap) {
+            //执行发送消息任务
+            BatchSendCourseAllDTO batchSendCourseAllDTO = entry.getValue();
+            openIMService.batchUrgeCourseTask(batchSendCourseAllDTO.getOpenImBatchMsgDTO(), batchSendCourseAllDTO.getImMsgSendDetailList());
+
+            // 执行结束,删除
+            this.redisTemplate.<String, BatchSendCourseAllDTO>opsForHash().delete(redisKey, entry.getKey());
+
+        }
+    }
+
+
 }

+ 79 - 4
fs-admin/src/main/java/com/fs/web/controller/common/CommonController.java

@@ -3,16 +3,15 @@ package com.fs.web.controller.common;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-
 import com.fs.common.core.domain.R;
+import com.fs.common.core.redis.RedisCache;
 import com.fs.common.exception.file.OssException;
-import com.fs.course.service.IHuaweiObsService;
-import com.fs.course.service.IHuaweiVodService;
+import com.fs.course.dto.BatchSendCourseAllDTO;;
 import com.fs.course.service.ITencentCloudCosService;
-import com.fs.course.service.impl.HuaweiObsServiceImpl;
 import com.fs.framework.config.ServerConfig;
 import com.fs.his.domain.FsExportTask;
 import com.fs.his.service.IFsExportTaskService;
+import com.fs.im.service.OpenIMService;
 import com.fs.system.oss.CloudStorageService;
 import com.fs.system.oss.OSSFactory;
 
@@ -22,6 +21,7 @@ import com.huaweicloud.sdk.vod.v1.model.BaseInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
@@ -36,6 +36,7 @@ import java.io.File;
 import java.io.IOException;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
 
 import static com.fs.course.service.impl.HuaweiObsServiceImpl.fileUrlMap;
 import static com.fs.course.service.impl.HuaweiObsServiceImpl.uploadProgress;
@@ -60,6 +61,17 @@ public class CommonController
     private ITencentCloudCosService tencentCloudCosService;
     @Autowired
     private IFsExportTaskService exportTaskService;
+
+    @Autowired
+    private OpenIMService openIMService;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    @Autowired
+    public RedisTemplate redisTemplate;
+
+    org.slf4j.Logger logger= LoggerFactory.getLogger(getClass());
     @GetMapping(value = "common/getTask/{taskId}")
     public R getTask(@PathVariable("taskId") Long taskId)
     {
@@ -227,7 +239,70 @@ public class CommonController
         return tencentCloudCosService.getKeyAndCredentials();
     }
 
+    /**
+     * 测试接口
+     */
+    @PostMapping("/common/im/testTask/course")
+    public void testIMCourseTask(){
+        String redisKey = "openIm:batchSendMsg:sendCourse";
+        Map<String, BatchSendCourseAllDTO> cacheMap = redisCache.getCacheMap(redisKey);
+        if(cacheMap == null || cacheMap.isEmpty()){
+            logger.info("=====================会员IM定时发课,不存在对应的redisKey==================");
+            return;
+        }
+        List<Map.Entry<String, BatchSendCourseAllDTO>> toSendMap = cacheMap.entrySet().parallelStream().filter((v) -> {
+            String[] split = v.getKey().split(":");
+            long timestamp = Long.parseLong(split[2]);
+            return timestamp < System.currentTimeMillis();
+        }).collect(Collectors.toList());
 
+        if(toSendMap.isEmpty()){
+            logger.info("=====================会员IM定时发课,不存在可执行的发课任务==================");
+            return;
+        }
+        for (Map.Entry<String, BatchSendCourseAllDTO> entry : toSendMap) {
+            //执行发送消息任务
+            BatchSendCourseAllDTO batchSendCourseAllDTO = entry.getValue();
+            openIMService.batchSendCourseTask(batchSendCourseAllDTO.getBatchSendCourseDTO(), batchSendCourseAllDTO.getOpenImBatchMsgDTO(), batchSendCourseAllDTO.getProject(), batchSendCourseAllDTO.getImMsgSendDetailList());
+
+            // 执行结束,删除
+            this.redisTemplate.<String, BatchSendCourseAllDTO>opsForHash().delete(redisKey, entry.getKey());
 
+        }
+
+    }
+
+    /**
+     * 测试接口
+     */
+    @PostMapping("/common/im/testTask/urge")
+    public void testIMUrgeTask(){
+        String redisKey = "openIm:batchSendMsg:urgeCourse";
+        Map<String, BatchSendCourseAllDTO> cacheMap = redisCache.getCacheMap(redisKey);
+        if(cacheMap == null || cacheMap.isEmpty()){
+            logger.info("===================== 会员-IM发消息催课,不存在对应的redisKey==================");
+            return;
+        }
+        List<Map.Entry<String, BatchSendCourseAllDTO>> toSendMap = cacheMap.entrySet().parallelStream().filter((v) -> {
+            String[] split = v.getKey().split(":");
+            long timestamp = Long.parseLong(split[2]);
+            return timestamp < System.currentTimeMillis();
+        }).collect(Collectors.toList());
+
+        if(toSendMap.isEmpty()){
+            logger.info("===================== 会员-IM发消息催课,不存在可发送的消息==================");
+            return;
+        }
+        for (Map.Entry<String, BatchSendCourseAllDTO> entry : toSendMap) {
+            //执行发送消息任务
+            BatchSendCourseAllDTO batchSendCourseAllDTO = entry.getValue();
+            openIMService.batchUrgeCourseTask(batchSendCourseAllDTO.getOpenImBatchMsgDTO(), batchSendCourseAllDTO.getImMsgSendDetailList());
+
+            // 执行结束,删除
+            this.redisTemplate.<String, BatchSendCourseAllDTO>opsForHash().delete(redisKey, entry.getKey());
+
+        }
+
+    }
 
 }

+ 103 - 0
fs-admin/src/test/java/com/fs/course/controller/OpenIMServiceTest.java

@@ -0,0 +1,103 @@
+package com.fs.course.controller;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fs.FSApplication;
+import com.fs.common.annotation.DataSource;
+import com.fs.im.dto.OpenImMsgDTO;
+import com.fs.im.dto.OpenImResponseDTO;
+import com.fs.im.service.OpenIMService;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.test.context.ActiveProfiles;
+
+import static org.junit.Assert.assertNotNull;
+
+@Slf4j
+@ActiveProfiles("druid-fby-test")
+@RunWith(org.springframework.test.context.junit4.SpringRunner.class)
+@SpringBootTest(classes = FSApplication.class)
+public class OpenIMServiceTest {
+
+    @Autowired
+    private OpenIMService openIMService;
+    @Test
+    public void openIMSendMsg() {
+        OpenImMsgDTO openImMsgDTO = new OpenImMsgDTO();
+        openImMsgDTO.setSendID("fbyC8584");
+        openImMsgDTO.setRecvID("fbyU1077739");
+//        openImMsgDTO.setGroupID("group789");
+        openImMsgDTO.setSenderNickname("测试用户");
+        openImMsgDTO.setSenderFaceURL("https://example.com/avatar.jpg");
+        openImMsgDTO.setSenderPlatformID(1);
+        openImMsgDTO.setContentType(101);
+        openImMsgDTO.setSessionType(1);
+        openImMsgDTO.setOnlineOnly(false);
+        openImMsgDTO.setNotOfflinePush(false);
+        openImMsgDTO.setSendTime(System.currentTimeMillis());
+        openImMsgDTO.setEx("额外信息");
+
+        // Content
+        OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
+        content.setContent("Hello World");
+        content.setData("test data");
+        content.setDescription("测试消息");
+        content.setExtension("ext");
+        openImMsgDTO.setContent(content);
+
+        // OfflinePushInfo
+        OpenImMsgDTO.OfflinePushInfo offlinePushInfo = new OpenImMsgDTO.OfflinePushInfo();
+        offlinePushInfo.setTitle("新消息");
+        offlinePushInfo.setDesc("您收到一条新消息");
+        offlinePushInfo.setEx("push ex");
+        offlinePushInfo.setIOSPushSound("default");
+        offlinePushInfo.setIOSBadgeCount(true);
+        openImMsgDTO.setOfflinePushInfo(offlinePushInfo);
+
+        // 调用方法
+        OpenImResponseDTO result = openIMService.openIMSendMsg(openImMsgDTO);
+
+        // 断言
+        assertNotNull(result);
+    }
+
+    @Test
+    public void aiAutoReply() {
+    }
+
+    @Test
+    public void sendUtil() {
+    }
+
+    @Test
+    public void sendUtilUserToDoctor() {
+    }
+
+    @Test
+    public void editConversation() {
+    }
+
+    @Test
+    public void sendCourse() throws JsonProcessingException {
+        Long userId = 1077739L;
+        Long companyUserId = 8584L;
+        String url = "https://example.com/course/123";
+        String title = "Java编程基础课程";
+        String linkImageUrl = "https://example.com/images/course-cover.jpg";
+        String cropId = "crop_123456";
+
+        OpenImResponseDTO actualResponse = openIMService.sendCourse(
+                userId, companyUserId, url, title, linkImageUrl, cropId
+        );
+        log.info("返回结果: {}",actualResponse);
+    }
+
+    @Test
+    public void sendPackageUtil() {
+    }
+}

+ 8 - 0
fs-company-app/src/main/java/com/fs/app/controller/CompanyUserController.java

@@ -394,4 +394,12 @@ public class CompanyUserController extends AppBaseController {
                 .collect(Collectors.toList());
         return R.ok().put("data",filteredDictVOS);
     }
+
+    @ApiOperation("查询所有项目")
+    @GetMapping("/getDictProject")
+    public R getDictProject(){
+        List<DictVO> dictVOS = dictDataService.selectDictDataListByType("sys_course_project");
+        return R.ok().put("data",dictVOS);
+    }
+
 }

+ 1 - 0
fs-company-app/src/main/java/com/fs/app/controller/FsUserController.java

@@ -90,6 +90,7 @@ public class FsUserController extends AppBaseController {
         log.debug("用户会员分页列表 param: {}", JSON.toJSONString(param));
         param.setUserId(Long.parseLong(getUserId()));
 //        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        param.setIsHidePhoneMiddle(false);
         PageInfo<FsUserPageListVO> fsUserPageListVOPageInfo = fsUserService.selectFsUserPageList(param);
 //        PageInfo<FsUserPageListVO> pageInfo = new PageInfo<>(list);
         return ResponseResult.ok(fsUserPageListVOPageInfo);

+ 107 - 12
fs-company-app/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java

@@ -1,27 +1,36 @@
 package com.fs.app.controller;
 
+import cn.hutool.core.date.DateUtil;
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fs.app.annotation.Login;
 import com.fs.app.config.ImageStorageConfig;
+import com.fs.common.annotation.Log;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
+import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.course.domain.FsUserCoursePeriod;
+import com.fs.course.dto.BatchSendCourseDTO;
+import com.fs.course.dto.BatchUrgeCourseDTO;
 import com.fs.course.param.FsCourseLinkCreateParam;
+import com.fs.course.param.FsCourseWatchLogListParam;
 import com.fs.course.param.FsWatchCourseTimeParam;
 import com.fs.course.param.newfs.FsCourseSortLinkParam;
+import com.fs.course.param.newfs.FsCourseWatchAppParam;
 import com.fs.course.param.newfs.FsUserCourseListParam;
 import com.fs.course.param.newfs.UserCourseVideoPageParam;
-import com.fs.course.service.IFsCourseLinkService;
-import com.fs.course.service.IFsUserCoursePeriodService;
-import com.fs.course.service.IFsUserCourseService;
-import com.fs.course.service.IFsUserCourseVideoService;
+import com.fs.course.service.*;
+import com.fs.course.vo.FsCourseWatchLogListVO;
 import com.fs.course.vo.FsUserCourseParticipationRecordVO;
-import com.fs.course.vo.newfs.FsUserCourseListVO;
-import com.fs.course.vo.newfs.FsUserCourseVideoDetailsVO;
-import com.fs.course.vo.newfs.FsUserCourseVideoPageListVO;
-import com.fs.course.vo.newfs.FsUserVideoListVO;
+import com.fs.course.vo.newfs.*;
+import com.fs.im.domain.FsImMsgSendLog;
+import com.fs.im.dto.OpenImResponseDTO;
+import com.fs.im.service.IFsImMsgSendDetailService;
+import com.fs.im.service.IFsImMsgSendLogService;
+import com.fs.im.service.OpenIMService;
+import com.fs.im.vo.FsImMsgSendLogVO;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.Api;
@@ -32,10 +41,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.io.InputStream;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
 import java.util.stream.Collectors;
 
 
@@ -62,6 +68,15 @@ public class FsUserCourseVideoController extends AppBaseController {
     @Autowired
     private ICompanyUserService companyUserService;
 
+    @Autowired
+    private IFsCourseWatchLogService fsCourseWatchLogService;
+
+    @Autowired
+    private OpenIMService openIMService;
+
+    @Autowired
+    private IFsImMsgSendLogService imMsgSendLogService;
+
     @Login
     @GetMapping("/pageList")
     @ApiOperation("课程分页列表")
@@ -251,4 +266,84 @@ public class FsUserCourseVideoController extends AppBaseController {
         return ResponseResult.ok(courseLinkService.getGotoWxAppLink(linkStr,appid));
     }
 
+    @ApiOperation("会员批量发送课程消息")
+    @PostMapping("/batchSendCourse")
+    public OpenImResponseDTO batchSendCourse(@RequestBody BatchSendCourseDTO batchSendCourseDTO) throws JsonProcessingException {
+        // 生成看课短链
+        FsCourseLinkCreateParam fsCourseLinkCreateParam = new FsCourseLinkCreateParam();
+        BeanUtils.copyProperties(batchSendCourseDTO, fsCourseLinkCreateParam);
+        R courseSortLink = fsUserCourseService.createAppCourseSortLink(fsCourseLinkCreateParam);
+        String url = courseSortLink.get("url").toString();
+        batchSendCourseDTO.setUrl(url);
+
+        return openIMService.batchSendCourse(batchSendCourseDTO);
+    }
+
+    @ApiOperation("会员一键催课")
+    @PostMapping("/batchUrgeCourse")
+    public OpenImResponseDTO batchUrgeCourse(@RequestBody BatchUrgeCourseDTO batchUrgeCourseDTO) throws JsonProcessingException {
+        // 查询生成短链需要的内容
+        Map<String, Object> params = new HashMap<>();
+        params.put("logDetailIds", batchUrgeCourseDTO.getImMsgSendDetailId());
+        List<FsImMsgSendLog> fsImMsgSendLogs = imMsgSendLogService.selectSendLogListByDetailId(params);
+        OpenImResponseDTO openImResponseDTO = null;
+        for (FsImMsgSendLog fsImMsgSendLog : fsImMsgSendLogs) {
+            FsCourseLinkCreateParam fsCourseLinkCreateParam = new FsCourseLinkCreateParam();
+            BeanUtils.copyProperties(fsImMsgSendLog, fsCourseLinkCreateParam);
+            fsCourseLinkCreateParam.setId(fsImMsgSendLog.getPeriodDaysId());
+            R courseSortLink = fsUserCourseService.createAppCourseSortLink(fsCourseLinkCreateParam);
+            String url = courseSortLink.get("url").toString();
+            openImResponseDTO = openIMService.batchUrgeCourse(batchUrgeCourseDTO, fsImMsgSendLog, url);
+        }
+        return openImResponseDTO;
+    }
+
+    @Login
+    @ApiOperation("app-看课记录(包含今日完课、今日催课)")
+    @GetMapping("/courseWatchLog")
+    public ResponseResult<PageInfo<FsCourseWatchLogListVO>> getCourseWatchLog(FsCourseWatchAppParam fsCourseWatchAppParam)
+    {
+        FsCourseWatchLogListParam param = new FsCourseWatchLogListParam();
+        BeanUtils.copyProperties(fsCourseWatchAppParam, param);
+        param.setCompanyUserId(Long.parseLong(getUserId()));
+        param.setCompanyId(getCompanyId());
+        param.setSTime(DateUtil.beginOfDay(new Date()));
+        param.setETime(DateUtil.endOfDay(new Date()));
+//        startPage();
+        PageHelper.startPage(fsCourseWatchAppParam.getPageNum (), fsCourseWatchAppParam.getPageSize());
+        List<FsCourseWatchLogListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogListVO(param);
+        PageInfo<FsCourseWatchLogListVO> pageInfo = new PageInfo<>(list);
+        return ResponseResult.ok(pageInfo);
+    }
+
+    @Login
+    @ApiOperation("任务列表")
+    @GetMapping("/im/sendLog")
+    public ResponseResult<PageInfo<FsImSendLogVO>> imSendLog(@RequestParam(defaultValue = "1") Integer pageNum,
+                                                             @RequestParam(defaultValue = "10") Integer pageSize) {
+        Map<String, Object> params = new HashMap<>();
+        params.put("companyId", getCompanyId());
+        params.put("companyUserId", Long.parseLong(getUserId()));
+
+        PageHelper.startPage(pageNum, pageSize);
+        List<FsImSendLogVO> list = imMsgSendLogService.selectFsImSendLogList(params);
+        PageInfo<FsImSendLogVO> pageInfo = new PageInfo<>(list);
+        return ResponseResult.ok(pageInfo);
+    }
+
+    @ApiOperation("任务详情")
+    @GetMapping("/im/sendLog/detail")
+    public ResponseResult<FsImMsgSendLogVO> imSendLogDetail(@RequestParam Long logId) {
+        FsImMsgSendLogVO fsImMsgSendLogVO = imMsgSendLogService.selectFsImMsgSendLogDetail(logId);
+        return ResponseResult.ok(fsImMsgSendLogVO);
+    }
+
+    @Login
+    @ApiOperation("删除任务")
+    @DeleteMapping("/im/sendLog")
+    @Log(title = "任务-删除任务", businessType = BusinessType.DELETE)
+    public ResponseResult<Boolean> deleteImSendLog(@RequestParam Long logId) {
+        return imMsgSendLogService.deleteFsImMsgSendLogAndDetail(logId);
+    }
+
 }

+ 4 - 0
fs-company-app/src/main/java/com/fs/core/config/RedisConfig.java

@@ -38,6 +38,10 @@ public class RedisConfig extends CachingConfigurerSupport
         template.setValueSerializer(serializer);
         // 使用StringRedisSerializer来序列化和反序列化redis的key值
         template.setKeySerializer(new StringRedisSerializer());
+
+        // Hash的key也采用StringRedisSerializer的序列化方式 这个才是redis的hash值的序列化方式 一直都没有序列化进去
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(serializer);
         template.afterPropertiesSet();
 
         // Hash的key也采用StringRedisSerializer的序列化方式 这个才是redis的hash值的序列化方式 一直都没有序列化进去

+ 3 - 3
fs-company/src/main/java/com/fs/company/controller/company/CompanyUserController.java

@@ -579,7 +579,7 @@ public class CompanyUserController extends BaseController
             requestBody = new JSONObject();
             userIds.add(userId);
             requestBody.put("checkUserIDs", userIds);
-            String body = HttpRequest.post("https://web.im.cdwjyyh.com/api/user/account_check")
+            String body = HttpRequest.post("https://web.im.ysya.top/api/user/account_check")
                     .header("operationID", String.valueOf(System.currentTimeMillis()))
                     .header("token", adminToken)
                     .body(requestBody.toString())
@@ -606,7 +606,7 @@ public class CompanyUserController extends BaseController
                     requestBody = new JSONObject();
                     userIds.add(userId);
                     requestBody.put("users", users);
-                    HttpRequest.post("https://web.im.cdwjyyh.com/api/user/user_register")
+                    HttpRequest.post("https://web.im.ysya.top/api/user/user_register")
                             .header("operationID", String.valueOf(System.currentTimeMillis()))
                             .header("token", adminToken).body(requestBody.toString()).execute().body();
                 }
@@ -619,7 +619,7 @@ public class CompanyUserController extends BaseController
             requestBody = new JSONObject();
             requestBody.put("platformID",5);
             requestBody.put("userID",userId);
-            String body1 = HttpRequest.post("https://web.im.cdwjyyh.com/api/auth/get_user_token")
+            String body1 = HttpRequest.post("https://web.im.ysya.top/api/auth/get_user_token")
                     .header("operationID", String.valueOf(System.currentTimeMillis()))
                     .header("token", adminToken)
                     .body(requestBody.toString()).execute().body();

+ 1 - 1
fs-company/src/main/java/com/fs/framework/config/SecurityConfig.java

@@ -110,7 +110,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
                         "/**/*.js",
                         "/profile/**"
                 ).permitAll()
-
+                .antMatchers("/test").anonymous()
                 .antMatchers("**/callerResult").anonymous()
                 .antMatchers("/qw/getJsapiTicket/**").anonymous()
                 .antMatchers("/msg/**").anonymous()

+ 26 - 0
fs-company/src/main/java/com/fs/user/FsUserAdminController.java

@@ -1,6 +1,7 @@
 package com.fs.user;
 
 import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
@@ -10,12 +11,17 @@ import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.cache.ICompanyUserCacheService;
+import com.fs.course.dto.BatchSendCourseDTO;
+import com.fs.course.param.FsCourseLinkCreateParam;
+import com.fs.course.service.IFsUserCourseService;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
 
 import com.fs.his.domain.FsUser;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.utils.PhoneUtil;
+import com.fs.im.dto.OpenImResponseDTO;
+import com.fs.im.service.OpenIMService;
 import com.fs.qw.domain.CustomerTransferApproval;
 import com.fs.qw.dto.FsUserTransferParamDTO;
 import com.fs.qw.service.ICustomerTransferApprovalService;
@@ -24,6 +30,7 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
@@ -51,6 +58,12 @@ public class FsUserAdminController extends BaseController {
     @Autowired
     private ICustomerTransferApprovalService transferApprovalService;
 
+    @Autowired
+    private IFsUserCourseService fsUserCourseService;
+
+    @Autowired
+    private OpenIMService openIMService;
+
     @PreAuthorize("@ss.hasPermi('user:fsUser:list')")
     @PostMapping("/list")
     @ApiOperation("会员列表(与移动端使用的相同查询)")
@@ -145,4 +158,17 @@ public class FsUserAdminController extends BaseController {
     }
 
 
+    @ApiOperation("后台会员批量发送课程消息")
+    @PostMapping("/batchSendCourse")
+    public OpenImResponseDTO batchSendCourse(@RequestBody BatchSendCourseDTO batchSendCourseDTO) throws JsonProcessingException {
+        // 生成看课短链
+        FsCourseLinkCreateParam fsCourseLinkCreateParam = new FsCourseLinkCreateParam();
+        BeanUtils.copyProperties(batchSendCourseDTO, fsCourseLinkCreateParam);
+        R courseSortLink = fsUserCourseService.createAppCourseSortLink(fsCourseLinkCreateParam);
+        String url = courseSortLink.get("url").toString();
+        batchSendCourseDTO.setUrl(url);
+
+        return openIMService.batchSendCourse(batchSendCourseDTO);
+    }
+
 }

+ 19 - 6
fs-doctor-app/src/main/java/com/fs/app/controller/CommonController.java

@@ -1,8 +1,9 @@
 package com.fs.app.controller;
 
 
-
 import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fs.app.annotation.Login;
 import com.fs.app.param.SignParam;
 import com.fs.app.utils.CityTreeUtil;
@@ -25,11 +26,10 @@ import com.fs.his.param.ImMsgParam;
 import com.fs.his.service.*;
 
 import com.fs.his.utils.ConfigUtil;
-import com.fs.im.dto.MsgCustomDTO;
-import com.fs.im.dto.MsgDTO;
-import com.fs.im.dto.MsgDataDTO;
-import com.fs.im.dto.MsgDataFormatDTO;
+import com.fs.im.dto.*;
 import com.fs.im.service.IImService;
+import com.fs.im.service.OpenIMService;
+import com.fs.im.vo.OpenImMsgCallBackVO;
 import com.fs.system.oss.CloudStorageService;
 import com.fs.system.oss.OSSFactory;
 import com.fs.system.service.ISysConfigService;
@@ -60,7 +60,6 @@ import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.logging.Logger;
 
-
 @Api("公共接口")
 @RestController
 @RequestMapping(value="/app/common")
@@ -102,6 +101,8 @@ public class CommonController {
 	private IFsFollowService followService;
 	@Autowired
 	private IImService imService;
+	@Autowired
+	private OpenIMService openIMService;
 	@ApiOperation("测试")
 	@GetMapping(value = "/getTest")
 	public AjaxResult getTest()
@@ -239,6 +240,18 @@ public class CommonController {
 		vo.setActionStatus("OK");
 		return vo;
 	}
+	@ApiOperation("openIm聊天数据回调")
+	@PostMapping(value = "/callbackAfterSendSingleMsgCommand")
+	public OpenImMsgCallBackResponse openImMsgCallBack(@RequestBody String body, HttpServletRequest request) throws JsonProcessingException {
+
+		Gson gson = new Gson();
+		OpenImMsgCallBackVO messageInfo = gson.fromJson(body, OpenImMsgCallBackVO.class);
+
+		//openIMService.AiAutoReply(messageInfo);
+
+		//log.info("收到的参数{}", JSON.toJSONString(messageInfo));
+		return inquiryOrderMsgService.openImSaveMsg(messageInfo);
+	}
 	/**
 	 * 生成验证码
 	 */

+ 5 - 0
fs-doctor-app/src/main/java/com/fs/app/controller/DiagnosisController.java

@@ -33,4 +33,9 @@ public class DiagnosisController extends AppBaseController{
         param.setDoctorId(Long.parseLong(getDoctorId()));
         return diagnosisService.fill(param);
     }
+
+    @GetMapping("/{id}")
+    public R detail(@PathVariable("id") Long id){
+        return R.ok().put("data", diagnosisService.selectFsFirstDiagnosisById(id));
+    }
 }

+ 7 - 3
fs-doctor-app/src/main/java/com/fs/app/controller/DoctorController.java

@@ -21,6 +21,8 @@ import com.fs.his.param.FsDoctorExtractListSParam;
 import com.fs.his.service.*;
 import com.fs.his.vo.FsDoctorBillListSVO;
 import com.fs.his.vo.FsDoctorExtractListSVO;
+import com.fs.im.config.IMConfig;
+import com.fs.im.service.OpenIMService;
 import com.fs.im.service.OpenIMService;
 import com.fs.sms.service.SmsService;
 import com.fs.system.service.ISysConfigService;
@@ -29,6 +31,7 @@ import com.github.pagehelper.PageInfo;
 import com.github.pagehelper.util.StringUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.json.JSONArray;
 import org.json.JSONObject;
@@ -43,6 +46,7 @@ import java.util.*;
 import java.util.concurrent.TimeUnit;
 
 
+@Slf4j
 @Api("个人中心")
 @RestController
 @RequestMapping(value="/app/doctor")
@@ -117,7 +121,7 @@ public class DoctorController extends  AppBaseController {
             requestBody = new JSONObject();
             userIds.add(userId);
             requestBody.put("checkUserIDs", userIds);
-            String body = HttpRequest.post("https://web.im.cdwjyyh.com/api/user/account_check")
+            String body = HttpRequest.post("https://web.im.ysya.top/api/user/account_check")
                     .header("operationID", String.valueOf(System.currentTimeMillis()))
                     .header("token", adminToken)
                     .body(requestBody.toString())
@@ -144,7 +148,7 @@ public class DoctorController extends  AppBaseController {
                     requestBody = new JSONObject();
                     userIds.add(userId);
                     requestBody.put("users", users);
-                    HttpRequest.post("https://web.im.cdwjyyh.com/api/user/user_register")
+                    HttpRequest.post("https://web.im.ysya.top/api/user/user_register")
                             .header("operationID", String.valueOf(System.currentTimeMillis()))
                             .header("token", adminToken).body(requestBody.toString()).execute().body();
                 }
@@ -157,7 +161,7 @@ public class DoctorController extends  AppBaseController {
             requestBody = new JSONObject();
             requestBody.put("platformID",5);
             requestBody.put("userID",userId);
-            String body1 = HttpRequest.post("https://web.im.cdwjyyh.com/api/auth/get_user_token")
+            String body1 = HttpRequest.post("https://web.im.ysya.top/api/auth/get_user_token")
                     .header("operationID", String.valueOf(System.currentTimeMillis()))
                     .header("token", adminToken)
                     .body(requestBody.toString()).execute().body();

+ 17 - 5
fs-doctor-app/src/main/java/com/fs/app/controller/DrugReportController.java

@@ -2,6 +2,8 @@ package com.fs.app.controller;
 
 
 import cn.hutool.json.JSONUtil;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fs.app.param.DrugReportAddParam;
 import com.fs.app.param.DrugReportFinishParam;
 import com.fs.common.annotation.RepeatSubmit;
@@ -19,8 +21,10 @@ import com.fs.his.service.IFsFollowService;
 import com.fs.his.vo.FsDrugReportDVO;
 import com.fs.his.vo.FsDrugReportListDVO;
 import com.fs.his.vo.FsFollowListDVO;
+import com.fs.im.config.IMConfig;
 import com.fs.im.dto.*;
 import com.fs.im.service.IImService;
+import com.fs.im.service.OpenIMService;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.Api;
@@ -53,7 +57,8 @@ public class DrugReportController extends AppBaseController {
     private IImService imService;
     @Autowired
     private IFsDrugReportCountService fsDrugReportCountService;
-
+    @Autowired
+    private OpenIMService openIMService;
     @ApiOperation("获取报告列表")
     @GetMapping("/getDrugReportList")
     public R getDrugReportList(FsDrugReportListDParam param)
@@ -74,7 +79,7 @@ public class DrugReportController extends AppBaseController {
 
     @ApiOperation("提交报告")
     @PostMapping("/addReport")
-    public R addReport(@Validated @RequestBody DrugReportAddParam param, HttpServletRequest request){
+    public R addReport(@Validated @RequestBody DrugReportAddParam param, HttpServletRequest request) throws JsonProcessingException {
         FsFollow follow=followService.selectFsFollowByFollowId(param.getFollowId());
 
         FsDrugReport report=new FsDrugReport();
@@ -104,7 +109,10 @@ public class DrugReportController extends AppBaseController {
             msg.setMsgContent(new MsgDataFormatDTO("drugReport",ext,report.getReportId().toString()));
             msgs.add(msg);
             msgDTO.setMsgBody(msgs);
-            imService.sendMsg(msgDTO);
+            //imService.sendMsg(msgDTO);
+            ObjectMapper objectMapper = new ObjectMapper();
+            String ex = objectMapper.writeValueAsString(customDTO);
+            openIMService.sendUtil("D"+follow.getDoctorId(),"U"+follow.getUserId(),110,"drugReport","","","",report.getReportId().toString(),ex);
 
             fsDrugReportCountService.addReportCountByUserIdAndDoctorId(follow.getUserId(),follow.getDoctorId());
 
@@ -118,7 +126,7 @@ public class DrugReportController extends AppBaseController {
     @ApiOperation("完成咨询")
     @PostMapping("/finishDrugReport")
     @RepeatSubmit
-    public R finishDrugReport(@Validated @RequestBody DrugReportFinishParam param, HttpServletRequest request){
+    public R finishDrugReport(@Validated @RequestBody DrugReportFinishParam param, HttpServletRequest request) throws JsonProcessingException {
         FsFollow follow=followService.selectFsFollowByFollowId(param.getFollowId());
         //发送给用户
         MsgDTO msgDTO=new MsgDTO();
@@ -136,7 +144,11 @@ public class DrugReportController extends AppBaseController {
         msg.setMsgContent(new MsgDataFormatDTO("您的用药咨询报告已出具,本次咨询结束"));
         msgs.add(msg);
         msgDTO.setMsgBody(msgs);
-        imService.sendMsg(msgDTO);
+        //imService.sendMsg(msgDTO);
+        ObjectMapper objectMapper = new ObjectMapper();
+        String ex = objectMapper.writeValueAsString(customDTO);
+        openIMService.sendUtil("D"+follow.getDoctorId(),"U"+follow.getUserId(),110,"finishDrugReport","","您的用药咨询报告已出具,本次咨询结束","","",ex);
+
         redisTemplate.delete("DrugReport:doctorId:" + follow.getDoctorId() + ":userId:" + follow.getUserId());
         return R.ok();
 

+ 35 - 15
fs-doctor-app/src/main/java/com/fs/app/controller/InquiryOrderController.java

@@ -5,6 +5,8 @@ import cn.hutool.core.util.IdUtil;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fs.app.annotation.Login;
 import com.fs.app.param.InquiryOrderMsgListParam;
 import com.fs.common.BeanCopyUtils;
@@ -30,6 +32,7 @@ import com.fs.im.dto.MsgDTO;
 import com.fs.im.dto.MsgDataDTO;
 import com.fs.im.dto.MsgDataFormatDTO;
 import com.fs.im.service.IImService;
+import com.fs.im.service.OpenIMService;
 import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
 import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
 import com.github.binarywang.wxpay.config.WxPayConfig;
@@ -84,7 +87,8 @@ public class InquiryOrderController extends  AppBaseController {
     private IFsInquiryOrderReportService orderReportService;
     @Autowired
     private IImService imService;
-
+    @Autowired
+    private OpenIMService openIMService;
     @Login
     @GetMapping("/getInquiryOrderList")
     public R getInquiryOrderList(FsInquiryOrderListPDParam param)
@@ -92,11 +96,7 @@ public class InquiryOrderController extends  AppBaseController {
         FsDoctor doctor=doctorService.selectFsDoctorByDoctorId(Long.parseLong(getDoctorId()));
         PageHelper.startPage(param.getPageNum(), param.getPageSize());
 
-        if (Objects.nonNull(param.getUserId())) {
-            param.setDoctorId(null);
-        } else if (Objects.nonNull(param.getDoctorId())) {
-            param.setDoctorId(Long.parseLong(getDoctorId()));
-        }
+        param.setDoctorId(Long.parseLong(getDoctorId()));
 
         param.setIsAccept(doctor.getIsAccept());
         param.setIsSelf(doctor.getIsSelf());
@@ -177,7 +177,7 @@ public class InquiryOrderController extends  AppBaseController {
     @Login
     @ApiOperation("抢单")
     @PostMapping("/acceptOrder")
-    public R acceptOrder(@Validated @RequestBody FsInquiryOrderAcceptParam param, HttpServletRequest request){
+    public R acceptOrder(@Validated @RequestBody FsInquiryOrderAcceptParam param, HttpServletRequest request) throws JsonProcessingException {
         param.setDoctorId(Long.parseLong(getDoctorId()));
         return inquiryOrderService.acceptOrder(param);
     }
@@ -185,7 +185,7 @@ public class InquiryOrderController extends  AppBaseController {
     @Login
     @ApiOperation("接单")
     @PostMapping("/receiveOrder")
-    public R receiveOrder(@Validated @RequestBody FsInquiryOrderReceiveParam param, HttpServletRequest request){
+    public R receiveOrder(@Validated @RequestBody FsInquiryOrderReceiveParam param, HttpServletRequest request) throws JsonProcessingException {
         param.setDoctorId(Long.parseLong(getDoctorId()));
         return inquiryOrderService.receiveOrder(param);
     }
@@ -201,7 +201,7 @@ public class InquiryOrderController extends  AppBaseController {
     @Login
     @ApiOperation("完成订单")
     @PostMapping("/finishOrder")
-    public R finishOrder(@Validated @RequestBody FsInquiryOrderFinishParam param, HttpServletRequest request){
+    public R finishOrder(@Validated @RequestBody FsInquiryOrderFinishParam param, HttpServletRequest request) throws JsonProcessingException {
         param.setDoctorId(Long.parseLong(getDoctorId()));
         return inquiryOrderService.finishOrder(param);
     }
@@ -254,7 +254,7 @@ public class InquiryOrderController extends  AppBaseController {
     @ApiOperation("提交诊断报告")
     @PostMapping("/submitInquiryOrderReport")
     @Transactional
-    public R submitInquiryOrderReport(@Validated @RequestBody FsInquiryOrderReportSubmitDParam param, HttpServletRequest request){
+    public R submitInquiryOrderReport(@Validated @RequestBody FsInquiryOrderReportSubmitDParam param, HttpServletRequest request) throws JsonProcessingException {
         FsInquiryOrderReport report=null;
         if(param.getReportId()!=null&&param.getReportId()>0){
             report=orderReportService.selectFsInquiryOrderReportByReportId(param.getReportId());
@@ -295,15 +295,15 @@ public class InquiryOrderController extends  AppBaseController {
 
         }
         FsInquiryOrder inquiryOrder=inquiryOrderService.selectFsInquiryOrderByOrderId(report.getOrderId());
-        MsgDTO msgDTO=new MsgDTO();
+        /*MsgDTO msgDTO=new MsgDTO();
         msgDTO.setFrom_Account("D-"+report.getDoctorId().toString());
-        msgDTO.setTo_Account("U-"+report.getUserId().toString());
+        msgDTO.setTo_Account("U-"+report.getUserId().toString());*/
         MsgCustomDTO customDTO=new MsgCustomDTO();
         customDTO.setType("startInquiry");
         customDTO.setImType(1);
         customDTO.setOrderType(inquiryOrder.getOrderType());
         customDTO.setOrderId(report.getOrderId().toString());
-        msgDTO.setCloudCustomData(JSONUtil.toJsonStr(customDTO));
+        /*msgDTO.setCloudCustomData(JSONUtil.toJsonStr(customDTO));
         List<MsgDataDTO> msgs=new ArrayList<>();
         MsgDataDTO msg=new MsgDataDTO();
         String ext= JSONUtil.toJsonStr(report);
@@ -311,8 +311,28 @@ public class InquiryOrderController extends  AppBaseController {
         msg.setMsgContent(new MsgDataFormatDTO("report",ext,orderId));
         msg.setMsgType("TIMCustomElem");//TIMCustomElem
         msgs.add(msg);
-        msgDTO.setMsgBody(msgs);
-        imService.sendMsg(msgDTO);
+        msgDTO.setMsgBody(msgs);*/
+        //imService.sendMsg(msgDTO);
+        ObjectMapper objectMapper = new ObjectMapper();
+        String ex = objectMapper.writeValueAsString(customDTO);
+        openIMService.sendUtil("D"+report.getDoctorId(),"U"+report.getUserId(),110,"report","","","",report.getOrderId().toString(),ex);
+        /*JSONObject jsonObject = new JSONObject();
+        OpenImMsgDTO openImMsgDTO = new OpenImMsgDTO();
+        openImMsgDTO.setSendID("D"+report.getDoctorId().toString());
+        openImMsgDTO.setRecvID("U"+report.getUserId().toString());
+        openImMsgDTO.setContentType(110);
+        openImMsgDTO.setSenderPlatformID(5);
+        openImMsgDTO.setSessionType(1);
+
+        OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
+        PayloadDTO payloadDTO = new PayloadDTO();
+        payloadDTO.setData("startInquiry");
+        PayloadDTO.Extension extension = new PayloadDTO.Extension();
+        extension.setTitle();
+        //content.setContent(ext);
+        openImMsgDTO.setContent(content);
+        openImMsgDTO.setEx(customDTO);
+        openIMService.openIMSendMsg(openImMsgDTO);*/
         return R.ok("操作成功");
     }
 

+ 67 - 5
fs-doctor-app/src/main/java/com/fs/app/controller/PrescribeController.java

@@ -2,23 +2,35 @@ package com.fs.app.controller;
 
 
 import cn.hutool.core.util.IdUtil;
+import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fs.app.annotation.Login;
 import com.fs.common.core.domain.R;
+import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.core.utils.OrderCodeUtils;
 import com.fs.his.domain.*;
 import com.fs.his.dto.FsInquiryOrderPatientDTO;
+import com.fs.his.dto.PayloadDTO;
 import com.fs.his.param.*;
 import com.fs.his.service.*;
 import com.fs.his.vo.FsDoctorPrescribeListDVO;
 import com.fs.his.vo.FsPrescribeListDVO;
+import com.fs.im.config.IMConfig;
+import com.fs.im.dto.MsgCustomDTO;
+import com.fs.im.dto.OpenImMsgDTO;
+import com.fs.im.dto.OpenImResponseDTO;
 import com.fs.im.service.IImService;
+import com.fs.im.service.OpenIMService;
+import com.fs.qw.domain.QwExternalContact;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.Synchronized;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
@@ -26,12 +38,10 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 
+@Slf4j
 @Api("处方接口")
 @RestController
 @RequestMapping(value="/app/prescribe")
@@ -55,7 +65,8 @@ public class PrescribeController extends  AppBaseController {
     private IFsStoreOrderService storeOrderService;
     @Autowired
     private IImService imService;
-
+    @Autowired
+    private OpenIMService openIMService;
     @Login
     @GetMapping("/getDoctorPrescribeList")
     public R getDoctorPrescribeList(FsDoctorPrescribeListDParam param)
@@ -275,4 +286,55 @@ public class PrescribeController extends  AppBaseController {
         String url=prescribeService.getPrescribeCodeUrl(prescribeId);
         return R.ok().put("url",url);
     }
+    @PostMapping("/test")
+    public R test(@RequestBody HashMap<String,String> map) throws JsonProcessingException {
+        ObjectMapper objectMapper = new ObjectMapper();
+        OpenImMsgDTO openImMsgDTO = new OpenImMsgDTO();
+        openImMsgDTO.setSendID("D"+79);
+        openImMsgDTO.setRecvID("U"+map.get("userId"));
+        openImMsgDTO.setContentType(110);
+        openImMsgDTO.setSenderPlatformID(5);
+        openImMsgDTO.setSessionType(1);
+        OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
+        //content.setContent(ext);
+        PayloadDTO payload = new PayloadDTO();
+        payload.setData("prescribe");
+        PayloadDTO.Extension extension = new PayloadDTO.Extension();
+        extension.setDiagnose("感冒发烧,胸闷");
+        payload.setExtension(extension);
+        //log.info("payload:{}",payload);
+        OpenImMsgDTO.ImData imData = new OpenImMsgDTO.ImData();
+
+        imData.setPayload(payload);
+
+        String imJson = objectMapper.writeValueAsString(imData);
+        content.setData(imJson);
+        openImMsgDTO.setContent(content);
+        //log.info("openImMsgDTO:{}",openImMsgDTO);
+        JSONObject jsonObject = new JSONObject(openImMsgDTO);
+        //log.info("jsonObject:{}",jsonObject);
+        MsgCustomDTO customDTO=new MsgCustomDTO();
+        //customDTO.setType("startInquiry");
+        customDTO.setType(map.get("payloadDAata").toString());
+        customDTO.setOrderType(2);
+        customDTO.setOrderId(map.get("orderId"));
+        String imtype = map.get("imtype").toString();
+
+        customDTO.setImType(Integer.parseInt(imtype));
+        //openImMsgDTO.setEx(payload);
+        String ex = objectMapper.writeValueAsString(customDTO);
+        QwExternalContact qwExternalContact = new QwExternalContact();
+        qwExternalContact.setId(1l);
+        qwExternalContact.setFsUserId(1l);
+        //WatchSleepData last = watchSleepDataMapper.getLast("861389060165680");
+        //watchAudioMsgLogMapper.insert(watchAudioMsgLog);
+        //qwExternalContactMapper.selectRemarkByCompanyUserAndFsUser(map.get("sendId"), map.get("userId"),"wwwwww");
+        //fsUserCouponService.updateFsUserCouponStatusByLimtType2();
+//        openIMService.checkAndImportFriendByDianBo(Long.parseLong(map.get("sendId")),map.get("userId"),qwExternalContact.getCorpId());
+        //OpenImResponseDTO openImResponseDTO = openIMService.sendCourse(Long.parseLong(map.get("userId")), Long.parseLong(map.get("sendId")), "/pages/courseAnswer/index?link=1932017457275338752", "《五仙传医2.0》","https://cos.his.cdwjyyh.com/fs/20241108/a8ed49ae9a264c7483cec5bdcbcf6060.png");
+        log.info("请求地址{}",IMConfig.URL);
+//        log.info("前缀{}",IMConfig.PREFIX);
+        //OpenImResponseDTO openImResponseDTO = openIMService.sendUtil("D" +map.get("sendId"), "U"+map.get("userId").toString(), 110, map.get("payloadDAata").toString(), "", map.get("title").toString(), "", "3135749",ex);
+        return R.ok().put("data",null);
+    }
 }

+ 1 - 1
fs-qwhook/src/main/resources/application.yml

@@ -10,4 +10,4 @@ spring:
 #    active: druid-yzt
 #    active: druid-hdt
 #    active: druid-sxjz
-    active: druid-sft
+    active: dev

+ 1 - 2
fs-service/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java

@@ -35,9 +35,8 @@ import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import com.fs.system.service.ISysConfigService;
 import com.google.gson.Gson;
-import com.hc.openapi.tool.util.ObjectUtils;
 import org.apache.commons.collections4.CollectionUtils;
-;
+import org.apache.commons.lang3.ObjectUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;

+ 1 - 1
fs-service/src/main/java/com/fs/company/vo/CompanyUserImportVO.java

@@ -116,7 +116,7 @@ public class CompanyUserImportVO extends BaseEntity {
     private String callerNo;
 
     private String voicePrintUrl;
-
+    @Excel(name = "销售区域编码")
     private String addressId;
 
     /** 看课域名 */

+ 5 - 0
fs-service/src/main/java/com/fs/course/config/CourseConfig.java

@@ -63,6 +63,11 @@ public class CourseConfig implements Serializable {
      */
     private Boolean isBound;
 
+    /**
+     * 是否开启IM
+     */
+    private Boolean isOpenIM;
+
 
     @Data
     public static class DisabledTimeVo{

+ 2 - 0
fs-service/src/main/java/com/fs/course/domain/FsCourseWatchLog.java

@@ -88,5 +88,7 @@ public class FsCourseWatchLog extends BaseEntity
     /** 营期id */
     private Long periodId;
 
+    /** im发送消息详情id */
+    private Long imMsgSendDetailId;
 
 }

+ 33 - 0
fs-service/src/main/java/com/fs/course/dto/BatchSendCourseAllDTO.java

@@ -0,0 +1,33 @@
+package com.fs.course.dto;
+
+import com.fs.im.domain.FsImMsgSendDetail;
+import com.fs.im.dto.OpenImBatchMsgDTO;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 批量发课-定时任务入参(存入redis)
+ */
+@Data
+@Accessors(chain = true)
+public class BatchSendCourseAllDTO implements Serializable {
+
+    @ApiModelProperty(value = "前端点击发送时的入参")
+    private BatchSendCourseDTO batchSendCourseDTO;
+
+    @ApiModelProperty(value = "发IM消息时的参数")
+    private OpenImBatchMsgDTO openImBatchMsgDTO;
+
+    @ApiModelProperty(value = "课程所属项目")
+    private Long project;
+
+    @ApiModelProperty(value = "消息发送记录详情")
+    private List<FsImMsgSendDetail> imMsgSendDetailList;
+
+
+}

+ 81 - 0
fs-service/src/main/java/com/fs/course/dto/BatchSendCourseDTO.java

@@ -0,0 +1,81 @@
+package com.fs.course.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 批量发课-入参
+ */
+@Data
+public class BatchSendCourseDTO implements Serializable {
+
+    @ApiModelProperty(value = "用户ids")
+    private List<Long> userIds;
+
+    @ApiModelProperty(value = "销售id,生成短链需要", required = true)
+    private Long companyUserId;
+
+    @ApiModelProperty(value = "公司id,生成短链需要", required = true)
+    private Long companyId;
+
+    @ApiModelProperty(value = "营期id,生成短链需要", required = true)
+    private Long periodId;
+
+    @ApiModelProperty(value = "课程id,生成短链需要", required = true)
+    private Long courseId;
+
+    @ApiModelProperty(value = "课程名称", required = true)
+    private String courseName;
+
+    @ApiModelProperty(value = "视频id,生成短链需要", required = true)
+    private Long videoId;
+
+    @ApiModelProperty(value = "视频名称", required = true)
+    private String videoName;
+
+    @ApiModelProperty(value = "标签ids,如果没有companyUserId或者userIds则必传")
+    private List<Long> tagIds;
+
+    @ApiModelProperty(value = "标签名称")
+    private List<String> tagNames;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "发送消息时间,定时发送需要传")
+    private Date sendTime;
+
+    @ApiModelProperty(value = "发送类型,1-定时;2-实时", required = true)
+    private Integer sendType;
+
+    @ApiModelProperty(value = "发送方式,1-app;2-销售后台", required = true)
+    private Integer sendMode;
+
+    @ApiModelProperty(value = "发课内容", required = true)
+    private String title;
+
+    @ApiModelProperty(value = "链接有效时长(分钟)")
+    private Integer effectiveDuration;
+
+    @ApiModelProperty(value = "营期课程id,生成短链需要", required = true)
+    private Long id;
+
+    /* 看课短链 */
+    private String url;
+
+    @ApiModelProperty(value = "项目id,生成短链需要", required = true)
+    private Long projectId;
+
+    @ApiModelProperty(value = "是否催课", required = true)
+    private Boolean isUrgeCourse;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "催课时间")
+    private Date urgeTime;
+
+    @ApiModelProperty(value = "催课内容")
+    private String urgeContent;
+}

+ 32 - 0
fs-service/src/main/java/com/fs/course/dto/BatchUrgeCourseDTO.java

@@ -0,0 +1,32 @@
+package com.fs.course.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 批量催课-入参
+ */
+@Data
+public class BatchUrgeCourseDTO implements Serializable {
+
+    @NotBlank
+    @ApiModelProperty(value = "任务详情id", required = true)
+    private List<Long> imMsgSendDetailId;
+
+    @NotNull
+    @ApiModelProperty(value = "是否需要发课", required = true)
+    private Boolean isSendCourse;
+
+    @NotNull
+    @ApiModelProperty(value = "发课内容", required = true)
+    private String title;
+
+    @NotBlank
+    @ApiModelProperty(value = "催课内容")
+    private String urgeContent;
+}

+ 4 - 0
fs-service/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java

@@ -6,6 +6,7 @@ import com.fs.course.domain.FsUserCourseVideo;
 import com.fs.course.dto.WatchLogDTO;
 import com.fs.course.param.*;
 import com.fs.course.vo.*;
+import com.fs.im.dto.OpenImBatchResponseDataDTO;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.sop.vo.QwRatingVO;
 import org.apache.ibatis.annotations.Param;
@@ -519,4 +520,7 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
     Long selectByWatchlxDay(@Param("userId") Long userId,@Param("projectId")  Long projectId);
 
     List<FsCourseWatchLogListVO> selectFsCourseWatchLogListVOexport(@Param("maps") FsCourseWatchLogListParam param);
+
+    List<FsCourseWatchLog> getWatchCourseByVideoId(@Param("videoId") Long videoId, @Param("userIds") List<Long> userIds);
+
 }

+ 2 - 0
fs-service/src/main/java/com/fs/course/mapper/FsUserCompanyUserMapper.java

@@ -93,4 +93,6 @@ public interface FsUserCompanyUserMapper extends BaseMapper<FsUserCompanyUser>{
     int batchUpdateStatus(@Param("ids") List<Long> ids, @Param("status") int status);
 
     List<Long> selectFsUserCompanyUserListByMap(@Param("param") Map<String, Object> param);
+
+    List<FsUserCompanyUser> selectFsUserCompanyUserByIds(@Param("param") Map<String, Object> param);
 }

+ 9 - 0
fs-service/src/main/java/com/fs/course/param/DiagnosisConfirmParam.java

@@ -0,0 +1,9 @@
+package com.fs.course.param;
+
+import lombok.Data;
+
+@Data
+public class DiagnosisConfirmParam {
+
+    private Long id;
+}

+ 1 - 1
fs-service/src/main/java/com/fs/course/param/FsCourseSendRewardUParam.java

@@ -22,7 +22,7 @@ public class FsCourseSendRewardUParam implements Serializable
     private String corpId;
     private Integer linkType;
     private Long qwExternalId;
-    private Integer source=1;//来源 1:h5  2:小程序
+    private Integer source=1;//来源 1:h5  2:小程序 3:app
     private Integer isRoom;
     private Integer sendType;
     private Long periodId;

+ 5 - 3
fs-service/src/main/java/com/fs/course/param/FsCourseWatchLogListParam.java

@@ -1,9 +1,6 @@
 package com.fs.course.param;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fs.common.annotation.Excel;
-import com.fs.common.core.domain.BaseEntity;
-import io.swagger.models.auth.In;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -79,6 +76,11 @@ public class FsCourseWatchLogListParam implements Serializable {
     //是否是会员
     private Integer isVip;
 
+    /**
+     * 所属项目
+     */
+    private Integer project;
+
     /**
      * sop主键id
      */

+ 1 - 0
fs-service/src/main/java/com/fs/course/param/FsUserCourseOrderDoPayParam.java

@@ -10,4 +10,5 @@ public class FsUserCourseOrderDoPayParam implements Serializable {
     @NotNull(message = "订单号不能为空")
     Long orderId;
     Long userId;
+    private String appId;
 }

+ 1 - 0
fs-service/src/main/java/com/fs/course/param/FsUserVipOrderPayUParam.java

@@ -11,4 +11,5 @@ public class FsUserVipOrderPayUParam implements Serializable {
    private Long userId;
    @NotNull(message = "orderId不能为空")
    private Long orderId;
+   private String appId;
 }

+ 31 - 0
fs-service/src/main/java/com/fs/course/param/newfs/FsCourseWatchAppParam.java

@@ -0,0 +1,31 @@
+package com.fs.course.param.newfs;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+@ApiModel(description = "app-看课记录入参")
+public class FsCourseWatchAppParam implements Serializable {
+
+    @ApiModelProperty(value = "页码,默认为1", required = true)
+    private Integer pageNum = 1;
+
+    @ApiModelProperty(value = "页大小,默认为10", required = true)
+    private Integer pageSize = 10;
+
+    /**
+     * 类型,1-看课中,2-完课,3-待看课,4-看课中断
+     */
+    @ApiModelProperty(value = "类型,1-看课中,2-完课,3-待看课,4-看课中断", required = true)
+    private Integer logType;
+
+    @ApiModelProperty(value = "发送方式:1-个微,2-企微", required = true)
+    private Integer sendType;
+
+    @ApiModelProperty(value = "所属项目")
+    private Integer project;
+
+}

+ 2 - 0
fs-service/src/main/java/com/fs/course/service/IFsUserCourseService.java

@@ -128,4 +128,6 @@ public interface IFsUserCourseService
     List<FsUserCourseVideoAppletVO> selectFsUserCourseVideoApplet();
 
     List<FsUserCourseVideoAppletVO.FsUserCourseVideo> selectFsUserCourseVideoAppletByCourseId(Long courseId);
+
+    R createAppCourseSortLink(FsCourseLinkCreateParam fsCourseLinkCreateParam);
 }

+ 1 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsCourseProductOrderServiceImpl.java

@@ -424,6 +424,7 @@ public class FsCourseProductOrderServiceImpl extends ServiceImpl<FsCourseProduct
                         o.setOpenid(fsUserWx.getOpenId());
                         o.setReqSeqId("product-"+storePayment.getPayCode());
                         o.setTransAmt(storePayment.getPayMoney().toString());
+                        o.setAppId(param.getAppId());
                         o.setGoodsDesc("拍商品订单支付");
                         HuifuCreateOrderResult result = huiFuService.createOrder(o);
                         logger.info("创建汇付支付:"+result);

+ 32 - 4
fs-service/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java

@@ -49,7 +49,9 @@ import com.fs.sop.mapper.SopUserLogsMapper;
 import com.fs.sop.service.IQwSopLogsService;
 import com.fs.store.service.cache.IFsUserCacheService;
 import com.fs.store.service.cache.IFsUserCourseCacheService;
+import com.fs.system.mapper.SysDictDataMapper;
 import com.fs.system.service.ISysConfigService;
+import com.fs.system.vo.DictVO;
 import com.hc.openapi.tool.util.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -126,6 +128,9 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
     @Autowired
     private HyWatchLogMapper hyWatchLogMapper;
 
+    @Autowired
+    private SysDictDataMapper sysDictDataMapper;
+
     /**
      * 查询短链课程看课记录
      *
@@ -366,9 +371,18 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
         for (String key : keys) {
             //取key中数据
             String[] parts = key.split(":");
-            Long userId = Long.parseLong(parts[3]);
-            Long videoId = Long.parseLong(parts[4]);
-            Long companyUserId = Long.parseLong(parts[5]);
+            Long userId=null;
+            Long videoId=null;
+            Long companyUserId=null;
+            try {
+                userId = Long.parseLong(parts[3]);
+                videoId = Long.parseLong(parts[4]);
+                companyUserId = Long.parseLong(parts[5]);
+
+            }catch (Exception e){
+                log.error("key中id为null:{}", key);
+                continue;
+            }
             String durationStr = redisCache.getCacheObject(key);
             if(durationStr==null){
                 log.error("key中数据为null:{}",key);
@@ -609,7 +623,21 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
 
     @Override
     public List<FsCourseWatchLogListVO> selectFsCourseWatchLogListVO(FsCourseWatchLogListParam param) {
-        return fsCourseWatchLogMapper.selectFsCourseWatchLogListVO(param);
+        List<FsCourseWatchLogListVO> list = fsCourseWatchLogMapper.selectFsCourseWatchLogListVO(param);
+
+        List<DictVO> dictVOS = sysDictDataMapper.selectDictDataListByType("sys_course_project");
+        if(!dictVOS.isEmpty()){
+            Map<String, String> projectMap = dictVOS.stream().collect(Collectors.toMap(DictVO::getDictValue, DictVO::getDictLabel));
+            for (FsCourseWatchLogListVO watchLog : list) {
+                if (watchLog.getProject() != null) {
+                    String projectName = projectMap.get(watchLog.getProject().toString());
+                    if (projectName != null) {
+                        watchLog.setProjectName(projectName);
+                    }
+                }
+            }
+        }
+        return list;
     }
 
     @Override

+ 4 - 3
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseOrderServiceImpl.java

@@ -487,6 +487,7 @@ public class FsUserCourseOrderServiceImpl implements IFsUserCourseOrderService
                         o.setReqSeqId("course-" + storePayment.getPayCode());
                         o.setTransAmt(storePayment.getPayMoney().toString());
                         o.setGoodsDesc("课程订单支付");
+                        o.setAppId(param.getAppId());
                         HuifuCreateOrderResult result = huiFuService.createOrder(o);
                         FsStorePayment mt = new FsStorePayment();
                         mt.setPaymentId(storePayment.getPaymentId());
@@ -496,10 +497,10 @@ public class FsUserCourseOrderServiceImpl implements IFsUserCourseOrderService
 
                     }
 
-                } else {
-                    return R.error("用户OPENID不存在");
                 }
             }
+        } else {
+            return R.error("用户OPENID不存在");
         }
         return R.error();
     }
@@ -738,7 +739,7 @@ public class FsUserCourseOrderServiceImpl implements IFsUserCourseOrderService
             param.setUserCouponId(order.getUserCouponId());
         }
         FsUser user=fsUserMapper.selectFsUserByUserId(order.getUserId());
-        if(user!=null&& StringUtils.isNotEmpty(user.getMaOpenId())){
+        if(user!=null){
             Map<String,Object> moneys=computeOrderMoney(order.getPayPrice(),param);
             return R.ok().put("moneys",moneys);
         }

+ 38 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java

@@ -130,6 +130,10 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
     public static final String shortLink = "/courseH5/pages/course/learning?s=";
 
     private static final String userRealLink = "/pages/user/users/becomeVIP?";
+
+    private static final String appRealLink = "/#/pages_course/videovip?course=";
+    public static final String appShortLink = "/#/pages_course/videovip?s=";
+
     /**
      * 查询课程
      *
@@ -708,6 +712,40 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
         return fsUserCourseMapper.selectFsUserCourseVideoAppletByCourseId(courseId);
     }
 
+    @Override
+    public R createAppCourseSortLink(FsCourseLinkCreateParam param) {
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        //短链参数
+        String random = generateRandomString();
+
+        //新增链接表信息
+        FsCourseLink link = new FsCourseLink();
+        BeanUtils.copyProperties(param, link);
+        link.setLinkType(0);
+        link.setIsRoom(0);
+        link.setLink(random);
+
+        FsCourseRealLink courseMap = new FsCourseRealLink();
+        BeanUtils.copyProperties(link, courseMap);
+        courseMap.setProjectId(param.getProjectId());
+        String courseJson = JSON.toJSONString(courseMap);
+        link.setRealLink(appRealLink + courseJson);
+
+        link.setCreateTime(new Date());
+
+        //获取过期时间
+        Calendar calendar = getExpireDay(param, config, link.getCreateTime());
+        link.setUpdateTime(calendar.getTime());
+        int i = fsCourseLinkMapper.insertFsCourseLink(link);
+        if (i > 0){
+            String domainName = getDomainName(param.getCompanyUserId(), config);
+            String sortLink = domainName + appShortLink + link.getLink();
+            return R.ok().put("url", sortLink).put("link", random);
+        }
+        return R.error("生成链接失败!");
+    }
+
 
     private Graphics2D initializeGraphics(BufferedImage combined) {
         Graphics2D graphics = combined.createGraphics();

+ 6 - 1
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -992,6 +992,12 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
 
+        // 判断来源是否是app,如是app,则发放积分奖励
+        int sourceApp = 3;
+        if(sourceApp == param.getSource()){
+            return sendIntegralReward(param, user, log, config);
+        }
+
         // 根据奖励类型发放不同奖励
         switch (config.getRewardType()) {
             // 红包奖励
@@ -1648,7 +1654,6 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
                 return ResponseResult.fail(504, "超过项目看课数量限制");
             }
         }
-
         //添加判断:该用户是否已经存在此课程的看课记录,并且看课记录的销售id不是传入的销售id
         if(watchCourseVideo != null){
             if(!watchCourseVideo.getCompanyUserId().equals(param.getCompanyUserId())) {

+ 3 - 2
fs-service/src/main/java/com/fs/course/service/impl/FsUserVipOrderServiceImpl.java

@@ -346,6 +346,7 @@ public class FsUserVipOrderServiceImpl implements IFsUserVipOrderService
                         o.setReqSeqId("appvip-" + storePayment.getPayCode());
                         o.setTransAmt(storePayment.getPayMoney().toString());
                         o.setGoodsDesc("会员开通订单支付");
+                        o.setAppId(param.getAppId());
                         HuifuCreateOrderResult result = huiFuService.createOrder(o);
                         FsStorePayment mt = new FsStorePayment();
                         mt.setPaymentId(storePayment.getPaymentId());
@@ -353,10 +354,10 @@ public class FsUserVipOrderServiceImpl implements IFsUserVipOrderService
                         storePaymentService.updateFsStorePayment(mt);
                         return R.ok().put("isPay", 0).put("data", result).put("type", "hf");
                     }
-                } else {
-                    return R.error("用户OPENID不存在");
                 }
             }
+        }  else {
+            return R.error("用户OPENID不存在");
         }
         return R.error();
     }

+ 5 - 0
fs-service/src/main/java/com/fs/course/vo/FsCourseWatchLogListVO.java

@@ -118,5 +118,10 @@ public class FsCourseWatchLogListVO extends BaseEntity
     private Long videoId;
     private Integer isVip;
 
+    /**
+     * im发送消息详情id
+     */
+    private Long imMsgSendDetailId;
+
 
 }

+ 52 - 0
fs-service/src/main/java/com/fs/course/vo/newfs/FsImSendLogVO.java

@@ -0,0 +1,52 @@
+package com.fs.course.vo.newfs;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author caolq
+ * im任务发送记录 VO
+ */
+@Data
+public class FsImSendLogVO implements Serializable {
+
+    @ApiModelProperty(value = "发送记录id")
+    private Long logId;
+
+    @ApiModelProperty(value = "视频id")
+    private Long videoId;
+
+    @ApiModelProperty(value = "视频标题")
+    private String videoName;
+
+    @ApiModelProperty(value = "计划发课时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date planSendTime;
+
+    @ApiModelProperty(value = "标签ids")
+    private String tagIds;
+
+    @ApiModelProperty(value = "标签名称")
+    private String tagNames;
+
+    @ApiModelProperty(value = "用户id,多个用逗号隔开")
+    private String userIds;
+
+    @ApiModelProperty(value = "用户昵称,多个用逗号隔开")
+    private String nickNames;
+
+    @ApiModelProperty(value = "是否催课,1-是;0-否")
+    private Integer isUrgeCourse;
+
+    @ApiModelProperty(value = "催课文案")
+    private String urgeSendTitle;
+
+    @ApiModelProperty(value = "发送状态,1-已发送;2-待发送")
+    private Integer sendStatus;
+
+
+}

+ 1 - 1
fs-service/src/main/java/com/fs/erp/http/JstErpHttpServiceImpl.java

@@ -15,7 +15,7 @@ import com.fs.erp.utils.SignUtil;
 import com.fs.ybPay.dto.RefundOrderDTO;
 import com.hc.openapi.tool.util.ObjectUtils;
 import lombok.extern.slf4j.Slf4j;
-
+//import org.apache.commons.lang3.ObjectUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;

+ 1 - 1
fs-service/src/main/java/com/fs/erp/service/impl/FsJstAftersalePushServiceImpl.java

@@ -20,7 +20,7 @@ import com.fs.his.mapper.FsStoreOrderMapper;
 import com.fs.his.service.IFsStoreOrderItemService;
 import com.fs.ybPay.dto.RefundOrderDTO;
 import lombok.extern.slf4j.Slf4j;
-
+//import org.apache.commons.lang3.StringUtils;
 import org.apache.http.util.Asserts;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;

+ 1 - 0
fs-service/src/main/java/com/fs/gtPush/service/impl/uniPush2ServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.http.HttpUtil;
 import cn.hutool.json.JSONUtil;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;

+ 7 - 0
fs-service/src/main/java/com/fs/his/config/FsSysConfig.java

@@ -3,6 +3,7 @@ package com.fs.his.config;
 import com.fs.erp.dto.df.DFConfigVo;
 import lombok.Data;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 @Data
@@ -74,4 +75,10 @@ public class FsSysConfig {
 
     //不推送erp的公司id
     List<Long> noErpCompany;
+
+    //最低定金金额
+    private BigDecimal retainer;
+
+    //物流代收定金比例
+    private BigDecimal rate;
 }

+ 1 - 0
fs-service/src/main/java/com/fs/his/domain/FsInquiryOrderMsg.java

@@ -42,4 +42,5 @@ public class FsInquiryOrderMsg extends BaseEntity
 
     private String msgKey;
     private Integer msgContentType;
+    private String companyUserAccount;
 }

+ 4 - 2
fs-service/src/main/java/com/fs/his/dto/PayloadDTO.java

@@ -2,16 +2,17 @@ package com.fs.his.dto;
 
 import lombok.Data;
 
+import java.io.Serializable;
 import java.util.Date;
 
 @Data
-public class PayloadDTO {
+public class PayloadDTO implements Serializable {
     private String data;
     private Extension extension;
     private String description;
 
     @Data
-    public static class Extension{
+    public static class Extension implements Serializable{
         private String title;
         private String patientName;
         private String sex;
@@ -27,6 +28,7 @@ public class PayloadDTO {
         private String courseUrl;
         private String appRealLink;
         private String writeStatus;
+        private String packageId;
 
     }
 

+ 1 - 0
fs-service/src/main/java/com/fs/his/mapper/FsDoctorMapper.java

@@ -209,4 +209,5 @@ public interface FsDoctorMapper
             "order by doctor_id desc"+
             "</script>"})
     List<FsDoctorVO> selectDocVOByNameAndPhone(@Param("param") FsDoctorParam param);
+    String selectDoctorNameByIds(@Param("doctorIds") String doctorIds);
 }

+ 1 - 0
fs-service/src/main/java/com/fs/his/mapper/FsFirstDiagnosisMapper.java

@@ -79,6 +79,7 @@ public interface FsFirstDiagnosisMapper extends BaseMapper<FsFirstDiagnosis>{
             "WHERE 1 = 1" +
             "<if test='maps.type == 0' > and  doctor_status = 0 and doctor_id is null</if>" +
             "<if test='maps.type == 1' > and  doctor_id = #{maps.doctorId}</if>" +
+            "<if test='maps.patientName != null'> and patient_name like concat('%',#{maps.patientName},'%')</if>" +
             "ORDER BY create_time desc" +
             "</script>"})
     List<FsDiagnosisListDVO> selectFsDiagnosisListDVO(@Param("maps") FsDiagnosisListDParam param);

+ 4 - 0
fs-service/src/main/java/com/fs/his/mapper/FsHfpayConfigMapper.java

@@ -3,6 +3,7 @@ package com.fs.his.mapper;
 import java.util.List;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.his.domain.FsHfpayConfig;
+import org.apache.ibatis.annotations.Select;
 
 /**
  * 汇付多支付配置Mapper接口
@@ -58,4 +59,7 @@ public interface FsHfpayConfigMapper extends BaseMapper<FsHfpayConfig>{
      * @return 结果
      */
     int deleteFsHfpayConfigByIds(Long[] ids);
+
+    @Select("select * from fs_hfpay_config where app_id = #{appId} limit 1")
+    FsHfpayConfig selectByAppId(String appId);
 }

+ 1 - 1
fs-service/src/main/java/com/fs/his/mapper/FsInquiryPatientInfoMapper.java

@@ -24,7 +24,7 @@ public interface FsInquiryPatientInfoMapper {
             "LEFT JOIN fs_patient p ON p.patient_id  = pi.patient_id " +
             "LEFT JOIN company_user u ON u.user_id = pi.company_user_id " +
             " left join fs_doctor d on d.doctor_id = pi.sub_doctor_id  " +
-            " 1=1 " +
+            " where 1 = 1 " +
             "<if test='param.userId != null'> AND pi.user_id = #{param.userId} </if> " +
             "ORDER BY pi.create_time desc " +
             "</script>"})

+ 5 - 0
fs-service/src/main/java/com/fs/his/param/FsDiagnosisListDParam.java

@@ -10,4 +10,9 @@ public class FsDiagnosisListDParam extends BaseParam{
      * 0-全部 1-我的
      */
     private Integer type;
+
+    /**
+     * 患者姓名
+     */
+    private String patientName;
 }

+ 1 - 1
fs-service/src/main/java/com/fs/his/param/FsInquiryOrderPayParam.java

@@ -8,5 +8,5 @@ import java.io.Serializable;
 public class FsInquiryOrderPayParam implements Serializable {
     Long orderId;
     Long userCouponId;
-
+    String appId;
 }

+ 2 - 1
fs-service/src/main/java/com/fs/his/service/IFsFirstDiagnosisService.java

@@ -3,6 +3,7 @@ package com.fs.his.service;
 import java.util.List;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.common.core.domain.R;
+import com.fs.course.param.DiagnosisConfirmParam;
 import com.fs.course.param.FsFirstDiagnosisListUParam;
 import com.fs.course.vo.FsFirstDiagnosisListUVO;
 import com.fs.his.domain.FsFirstDiagnosis;
@@ -85,5 +86,5 @@ public interface IFsFirstDiagnosisService extends IService<FsFirstDiagnosis>{
 
     FsFirstDiagnosisListUVO getInfo(Long id);
 
-    R confirm(Long id);
+    R confirm(DiagnosisConfirmParam param);
 }

+ 3 - 1
fs-service/src/main/java/com/fs/his/service/IFsFollowService.java

@@ -1,6 +1,8 @@
 package com.fs.his.service;
 
 import java.util.List;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fs.his.domain.FsFollow;
 import com.fs.his.domain.FsPackageOrder;
 import com.fs.his.param.FsFollowListDParam;
@@ -68,7 +70,7 @@ public interface IFsFollowService
 
     FsFollowVO selectFsFollowVOByFollowId(Long followId);
 
-    void addFsFollowByPackageOrder(FsPackageOrder order);
+    void addFsFollowByPackageOrder(FsPackageOrder order) throws JsonProcessingException;
 
     List<FsFollowListUVO> selectFsFollowListUVO(FsFollowListUParam param);
 

+ 6 - 0
fs-service/src/main/java/com/fs/his/service/IFsInquiryOrderMsgService.java

@@ -1,10 +1,14 @@
 package com.fs.his.service;
 
 import java.util.List;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fs.his.domain.FsInquiryOrderMsg;
 import com.fs.his.param.FsInquiryOrderMsgListDParam;
 import com.fs.his.param.ImMsgParam;
 import com.fs.his.vo.FsInquiryOrderMsgListDVO;
+import com.fs.im.dto.OpenImMsgCallBackResponse;
+import com.fs.im.vo.OpenImMsgCallBackVO;
 
 /**
  * 图文订单Service接口
@@ -65,4 +69,6 @@ public interface IFsInquiryOrderMsgService
     void saveMsg(ImMsgParam messageInfo);
 
     List<FsInquiryOrderMsgListDVO> selectFsInquiryOrderMsgListDVO(FsInquiryOrderMsgListDParam param);
+
+    OpenImMsgCallBackResponse openImSaveMsg(OpenImMsgCallBackVO messageInfo) throws JsonProcessingException;
 }

+ 6 - 5
fs-service/src/main/java/com/fs/his/service/IFsInquiryOrderService.java

@@ -2,6 +2,7 @@ package com.fs.his.service;
 
 import java.util.List;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fs.common.core.domain.R;
 import com.fs.his.domain.*;
 import com.fs.his.param.*;
@@ -81,15 +82,15 @@ public interface IFsInquiryOrderService
 
     List<FsInquiryOrderListDVO> selectFsInquiryOrderListDVO(FsInquiryOrderListDParam param);
 
-    R acceptOrder(FsInquiryOrderAcceptParam param);
+    R acceptOrder(FsInquiryOrderAcceptParam param) throws JsonProcessingException;
 
-    R receiveOrder(FsInquiryOrderReceiveParam param);
+    R receiveOrder(FsInquiryOrderReceiveParam param) throws JsonProcessingException;
 
     R refuseOrder(FsInquiryOrderRefuseParam param);
 
-    R finishOrder(FsInquiryOrderFinishParam param);
+    R finishOrder(FsInquiryOrderFinishParam param) throws JsonProcessingException;
 
-    R autoFinishOrder(FsInquiryOrderFinishParam param);
+    R autoFinishOrder(FsInquiryOrderFinishParam param) throws JsonProcessingException;
 
     R pingOrder(FsInquiryOrderPingParam param);
 
@@ -109,7 +110,7 @@ public interface IFsInquiryOrderService
 
     R createOrderByPackageOrderStatus4(FsPackageOrder packageOrder);
 
-    String sendStartMsg(Long orderId);
+    String sendStartMsg(Long orderId) throws JsonProcessingException;
 
     R computeOrder(FsInquiryOrderComputeParam param, FsInquiryOrder order, FsUser user);
 

+ 45 - 8
fs-service/src/main/java/com/fs/his/service/impl/FsDoctorServiceImpl.java

@@ -2,6 +2,7 @@ package com.fs.his.service.impl;
 
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.SecurityUtils;
@@ -21,11 +22,10 @@ import com.fs.his.utils.ConfigUtil;
 import com.fs.his.utils.HttpUtil;
 import com.fs.his.utils.qrcode.QRCodeUtils;
 import com.fs.his.vo.*;
-import com.fs.im.dto.MsgCustomDTO;
-import com.fs.im.dto.MsgDTO;
-import com.fs.im.dto.MsgDataDTO;
-import com.fs.im.dto.MsgDataFormatDTO;
+import com.fs.im.config.IMConfig;
+import com.fs.im.dto.*;
 import com.fs.im.service.IImService;
+import com.fs.im.service.OpenIMService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import com.fs.system.oss.CloudStorageService;
@@ -33,6 +33,7 @@ import com.fs.system.oss.OSSFactory;
 import com.google.common.reflect.TypeToken;
 import com.google.gson.Gson;
 import com.google.zxing.WriterException;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -51,6 +52,7 @@ import java.util.List;
  * @author fs
  * @date 2023-06-05
  */
+@Slf4j
 @Service
 public class FsDoctorServiceImpl implements IFsDoctorService
 {
@@ -71,6 +73,9 @@ public class FsDoctorServiceImpl implements IFsDoctorService
     private IFsPrescribeService fsPrescribeService;
     @Autowired
     ConfigUtil configUtil;
+    @Autowired
+    private OpenIMService openIMService;
+
     /**
      * 查询医生管理
      *
@@ -411,7 +416,21 @@ public class FsDoctorServiceImpl implements IFsDoctorService
                         msg.setMsgType("TIMCustomElem");//TIMCustomElem
                         msgs.add(msg);
                         msgDTO.setMsgBody(msgs);
-                        imService.sendMsg(msgDTO);
+                        //imService.sendMsg(msgDTO);
+                        ObjectMapper objectMapper = new ObjectMapper();
+                        String ex = objectMapper.writeValueAsString(customDTO3);
+                        openIMService.sendUtil("D"+fsFollow.getDoctorId(),"U"+fsFollow.getUserId(),110,"follow","","",followId,"",ex);
+                        /*OpenImMsgDTO openImMsgDTO = new OpenImMsgDTO();
+                        openImMsgDTO.setSendID("D"+fsFollow.getDoctorId().toString());
+                        openImMsgDTO.setRecvID("U"+fsFollow.getUserId().toString());
+                        openImMsgDTO.setContentType(110);
+                        openImMsgDTO.setSenderPlatformID(5);
+                        openImMsgDTO.setSessionType(1);
+                        OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
+                        content.setContent(ext);
+                        openImMsgDTO.setContent(content);
+                        //openImMsgDTO.setEx(customDTO);
+                        openIMService.openIMSendMsg(openImMsgDTO);*/
 
                         MsgDTO msgDTO2 = new MsgDTO();
                         MsgCustomDTO customDTO = new MsgCustomDTO();
@@ -430,10 +449,28 @@ public class FsDoctorServiceImpl implements IFsDoctorService
                         msg2.setMsgType("TIMTextElem");//TIMCustomElem
                         msgs2.add(msg2);
                         msgDTO2.setMsgBody(msgs2);
-                        imService.sendMsg(msgDTO2);
+                        //imService.sendMsg(msgDTO2);
+                        OpenImMsgDTO openImMsgDTO1 = new OpenImMsgDTO();
+                        openImMsgDTO1.setSendID("D"+fsFollow.getDoctorId().toString());
+                        openImMsgDTO1.setRecvID("U"+fsFollow.getUserId().toString());
+                        openImMsgDTO1.setContentType(101);
+                        openImMsgDTO1.setSenderPlatformID(5);
+                        openImMsgDTO1.setSessionType(1);
+                        OpenImMsgDTO.Content content1 = new OpenImMsgDTO.Content();
+                        content1.setContent("尊敬的用户,为了您的健康,请认真填写随访单,以便医生随时了解您的用药情况,评估治疗效果。如果在用药中出现任何不适,可直接在对话框中描述您目前的情况,我将及时为您解答!");
+                        openImMsgDTO1.setContent(content1);
+                        //openImMsgDTO.setEx(customDTO);
+                        OpenImMsgDTO.OfflinePushInfo offlinePushInfo = new OpenImMsgDTO.OfflinePushInfo();
+                        offlinePushInfo.setDesc(content1.getContent());
+                        String doctorNameByIds = fsDoctorMapper.selectDoctorNameByIds(fsFollow.getDoctorId().toString());
+                        offlinePushInfo.setTitle(doctorNameByIds);
+                        offlinePushInfo.setIOSBadgeCount(true);
+                        offlinePushInfo.setIOSPushSound("");
+                        openImMsgDTO1.setOfflinePushInfo(offlinePushInfo);
+                        openIMService.openIMSendMsg(openImMsgDTO1);
                     }
                 }catch (Exception e){
-
+                    log.error("随访失败!订单编号: {}",order.getOrderId(),e);
                 }
             }
         }
@@ -459,7 +496,7 @@ public class FsDoctorServiceImpl implements IFsDoctorService
 
     @Override
     public String selectDoctorByIds(String doctorId) {
-        return fsDoctorMapper.selectDoctorNameByIds(doctorIds);
+        return fsDoctorMapper.selectDoctorNameByIds(doctorId);
     }
 
     @Override

+ 7 - 5
fs-service/src/main/java/com/fs/his/service/impl/FsFirstDiagnosisServiceImpl.java

@@ -7,6 +7,7 @@ import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.DateUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.course.param.DiagnosisConfirmParam;
 import com.fs.course.param.FsFirstDiagnosisListUParam;
 import com.fs.course.vo.FsFirstDiagnosisListUVO;
 import com.fs.his.domain.FsDoctor;
@@ -156,8 +157,8 @@ public class FsFirstDiagnosisServiceImpl extends ServiceImpl<FsFirstDiagnosisMap
     }
 
     @Override
-    public R confirm(Long id) {
-        FsFirstDiagnosis diagnosis = diagnosisMapper.selectById(id);
+    public R confirm(DiagnosisConfirmParam param) {
+        FsFirstDiagnosis diagnosis = diagnosisMapper.selectFsFirstDiagnosisById(param.getId());
         if (diagnosis == null) {
             return R.error("初诊单不存在");
         }
@@ -170,7 +171,7 @@ public class FsFirstDiagnosisServiceImpl extends ServiceImpl<FsFirstDiagnosisMap
         FsFirstDiagnosis map = new FsFirstDiagnosis();
         map.setId(diagnosis.getId());
         map.setUserStatus(1);
-        int i = diagnosisMapper.updateFsFirstDiagnosis(diagnosis);
+        int i = diagnosisMapper.updateFsFirstDiagnosis(map);
         if (i > 0) {
             return R.ok();
         }
@@ -182,7 +183,7 @@ public class FsFirstDiagnosisServiceImpl extends ServiceImpl<FsFirstDiagnosisMap
         if (param.getId() == null) {
             return R.error("初诊单id不能为空");
         }
-        FsFirstDiagnosis diagnosis = diagnosisMapper.selectById(param.getId());
+        FsFirstDiagnosis diagnosis = diagnosisMapper.selectFsFirstDiagnosisById(param.getId());
         FsFirstDiagnosis map = new FsFirstDiagnosis();
         if (diagnosis == null) {
             return R.error("初诊单不存在");
@@ -199,7 +200,8 @@ public class FsFirstDiagnosisServiceImpl extends ServiceImpl<FsFirstDiagnosisMap
         }
         map.setId(diagnosis.getId());
         map.setDoctorStatus(1);
-        int i = diagnosisMapper.updateFsFirstDiagnosis(diagnosis);
+        BeanUtils.copyProperties(param, map);
+        int i = diagnosisMapper.updateFsFirstDiagnosis(map);
         if (i > 0) {
             return R.ok();
         }

+ 4 - 2
fs-service/src/main/java/com/fs/his/service/impl/FsFollowReportServiceImpl.java

@@ -29,6 +29,7 @@ import io.swagger.models.auth.In;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import com.fs.his.mapper.FsFollowReportMapper;
 import com.fs.his.service.IFsFollowReportService;
@@ -43,6 +44,7 @@ import com.fs.his.service.IFsFollowReportService;
 public class FsFollowReportServiceImpl implements IFsFollowReportService
 {
     @Autowired
+    @Lazy
     private FsFollowReportMapper fsFollowReportMapper;
     @Autowired
     private FsDoctorMapper  doctorMapper;
@@ -50,9 +52,9 @@ public class FsFollowReportServiceImpl implements IFsFollowReportService
     private FsStoreOrderMapper fsStoreOrderMapper;
     @Autowired
     private FsPrescribeMapper fsPrescribeMapper;
+
     @Autowired
-    private IImService imService;
-    @Autowired
+    @Lazy
     SmsServiceImpl smsService;
     Logger logger= LoggerFactory.getLogger(getClass());
     /**

+ 53 - 10
fs-service/src/main/java/com/fs/his/service/impl/FsFollowServiceImpl.java

@@ -5,10 +5,13 @@ import java.util.*;
 
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fs.common.annotation.Log;
 import com.fs.common.utils.DateUtils;
 import com.fs.his.domain.FsFollowTemp;
 import com.fs.his.domain.FsPackageOrder;
+import com.fs.his.mapper.FsDoctorMapper;
 import com.fs.his.mapper.FsFollowTempMapper;
 import com.fs.his.mapper.FsPackageOrderMapper;
 import com.fs.his.param.FsFollowListDParam;
@@ -16,8 +19,10 @@ import com.fs.his.param.FsFollowListUParam;
 import com.fs.his.param.FsFollowParam;
 import com.fs.his.param.FsStoreOrderParam;
 import com.fs.his.vo.*;
+import com.fs.im.config.IMConfig;
 import com.fs.im.dto.*;
 import com.fs.im.service.IImService;
+import com.fs.im.service.OpenIMService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import org.slf4j.Logger;
@@ -47,6 +52,10 @@ public class FsFollowServiceImpl implements IFsFollowService
     private IImService imService;
     @Autowired
     private SysConfigMapper sysConfigMapper;
+    @Autowired
+    private OpenIMService openIMService;
+    @Autowired
+    private FsDoctorMapper fsDoctorMapper;
     Logger logger= LoggerFactory.getLogger(getClass());
     /**
      * 查询随访管理
@@ -133,7 +142,7 @@ public class FsFollowServiceImpl implements IFsFollowService
     }
 
     @Override
-    public void addFsFollowByPackageOrder(FsPackageOrder order) {
+    public void addFsFollowByPackageOrder(FsPackageOrder order) throws JsonProcessingException {
         SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.package");
         Map<String, Object> config = (Map<String, Object>) JSON.parse(sysConfig.getConfigValue());
         Integer followRate = (Integer)config.get("followRate");
@@ -160,17 +169,17 @@ public class FsFollowServiceImpl implements IFsFollowService
             fsFollow.setFormJson(fsFollowTemp.getFormJson());
             fsFollow.setCreateTime(DateUtils.getNowDate());
             int i = fsFollowMapper.insertFsFollow(fsFollow);
-            MsgDTO msgDTO=new MsgDTO();
+            //MsgDTO msgDTO=new MsgDTO();
             MsgCustomDTO customDTO=new MsgCustomDTO();
             customDTO.setType("follow");
             customDTO.setOrderType(2);
             customDTO.setFollowId(fsFollow.getFollowId().toString());
             customDTO.setOrderId(fsFollow.getPackageOrderId().toString());
             customDTO.setImType(2);
-            msgDTO.setCloudCustomData(JSONUtil.toJsonStr(customDTO));
+            //msgDTO.setCloudCustomData(JSONUtil.toJsonStr(customDTO));
 
-            msgDTO.setFrom_Account("D-"+fsFollow.getDoctorId());
-            msgDTO.setTo_Account("U-"+fsFollow.getUserId());
+            //msgDTO.setFrom_Account("D-"+fsFollow.getDoctorId());
+            //msgDTO.setTo_Account("U-"+fsFollow.getUserId());
             List<MsgDataDTO> msgs=new ArrayList<>();
             MsgDataDTO msg=new MsgDataDTO();
             String ext= JSONUtil.toJsonStr(fsFollow);
@@ -178,9 +187,24 @@ public class FsFollowServiceImpl implements IFsFollowService
             msg.setMsgContent(new MsgDataFormatDTO("follow",ext,followId));
             msg.setMsgType("TIMCustomElem");//TIMCustomElem
             msgs.add(msg);
-            msgDTO.setMsgBody(msgs);
-            MsgResponseDTO msgResponseDTO = imService.sendMsg(msgDTO);
-            logger.info("发送随访"+msgResponseDTO);
+            //msgDTO.setMsgBody(msgs);
+            //MsgResponseDTO msgResponseDTO = imService.sendMsg(msgDTO);
+            ObjectMapper objectMapper = new ObjectMapper();
+            String ex = objectMapper.writeValueAsString(customDTO);
+            OpenImResponseDTO follow = openIMService.sendUtil("D"+fsFollow.getDoctorId(), "U"+fsFollow.getUserId(), 110, "follow", "", "", followId, "",ex);
+            /*OpenImMsgDTO openImMsgDTO = new OpenImMsgDTO();
+            openImMsgDTO.setSendID("D"+fsFollow.getDoctorId().toString());
+            openImMsgDTO.setRecvID("U"+fsFollow.getUserId().toString());
+            openImMsgDTO.setContentType(110);
+            openImMsgDTO.setSenderPlatformID(5);
+            openImMsgDTO.setSessionType(1);
+            OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
+            content.setContent(ext);
+            openImMsgDTO.setContent(content);
+            //openImMsgDTO.setEx(customDTO);
+            OpenImResponseDTO openImResponseDTO = openIMService.openIMSendMsg(openImMsgDTO);*/
+
+            logger.info("发送随访"+follow);
 
             MsgDTO msgDTO2=new MsgDTO();
             msgDTO2.setCloudCustomData(JSONUtil.toJsonStr(customDTO));
@@ -195,8 +219,27 @@ public class FsFollowServiceImpl implements IFsFollowService
             msgs2.add(msg2);
             msgDTO2.setMsgBody(msgs2);
 
-            MsgResponseDTO msgResponseDTO2 = imService.sendMsg(msgDTO2);
-            logger.info("发送随访2"+msgResponseDTO2);
+            //MsgResponseDTO msgResponseDTO2 = imService.sendMsg(msgDTO2);
+            OpenImMsgDTO openImMsgDTO1 = new OpenImMsgDTO();
+            openImMsgDTO1.setSendID("D"+fsFollow.getDoctorId().toString());
+            openImMsgDTO1.setRecvID("U"+fsFollow.getUserId().toString());
+            openImMsgDTO1.setContentType(101);
+            openImMsgDTO1.setSenderPlatformID(5);
+            openImMsgDTO1.setSessionType(1);
+            OpenImMsgDTO.Content content1 = new OpenImMsgDTO.Content();
+            content1.setContent("尊敬的用户,为了您的健康,请认真填写随访单,以便医生随时了解您的用药情况,评估治疗效果。如果在用药中出现任何不适,可直接在对话框中描述您目前的情况,我将及时为您解答!");
+            openImMsgDTO1.setContent(content1);
+            //openImMsgDTO.setEx(customDTO);
+            OpenImMsgDTO.OfflinePushInfo offlinePushInfo = new OpenImMsgDTO.OfflinePushInfo();
+            offlinePushInfo.setDesc(content1.getContent());
+            String doctorNameByIds = fsDoctorMapper.selectDoctorNameByIds(fsFollow.getDoctorId().toString());
+            offlinePushInfo.setTitle(doctorNameByIds);
+            offlinePushInfo.setIOSBadgeCount(true);
+            offlinePushInfo.setIOSPushSound("");
+            openImMsgDTO1.setOfflinePushInfo(offlinePushInfo);
+            OpenImResponseDTO openImResponseDTO1 = openIMService.openIMSendMsg(openImMsgDTO1);
+
+            logger.info("发送随访"+openImResponseDTO1);
             if (i>0){
                 FsPackageOrder fsPackageOrder = new FsPackageOrder();
                 fsPackageOrder.setOrderId(order.getOrderId());

+ 277 - 4
fs-service/src/main/java/com/fs/his/service/impl/FsInquiryOrderMsgServiceImpl.java

@@ -9,32 +9,43 @@ import java.util.List;
 import java.util.Map;
 
 import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.json.JsonMapper;
 import com.fs.common.service.impl.SmsServiceImpl;
 import com.fs.common.utils.DateUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.event.TemplateBean;
 import com.fs.event.TemplateEvent;
 import com.fs.event.TemplateListenEnum;
 import com.fs.event.TemplateListener;
 import com.fs.his.domain.*;
 import com.fs.his.dto.FsInquiryOrderPatientDTO;
-import com.fs.his.mapper.FsDoctorMapper;
-import com.fs.his.mapper.FsFollowReportMapper;
-import com.fs.his.mapper.FsUserMapper;
+import com.fs.his.dto.PayloadDTO;
+import com.fs.his.mapper.*;
 import com.fs.his.param.FsFollowReportParam;
 import com.fs.his.param.FsInquiryOrderMsgListDParam;
 import com.fs.his.param.ImMsgParam;
 import com.fs.his.service.IFsFollowReportService;
+import com.fs.his.service.IFsInquiryOrderReportService;
 import com.fs.his.vo.FsInquiryOrderMsgListDVO;
+import com.fs.im.config.IMConfig;
+import com.fs.im.dto.OpenImMsgCallBackResponse;
 import com.fs.im.service.IImService;
+import com.fs.im.vo.OpenImMsgCallBackVO;
 import com.fs.system.oss.CloudStorageService;
 import com.fs.system.oss.OSSFactory;
+import com.fs.watch.domain.WatchDeviceInfo;
+import com.fs.watch.mapper.WatchDeviceInfoMapper;
+import com.fs.watch.service.DeviceSetUpService;
+import lombok.extern.slf4j.Slf4j;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
-import com.fs.his.mapper.FsInquiryOrderMsgMapper;
 import com.fs.his.service.IFsInquiryOrderMsgService;
 
 /**
@@ -43,6 +54,7 @@ import com.fs.his.service.IFsInquiryOrderMsgService;
  * @author fs
  * @date 2023-06-12
  */
+@Slf4j
 @Service
 public class FsInquiryOrderMsgServiceImpl implements IFsInquiryOrderMsgService
 {
@@ -51,15 +63,25 @@ public class FsInquiryOrderMsgServiceImpl implements IFsInquiryOrderMsgService
     @Autowired
     private IFsFollowReportService fsFollowReportService;
     @Autowired
+    @Lazy
     private FsFollowReportMapper fsFollowReportMapper;
     @Autowired
     private FsDoctorMapper  doctorMapper;
     @Autowired
+            @Lazy
     SmsServiceImpl smsService;
     @Autowired
     FsUserMapper fsUserMapper;
     @Autowired
     ApplicationEventPublisher publisher;
+    @Autowired
+    private FsPrescribeMapper fsPrescribeMapper;
+    @Autowired
+    private IFsInquiryOrderReportService fsInquiryOrderReportService;
+    @Autowired
+    private WatchDeviceInfoMapper watchDeviceInfoMapper;
+    @Autowired
+    private DeviceSetUpService deviceSetUpService;
 
 //    @Autowired
 //    TemplateListener publisher;
@@ -308,5 +330,256 @@ public class FsInquiryOrderMsgServiceImpl implements IFsInquiryOrderMsgService
     public List<FsInquiryOrderMsgListDVO> selectFsInquiryOrderMsgListDVO(FsInquiryOrderMsgListDParam param) {
         return fsInquiryOrderMsgMapper.selectFsInquiryOrderMsgListDVO(param);
     }
+    @Override
+    public OpenImMsgCallBackResponse openImSaveMsg(OpenImMsgCallBackVO openImMsgCallBackVO) throws JsonProcessingException {
+        OpenImMsgCallBackResponse openImMsgCallBackResponse = new OpenImMsgCallBackResponse();
+        ObjectMapper objectMapper = new ObjectMapper();
+        try {
+            if (openImMsgCallBackVO.getCallbackCommand().equals("callbackBeforeAfterMsgCommand")){
+                fsInquiryOrderMsgMapper.deleteFsInquiryOrderMsgByMsgKey(openImMsgCallBackVO.getClientMsgID());
+                return openImMsgCallBackResponse;
+            }
+            String send =openImMsgCallBackVO.getSendID();
+            String to =openImMsgCallBackVO.getRecvID();
+            Long time =openImMsgCallBackVO.getSendTime();
+            Date date = new Date(time);
+            String content = openImMsgCallBackVO.getContent();
+
+
+            String userId="";
+            String doctorId="";
+            String companyUserId="";
+            String msgType="2";
+            //用户发送消息
+            if (send.contains("U")){
+                msgType="1";
+                userId=send.replace("U","");
+                if (to.contains("D")){
+                    doctorId=to.replace("D","");
+                    fsFollowReportService.addReport(userId,doctorId);
+                }else if (to.contains("C")){
+                    companyUserId=to.replace("C","");
+                }
+                //医生发送消息
+            }else if (send.contains("D")){
+                doctorId=send.replace("D","");
+                if (to.contains("U")){
+                    userId=to.replace("U","");
+                    TemplateBean templateBean = TemplateBean.builder()
+                            .title("您收到咨询回复")
+                            .remark("您的咨询已回复")
+                            .uid(Long.parseLong(userId))
+                            .templateType(TemplateListenEnum.TYPE_5.getValue())
+                            .build();
+                    publisher.publishEvent(new TemplateEvent(this, templateBean));
+                    if (openImMsgCallBackVO.getContentType()==101){
+                        if (content.contains("您的信息我已收到")){
+                            long doctorIdL = Long.parseLong(doctorId);
+                            long userIdL = Long.parseLong(userId);
+                            int count = fsFollowReportMapper.selectFollowByUserIdAndDoctorIdAndType(userIdL, doctorIdL);
+                            if (count==0){
+                                FsUser fsUser = fsUserMapper.selectFsUserByUserId(userIdL);
+                                if (fsUser!=null&&fsUser.getPhone()!=null){
+                                    FsInquiryOrder order = fsFollowReportMapper.selectFsInquiryOrderByUserAndDoc(userIdL, doctorIdL);
+                                    if (order!=null){
+                                        FsInquiryOrderPatientDTO patientDTO = JSON.parseObject(order.getPatientJson(),FsInquiryOrderPatientDTO.class);
+                                        if (patientDTO!=null&&patientDTO.getPatientName()!=null){
+                                            FsDoctor doctor=doctorMapper.selectFsDoctorByDoctorId(doctorIdL);
+                                            if (doctor.getDeptId()!=null&&doctor.getDeptId().compareTo(39L)==0){
+                                                logger.info("药师回复发送短信:"+fsUser.getPhone()+patientDTO.getPatientName());
+                                                smsService.sendUserSms(fsUser.getPhone(), patientDTO.getPatientName(), "7");
+                                            }else {
+                                                logger.info("医生回复发送短信:"+patientDTO.getMobile()+patientDTO.getPatientName());
+                                                smsService.sendUserSms(fsUser.getPhone(), patientDTO.getPatientName(), "4");
+                                            }
+                                        }
+                                    }else {
+                                        FsFollow fo = fsFollowReportMapper.selectFsFollowById(userIdL, doctorIdL);
+                                        if (fo!=null&&fo.getPatientName()!=null){
+                                            logger.info("药师回复发送短信:"+fsUser.getPhone()+fo.getPatientName());
+                                            smsService.sendUserSms(fsUser.getPhone(), fo.getPatientName(), "7");
+                                        }
+                                    }
+
+                                }
+
+                            }
+                        }
+                    }
+                }else {
+                    companyUserId = to.replace("C","");
+                }
+                //销售发送消息
+            }else if (send.contains("C")){
+                companyUserId=send.replace("C","");
+                if (to.contains("U")){
+                    userId=to.replace("U","");
+                }else {
+                    doctorId = to.replace("D","");
+                }
+            }
+            Long orderId = fsInquiryOrderMsgMapper.selectFsInquiryOrderMsgOrderId(doctorId, userId);
+            if (orderId==null){
+                orderId = fsInquiryOrderMsgMapper.selectFsInquiryOrderMsgOrderIdByDate(doctorId, userId,date);
+            }
+
+            Integer msgContentType = openImMsgCallBackVO.getContentType();
+            Integer type=0;
+            String cont="";
+            JsonNode jsonNode = null;
+            if (msgContentType != null ) {
+                switch (msgContentType) {
+                    //普通消息
+                    case 101:
+                        type=1;
+                        jsonNode = objectMapper.readTree(content);
+                        cont=jsonNode.get("content").asText();
+                        break;
+                    //语音消息
+                    case 103:
+                        jsonNode = objectMapper.readTree(content); // 转为 JsonNode
+                        String soundUrl = jsonNode.get("sourceUrl").asText();
+                        try {
+                            // 创建URL对象
+                            URL url = new URL(soundUrl);
+                            InputStream in =  url.openStream();
+                            CloudStorageService storage = OSSFactory.build();
+                            cont = storage.uploadSuffix(in, ".m4a");
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        }
+                        type=2;
+                        //医生发送的语音消息,这一段是同步语音消息到腕表的
+                        /*if (send.contains("D")){
+                            WatchDeviceInfo u = watchDeviceInfoMapper.selectByUserId(to.replace("U", ""));
+                            if (u!=null&& StringUtils.isNotEmpty(u.getDeviceNumber())){
+                                DeviceSendParam deviceSendParam = new DeviceSendParam();
+                                deviceSendParam.setDeviceId(u.getDeviceNumber());
+                                deviceSendParam.setFileUrl(soundUrl);
+                                deviceSendParam.setSendUserName(openImMsgCallBackVO.getSenderNickname());
+                                deviceSetUpService.sendMp3(deviceSendParam);
+                            }
+                        }*/
+                        break;
+                    //图片消息
+                    case 102:
+                        jsonNode = objectMapper.readTree(content); // 转为 JsonNode
+                        String imgUrl = jsonNode.get("sourcePicture").get("url").asText();
+                        try {
+                            URL url = new URL(imgUrl);
+                            InputStream in =  url.openStream();
+                            CloudStorageService storage = OSSFactory.build();
+                            cont = storage.uploadSuffix(in, ".jpg");
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        }
+                        type=3;
+                        break;
+                    //视频消息
+                    case 104:
+                        jsonNode = objectMapper.readTree(content); // 转为 JsonNode
+                        String videoUrl = jsonNode.get("videoUrl").asText();
+                        try {
+                            URL url = new URL(videoUrl);
+                            InputStream in =  url.openStream();
+                            CloudStorageService storage = OSSFactory.build();
+                            cont = storage.uploadSuffix(in, "."+jsonNode.get("videoType").asText());
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        }
+                        type=4;
+                        break;
+                    //自定义消息
+                    case 110:
+                        PayloadDTO payloadDTO = objectMapper.readValue(content, PayloadDTO.class);
+
+                        jsonNode = objectMapper.readTree(payloadDTO.getData());
+                        JsonNode payload = jsonNode.get("payload");
+                        String data = payload.get("data").asText();
+                        JsonNode extension = payload.get("extension");
+                        if (data.equals("prescribe")){
+                            String prescribeId = extension.get("prescribeId").asText();
+                            FsPrescribe fsPrescribe = fsPrescribeMapper.selectFsPrescribeByPrescribeId(Long.parseLong(prescribeId));
+                            cont=objectMapper.writeValueAsString(fsPrescribe);
+                            //orderId = fsPrescribe.getInquiryOrderId();
+                            type=5;
+                            break;
+                        }else if (data.equals("report")){
+
+                            String description = payload.get("description").asText();
+                            FsInquiryOrderReport fsInquiryOrderReport = fsInquiryOrderReportService.selectFsInquiryOrderReportByOrderId(Long.parseLong(description));
+                            if (fsInquiryOrderReport!=null){
+                                cont = fsInquiryOrderReport.getOrderId().toString();
+                            }
+                            type=6;
+                            break;
+                        }else if (data.equals("follow")){
+                            cont=payload.get("extension").get("followId").asText();
+                            type= 7;
+                            //orderId = payload.get("extension").get("followId").asLong();
+                            break;
+                        }else if (data.equals("drugReport")){
+                            cont=payload.get("description").asText();
+                            //orderId = payload.get("description").asLong();
+                            type= 8;
+                            break;
+                        } else if (data.equals("package")){
+                            cont=payload.get("extension").get("title").asText();
+                            //orderId = payload.get("description").asLong();
+                            type= 9;
+                            break;
+                        }else if (data.equals("couponPackage")){
+                            cont=payload.get("extension").get("title").asText();
+                            //orderId = payload.get("description").asLong();
+                            type= 10;
+                            break;
+                        }else if (data.equals("inquirySelect")){
+                            cont=payload.get("extension").get("title").asText();
+                            //orderId = payload.get("description").asLong();
+                            type= 11;
+                            break;
+                        }else if (data.equals("startInquiry")||data.equals("finishInquiry")){
+                            cont =payload.get("extension").get("title").asText();
+                            type=1;
+                            break;
+                        }
+
+
+                }
+            }
+            if (StringUtils.isEmpty(cont)){
+                openImMsgCallBackResponse.setErrMsg("无消息内容,未保存到数据库");
+                return openImMsgCallBackResponse;
+            }
+            if (orderId==null&&StringUtils.isNotEmpty(openImMsgCallBackVO.getEx())){
+                JsonNode exJson = objectMapper.readTree(openImMsgCallBackVO.getEx());
+                orderId = exJson.get("orderId").asLong();
+            }
+            FsInquiryOrderMsg msg = new FsInquiryOrderMsg();
+            msg.setOrderId(orderId);
+            msg.setMsgContentType(type);
+            msg.setFromAccount(userId);
+            msg.setCompanyUserAccount(companyUserId);
+            msg.setToAccount(doctorId);
+            msg.setMsgKey(openImMsgCallBackVO.getClientMsgID());
+            msg.setContent(cont);
+            msg.setCreateTime(date);
+            msg.setMsgType(msgType);
+            fsInquiryOrderMsgMapper.insertFsInquiryOrderMsg(msg);
+            // 极光推送
+            //String pushContent = (type == 1) ? content :"您有一条新消息";
+            //uniPush2Service.pushOne(Long.parseLong(to.replace("U","")), orderId, null, "新消息提醒", pushContent, PushLogTypeEnum.MARKET.getValue(), PushLogDesTypeEnum.MARKET_PUSH.getValue());
+            log.info("返回的参数 {}", JSON.toJSONString(openImMsgCallBackResponse));
+            return openImMsgCallBackResponse;
+        } catch (Exception e){
+            openImMsgCallBackResponse.setActionCode(202);
+            openImMsgCallBackResponse.setErrCode(100);
+            openImMsgCallBackResponse.setErrDlt("");
+            openImMsgCallBackResponse.setErrMsg(e.getMessage());
+            log.info("返回的参数 {}", JSON.toJSONString(openImMsgCallBackResponse));
+            return openImMsgCallBackResponse;
+        }
+
+    }
 
 }

+ 115 - 22
fs-service/src/main/java/com/fs/his/service/impl/FsInquiryOrderServiceImpl.java

@@ -8,6 +8,8 @@ import cn.hutool.json.JSONUtil;
 import cn.jiguang.common.resp.APIConnectionException;
 import cn.jiguang.common.resp.APIRequestException;
 import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fs.common.constant.FsConstants;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
@@ -44,8 +46,10 @@ import com.fs.his.vo.*;
 import com.fs.huifuPay.domain.HuiFuRefundResult;
 import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayRefundRequest;
 import com.fs.huifuPay.service.HuiFuService;
+import com.fs.im.config.IMConfig;
 import com.fs.im.dto.*;
 import com.fs.im.service.IImService;
+import com.fs.im.service.OpenIMService;
 import com.fs.jpush.service.JpushService;
 import com.fs.repeat.vo.RepeatUploadVo;
 import com.fs.system.domain.SysConfig;
@@ -180,6 +184,8 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
 
     @Autowired
     private ConfigUtil configUtil;
+    @Autowired
+    private OpenIMService openIMService;
     /**
      * 查询问诊订单
      *
@@ -641,7 +647,18 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
         }
         else if(param.getInquiryType().equals(2)){
             //快速
-
+            FsDoctor doctor = null;
+            //获取销售绑定的医生信息
+            if (param.getCompanyUserId() != null) {
+                CompanyUser companyUser = companyUserService.selectCompanyUserById(param.getCompanyUserId());
+                if (companyUser != null && companyUser.getDoctorId() != null) {
+                    doctor = doctorMapper.selectFsDoctorByDoctorId(companyUser.getDoctorId());
+                    if (doctor != null) {
+                        order.setDoctorId(doctor.getDoctorId());
+                        order.setDepartmentId(doctor.getDeptId());
+                    }
+                }
+            }
             List<FsPriceDTO> price = configDTO.getPrices().stream().filter(x -> x.getType().equals(param.getOrderType())).collect(Collectors.toList());
             if(price!=null&&price.size()==1){
                 order.setMoney(price.get(0).getPrice());
@@ -660,6 +677,9 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
                 report.setPatientJson(JSONUtil.toJsonStr(dto));
                 report.setReportSn(reportSn);
                 report.setStatus(1);
+                if (doctor != null) {
+                    report.setDoctorId(doctor.getDoctorId());
+                }
                 order.setIsAudit(1);
             }
             else{
@@ -674,9 +694,13 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
                 report.setPatientJson(JSONUtil.toJsonStr(dto));
                 report.setReportSn(reportSn);
                 report.setStatus(0);
+                if (doctor != null) {
+                    report.setDoctorId(doctor.getDoctorId());
+                }
                 order.setIsAudit(0);
             }
 
+
         }
         else if(param.getInquiryType().equals(3)){
             //开药
@@ -870,7 +894,7 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
     @Override
     @Transactional
     @Synchronized
-    public R acceptOrder(FsInquiryOrderAcceptParam param) {
+    public R acceptOrder(FsInquiryOrderAcceptParam param) throws JsonProcessingException {
         FsInquiryOrder order=fsInquiryOrderMapper.selectFsInquiryOrderByOrderId(param.getOrderId());
         if(!order.getStatus().equals(FsInquiryOrderStatusEnum.STATUS_2.getValue())){
             return R.error("非法操作");
@@ -913,32 +937,44 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
 
             }
         }
-        MsgDTO msgDTO=new MsgDTO();
+        //MsgDTO msgDTO=new MsgDTO();
         MsgCustomDTO customDTO=new MsgCustomDTO();
         customDTO.setType("startInquiry");
         customDTO.setOrderType(order.getOrderType());
         customDTO.setOrderId(order.getOrderId().toString());
         customDTO.setImType(1);
-        msgDTO.setCloudCustomData(JSONUtil.toJsonStr(customDTO));
+        /*msgDTO.setCloudCustomData(JSONUtil.toJsonStr(customDTO));
         msgDTO.setFrom_Account("D-"+param.getDoctorId());
-        msgDTO.setTo_Account("U-"+order.getUserId());
-        List<MsgDataDTO> msgs=new ArrayList<>();
+        msgDTO.setTo_Account("U-"+order.getUserId());*/
+        /*List<MsgDataDTO> msgs=new ArrayList<>();
         MsgDataDTO msg=new MsgDataDTO();
-        msg.setMsgType("TIMCustomElem");
+        msg.setMsgType("TIMCustomElem");*/
         FsDoctor doctor=doctorMapper.selectFsDoctorByDoctorId(param.getDoctorId());
         String doc="医生";
         if (doctor.getDeptId()!=null&&doctor.getDeptId().compareTo(39L)==0){
             doc="药师";
         }
-        InquiryOrderMsgDTO inquiryOrderMsgDTO=new InquiryOrderMsgDTO();
+        /*InquiryOrderMsgDTO inquiryOrderMsgDTO=new InquiryOrderMsgDTO();
         inquiryOrderMsgDTO.setTitle(doctor.getDoctorName()+doc+"为您服务");
         String ext= JSONUtil.toJsonStr(inquiryOrderMsgDTO);
         msg.setMsgContent(new MsgDataFormatDTO("startInquiry",ext,order.getOrderId().toString()));
         msgs.add(msg);
-        msgDTO.setMsgBody(msgs);
-        imService.sendMsg(msgDTO);
-
-
+        msgDTO.setMsgBody(msgs);*/
+        //imService.sendMsg(msgDTO);
+        ObjectMapper objectMapper = new ObjectMapper();
+        String ex = objectMapper.writeValueAsString(customDTO);
+        openIMService.sendUtil("D"+param.getDoctorId(),"U"+order.getUserId(),110,"startInquiry","",doctor.getDoctorName()+doc+"为您服务","","","");
+        /*OpenImMsgDTO openImMsgDTO = new OpenImMsgDTO();
+        openImMsgDTO.setSendID("D"+param.getDoctorId().toString());
+        openImMsgDTO.setRecvID("U"+order.getUserId().toString());
+        openImMsgDTO.setContentType(110);
+        openImMsgDTO.setSenderPlatformID(5);
+        openImMsgDTO.setSessionType(1);
+        OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
+        content.setContent(ext);
+        openImMsgDTO.setContent(content);
+        openImMsgDTO.setEx(customDTO);
+        openIMService.openIMSendMsg(openImMsgDTO);*/
         if (doc.equals("药师")){
             MsgDTO msgDTO1=new MsgDTO();
             MsgCustomDTO customDTO1=new MsgCustomDTO();
@@ -956,7 +992,22 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
             msg1.setMsgContent(dto1);
             msgs1.add(msg1);
             msgDTO1.setMsgBody(msgs1);
-            imService.sendMsg(msgDTO1);
+            //imService.sendMsg(msgDTO1);
+
+            ObjectMapper objectMapper1 = new ObjectMapper();
+            String ex1 = objectMapper.writeValueAsString(customDTO1);
+            openIMService.sendUtil("D"+param.getDoctorId(),"U"+order.getUserId(),110,"startInquiry","","您好,我是芸医汇互联网医院执业药师,请问您有什么问题想咨询?","","",ex1);
+            /*OpenImMsgDTO openImMsgDTO1 = new OpenImMsgDTO();
+            openImMsgDTO1.setSendID("D"+param.getDoctorId().toString());
+            openImMsgDTO1.setRecvID("U"+order.getUserId().toString());
+            openImMsgDTO1.setContentType(101);
+            openImMsgDTO1.setSenderPlatformID(5);
+            openImMsgDTO1.setSessionType(1);
+            OpenImMsgDTO.Content content1 = new OpenImMsgDTO.Content();
+            content1.setContent(ext);
+            openImMsgDTO1.setContent(content1);
+            openImMsgDTO1.setEx(customDTO);
+            openIMService.openIMSendMsg(openImMsgDTO1);*/
         }
 
 
@@ -1010,7 +1061,7 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
 
     @Override
     @Transactional
-    public R receiveOrder(FsInquiryOrderReceiveParam param) {
+    public R receiveOrder(FsInquiryOrderReceiveParam param) throws JsonProcessingException {
         FsInquiryOrder order=fsInquiryOrderMapper.selectFsInquiryOrderByOrderId(param.getOrderId());
         if(!order.getStatus().equals(FsInquiryOrderStatusEnum.STATUS_2.getValue())){
             return R.error("非法操作");
@@ -1073,7 +1124,21 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
         msg.setMsgContent(new MsgDataFormatDTO("startInquiry",ext,order.getOrderId().toString()));
         msgs.add(msg);
         msgDTO.setMsgBody(msgs);
-        imService.sendMsg(msgDTO);
+        //imService.sendMsg(msgDTO);
+        ObjectMapper objectMapper = new ObjectMapper();
+        String ex = objectMapper.writeValueAsString(customDTO);
+        openIMService.sendUtil("D"+order.getDoctorId(),"U"+order.getUserId(),110,"startInquiry","",doctor.getDoctorName()+doc+"为您服务","","",ex);
+        /*OpenImMsgDTO openImMsgDTO = new OpenImMsgDTO();
+        openImMsgDTO.setSendID("D"+order.getDoctorId().toString());
+        openImMsgDTO.setRecvID("U"+order.getUserId().toString());
+        openImMsgDTO.setContentType(110);
+        openImMsgDTO.setSenderPlatformID(5);
+        openImMsgDTO.setSessionType(1);
+        OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
+        content.setContent(ext);
+        openImMsgDTO.setContent(content);
+        openImMsgDTO.setEx(customDTO);
+        openIMService.openIMSendMsg(openImMsgDTO);*/
         if (doc.equals("药师")){
             MsgDTO msgDTO1=new MsgDTO();
             MsgCustomDTO customDTO1=new MsgCustomDTO();
@@ -1091,7 +1156,22 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
             msg1.setMsgContent(dto1);
             msgs1.add(msg1);
             msgDTO1.setMsgBody(msgs1);
-            imService.sendMsg(msgDTO1);
+            //imService.sendMsg(msgDTO1);
+
+            ObjectMapper objectMapper1 = new ObjectMapper();
+            String ex1 = objectMapper.writeValueAsString(customDTO1);
+            openIMService.sendUtil("D"+param.getDoctorId(),"U"+order.getUserId(),110,"startInquiry","","您好,我是芸医汇互联网医院执业药师,请问您有什么问题想咨询?","","",ex1);
+           /* OpenImMsgDTO openImMsgDTO1 = new OpenImMsgDTO();
+            openImMsgDTO1.setSendID("D"+order.getDoctorId().toString());
+            openImMsgDTO1.setRecvID("U"+order.getUserId().toString());
+            openImMsgDTO1.setContentType(110);
+            openImMsgDTO1.setSenderPlatformID(5);
+            openImMsgDTO1.setSessionType(1);
+            OpenImMsgDTO.Content content1 = new OpenImMsgDTO.Content();
+            content1.setContent(ext);
+            openImMsgDTO1.setContent(content1);
+            openImMsgDTO1.setEx(customDTO);
+            openIMService.openIMSendMsg(openImMsgDTO1);*/
         }
         //发送给医生
 //        MsgDTO msgDTO1=new MsgDTO();
@@ -1188,7 +1268,7 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
 
     @Override
     @Transactional
-    public R finishOrder(FsInquiryOrderFinishParam param) {
+    public R finishOrder(FsInquiryOrderFinishParam param) throws JsonProcessingException {
         FsInquiryOrder order=fsInquiryOrderMapper.selectFsInquiryOrderByOrderId(param.getOrderId());
         if(!order.getStatus().equals(FsInquiryOrderStatusEnum.STATUS_3.getValue())){
             return R.error("非法操作");
@@ -1228,7 +1308,11 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
         msg.setMsgContent(new MsgDataFormatDTO("finishInquiry",ext,order.getOrderId().toString()));
         msgs.add(msg);
         msgDTO.setMsgBody(msgs);
-        imService.sendMsg(msgDTO);
+        //imService.sendMsg(msgDTO);
+        ObjectMapper objectMapper = new ObjectMapper();
+        String ex = objectMapper.writeValueAsString(customDTO);
+        openIMService.sendUtil("D"+order.getDoctorId(),"U"+order.getUserId(),110,"finishInquiry","","医生完成订单","","",ex);
+
         //发送给医生
 //        MsgDTO msgDTO1=new MsgDTO();
 //        MsgCustomDTO customDTO1=new MsgCustomDTO();
@@ -1258,7 +1342,7 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
     }
     @Override
     @Transactional
-    public R autoFinishOrder(FsInquiryOrderFinishParam param) {
+    public R autoFinishOrder(FsInquiryOrderFinishParam param) throws JsonProcessingException {
         FsInquiryOrder order=fsInquiryOrderMapper.selectFsInquiryOrderByOrderId(param.getOrderId());
         if(!order.getStatus().equals(FsInquiryOrderStatusEnum.STATUS_3.getValue())){
             return R.error("非法操作");
@@ -1297,7 +1381,11 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
         msg.setMsgContent(new MsgDataFormatDTO("finishInquiry",ext,order.getOrderId().toString()));
         msgs.add(msg);
         msgDTO.setMsgBody(msgs);
-        imService.sendMsg(msgDTO);
+        //imService.sendMsg(msgDTO);
+        ObjectMapper objectMapper = new ObjectMapper();
+        String ex = objectMapper.writeValueAsString(customDTO);
+        openIMService.sendUtil("D"+order.getDoctorId(),"U"+order.getUserId(),110,"finishInquiry","","医生完成订单","","",ex);
+
         redisTemplate.delete("DrugReport:doctorId:" + order.getDoctorId() + ":userId:" + order.getUserId());
         return R.ok();
     }
@@ -1579,7 +1667,7 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
     }
 
     @Override
-    public String sendStartMsg(Long orderId) {
+    public String sendStartMsg(Long orderId) throws JsonProcessingException {
 
         FsInquiryOrder order = fsInquiryOrderMapper.selectFsInquiryOrderByOrderId(orderId);
         MsgDTO msgDTO=new MsgDTO();
@@ -1601,7 +1689,12 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
         msg.setMsgContent(new MsgDataFormatDTO("startInquiry",ext,order.getOrderId().toString()));
         msgs.add(msg);
         msgDTO.setMsgBody(msgs);
-        imService.sendMsg(msgDTO);
+        //imService.sendMsg(msgDTO);
+
+        ObjectMapper objectMapper = new ObjectMapper();
+        String ex = objectMapper.writeValueAsString(customDTO);
+        openIMService.sendUtil("D"+order.getDoctorId(),"U"+order.getUserId(),110,"startInquiry","1","为您服务","","",ex);
+
         return "OK";
     }
 

+ 53 - 8
fs-service/src/main/java/com/fs/his/service/impl/FsPackageOrderServiceImpl.java

@@ -318,9 +318,12 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
         }
 
         if (param.getType()==1) {
-            if (StringUtils.isBlank(user.getMaOpenId()) && !CloudHostUtils.hasCloudHostName("弘德堂")) {
-                return R.error("用户OPENID不存在");
-            }
+//            if (StringUtils.isBlank(user.getMaOpenId()) && !CloudHostUtils.hasCloudHostName("弘德堂")) {
+//                return R.error("用户OPENID不存在");
+//            }
+//            if (!CloudHostUtils.hasCloudHostName("弘德堂")) {
+//                return R.error("用户OPENID不存在");
+//            }
 
             param.setCompanyId(order.getCompanyId());
             param.setCompanyUserId(order.getUserId());
@@ -345,6 +348,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
         BigDecimal payDelivery = new BigDecimal(0);
         BigDecimal discountMoney = new BigDecimal(0);
         String json = configService.selectConfigByKey("his.package");
+        FsSysConfig sysConfig = configUtil.getSysConfig();
         PackageConfigDTO configDTO = JSONUtil.toBean(json, PackageConfigDTO.class);
         if (param.getUserCouponId() != null && param.getUserCouponId() > 0l) {
             FsUserCoupon userCoupon = userCouponService.selectFsUserCouponById(param.getUserCouponId());
@@ -407,7 +411,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
             payPrice = orderPrice;
             discountMoney = new BigDecimal(0);
         }
-
+        //payRemain-代收金额 payDelivery-邮费 payPrice-实际支付金额 payMoney-支付金额
         if (payPrice.compareTo(new BigDecimal(0)) == 1) {
             if (param.getPayType().equals(1)) {
                 //全款
@@ -417,13 +421,35 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
 
             } else if (param.getPayType().equals(2)) {
                 //代收
-                payMoney = payPrice.multiply(new BigDecimal((100 - configDTO.getPayRate()))).divide(new BigDecimal(100));
-                payMoney = new BigDecimal(payMoney.setScale(0, BigDecimal.ROUND_HALF_UP).longValue());
+//                payMoney = payPrice.multiply(new BigDecimal((100 - configDTO.getPayRate()))).divide(new BigDecimal(100));
+//                payMoney = new BigDecimal(payMoney.setScale(0, BigDecimal.ROUND_HALF_UP).longValue());
+//                payRemain = payPrice.subtract(payMoney);
+//                payDelivery = new BigDecimal(0);
+//                if (payRemain.compareTo(new BigDecimal(0)) == 0) {
+//                    throw new CustomException("代收金额应大于0");
+//                }
+                if (sysConfig.getRetainer() != null && sysConfig.getRate() != null && sysConfig.getRate().compareTo(new BigDecimal(0)) > 0) {
+                    if (payPrice.compareTo(new BigDecimal(100)) < 0) {
+                        throw new CustomException("订单金额应大于等于100");
+                    }
+                    //有最低定金金额和提成比率
+                    if (payPrice.compareTo(new BigDecimal(1000)) < 0) {
+                        payMoney = new BigDecimal(100);
+                    } else {
+                        payMoney = payPrice.multiply(sysConfig.getRate()).divide(new BigDecimal(100));
+                        payMoney = new BigDecimal(payMoney.setScale(0, BigDecimal.ROUND_HALF_UP).longValue());
+                    }
+                } else {
+                    payMoney = payPrice.multiply(new BigDecimal((100 - configDTO.getPayRate()))).divide(new BigDecimal(100));
+                    payMoney = new BigDecimal(payMoney.setScale(0, BigDecimal.ROUND_HALF_UP).longValue());
+                }
                 payRemain = payPrice.subtract(payMoney);
                 payDelivery = new BigDecimal(0);
                 if (payRemain.compareTo(new BigDecimal(0)) == 0) {
                     throw new CustomException("代收金额应大于0");
                 }
+
+
             } else if (param.getPayType().equals(3)) {
                 //货到付款
                 payMoney = configDTO.getPayDelivery();
@@ -459,8 +485,15 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
         }else {
             return R.error("请提交患者信息");
         }
+        logger.info("用户{}创建套餐订单,套餐id{},患者id{}",param.getUserId(),param.getPackageId(),param.getPatientId());
 
         FsPackage fsPackage=fsPackageMapper.selectFsPackageByPackageId(param.getPackageId());
+        logger.info("是否是中药或者西药{},{}",fsPackage.getProductType(),fsPackage.getProductType() == 1 || fsPackage.getProductType() == 2);
+        if (fsPackage.getProductType() == 1 || fsPackage.getProductType() == 2) {
+            if (StringUtils.isEmpty(patient.getIdCard())) {
+                return R.error("请完善患者身份证信息");
+            }
+        }
         if(fsPackage.getStatus().equals(0)){
             return R.error("套餐名已下架");
         }
@@ -475,6 +508,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
                 return R.error("您正在咨询此医生,请先结束当前订单");
             }
         }
+        //私域下套餐包(可覆盖医生信息 使用销售绑定的医生信息)
         if (fsPackage.getIsShow()==0){
             if (param.getCompanyId()==null||param.getCompanyUserId()==null){
                 return R.error("商品信息过期");
@@ -483,7 +517,11 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
             if (companyUser==null){
                 return R.error("商品信息过期");
             }
+            //获取销售绑定医生
+            if (companyUser.getDoctorId() != null) {
+                doctor = doctorMapper.selectFsDoctorByDoctorId(companyUser.getDoctorId());
 
+            }
         }
 
 
@@ -505,7 +543,11 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
         order.setOrderSn(orderSn);
         order.setStoreId(fsPackage.getStoreId());
         order.setUserId(param.getUserId());
-        order.setDoctorId(param.getDoctorId());
+        if (doctor != null) {
+            order.setDoctorId(doctor.getDoctorId());
+        } else {
+            order.setDoctorId(param.getDoctorId());
+        }
         order.setPackageId(param.getPackageId());
         order.setPackageName(fsPackage.getPackageName());
         order.setTotalPrice(fsPackage.getTotalPrice());
@@ -719,6 +761,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
             inquiryOrderService.createOrderByPackageOrder(order);
         }
         if (packageSubType!=1){
+            logger.info("创建订单2");
             storeOrderService.createOrderByPackageOrder(order);
             logger.info("创建订单");
         }
@@ -729,6 +772,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
             u.setIsBuy(1);
             fsUserService.updateFsUser(u);
         }
+        logger.info("更新完成");
         return R.ok();
     }
 
@@ -1185,7 +1229,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
         }
         //如果存在优惠券  判断优惠券是否已使用
         FsUser user=userService.selectFsUserByUserId(param.getUserId());
-        if(user!=null&& StringUtils.isNotEmpty(user.getMpOpenId())){
+        if(user!=null){
             if(fsPackageOrder.getPayMoney().compareTo(new BigDecimal(0))==1){
                 String json = configService.selectConfigByKey("his.pay");
                 PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
@@ -1241,6 +1285,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
                         o.setReqSeqId("package-"+storePayment.getPayCode());
                         o.setTransAmt(storePayment.getPayMoney().toString());
                         o.setGoodsDesc("套餐包订单支付");
+                        o.setAppId(param.getAppId());
                         HuifuCreateOrderResult result = huiFuService.createOrder(o);
                         logger.info("创建汇付支付:"+result);
                         FsStorePayment mt=new FsStorePayment();

+ 1 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsPrescribeServiceImpl.java

@@ -528,6 +528,7 @@ public class FsPrescribeServiceImpl implements IFsPrescribeService
         if (fsDoctor==null){
             throw new CustomException("医生查询错误:"+packageOrder.getDoctorId());
         }
+
         fsPrescribe.setPrescribeDoctorId(fsDoctor.getDoctorId());
         fsPrescribe.setPrescribeDoctorSignUrl(fsDoctor.getSignUrl());
 

+ 9 - 3
fs-service/src/main/java/com/fs/his/service/impl/FsStoreOrderServiceImpl.java

@@ -665,21 +665,25 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
 
     @Override
     public R createOrderByPackageOrder(FsPackageOrder packageOrder) {
+        logger.info("111111111111111");
         if (packageOrder.getDoctorId() == null) {
             Long doctorID = iFsDoctorService.selectFsDoctorDoctorByPackage();
             packageOrder.setDoctorId(doctorID);
         }
+        logger.info("2222222222222");
         FsPackage fsPackage = fsPackageMapper.selectFsPackageByPackageId(packageOrder.getPackageId());
         JSONArray objects = JSONUtil.parseArray(fsPackage.getProductJson());
         List<FsPackagePruductDTO> products = JSONUtil.toList(objects, FsPackagePruductDTO.class);
-
+        logger.info("3333333333333333333");
         Map<String, Object> packageJson = (Map) JSON.parse(packageOrder.getPackageJson());
+        logger.info("55555555555555555555");
         Integer packageSubType = (Integer) packageJson.get("packageSubType");
         if (packageSubType == 3) {
             inquiryOrderService.createOrderByPackageOrderStatus4(packageOrder);
         }
+        logger.info("4444444444444444444");
         Long prescribeId = fsPrescribeService.insertFsPrescribeByPackageOrder(packageOrder);
-
+        logger.info("66666666666666666");
         FsStoreOrder order = new FsStoreOrder();
         List<FsStoreOrderItem> items = new ArrayList<>();
         log.info("套餐包生成药品订单:{}", packageOrder.getOrderSn());
@@ -1211,7 +1215,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
 
         FsUser user = userService.selectFsUserByUserId(order.getUserId());
         Map<String, BigDecimal> data = new HashMap<>();
-        if (user != null && StringUtils.isNotEmpty(user.getMaOpenId())) {
+        if (user != null ) {
             if (param.getUserCouponId() != null && param.getUserCouponId() > 0l) {
                 FsUserCoupon userCoupon = userCouponService.selectFsUserCouponById(param.getUserCouponId());
                 if (userCoupon == null) {
@@ -2802,6 +2806,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
                         o.setReqSeqId("store-" + storePayment.getPayCode());
                         o.setTransAmt(storePayment.getPayMoney().toString());
                         o.setGoodsDesc("药品订单支付");
+                        o.setAppId(param.getAppId());
                         HuifuCreateOrderResult result = huiFuService.createOrder(o);
                         FsStorePayment mt = new FsStorePayment();
                         mt.setPaymentId(storePayment.getPaymentId());
@@ -2890,6 +2895,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
                         o.setReqSeqId("store-" + storePayment.getPayCode());
                         o.setTransAmt(storePayment.getPayMoney().toString());
                         o.setGoodsDesc("药品订单支付");
+                        o.setAppId(param.getAppId());
                         HuifuCreateOrderResult result = huiFuService.createOrder(o);
                         FsStorePayment mt = new FsStorePayment();
                         mt.setPaymentId(storePayment.getPaymentId());

+ 17 - 6
fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java

@@ -58,6 +58,7 @@ import com.fs.his.vo.FsUserVO;
 import com.fs.his.vo.FsUserExportListVO;
 import com.fs.his.vo.FsUserFollowDoctorVO;
 import com.fs.his.vo.UserVo;
+import com.fs.im.service.OpenIMService;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
 import com.fs.hisStore.domain.FsUserBillScrm;
 import com.fs.hisStore.domain.FsUserScrm;
@@ -94,9 +95,9 @@ import com.fs.his.service.IFsUserService;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
-import static com.fs.his.utils.PhoneUtil.decryptPhoneMk;
-import static com.fs.his.utils.PhoneUtil.encryptPhone;
+import static com.fs.his.utils.PhoneUtil.*;
 import static com.fs.hisStore.enums.BillDetailEnum.CATEGORY_1;
+import static com.fs.his.utils.PhoneUtil.*;
 import static com.fs.hisStore.enums.BillDetailEnum.CATEGORY_3;
 
 /**
@@ -167,6 +168,8 @@ public class FsUserServiceImpl implements IFsUserService {
     @Autowired
     private FsUserCourseCountMapper fsUserCourseCountMapper;
 
+    @Autowired
+    private OpenIMService openIMService;
     @Autowired
     private IFsUserBillScrmService billService;
     @Autowired
@@ -595,12 +598,17 @@ public class FsUserServiceImpl implements IFsUserService {
             }
 
             //解密
-            if (fsUserPageListVO.getPhone() != null && fsUserPageListVO.getPhone() != "") {
-                if (fsUserPageListVO.getPhone().length() > 11) {
-                    fsUserPageListVO.setPhone(decryptPhoneMk(fsUserPageListVO.getPhone()));
+            if(fsUserPageListVO.getPhone() != null && fsUserPageListVO.getPhone() != ""){
+                if(param.getIsHidePhoneMiddle()){
+                    if (fsUserPageListVO.getPhone().length()>11){
+                        fsUserPageListVO.setPhone(decryptPhoneMk(fsUserPageListVO.getPhone()));
+                    }else {
+                        fsUserPageListVO.setPhone(fsUserPageListVO.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+                    }
                 } else {
-                    fsUserPageListVO.setPhone(fsUserPageListVO.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+                    fsUserPageListVO.setPhone(decryptPhone(fsUserPageListVO.getPhone()));
                 }
+
             }
         }
 
@@ -1083,6 +1091,9 @@ public class FsUserServiceImpl implements IFsUserService {
 //            this.setRepeatFansTag(param);
 //        }
 
+        // 与im账号绑定
+        openIMService.checkAndImportFriend(param.getCompanyUserId(), String.valueOf(param.getUserId()));
+
         //如果是设置了需要进入小黑屋,则需要返回提示,否则正常返回
         if (isDefaultBlack == 1) {
             return ResponseResult.fail(402, "已成功注册,待管理审核");

+ 2 - 0
fs-service/src/main/java/com/fs/hisStore/param/FsStorePaymentPayParam.java

@@ -20,4 +20,6 @@ public class FsStorePaymentPayParam implements Serializable
     private Long companyUserId;
 
     private String code;
+
+    private String appId;
 }

+ 33 - 1
fs-service/src/main/java/com/fs/huifuPay/service/impl/HuiFuServiceImpl.java

@@ -5,7 +5,9 @@ import com.alibaba.fastjson.JSONObject;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.spring.SpringUtils;
+import com.fs.his.domain.FsHfpayConfig;
 import com.fs.his.domain.FsPayConfig;
+import com.fs.his.mapper.FsHfpayConfigMapper;
 import com.fs.huifuPay.domain.*;
 import com.fs.huifuPay.sdk.opps.core.config.MerConfig;
 import com.fs.huifuPay.sdk.opps.core.request.*;
@@ -19,6 +21,7 @@ import com.google.gson.Gson;
 import io.lettuce.core.ScriptOutputType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
@@ -37,9 +40,23 @@ public class HuiFuServiceImpl implements HuiFuService {
 
     @Override
     public HuifuCreateOrderResult createOrder(HuiFuCreateOrder order) {
+        logger.info("汇付传参HuiFuCreateOrder==============>{}",order);
         HuifuCreateOrderResult huifuCreateOrderResult =null;
         try {
-            doInit(getMerConfig());
+
+            if (order.getAppId() != null) {
+                FsHfpayConfigMapper fsHfpayConfigMapper = SpringUtils.getBean(FsHfpayConfigMapper.class);
+                FsHfpayConfig fsHfpayConfig = fsHfpayConfigMapper.selectByAppId(order.getAppId());
+                if (fsHfpayConfig != null) {
+                    //多汇付支付获取配置
+                    doInit(getMerConfig(fsHfpayConfig));
+                } else {
+                    //多小程序
+                    doInit(getMerConfig());
+                }
+            } else {
+                doInit(getMerConfig());
+            }
             V2TradePaymentJspayRequest request = new V2TradePaymentJspayRequest();
             request.setReqDate(DateTools.getCurrentDateYYYYMMDD());
             request.setReqSeqId(order.getReqSeqId());
@@ -290,4 +307,19 @@ public class HuiFuServiceImpl implements HuiFuService {
         merConfig.setHuifuId(fsPayConfig.getHuifuId());
         return merConfig;
     }
+
+    public MerConfig getMerConfig(FsHfpayConfig fsHfpayConfig) {
+        MerConfig merConfig = new MerConfig();
+        merConfig.setProcutId(fsHfpayConfig.getHfProductId());
+        merConfig.setSysId(fsHfpayConfig.getHfSysId());
+        merConfig.setRsaPrivateKey(fsHfpayConfig.getHfRsaPrivateKey());
+        merConfig.setRsaPublicKey(fsHfpayConfig.getHfRsaPublicKey());
+        merConfig.setHuifuId(fsHfpayConfig.getHuifuId());
+
+        FsPayConfig fsPayConfig = new FsPayConfig();
+        BeanUtils.copyProperties(fsHfpayConfig,fsPayConfig);
+
+        config = fsPayConfig;
+        return merConfig;
+    }
 }

+ 31 - 0
fs-service/src/main/java/com/fs/im/config/IMConfig.java

@@ -3,6 +3,8 @@ package com.fs.im.config;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 
+import javax.annotation.PostConstruct;
+
 @Component
 //@ConfigurationProperties(prefix = "openIM")
 public class IMConfig {
@@ -10,6 +12,19 @@ public class IMConfig {
     private String secret;
     @Value("${openIM.userID}")
     private String userID;
+    @Value("${openIM.url}")
+    private String url;
+//    @Value("${openIM.prefix}")
+//    private String prefix;
+    // 静态常量
+    public static String PREFIX;
+    public static String URL;
+
+    @PostConstruct
+    public void init() {
+//        PREFIX = this.prefix;
+        URL = this.url;
+    }
 
     public String getSecret() {
         return secret;
@@ -26,4 +41,20 @@ public class IMConfig {
     public void setUserID(String userID) {
         this.userID = userID;
     }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+//    public String getPrefix() {
+//        return prefix;
+//    }
+//
+//    public void setPrefix(String scrm) {
+//        this.prefix = scrm;
+//    }
 }

+ 72 - 0
fs-service/src/main/java/com/fs/im/domain/FsImMsgSendDetail.java

@@ -0,0 +1,72 @@
+package com.fs.im.domain;
+
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * openim消息记录详情对象 fs_im_msg_send_detail
+ *
+ * @author fs
+ * @date 2025-08-21
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Accessors(chain = true)
+public class FsImMsgSendDetail extends BaseEntity{
+
+    /** 记录详情id */
+    @TableId(type = IdType.AUTO)
+    private Long logDetailId;
+
+    /** 发课记录主表id */
+    @Excel(name = "发课记录主表id")
+    private Long logId;
+
+    /** 销售id(发送人id) */
+    @Excel(name = "销售id", readConverterExp = "发送人id")
+    private Long companyUserId;
+
+    /** 用户id(接收人id) */
+    @Excel(name = "用户id", readConverterExp = "接收人id")
+    private Long userId;
+
+    /** 预计发送时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "预计发送时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date planSendTime;
+
+    /** 实际发送时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "实际发送时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date actualSendTime;
+
+    /** 发送状态,1-已发送;2-待发送 */
+    @Excel(name = "发送状态,1-已发送;2-待发送")
+    private Integer sendStatus;
+
+    /** 执行入参json */
+    @Excel(name = "执行入参json")
+    private String paramJson;
+
+    /** 执行状态,0-正常;1-失败 */
+    @Excel(name = "执行状态,0-正常;1-失败")
+    private Integer status;
+
+    /** 执行结果 */
+    @Excel(name = "执行结果")
+    private String resultMessage;
+
+    /** 异常信息 */
+    @Excel(name = "异常信息")
+    private String exceptionInfo;
+
+
+}

+ 106 - 0
fs-service/src/main/java/com/fs/im/domain/FsImMsgSendLog.java

@@ -0,0 +1,106 @@
+package com.fs.im.domain;
+
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * openim消息记录主对象 fs_im_msg_send_log
+ *
+ * @author fs
+ * @date 2025-08-21
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Accessors(chain = true)
+public class FsImMsgSendLog extends BaseEntity{
+
+    /** 发送记录id */
+    @TableId(type = IdType.AUTO)
+    private Long logId;
+
+    /** 销售id(发送人id) */
+    @Excel(name = "销售id", readConverterExp = "发送人id")
+    private Long companyUserId;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 课程id */
+    @Excel(name = "课程id")
+    private Long courseId;
+
+    /** 课程名称 */
+    @Excel(name = "课程名称")
+    private String courseName;
+
+    /** 视频id */
+    @Excel(name = "视频id")
+    private Long videoId;
+
+    /** 视频标题 */
+    @Excel(name = "视频标题")
+    private String videoName;
+
+    /** 营期id */
+    @Excel(name = "营期id")
+    private Long periodId;
+
+    /** 发送内容 */
+    @Excel(name = "发送内容")
+    private String sendTitle;
+
+    /** 预计发送时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "预计发送时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date planSendTime;
+
+    /** 发送类型,1-定时;2-实时 */
+    @Excel(name = "发送类型,1-定时;2-实时")
+    private Integer sendType;
+
+    /** 发送方式,1-app;2-销售后台 */
+    @Excel(name = "发送方式,1-app;2-销售后台")
+    private Integer sendMode;
+
+    /** 发送状态,1-已发送;2-待发送 */
+    @Excel(name = "发送状态,1-已发送;2-待发送")
+    private Integer sendStatus;
+
+    /** 是否催课,1-是;0-否 */
+    @Excel(name = "是否催课,1-是;0-否")
+    private Integer isUrgeCourse;
+
+    /** 消息类型,1-发课;2-催课 */
+    @Excel(name = "消息类型,1-发课;2-催课")
+    private Integer msgType;
+
+    /** 关联id,发课和催课记录关联id */
+    @Excel(name = "关联id,发课和催课记录关联id")
+    private String sendUnionId;
+
+    /** 关联标签id,仅用于展示 */
+    @Excel(name = "关联标签id,仅用于展示")
+    private String tagIds;
+
+    /** 关联标签名称,用于展示 */
+    @Excel(name = "关联标签名称,用于展示")
+    private String tagNames;
+
+    /** 课程所属项目id */
+    @Excel(name = "课程所属项目id")
+    private Long projectId;
+
+    /** 营期课程表id */
+    @Excel(name = "营期课程表id")
+    private Long periodDaysId;
+
+}

+ 67 - 0
fs-service/src/main/java/com/fs/im/domain/ImSendLog.java

@@ -0,0 +1,67 @@
+package com.fs.im.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.EqualsAndHashCode;
+
+/**
+ * openim消息发送记录对象 im_send_log
+ *
+ * @author fs
+ * @date 2025-08-12
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ImSendLog extends BaseEntity{
+
+    /** 发送记录id */
+    private Long logId;
+
+    /** 发送者id */
+    @Excel(name = "发送者id")
+    private String sendId;
+
+    /** 接收者id */
+    @Excel(name = "接收者id")
+    private String recvId;
+
+    /** 发送的标题 */
+    @Excel(name = "发送的标题")
+    private String sendTitle;
+
+    /** 预计发送时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "预计发送时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date planSendTime;
+
+    /** 实际发送时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "实际发送时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date actualSendTime;
+
+    /** 发送类型,1-定时;2-实时 */
+    @Excel(name = "发送类型,1-定时;2-实时")
+    private Integer sendType;
+
+    /** 执行入参json */
+    @Excel(name = "执行入参json")
+    private String paramJson;
+
+    /** 执行状态,0-正常;1-失败 */
+    @Excel(name = "执行状态,0-正常;1-失败")
+    private Integer status;
+
+    /** 执行结果 */
+    @Excel(name = "执行结果")
+    private String resultMessage;
+
+    /** 异常信息 */
+    @Excel(name = "异常信息")
+    private String exceptionInfo;
+
+
+}

+ 53 - 0
fs-service/src/main/java/com/fs/im/dto/OpenImBatchMsgDTO.java

@@ -0,0 +1,53 @@
+package com.fs.im.dto;
+
+import com.fs.his.dto.PayloadDTO;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 批量发送消息-请求参数
+ */
+@Data
+@Accessors(chain = true)
+public class OpenImBatchMsgDTO implements Serializable {
+
+    private String sendID;
+    private List<String> recvIDs;
+    private String senderNickname;
+    private String senderFaceURL;
+    private Integer senderPlatformID;
+    private Content content;
+    private Integer contentType;
+    private Integer sessionType;
+    private Boolean isOnlineOnly;
+    private Boolean notOfflinePush;
+    private Long sendTime;
+    private OfflinePushInfo offlinePushInfo;
+    private String ex;
+    private Boolean isSendAll; //是否发送给全部人
+
+
+    @Data
+    public static class Content implements Serializable {
+        private String content;
+        private String data; //自定义消息
+        private String description;
+        private String extension;
+    }
+    @Data
+    public static class ImData implements Serializable {
+        private PayloadDTO payload;
+    }
+    @Data
+    public static class OfflinePushInfo implements Serializable {
+        private String title;
+        private String desc;
+        private String ex;
+        private String iOSPushSound;
+        private Boolean iOSBadgeCount;
+
+    }
+}

+ 31 - 0
fs-service/src/main/java/com/fs/im/dto/OpenImBatchResponseDataDTO.java

@@ -0,0 +1,31 @@
+package com.fs.im.dto;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ * 批量发送消息-相应参数的data参数
+ */
+@Data
+@Accessors(chain = true)
+public class OpenImBatchResponseDataDTO {
+    /**
+     * 结果列表
+     */
+    private List<Results> results;
+    /**
+     * 向其发送消息失败的用户ID列表
+     */
+    private String[] failedUserIDs;
+
+    @Data
+    public static class Results {
+        private String serverMsgID;//服务器消息ID,预留字段
+        private String clientMsgID;//客户端消息ID,此ID为消息唯一ID
+        private Long sendTime;
+        private String recvID;
+    }
+
+}

+ 12 - 0
fs-service/src/main/java/com/fs/im/dto/OpenImMsgCallBackResponse.java

@@ -0,0 +1,12 @@
+package com.fs.im.dto;
+
+import lombok.Data;
+
+@Data
+public class OpenImMsgCallBackResponse {
+    private Integer actionCode = 0;
+    private Integer errCode = 0;
+    private String errMsg = "";
+    private String errDlt = "";
+    private Integer nextCode = 0;
+}

+ 11 - 0
fs-service/src/main/java/com/fs/im/dto/OpenImResponseDataDTO.java

@@ -0,0 +1,11 @@
+package com.fs.im.dto;
+
+import lombok.Data;
+
+@Data
+public class OpenImResponseDataDTO {
+    private String serverMsgID;
+    private String clientMsgID;
+    private Long sendTime;
+    private String modify;
+}

+ 65 - 0
fs-service/src/main/java/com/fs/im/mapper/FsImMsgSendDetailMapper.java

@@ -0,0 +1,65 @@
+package com.fs.im.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.im.domain.FsImMsgSendDetail;
+import com.fs.im.vo.FsImMsgSendDetailVO;
+
+/**
+ * openim消息记录详情Mapper接口
+ *
+ * @author fs
+ * @date 2025-08-21
+ */
+public interface FsImMsgSendDetailMapper extends BaseMapper<FsImMsgSendDetail>{
+    /**
+     * 查询openim消息记录详情
+     *
+     * @param logDetailId openim消息记录详情主键
+     * @return openim消息记录详情
+     */
+    FsImMsgSendDetail selectFsImMsgSendDetailByLogDetailId(Long logDetailId);
+
+    /**
+     * 查询openim消息记录详情列表
+     *
+     * @param fsImMsgSendDetail openim消息记录详情
+     * @return openim消息记录详情集合
+     */
+    List<FsImMsgSendDetail> selectFsImMsgSendDetailList(FsImMsgSendDetail fsImMsgSendDetail);
+
+    /**
+     * 新增openim消息记录详情
+     *
+     * @param fsImMsgSendDetail openim消息记录详情
+     * @return 结果
+     */
+    int insertFsImMsgSendDetail(FsImMsgSendDetail fsImMsgSendDetail);
+
+    /**
+     * 修改openim消息记录详情
+     *
+     * @param fsImMsgSendDetail openim消息记录详情
+     * @return 结果
+     */
+    int updateFsImMsgSendDetail(FsImMsgSendDetail fsImMsgSendDetail);
+
+    /**
+     * 删除openim消息记录详情
+     *
+     * @param logDetailId openim消息记录详情主键
+     * @return 结果
+     */
+    int deleteFsImMsgSendDetailByLogDetailId(Long logDetailId);
+
+    /**
+     * 批量删除openim消息记录详情
+     *
+     * @param logDetailIds 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsImMsgSendDetailByLogDetailIds(Long[] logDetailIds);
+
+    List<FsImMsgSendDetailVO> selectSendDetailVOList(Long logId);
+
+}

+ 75 - 0
fs-service/src/main/java/com/fs/im/mapper/FsImMsgSendLogMapper.java

@@ -0,0 +1,75 @@
+package com.fs.im.mapper;
+
+import java.util.List;
+import java.util.Map;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.course.vo.newfs.FsImSendLogVO;
+import com.fs.im.domain.FsImMsgSendLog;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * openim消息记录主Mapper接口
+ *
+ * @author fs
+ * @date 2025-08-21
+ */
+public interface FsImMsgSendLogMapper extends BaseMapper<FsImMsgSendLog>{
+    /**
+     * 查询openim消息记录主
+     *
+     * @param logId openim消息记录主主键
+     * @return openim消息记录主
+     */
+    FsImMsgSendLog selectFsImMsgSendLogByLogId(Long logId);
+
+    /**
+     * 查询openim消息记录主列表
+     *
+     * @param fsImMsgSendLog openim消息记录主
+     * @return openim消息记录主集合
+     */
+    List<FsImMsgSendLog> selectFsImMsgSendLogList(FsImMsgSendLog fsImMsgSendLog);
+
+    /**
+     * 新增openim消息记录主
+     *
+     * @param fsImMsgSendLog openim消息记录主
+     * @return 结果
+     */
+    int insertFsImMsgSendLog(FsImMsgSendLog fsImMsgSendLog);
+
+    /**
+     * 修改openim消息记录主
+     *
+     * @param fsImMsgSendLog openim消息记录主
+     * @return 结果
+     */
+    int updateFsImMsgSendLog(FsImMsgSendLog fsImMsgSendLog);
+
+    /**
+     * 删除openim消息记录主
+     *
+     * @param logId openim消息记录主主键
+     * @return 结果
+     */
+    int deleteFsImMsgSendLogByLogId(Long logId);
+
+    /**
+     * 批量删除openim消息记录主
+     *
+     * @param logIds 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsImMsgSendLogByLogIds(Long[] logIds);
+
+    /**
+     *  查询当前销售的所有发消息任务
+     * @param params 参数
+     * @return
+     */
+    List<FsImSendLogVO> selectFsImSendLogList(@Param("params") Map<String, Object> params);
+
+    List<FsImMsgSendLog> selectSendLogListByDetailId(@Param("params") Map<String, Object> params);
+
+}

+ 70 - 0
fs-service/src/main/java/com/fs/im/mapper/ImSendLogMapper.java

@@ -0,0 +1,70 @@
+package com.fs.im.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.im.domain.ImSendLog;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * openim消息发送记录Mapper接口
+ *
+ * @author fs
+ * @date 2025-08-12
+ */
+public interface ImSendLogMapper extends BaseMapper<ImSendLog>{
+    /**
+     * 查询openim消息发送记录
+     *
+     * @param logId openim消息发送记录主键
+     * @return openim消息发送记录
+     */
+    ImSendLog selectImSendLogByLogId(Long logId);
+
+    /**
+     * 查询openim消息发送记录列表
+     *
+     * @param imSendLog openim消息发送记录
+     * @return openim消息发送记录集合
+     */
+    List<ImSendLog> selectImSendLogList(ImSendLog imSendLog);
+
+    /**
+     * 新增openim消息发送记录
+     *
+     * @param imSendLog openim消息发送记录
+     * @return 结果
+     */
+    int insertImSendLog(ImSendLog imSendLog);
+
+    /**
+     * 修改openim消息发送记录
+     *
+     * @param imSendLog openim消息发送记录
+     * @return 结果
+     */
+    int updateImSendLog(ImSendLog imSendLog);
+
+    /**
+     * 删除openim消息发送记录
+     *
+     * @param logId openim消息发送记录主键
+     * @return 结果
+     */
+    int deleteImSendLogByLogId(Long logId);
+
+    /**
+     * 批量删除openim消息发送记录
+     *
+     * @param logIds 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteImSendLogByLogIds(Long[] logIds);
+
+    /**
+     * 批量新增
+     * @param sendLogs
+     * @return
+     */
+    int insertImSendLogBatch(@Param("sendLogs") List<ImSendLog> sendLogs);
+
+}

+ 61 - 0
fs-service/src/main/java/com/fs/im/service/IFsImMsgSendDetailService.java

@@ -0,0 +1,61 @@
+package com.fs.im.service;
+
+import java.util.List;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.im.domain.FsImMsgSendDetail;
+
+/**
+ * openim消息记录详情Service接口
+ * 
+ * @author fs
+ * @date 2025-08-21
+ */
+public interface IFsImMsgSendDetailService extends IService<FsImMsgSendDetail>{
+    /**
+     * 查询openim消息记录详情
+     * 
+     * @param logDetailId openim消息记录详情主键
+     * @return openim消息记录详情
+     */
+    FsImMsgSendDetail selectFsImMsgSendDetailByLogDetailId(Long logDetailId);
+
+    /**
+     * 查询openim消息记录详情列表
+     * 
+     * @param fsImMsgSendDetail openim消息记录详情
+     * @return openim消息记录详情集合
+     */
+    List<FsImMsgSendDetail> selectFsImMsgSendDetailList(FsImMsgSendDetail fsImMsgSendDetail);
+
+    /**
+     * 新增openim消息记录详情
+     * 
+     * @param fsImMsgSendDetail openim消息记录详情
+     * @return 结果
+     */
+    int insertFsImMsgSendDetail(FsImMsgSendDetail fsImMsgSendDetail);
+
+    /**
+     * 修改openim消息记录详情
+     * 
+     * @param fsImMsgSendDetail openim消息记录详情
+     * @return 结果
+     */
+    int updateFsImMsgSendDetail(FsImMsgSendDetail fsImMsgSendDetail);
+
+    /**
+     * 批量删除openim消息记录详情
+     * 
+     * @param logDetailIds 需要删除的openim消息记录详情主键集合
+     * @return 结果
+     */
+    int deleteFsImMsgSendDetailByLogDetailIds(Long[] logDetailIds);
+
+    /**
+     * 删除openim消息记录详情信息
+     * 
+     * @param logDetailId openim消息记录详情主键
+     * @return 结果
+     */
+    int deleteFsImMsgSendDetailByLogDetailId(Long logDetailId);
+}

+ 94 - 0
fs-service/src/main/java/com/fs/im/service/IFsImMsgSendLogService.java

@@ -0,0 +1,94 @@
+package com.fs.im.service;
+
+import java.util.List;
+import java.util.Map;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.common.core.domain.ResponseResult;
+import com.fs.course.vo.newfs.FsImSendLogVO;
+import com.fs.im.domain.FsImMsgSendLog;
+import com.fs.im.vo.FsImMsgSendLogVO;
+
+/**
+ * openim消息记录主Service接口
+ *
+ * @author fs
+ * @date 2025-08-21
+ */
+public interface IFsImMsgSendLogService extends IService<FsImMsgSendLog>{
+    /**
+     * 查询openim消息记录主
+     *
+     * @param logId openim消息记录主主键
+     * @return openim消息记录主
+     */
+    FsImMsgSendLog selectFsImMsgSendLogByLogId(Long logId);
+
+    /**
+     * 查询openim消息记录主列表
+     *
+     * @param fsImMsgSendLog openim消息记录主
+     * @return openim消息记录主集合
+     */
+    List<FsImMsgSendLog> selectFsImMsgSendLogList(FsImMsgSendLog fsImMsgSendLog);
+
+    /**
+     * 新增openim消息记录主
+     *
+     * @param fsImMsgSendLog openim消息记录主
+     * @return 结果
+     */
+    int insertFsImMsgSendLog(FsImMsgSendLog fsImMsgSendLog);
+
+    /**
+     * 修改openim消息记录主
+     *
+     * @param fsImMsgSendLog openim消息记录主
+     * @return 结果
+     */
+    int updateFsImMsgSendLog(FsImMsgSendLog fsImMsgSendLog);
+
+    /**
+     * 批量删除openim消息记录主
+     *
+     * @param logIds 需要删除的openim消息记录主主键集合
+     * @return 结果
+     */
+    int deleteFsImMsgSendLogByLogIds(Long[] logIds);
+
+    /**
+     * 删除openim消息记录主信息
+     *
+     * @param logId openim消息记录主主键
+     * @return 结果
+     */
+    int deleteFsImMsgSendLogByLogId(Long logId);
+
+    /**
+     * 查询当前销售的所有发消息任务
+     * @return FsImSendLogVO
+     */
+    List<FsImSendLogVO> selectFsImSendLogList(Map<String, Object> params);
+
+    /**
+     * 根据日志详情id获取日志主表信息
+     * @param params 参数
+     * @return
+     */
+    List<FsImMsgSendLog> selectSendLogListByDetailId(Map<String, Object> params);
+
+    /**
+     * 删除消息记录及详情和缓存
+     * @param logId 消息记录id
+     * @return
+     */
+    ResponseResult<Boolean> deleteFsImMsgSendLogAndDetail(Long logId);
+
+    /**
+     * 查询任务详情
+     * @param logId 任务id
+     * @return
+     */
+    FsImMsgSendLogVO selectFsImMsgSendLogDetail(Long logId);
+
+}

+ 61 - 0
fs-service/src/main/java/com/fs/im/service/IImSendLogService.java

@@ -0,0 +1,61 @@
+package com.fs.im.service;
+
+import java.util.List;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.im.domain.ImSendLog;
+
+/**
+ * openim消息发送记录Service接口
+ * 
+ * @author fs
+ * @date 2025-08-12
+ */
+public interface IImSendLogService extends IService<ImSendLog>{
+    /**
+     * 查询openim消息发送记录
+     * 
+     * @param logId openim消息发送记录主键
+     * @return openim消息发送记录
+     */
+    ImSendLog selectImSendLogByLogId(Long logId);
+
+    /**
+     * 查询openim消息发送记录列表
+     * 
+     * @param imSendLog openim消息发送记录
+     * @return openim消息发送记录集合
+     */
+    List<ImSendLog> selectImSendLogList(ImSendLog imSendLog);
+
+    /**
+     * 新增openim消息发送记录
+     * 
+     * @param imSendLog openim消息发送记录
+     * @return 结果
+     */
+    int insertImSendLog(ImSendLog imSendLog);
+
+    /**
+     * 修改openim消息发送记录
+     * 
+     * @param imSendLog openim消息发送记录
+     * @return 结果
+     */
+    int updateImSendLog(ImSendLog imSendLog);
+
+    /**
+     * 批量删除openim消息发送记录
+     * 
+     * @param logIds 需要删除的openim消息发送记录主键集合
+     * @return 结果
+     */
+    int deleteImSendLogByLogIds(Long[] logIds);
+
+    /**
+     * 删除openim消息发送记录信息
+     * 
+     * @param logId openim消息发送记录主键
+     * @return 结果
+     */
+    int deleteImSendLogByLogId(Long logId);
+}

+ 51 - 1
fs-service/src/main/java/com/fs/im/service/OpenIMService.java

@@ -3,6 +3,11 @@ package com.fs.im.service;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fs.common.core.domain.R;
 import com.fs.company.domain.CompanyUser;
+import com.fs.course.dto.BatchSendCourseDTO;
+import com.fs.course.dto.BatchUrgeCourseDTO;
+import com.fs.im.domain.FsImMsgSendDetail;
+import com.fs.im.domain.FsImMsgSendLog;
+import com.fs.im.dto.OpenImBatchMsgDTO;
 import com.fs.im.dto.OpenImEditConversationDTO;
 import com.fs.im.dto.OpenImMsgDTO;
 import com.fs.im.dto.OpenImResponseDTO;
@@ -29,6 +34,51 @@ public interface OpenIMService {
     R accountCheck(String userId, String type);
     void checkAndImportFriend(Long companyUserId,String fsUserId);
     OpenImResponseDTO sendCourse(Long userId,Long companyUserId,String url,String title,String linkImageUrl,String cropId) throws JsonProcessingException;
-    void checkAndImportFriendByDianBo(Long companyUserId,String fsUserId,String cropId);
+    void checkAndImportFriendByDianBo(Long companyUserId,String fsUserId,String cropId, boolean isUpdate);
     OpenImResponseDTO updateUserInfo(CompanyUser companyUser);
+
+    OpenImResponseDTO sendPackageUtil(String sendID, String recvID, Integer contentType, String payloadData,String packageName,String packageId);
+
+    /**
+     * 批量发送消息
+     * @param openImBatchMsgDTO 入参
+     * @return
+     */
+    OpenImResponseDTO openIMBatchSendMsg(OpenImBatchMsgDTO openImBatchMsgDTO);
+
+    /**
+     * 会员批量发课
+     * @param batchSendCourseDTO
+     * @return
+     * @throws JsonProcessingException
+     */
+    OpenImResponseDTO batchSendCourse(BatchSendCourseDTO batchSendCourseDTO) throws JsonProcessingException;
+
+    /**
+     * 会员批量发课-任务
+     * @param batchSendCourseDTO
+     * @param openImBatchMsgDTO
+     * @param project
+     * @param imMsgSendDetailList
+     * @return
+     */
+    OpenImResponseDTO batchSendCourseTask(BatchSendCourseDTO batchSendCourseDTO, OpenImBatchMsgDTO openImBatchMsgDTO, Long project, List<FsImMsgSendDetail> imMsgSendDetailList);
+
+    /**
+     * 会员批量催课-定时任务
+     * @param openImBatchMsgDTO
+     * @param imMsgSendDetailList
+     * @return
+     */
+    OpenImResponseDTO batchUrgeCourseTask(OpenImBatchMsgDTO openImBatchMsgDTO, List<FsImMsgSendDetail> imMsgSendDetailList);
+
+    /**
+     * 会员一键催课
+     * @param batchUrgeCourseDTO
+     * @param fsImMsgSendLog
+     * @return
+     * @throws JsonProcessingException
+     */
+    OpenImResponseDTO batchUrgeCourse(BatchUrgeCourseDTO batchUrgeCourseDTO, FsImMsgSendLog fsImMsgSendLog, String url) throws JsonProcessingException;
+
 }

+ 93 - 0
fs-service/src/main/java/com/fs/im/service/impl/FsImMsgSendDetailServiceImpl.java

@@ -0,0 +1,93 @@
+package com.fs.im.service.impl;
+
+import java.util.List;
+import com.fs.common.utils.DateUtils;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.fs.im.mapper.FsImMsgSendDetailMapper;
+import com.fs.im.domain.FsImMsgSendDetail;
+import com.fs.im.service.IFsImMsgSendDetailService;
+
+/**
+ * openim消息记录详情Service业务层处理
+ * 
+ * @author fs
+ * @date 2025-08-21
+ */
+@Service
+public class FsImMsgSendDetailServiceImpl extends ServiceImpl<FsImMsgSendDetailMapper, FsImMsgSendDetail> implements IFsImMsgSendDetailService {
+
+    /**
+     * 查询openim消息记录详情
+     * 
+     * @param logDetailId openim消息记录详情主键
+     * @return openim消息记录详情
+     */
+    @Override
+    public FsImMsgSendDetail selectFsImMsgSendDetailByLogDetailId(Long logDetailId)
+    {
+        return baseMapper.selectFsImMsgSendDetailByLogDetailId(logDetailId);
+    }
+
+    /**
+     * 查询openim消息记录详情列表
+     * 
+     * @param fsImMsgSendDetail openim消息记录详情
+     * @return openim消息记录详情
+     */
+    @Override
+    public List<FsImMsgSendDetail> selectFsImMsgSendDetailList(FsImMsgSendDetail fsImMsgSendDetail)
+    {
+        return baseMapper.selectFsImMsgSendDetailList(fsImMsgSendDetail);
+    }
+
+    /**
+     * 新增openim消息记录详情
+     * 
+     * @param fsImMsgSendDetail openim消息记录详情
+     * @return 结果
+     */
+    @Override
+    public int insertFsImMsgSendDetail(FsImMsgSendDetail fsImMsgSendDetail)
+    {
+        fsImMsgSendDetail.setCreateTime(DateUtils.getNowDate());
+        return baseMapper.insertFsImMsgSendDetail(fsImMsgSendDetail);
+    }
+
+    /**
+     * 修改openim消息记录详情
+     * 
+     * @param fsImMsgSendDetail openim消息记录详情
+     * @return 结果
+     */
+    @Override
+    public int updateFsImMsgSendDetail(FsImMsgSendDetail fsImMsgSendDetail)
+    {
+        return baseMapper.updateFsImMsgSendDetail(fsImMsgSendDetail);
+    }
+
+    /**
+     * 批量删除openim消息记录详情
+     * 
+     * @param logDetailIds 需要删除的openim消息记录详情主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsImMsgSendDetailByLogDetailIds(Long[] logDetailIds)
+    {
+        return baseMapper.deleteFsImMsgSendDetailByLogDetailIds(logDetailIds);
+    }
+
+    /**
+     * 删除openim消息记录详情信息
+     * 
+     * @param logDetailId openim消息记录详情主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsImMsgSendDetailByLogDetailId(Long logDetailId)
+    {
+        return baseMapper.deleteFsImMsgSendDetailByLogDetailId(logDetailId);
+    }
+}

+ 193 - 0
fs-service/src/main/java/com/fs/im/service/impl/FsImMsgSendLogServiceImpl.java

@@ -0,0 +1,193 @@
+package com.fs.im.service.impl;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.fs.common.core.domain.ResponseResult;
+import com.fs.common.core.redis.RedisCache;
+import com.fs.common.utils.DateUtils;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.course.dto.BatchSendCourseAllDTO;
+import com.fs.course.vo.newfs.FsImSendLogVO;
+import com.fs.im.domain.FsImMsgSendDetail;
+import com.fs.im.mapper.FsImMsgSendDetailMapper;
+import com.fs.im.vo.FsImMsgSendDetailVO;
+import com.fs.im.vo.FsImMsgSendLogVO;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+import com.fs.im.mapper.FsImMsgSendLogMapper;
+import com.fs.im.domain.FsImMsgSendLog;
+import com.fs.im.service.IFsImMsgSendLogService;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * openim消息记录主Service业务层处理
+ *
+ * @author fs
+ * @date 2025-08-21
+ */
+@Service
+public class FsImMsgSendLogServiceImpl extends ServiceImpl<FsImMsgSendLogMapper, FsImMsgSendLog> implements IFsImMsgSendLogService {
+
+    @Autowired
+    private FsImMsgSendDetailMapper fsImMsgSendDetailMapper;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    @Autowired
+    public RedisTemplate redisTemplate;
+
+    /**
+     * 查询openim消息记录主
+     *
+     * @param logId openim消息记录主主键
+     * @return openim消息记录主
+     */
+    @Override
+    public FsImMsgSendLog selectFsImMsgSendLogByLogId(Long logId)
+    {
+        return baseMapper.selectFsImMsgSendLogByLogId(logId);
+    }
+
+    /**
+     * 查询openim消息记录主列表
+     *
+     * @param fsImMsgSendLog openim消息记录主
+     * @return openim消息记录主
+     */
+    @Override
+    public List<FsImMsgSendLog> selectFsImMsgSendLogList(FsImMsgSendLog fsImMsgSendLog)
+    {
+        return baseMapper.selectFsImMsgSendLogList(fsImMsgSendLog);
+    }
+
+    /**
+     * 新增openim消息记录主
+     *
+     * @param fsImMsgSendLog openim消息记录主
+     * @return 结果
+     */
+    @Override
+    public int insertFsImMsgSendLog(FsImMsgSendLog fsImMsgSendLog)
+    {
+        fsImMsgSendLog.setCreateTime(DateUtils.getNowDate());
+        return baseMapper.insertFsImMsgSendLog(fsImMsgSendLog);
+    }
+
+    /**
+     * 修改openim消息记录主
+     *
+     * @param fsImMsgSendLog openim消息记录主
+     * @return 结果
+     */
+    @Override
+    public int updateFsImMsgSendLog(FsImMsgSendLog fsImMsgSendLog)
+    {
+        fsImMsgSendLog.setUpdateTime(DateUtils.getNowDate());
+        return baseMapper.updateFsImMsgSendLog(fsImMsgSendLog);
+    }
+
+    /**
+     * 批量删除openim消息记录主
+     *
+     * @param logIds 需要删除的openim消息记录主主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsImMsgSendLogByLogIds(Long[] logIds)
+    {
+        return baseMapper.deleteFsImMsgSendLogByLogIds(logIds);
+    }
+
+    /**
+     * 删除openim消息记录主信息
+     *
+     * @param logId openim消息记录主主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsImMsgSendLogByLogId(Long logId)
+    {
+        return baseMapper.deleteFsImMsgSendLogByLogId(logId);
+    }
+
+    @Override
+    public List<FsImSendLogVO> selectFsImSendLogList(Map<String, Object> params) {
+        return baseMapper.selectFsImSendLogList(params);
+    }
+
+    @Override
+    public List<FsImMsgSendLog> selectSendLogListByDetailId(Map<String, Object> params) {
+        return baseMapper.selectSendLogListByDetailId(params);
+    }
+
+    @Override
+    @Transactional
+    public ResponseResult<Boolean> deleteFsImMsgSendLogAndDetail(Long logId) {
+        FsImMsgSendLog fsImMsgSendLog = baseMapper.selectFsImMsgSendLogByLogId(logId);
+        if(fsImMsgSendLog == null){
+            return ResponseResult.fail(400, "当前任务不存在");
+        }
+        if(fsImMsgSendLog.getSendStatus() == 1){
+            return ResponseResult.fail(400, "当前任务已完成,不允许删除");
+        }
+
+        // 删除数据
+        Map<String, Object> map = new HashMap<>();
+        map.put("send_union_id", fsImMsgSendLog.getSendUnionId());
+        List<FsImMsgSendLog> fsImMsgSendLogs = baseMapper.selectByMap(map);
+        List<Long> logIds = fsImMsgSendLogs.stream().map(FsImMsgSendLog::getLogId).collect(Collectors.toList());
+        baseMapper.deleteBatchIds(logIds);
+
+        fsImMsgSendDetailMapper.delete(Wrappers.<FsImMsgSendDetail>query().lambda()
+                .in(FsImMsgSendDetail::getLogId, logIds));
+
+        // 删除redis缓存
+//        if(fsImMsgSendLog.getMsgType() == 1){
+            String sendCourseRedisKey = "openIm:batchSendMsg:sendCourse";
+            Map<String, BatchSendCourseAllDTO> sendCourseMap = redisCache.getCacheMap(sendCourseRedisKey);
+
+            if(sendCourseMap != null && !sendCourseMap.isEmpty()){
+                // 组合key
+                if(fsImMsgSendLog.getPlanSendTime() != null) {
+                    String key = fsImMsgSendLog.getCourseId() + ":" + fsImMsgSendLog.getVideoId() + ":" + fsImMsgSendLog.getPlanSendTime().getTime();
+                    redisTemplate.opsForHash().delete(sendCourseRedisKey, key);
+                }
+            }
+//        } else {
+            String urgeCourseRedisKey = "openIm:batchSendMsg:urgeCourse";
+            Map<String, BatchSendCourseAllDTO> urgeCourseMap = redisCache.getCacheMap(urgeCourseRedisKey);
+            if(urgeCourseMap != null && !urgeCourseMap.isEmpty()){
+                // 组合key
+                for (FsImMsgSendLog imMsgSendLog : fsImMsgSendLogs) {
+                    if(imMsgSendLog.getPlanSendTime() != null && imMsgSendLog.getMsgType() == 2) {
+                        String key = imMsgSendLog.getCourseId() + ":" + imMsgSendLog.getVideoId() + ":" + imMsgSendLog.getPlanSendTime().getTime();
+                        redisTemplate.opsForHash().delete(urgeCourseRedisKey, key);
+                    }
+                }
+            }
+//        }
+        return ResponseResult.ok();
+    }
+
+    @Override
+    public FsImMsgSendLogVO selectFsImMsgSendLogDetail(Long logId) {
+        FsImMsgSendLog fsImMsgSendLog = baseMapper.selectFsImMsgSendLogByLogId(logId);
+        FsImMsgSendLogVO fsImMsgSendLogVO = new FsImMsgSendLogVO();
+        BeanUtils.copyProperties(fsImMsgSendLog, fsImMsgSendLogVO);
+
+        List<FsImMsgSendLog> fsImMsgSendLogs = baseMapper.selectList(Wrappers.<FsImMsgSendLog>query().lambda()
+                .eq(FsImMsgSendLog::getSendUnionId, fsImMsgSendLog.getSendUnionId()).eq(FsImMsgSendLog::getMsgType,2));
+        List<String> urgeContents = fsImMsgSendLogs.stream().map(FsImMsgSendLog::getSendTitle).collect(Collectors.toList());
+        fsImMsgSendLogVO.setUrgeContent(urgeContents);
+
+        List<FsImMsgSendDetailVO> fsImMsgSendDetails = fsImMsgSendDetailMapper.selectSendDetailVOList(logId);
+        fsImMsgSendLogVO.setDetailList(fsImMsgSendDetails);
+        return fsImMsgSendLogVO;
+    }
+}

+ 92 - 0
fs-service/src/main/java/com/fs/im/service/impl/ImSendLogServiceImpl.java

@@ -0,0 +1,92 @@
+package com.fs.im.service.impl;
+
+import java.util.List;
+import com.fs.common.utils.DateUtils;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+import com.fs.im.mapper.ImSendLogMapper;
+import com.fs.im.domain.ImSendLog;
+import com.fs.im.service.IImSendLogService;
+
+/**
+ * openim消息发送记录Service业务层处理
+ *
+ * @author fs
+ * @date 2025-08-12
+ */
+@Service
+public class ImSendLogServiceImpl extends ServiceImpl<ImSendLogMapper, ImSendLog> implements IImSendLogService {
+
+    /**
+     * 查询openim消息发送记录
+     *
+     * @param logId openim消息发送记录主键
+     * @return openim消息发送记录
+     */
+    @Override
+    public ImSendLog selectImSendLogByLogId(Long logId)
+    {
+        return baseMapper.selectImSendLogByLogId(logId);
+    }
+
+    /**
+     * 查询openim消息发送记录列表
+     *
+     * @param imSendLog openim消息发送记录
+     * @return openim消息发送记录
+     */
+    @Override
+    public List<ImSendLog> selectImSendLogList(ImSendLog imSendLog)
+    {
+        return baseMapper.selectImSendLogList(imSendLog);
+    }
+
+    /**
+     * 新增openim消息发送记录
+     *
+     * @param imSendLog openim消息发送记录
+     * @return 结果
+     */
+    @Override
+    public int insertImSendLog(ImSendLog imSendLog)
+    {
+        imSendLog.setCreateTime(DateUtils.getNowDate());
+        return baseMapper.insertImSendLog(imSendLog);
+    }
+
+    /**
+     * 修改openim消息发送记录
+     *
+     * @param imSendLog openim消息发送记录
+     * @return 结果
+     */
+    @Override
+    public int updateImSendLog(ImSendLog imSendLog)
+    {
+        return baseMapper.updateImSendLog(imSendLog);
+    }
+
+    /**
+     * 批量删除openim消息发送记录
+     *
+     * @param logIds 需要删除的openim消息发送记录主键
+     * @return 结果
+     */
+    @Override
+    public int deleteImSendLogByLogIds(Long[] logIds)
+    {
+        return baseMapper.deleteImSendLogByLogIds(logIds);
+    }
+
+    /**
+     * 删除openim消息发送记录信息
+     *
+     * @param logId openim消息发送记录主键
+     * @return 结果
+     */
+    @Override
+    public int deleteImSendLogByLogId(Long logId)
+    {
+        return baseMapper.deleteImSendLogByLogId(logId);
+    }
+}

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 679 - 47
fs-service/src/main/java/com/fs/im/service/impl/OpenIMServiceImpl.java


+ 46 - 0
fs-service/src/main/java/com/fs/im/vo/FsImMsgSendDetailVO.java

@@ -0,0 +1,46 @@
+package com.fs.im.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+import java.util.Date;
+
+/**
+ * openim消息记录详情VO
+ *
+ * @author caolq
+ */
+@Data
+@Accessors(chain = true)
+public class FsImMsgSendDetailVO{
+
+    @ApiModelProperty(value = "记录详情id")
+    private Long logDetailId;
+
+    @ApiModelProperty(value = "发课记录主表id")
+    private Long logId;
+
+    @ApiModelProperty(value = "销售id")
+    private Long companyUserId;
+
+    @ApiModelProperty(value = "销售名称")
+    private String companyUserName;
+
+    @ApiModelProperty(value = "用户id")
+    private Long userId;
+
+    @ApiModelProperty(value = "用户名称")
+    private String userName;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "实际发送时间")
+    private Date actualSendTime;
+
+    @ApiModelProperty(value = "发送状态,1-已发送;2-待发送")
+    private Integer sendStatus;
+
+    @ApiModelProperty(value = "执行状态,0-正常;1-失败")
+    private Integer status;
+
+}

+ 70 - 0
fs-service/src/main/java/com/fs/im/vo/FsImMsgSendLogVO.java

@@ -0,0 +1,70 @@
+package com.fs.im.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * openim消息记录主对象VO
+ *
+ * @author caolq
+ */
+@Data
+@Accessors(chain = true)
+public class FsImMsgSendLogVO implements Serializable {
+
+    @ApiModelProperty(value = "发送记录id")
+    private Long logId;
+
+    @ApiModelProperty(value = "课程id")
+    private Long courseId;
+
+    @ApiModelProperty(value = "课程名称")
+    private String courseName;
+
+    @ApiModelProperty(value = "视频id")
+    private Long videoId;
+
+    @ApiModelProperty(value = "视频标题")
+    private String videoName;
+
+    @ApiModelProperty(value = "发课内容")
+    private String sendTitle;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "发送时间")
+    private Date planSendTime;
+
+    @ApiModelProperty(value = "发送类型,1-定时;2-实时")
+    private Integer sendType;
+
+//    @ApiModelProperty(value = "发送状态,1-已发送;2-待发送")
+//    private Integer sendStatus;
+
+    @ApiModelProperty(value = "是否催课,1-是;0-否")
+    private Integer isUrgeCourse;
+
+    @ApiModelProperty(value = "催课内容")
+    private List<String> urgeContent;
+
+//    @ApiModelProperty(value = "消息类型,1-发课;2-催课")
+//    private Integer msgType;
+
+//    @ApiModelProperty(value = "关联id")
+//    private String sendUnionId;
+
+    @ApiModelProperty(value = "关联标签id")
+    private String tagIds;
+
+    @ApiModelProperty(value = "关联标签名称")
+    private String tagNames;
+
+    @ApiModelProperty(value = "任务详情列表")
+    private List<FsImMsgSendDetailVO> detailList;
+
+}

+ 2 - 0
fs-service/src/main/java/com/fs/qw/domain/QwExternalContactInfo.java

@@ -147,4 +147,6 @@ public class QwExternalContactInfo extends BaseEntity
     private String diseaseTalk;
     @Excel(name = "渠道类型")
     private String channelType;
+    @Excel(name = "手机号")
+    private String phone;
 }

+ 6 - 5
fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactMapper.java

@@ -483,11 +483,6 @@ public interface QwExternalContactMapper extends BaseMapper<QwExternalContact> {
 
     List<QwExternalContact> selectExternalByFsUserIds(@Param("userIds")List<Long> userIds);
 
-    List<QwExternalContactComplaintVO> selectFsUserCourseComplaintRecordByUserId(Long userId);
-
-    @Select("select content from fastgpt_chat_artificial_words")
-    List<FastgptChatArtificialWords> selectChatGptChatArtificialWords();
-
     @Select({"<script> " +
             "SELECT qe.remark FROM qw_external_contact qe " +
             "where qe.company_user_id = #{companyUserId} and qe.fs_user_id = #{userId}" +
@@ -495,6 +490,12 @@ public interface QwExternalContactMapper extends BaseMapper<QwExternalContact> {
             "</script>"})
     List<String> selectRemarkByCompanyUserAndFsUser(@Param("userId")String userId,@Param("companyUserId") String companyUserId,@Param("cropId") String cropId);
 
+
+    List<QwExternalContactComplaintVO> selectFsUserCourseComplaintRecordByUserId(Long userId);
+
+    @Select("select content from fastgpt_chat_artificial_words")
+    List<FastgptChatArtificialWords> selectChatGptChatArtificialWords();
+
     List<QwExternalContact> selectQwExternalContactByFsUserId(@Param("userId") Long userId);
 
     int insertQwUserDelLossLog(@Param("param") QwUserDelLossLog qwUserDelLossLog);

+ 9 - 0
fs-service/src/main/java/com/fs/qw/service/IQwExternalContactInfoService.java

@@ -69,4 +69,13 @@ public interface IQwExternalContactInfoService
     int updateQwExternalContactInfoByQwUserId(Long id);
 
     void updateQwExternalContactInfoByExternalContactId(QwExternalContactInfo qwExternalContactInfo);
+
+    /**
+     * 生成初诊单
+     * @param exId 外部联系人id
+     * @param companyUserId 销售id
+     * @param userId 用户id
+     * @return 是否生成初诊单
+     */
+    Boolean generateDiagnosis(Long exId,Long companyUserId,Long userId);
 }

+ 1 - 0
fs-service/src/main/java/com/fs/qw/service/impl/AsyncSopTestService.java

@@ -501,6 +501,7 @@ public class AsyncSopTestService {
     public void  asyncSendMsgBySopAppLink(Long externalId,String linkTile,String linkDescribe,String link){
 //        push2Service.pushSopAppLinkMsgByExternal(externalId,linkTile,linkDescribe,link);
     }
+
     /**
      * 异步录入 发送有app的客户 之 正常sop版
      */

+ 60 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactInfoServiceImpl.java

@@ -1,10 +1,19 @@
 package com.fs.qw.service.impl;
 
+import com.fs.common.exception.CustomException;
 import com.fs.common.utils.DateUtils;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.service.ICompanyUserService;
+import com.fs.his.domain.FsFirstDiagnosis;
+import com.fs.his.domain.FsUser;
+import com.fs.his.mapper.FsFirstDiagnosisMapper;
+import com.fs.his.service.IFsUserService;
 import com.fs.qw.domain.QwExternalContactInfo;
 import com.fs.qw.mapper.QwExternalContactInfoMapper;
 import com.fs.qw.mapper.QwExternalContactMapper;
 import com.fs.qw.service.IQwExternalContactInfoService;
+import lombok.extern.slf4j.Slf4j;
+import org.jetbrains.annotations.NotNull;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
@@ -18,6 +27,7 @@ import java.util.List;
  * @author fs
  * @date 2024-11-22
  */
+@Slf4j
 @Service
 public class QwExternalContactInfoServiceImpl implements IQwExternalContactInfoService
 {
@@ -25,6 +35,12 @@ public class QwExternalContactInfoServiceImpl implements IQwExternalContactInfoS
     private QwExternalContactInfoMapper qwExternalContactInfoMapper;
     @Autowired
     QwExternalContactMapper qwExternalContactMapper;
+    @Autowired
+    private ICompanyUserService companyUserService;
+    @Autowired
+    private IFsUserService userService;
+    @Autowired
+    private FsFirstDiagnosisMapper diagnosisMapper;
     /**
      * 查询外部联系人信息表
      *
@@ -141,4 +157,48 @@ public class QwExternalContactInfoServiceImpl implements IQwExternalContactInfoS
     public void updateQwExternalContactInfoByExternalContactId(QwExternalContactInfo qwExternalContactInfo) {
         qwExternalContactInfoMapper.updateQwExternalContactInfoByExternalContactId(qwExternalContactInfo);
     }
+
+    @Override
+    public Boolean generateDiagnosis(Long exId, Long companyUserId, Long userId) {
+        log.info("生成初诊单参数=============>exId:{},companyUserId:{},userId:{}", exId, companyUserId, userId);
+        if (exId == null || companyUserId == null || userId == null) {
+            throw new CustomException("参数异常");
+        }
+        QwExternalContactInfo qwExternalContactInfo = qwExternalContactInfoMapper.selectQwExternalContactInfoByExternalContactId(exId);
+        if (qwExternalContactInfo == null) {
+            throw new CustomException("外部联系人信息不存在");
+        }
+        log.info("外部联系人信息:{}", qwExternalContactInfo);
+        CompanyUser companyUser = companyUserService.selectCompanyUserById(companyUserId);
+        if (companyUser == null) {
+            throw new CustomException("公司用户信息不存在");
+        }
+        log.info("销售信息:{}", companyUser);
+        FsUser fsUser = userService.selectFsUserByUserId(userId);
+        if (fsUser == null) {
+            throw new CustomException("用户信息不存在");
+        }
+        log.info("用户信息:{}", fsUser);
+        FsFirstDiagnosis diagnosis = getFsFirstDiagnosis(companyUserId, userId, qwExternalContactInfo);
+        int i = diagnosisMapper.insertFsFirstDiagnosis(diagnosis);
+        return i > 0;
+    }
+
+    private static @NotNull FsFirstDiagnosis getFsFirstDiagnosis(Long companyUserId, Long userId, QwExternalContactInfo qwExternalContactInfo) {
+        FsFirstDiagnosis diagnosis = new FsFirstDiagnosis();
+        diagnosis.setUserId(userId);
+        diagnosis.setQwUserId(companyUserId);
+        diagnosis.setAge(qwExternalContactInfo.getAge());
+        long sex = 0L;
+        if ("男".equals(qwExternalContactInfo.getSex())) {
+            sex = 1L;
+        } else if ("女".equals(qwExternalContactInfo.getSex())) {
+            sex = 2L;
+        }
+        diagnosis.setGender(sex);
+        diagnosis.setPhone(qwExternalContactInfo.getPhone());
+        diagnosis.setPatientName(qwExternalContactInfo.getName());
+        diagnosis.setPhysicalCondition(qwExternalContactInfo.getBody());
+        return diagnosis;
+    }
 }

+ 4 - 0
fs-service/src/main/java/com/fs/store/param/h5/FsUserPageListParam.java

@@ -84,6 +84,10 @@ public class FsUserPageListParam implements Serializable {
 
     @ApiModelProperty(value = "状态 0小黑屋 1正常 2拉黑")
     private Integer status;
+    /**
+     * 电话是否隐藏中间部分
+     */
+    private Boolean isHidePhoneMiddle = Boolean.TRUE;
 
 
 }

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů