Explorar el Código

Merge branch 'master' of http://1.14.104.71:10880/root/ylrz_his_scrm_java

15376779826 hace 2 días
padre
commit
0b52c5fc4e
Se han modificado 97 ficheros con 2173 adiciones y 549 borrados
  1. 2 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreAfterSalesScrmController.java
  2. 3 0
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreHealthOrderScrmController.java
  3. 3 0
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java
  4. 7 5
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStorePaymentScrmController.java
  5. 10 6
      fs-admin/src/main/java/com/fs/hisStore/task/LiveTask.java
  6. 6 0
      fs-admin/src/main/java/com/fs/hisStore/task/MallStoreTask.java
  7. 13 0
      fs-admin/src/main/java/com/fs/live/controller/LiveAfterSalesController.java
  8. 59 13
      fs-admin/src/main/java/com/fs/live/controller/LiveOrderController.java
  9. 75 0
      fs-admin/src/main/java/com/fs/qw/qwTask/qwTask.java
  10. 30 39
      fs-admin/src/main/java/com/fs/web/controller/system/SysConfigController.java
  11. 5 0
      fs-company/src/main/java/com/fs/company/controller/qw/SopUserLogsController.java
  12. 1 6
      fs-doctor-app/src/main/java/com/fs/app/controller/FsUserInformationCollectionController.java
  13. 45 13
      fs-ipad-task/src/main/java/com/fs/app/service/IpadSendServer.java
  14. 2 1
      fs-quartz/src/main/java/com/fs/quartz/config/ScheduleConfig.java
  15. 76 3
      fs-qw-task/src/main/java/com/fs/app/controller/CommonController.java
  16. 4 1
      fs-service/src/main/java/com/fs/company/mapper/CompanyMapper.java
  17. 5 0
      fs-service/src/main/java/com/fs/company/vo/CompanyVO.java
  18. 19 0
      fs-service/src/main/java/com/fs/course/config/RandomRedPacketConfig.java
  19. 28 0
      fs-service/src/main/java/com/fs/course/config/RandomRedPacketRule.java
  20. 6 0
      fs-service/src/main/java/com/fs/course/domain/FsUserCourseVideo.java
  21. 1 1
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java
  22. 2 0
      fs-service/src/main/java/com/fs/course/service/IFsCoursePlaySourceConfigService.java
  23. 0 5
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseLinkServiceImpl.java
  24. 6 0
      fs-service/src/main/java/com/fs/course/service/impl/FsCoursePlaySourceConfigServiceImpl.java
  25. 2 1
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseProductOrderServiceImpl.java
  26. 9 0
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java
  27. 313 3
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  28. 6 0
      fs-service/src/main/java/com/fs/course/vo/FsUserCourseVideoQVO.java
  29. 4 0
      fs-service/src/main/java/com/fs/erp/dto/sdk/df/DfClient.java
  30. 48 0
      fs-service/src/main/java/com/fs/erp/service/impl/DfOrderServiceImpl.java
  31. 6 4
      fs-service/src/main/java/com/fs/erp/service/impl/JSTErpOrderServiceImpl.java
  32. 2 0
      fs-service/src/main/java/com/fs/his/service/IFsUserInformationCollectionService.java
  33. 8 2
      fs-service/src/main/java/com/fs/his/service/impl/FsPrescribeServiceImpl.java
  34. 27 0
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreOrderServiceImpl.java
  35. 36 0
      fs-service/src/main/java/com/fs/his/service/impl/FsUserInformationCollectionServiceImpl.java
  36. 20 0
      fs-service/src/main/java/com/fs/his/utils/IdCardUtil.java
  37. 2 0
      fs-service/src/main/java/com/fs/his/vo/FsUserInformationCollectionAndPatientVO.java
  38. 3 1
      fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreOrderItemScrmMapper.java
  39. 3 0
      fs-service/src/main/java/com/fs/hisStore/param/FsStoreOrderParam.java
  40. 2 1
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreAfterSalesScrmServiceImpl.java
  41. 6 5
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java
  42. 3 0
      fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderItemExportVO.java
  43. 4 0
      fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderVO.java
  44. 2 0
      fs-service/src/main/java/com/fs/live/domain/Live.java
  45. 3 0
      fs-service/src/main/java/com/fs/live/mapper/LiveCouponMapper.java
  46. 4 1
      fs-service/src/main/java/com/fs/live/mapper/LiveOrderMapper.java
  47. 21 0
      fs-service/src/main/java/com/fs/live/param/LiveNotifyParam.java
  48. 3 0
      fs-service/src/main/java/com/fs/live/param/LiveOrderParam.java
  49. 7 0
      fs-service/src/main/java/com/fs/live/service/ILiveAutoTaskService.java
  50. 3 1
      fs-service/src/main/java/com/fs/live/service/ILiveOrderService.java
  51. 2 1
      fs-service/src/main/java/com/fs/live/service/ILiveService.java
  52. 14 5
      fs-service/src/main/java/com/fs/live/service/impl/LiveAfterSalesServiceImpl.java
  53. 242 4
      fs-service/src/main/java/com/fs/live/service/impl/LiveAutoTaskServiceImpl.java
  54. 52 0
      fs-service/src/main/java/com/fs/live/service/impl/LiveCouponIssueServiceImpl.java
  55. 84 4
      fs-service/src/main/java/com/fs/live/service/impl/LiveCouponServiceImpl.java
  56. 43 0
      fs-service/src/main/java/com/fs/live/service/impl/LiveGoodsServiceImpl.java
  57. 36 0
      fs-service/src/main/java/com/fs/live/service/impl/LiveLotteryConfServiceImpl.java
  58. 63 13
      fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java
  59. 36 0
      fs-service/src/main/java/com/fs/live/service/impl/LiveRedConfServiceImpl.java
  60. 23 13
      fs-service/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java
  61. 4 0
      fs-service/src/main/java/com/fs/live/vo/LiveOrderVO.java
  62. 3 0
      fs-service/src/main/java/com/fs/live/vo/LiveOrderVoZm.java
  63. 2 0
      fs-service/src/main/java/com/fs/live/vo/LiveVo.java
  64. 1 0
      fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java
  65. 5 0
      fs-service/src/main/java/com/fs/qw/param/FsUserCourseRedPageParam.java
  66. 2 2
      fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java
  67. 3 0
      fs-service/src/main/java/com/fs/sop/service/IQwSopTempContentService.java
  68. 11 0
      fs-service/src/main/java/com/fs/sop/service/IQwSopTempDayService.java
  69. 5 0
      fs-service/src/main/java/com/fs/sop/service/IQwSopTempRulesService.java
  70. 2 0
      fs-service/src/main/java/com/fs/sop/service/ISopUserLogsService.java
  71. 7 0
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempContentServiceImpl.java
  72. 23 0
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempDayServiceImpl.java
  73. 13 0
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempRulesServiceImpl.java
  74. 60 45
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempServiceImpl.java
  75. 2 2
      fs-service/src/main/java/com/fs/sop/service/impl/SopUserLogsInfoServiceImpl.java
  76. 147 91
      fs-service/src/main/java/com/fs/sop/service/impl/SopUserLogsServiceImpl.java
  77. 7 0
      fs-service/src/main/resources/application-config-dev-jnlzjk.yml
  78. 15 11
      fs-service/src/main/resources/application-config-druid-bjczwh.yml
  79. 6 0
      fs-service/src/main/resources/application-config-druid-hzyy.yml
  80. 3 0
      fs-service/src/main/resources/application-dev.yml
  81. 159 150
      fs-service/src/main/resources/application-druid-bjczwh.yml
  82. 3 0
      fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml
  83. 1 1
      fs-service/src/main/resources/mapper/course/FsUserCourseTrainingCampMapper.xml
  84. 3 0
      fs-service/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml
  85. 2 1
      fs-service/src/main/resources/mapper/his/FsUserInformationCollectionMapper.xml
  86. 1 1
      fs-service/src/main/resources/mapper/his/FsUserMapper.xml
  87. 24 3
      fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml
  88. 19 7
      fs-service/src/main/resources/mapper/live/LiveOrderMapper.xml
  89. 5 0
      fs-service/src/main/resources/mapper/qw/QwUserMapper.xml
  90. 2 0
      fs-service/src/main/resources/mapper/sop/SopUserLogsMapper.xml
  91. 2 18
      fs-user-app/src/main/java/com/fs/app/controller/CompanyUserController.java
  92. 5 38
      fs-user-app/src/main/java/com/fs/app/controller/FsUserInformationCollectionController.java
  93. 2 2
      fs-user-app/src/main/java/com/fs/app/controller/UserController.java
  94. 3 2
      fs-user-app/src/main/java/com/fs/app/controller/live/LiveController.java
  95. 38 0
      fs-user-app/src/main/java/com/fs/app/controller/store/IndexScrmController.java
  96. 12 1
      fs-user-app/src/main/java/com/fs/app/controller/store/UserScrmController.java
  97. 21 21
      fs-user-app/src/main/java/com/fs/app/param/FsUserEditParam.java

+ 2 - 1
fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreAfterSalesScrmController.java

@@ -9,6 +9,7 @@ import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.framework.web.service.TokenService;
 import com.fs.his.domain.FsUser;
@@ -79,7 +80,7 @@ public class FsStoreAfterSalesScrmController extends BaseController
     @GetMapping("/export")
     public AjaxResult export(FsStoreAfterSalesScrm fsStoreAfterSales)
     {
-        if (fsStoreAfterSales.getBeginTime().equals("") && fsStoreAfterSales.getEndTime().equals("")){
+        if (StringUtils.isNotEmpty(fsStoreAfterSales.getBeginTime()) && StringUtils.isNotEmpty(fsStoreAfterSales.getEndTime())){
             fsStoreAfterSales.setBeginTime(null);
             fsStoreAfterSales.setEndTime(null);
         }

+ 3 - 0
fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreHealthOrderScrmController.java

@@ -121,6 +121,7 @@ public class FsStoreHealthOrderScrmController extends BaseController {
                     vo.setPayDelivery(BigDecimal.ZERO);
                     vo.setBarCode("");
                     vo.setCateName("");
+                    vo.setBankTransactionId("");
                 }
 
             }
@@ -308,6 +309,7 @@ public class FsStoreHealthOrderScrmController extends BaseController {
                     vo.setFPrice(BigDecimal.ZERO);
                     vo.setBarCode("");
                     vo.setCateName("");
+                    vo.setBankTransactionId("");
                 }
             }
         }
@@ -359,6 +361,7 @@ public class FsStoreHealthOrderScrmController extends BaseController {
                     vo.setFPrice(BigDecimal.ZERO);
                     vo.setBarCode("");
                     vo.setCateName("");
+                    vo.setBankTransactionId("");
                 }
             }
         }

+ 3 - 0
fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java

@@ -217,6 +217,7 @@ public class FsStoreOrderScrmController extends BaseController {
                     vo.setPayDelivery(BigDecimal.ZERO);
                     vo.setBarCode("");
                     vo.setCateName("");
+                    vo.setBankTransactionId("");
                 }
             }
         }
@@ -473,6 +474,7 @@ public class FsStoreOrderScrmController extends BaseController {
                     vo.setFPrice(BigDecimal.ZERO);
                     vo.setBarCode("");
                     vo.setCateName("");
+                    vo.setBankTransactionId("");
                 }
             }
         }
@@ -528,6 +530,7 @@ public class FsStoreOrderScrmController extends BaseController {
                     vo.setFPrice(BigDecimal.ZERO);
                     vo.setBarCode("");
                     vo.setCateName("");
+                    vo.setBankTransactionId("");
                 }
             }
         }

+ 7 - 5
fs-admin/src/main/java/com/fs/hisStore/controller/FsStorePaymentScrmController.java

@@ -194,11 +194,11 @@ public class FsStorePaymentScrmController extends BaseController
 
         if(payment.getPayTypeCode().equals("weixin")){
             String json;
-            if (CloudHostUtils.hasCloudHostName("康年堂")){
+//            if (CloudHostUtils.hasCloudHostName("康年堂")){
                 json = configService.selectConfigByKey("his.pay");
-            } else {
-                json = configService.selectConfigByKey("store.pay");
-            }
+//            } else {
+//                json = configService.selectConfigByKey("store.pay");
+//            }
             if (StringUtils.isBlank(json)) {
                 return R.error("缺少支付相关配置");
             }
@@ -226,6 +226,7 @@ public class FsStorePaymentScrmController extends BaseController
                 Map<String, Object> extendInfoMap = new HashMap<>();
                 extendInfoMap.put("org_party_order_id", payment.getBankSerialNo());
                 request.setExtendInfo(extendInfoMap);
+                logger.info("请求参数:"+request);
                 HuiFuRefundResult refund = huiFuService.refund(request);
                 logger.info("退款:"+refund);
                 if((refund.getResp_code().equals("00000000")||refund.getResp_code().equals("00000100"))&&(refund.getTrans_stat().equals("S")||refund.getTrans_stat().equals("P"))){
@@ -243,7 +244,8 @@ public class FsStorePaymentScrmController extends BaseController
                     return R.error(refund.getResp_desc());
                 }
 
-            }else if (payment.getPayMode()!=null&&payment.getPayMode().equals("wx")){
+            }
+            else if (payment.getPayMode()!=null&&payment.getPayMode().equals("wx")){
 
             }
 

+ 10 - 6
fs-admin/src/main/java/com/fs/hisStore/task/LiveTask.java

@@ -150,10 +150,14 @@ public class LiveTask {
     private JdbcTemplate jdbcTemplate;
 
     public void PushErp() throws ParseException {
-//        List<Long> ids = liveOrderMapper.selectOrderIdByNoErp();
-//        for (Long id : ids) {
-//            liveOrderService.createOmsOrder(id);
-//        }
+        List<Long> ids = liveOrderMapper.selectOrderIdByNoErp();
+        if(ids == null) return;
+        if (ids.size() > 50) {
+            ids = ids.subList(0, 50);
+        }
+        for (Long id : ids) {
+            liveOrderService.createOmsOrder(id);
+        }
     }
 
     public void redPacketSubMoney() throws Exception {
@@ -182,8 +186,8 @@ public class LiveTask {
     public void deliveryOp() {
         List<LiveOrder> list = liveOrderService.selectUpdateExpress();
         if(list == null || list.isEmpty()) return;
-        if (list.size() > 100) {
-            list = list.subList(0, 100);
+        if (list.size() > 50) {
+            list = list.subList(0, 50);
         }
         for (LiveOrder order : list) {
             ErpOrderQueryRequert request = new ErpOrderQueryRequert();

+ 6 - 0
fs-admin/src/main/java/com/fs/hisStore/task/MallStoreTask.java

@@ -165,6 +165,9 @@ public class MallStoreTask
         } else {
             ids = fsStoreOrderMapper.selectFsStoreOrderNoCreateOms();
         }
+        if (!ids.isEmpty() && ids.size() > 50) {
+            ids = ids.subList(0, 50);
+        }
         for (Long id : ids) {
             fsStoreOrderService.createOmsOrder(id);
         }
@@ -204,6 +207,9 @@ public class MallStoreTask
     public void deliveryOp()
     {
         List<FsStoreOrderScrm> list = fsStoreOrderMapper.selectUpdateExpress();
+        if (list != null && list.size() > 50) {
+            list = list.subList(0, 50);
+        }
         for (FsStoreOrderScrm order : list){
             ErpOrderQueryRequert request = new ErpOrderQueryRequert();
             request.setCode(order.getExtendOrderId());

+ 13 - 0
fs-admin/src/main/java/com/fs/live/controller/LiveAfterSalesController.java

@@ -1,5 +1,6 @@
 package com.fs.live.controller;
 
+import cn.hutool.core.date.DateTime;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
@@ -11,7 +12,9 @@ import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.framework.web.service.TokenService;
+import com.fs.his.domain.FsStoreAfterSalesLogs;
 import com.fs.his.domain.FsUser;
+import com.fs.his.enums.FsStoreAfterSalesStatusEnum;
 import com.fs.his.service.IFsUserService;
 import com.fs.live.domain.LiveAfterSales;
 import com.fs.live.domain.LiveAfterSalesItem;
@@ -130,6 +133,16 @@ public class LiveAfterSalesController extends BaseController
     @PutMapping
     public AjaxResult edit(@RequestBody LiveAfterSales liveAfterSales)
     {
+
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        //操作记录
+        LiveAfterSalesLogs logs = new LiveAfterSalesLogs();
+        logs.setChangeTime(new DateTime());
+        logs.setChangeType(2);
+        logs.setOperator(loginUser.getUser().getNickName());
+        logs.setStoreAfterSalesId(liveAfterSales.getId());
+        logs.setChangeMessage(FsStoreAfterSalesStatusEnum.STATUS_2.getDesc());
+        liveAfterSalesLogsService.insertLiveAfterSalesLogs(logs);
         return toAjax(liveAfterSalesService.updateLiveAfterSales(liveAfterSales));
     }
 

+ 59 - 13
fs-admin/src/main/java/com/fs/live/controller/LiveOrderController.java

@@ -31,6 +31,8 @@ import com.fs.his.enums.FsStoreOrderLogEnum;
 import com.fs.his.service.IFsDfAccountService;
 import com.fs.his.service.IFsExpressService;
 import com.fs.his.service.IFsUserService;
+import com.fs.his.utils.ConfigUtil;
+import com.fs.hisStore.config.FsErpConfig;
 import com.fs.hisStore.dto.StoreOrderExpressExportDTO;
 import com.fs.hisStore.param.*;
 import com.fs.hisStore.service.IFsExpressScrmService;
@@ -116,6 +118,27 @@ public class LiveOrderController extends BaseController
 
     @Autowired
     private LiveTask liveTask;
+    @Autowired
+    @Qualifier("erpOrderServiceImpl")
+    private IErpOrderService gyOrderService;
+
+    @Autowired
+    @Qualifier("wdtErpOrderServiceImpl")
+    private IErpOrderService wdtOrderService;
+    @Autowired
+    @Qualifier("hzOMSErpOrderServiceImpl")
+    private IErpOrderService hzOMSErpOrderService;
+    @Autowired
+    @Qualifier("dfOrderServiceImpl")
+    private IErpOrderService dfOrderService;
+    @Autowired
+    @Qualifier("k9OrderScrmServiceImpl")
+    private IErpOrderService k9OrderService;
+    @Autowired
+    @Qualifier("JSTErpOrderServiceImpl")
+    private IErpOrderService jSTOrderService;
+    @Autowired
+    private ConfigUtil configUtil;
 
 
 
@@ -181,6 +204,7 @@ public class LiveOrderController extends BaseController
                 vo.setPayDelivery(BigDecimal.ZERO);
                 vo.setBarCode("");
                 vo.setCateName("");
+                vo.setBankTransactionId("");
             }
             vo.setCost(vo.getCostPrice());
 
@@ -205,11 +229,12 @@ public class LiveOrderController extends BaseController
             vo.setUserAddress(ParseUtils.parseAddress(vo.getUserAddress()));
             // 财务独特字段
             if (loginUser.getPermissions().contains("live:liveOrder:finance") || loginUser.getPermissions().contains("*:*:*")) {
-                vo.setCostPrice(vo.getCostPrice());
+                vo.setCostPrice(vo.getCost());
                 vo.setFPrice(vo.getCostPrice().multiply(BigDecimal.valueOf(Long.parseLong(vo.getTotalNum()))));
             } else {
                 vo.setCostPrice(BigDecimal.ZERO);
                 vo.setFPrice(BigDecimal.ZERO);
+                vo.setBankTransactionId("");
             }
             vo.setCost(vo.getCostPrice());
         }
@@ -435,20 +460,41 @@ public class LiveOrderController extends BaseController
     @PreAuthorize("@ss.hasPermi('live:liveOrder:getEroOrder')")
     @GetMapping("/getEroOrder")
     public R getEroOrder(@RequestParam("extendOrderId") String extendOrderId) {
+        IErpOrderService erpOrderService = getErpService();
         ErpOrderQueryRequert request = new ErpOrderQueryRequert();
         request.setCode(extendOrderId);
-        if(StringUtils.isEmpty(extendOrderId)) return R.error("物流订单ID为空!");
-
-        LiveOrder order = liveOrderService.selectLiveOrderByExtendId(extendOrderId);
-
-        // 根据仓库code找erp
-//        if(com.fs.common.utils.StringUtils.isNotBlank(order.getStoreHouseCode())){
-//            String erp = fsWarehousesMapper.selectErpByCode(order.getStoreHouseCode());
-//            ErpContextHolder.setErpType(erp);
-//        }
-
-//        ErpOrderQueryResponse response = erpOrderService.getOrderLive(request);
-        return R.ok().put("data","123");
+        ErpOrderQueryResponse response = erpOrderService.getLiveOrder(request);
+        return R.ok().put("data",response);
+    }
+    private IErpOrderService getErpService(){
+        //判断是否开启erp
+        IErpOrderService erpOrderService = null;
+        FsErpConfig erpConfig = configUtil.getErpConfig();
+        Integer erpOpen = erpConfig.getErpOpen();
+        if (erpOpen != null && erpOpen == 1) {
+            //判断erp类型
+            Integer erpType = erpConfig.getErpType();
+            if (erpType != null) {
+                if (erpType == 1){
+                    //管易
+                    erpOrderService =  gyOrderService;
+                } else if (erpType == 2){
+                    //旺店通
+                    erpOrderService =  wdtOrderService;
+                } else if (erpType == 3){
+                    //
+                    erpOrderService =  hzOMSErpOrderService;
+                } else if (erpType == 4){
+                    //代服
+                    erpOrderService =  dfOrderService;
+                }else if(erpType == 5){
+                    erpOrderService=jSTOrderService;
+                }else if(erpType == 6){
+                    erpOrderService=k9OrderService;
+                }
+            }
+        }
+        return erpOrderService;
     }
 
     @Log(title = "冻结、解冻佣金", businessType = BusinessType.UPDATE)

+ 75 - 0
fs-admin/src/main/java/com/fs/qw/qwTask/qwTask.java

@@ -1,17 +1,24 @@
 package com.fs.qw.qwTask;
 
 import com.fs.course.service.IFsUserCourseService;
+import com.fs.qw.domain.QwIpadServerLog;
+import com.fs.qw.domain.QwUser;
+import com.fs.qw.mapper.QwUserMapper;
 import com.fs.qw.service.*;
 import com.fs.sop.service.impl.QwSopLogsServiceImpl;
 import com.fs.sop.service.impl.QwSopServiceImpl;
 import com.fs.sop.service.ISopUserLogsService;
 import com.fs.statis.IFsStatisQwWatchService;
 import com.fs.statis.service.FsStatisSalerWatchService;
+import com.fs.wxwork.dto.WxWorkGetQrCodeDTO;
+import com.fs.wxwork.service.WxWorkService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
+import java.util.Date;
+import java.util.List;
 
 @Component("qwTask")
 public class qwTask {
@@ -47,6 +54,23 @@ public class qwTask {
     private IQwMaterialService iQwMaterialService;
 
 
+    @Autowired
+    private QwUserMapper qwUserMapper;
+
+    @Autowired
+    private IQwIpadServerService ipadServerService;
+
+    @Autowired
+    private IQwIpadServerLogService qwIpadServerLogService;
+
+    @Autowired
+    private IQwIpadServerUserService qwIpadServerUserService;
+
+    @Autowired
+    private IQwExternalContactService externalContactService;
+
+    @Autowired
+    private WxWorkService wxWorkService;
 
 
     //正在使用
@@ -211,4 +235,55 @@ public class qwTask {
 
 
     }
+
+    /**
+     * 定时清除 占着茅坑不拉屎的ipad 账号
+     */
+    public void selectQwUserByUnbindIpad(){
+        List<QwUser> list = qwUserMapper.selectQwUserByTest();
+        for (QwUser qwUser : list) {
+            try {
+                Integer serverStatus = qwUser.getServerStatus();
+                Long serverId = qwUser.getServerId();
+                if (serverStatus==0){
+                    System.out.println("不需要解绑");
+                }
+                if (serverId==null){
+                    System.out.println("serverId不存在");
+                }
+                QwUser u = new QwUser();
+                u.setId(qwUser.getId());
+                u.setServerId(null);
+                u.setServerStatus(0);
+                qwUserMapper.updateQwUser(u);
+                ipadServerService.addServer(serverId);
+                QwIpadServerLog qwIpadServerLog = new QwIpadServerLog();
+                qwIpadServerLog.setType(2);
+                qwIpadServerLog.setTilie("解绑");
+                qwIpadServerLog.setServerId(serverId);
+                qwIpadServerLog.setQwUserId(qwUser.getId());
+                qwIpadServerLog.setCompanyUserId(qwUser.getCompanyUserId());
+                qwIpadServerLog.setCompanyId(qwUser.getCompanyId());
+                qwIpadServerLog.setCreateTime(new Date());
+                qwIpadServerLogService.insertQwIpadServerLog(qwIpadServerLog);
+                qwIpadServerUserService.deleteQwIpadServerUserByQwUserId(qwUser.getId());
+                WxWorkGetQrCodeDTO wxWorkGetQrCodeDTO = new WxWorkGetQrCodeDTO();
+                wxWorkGetQrCodeDTO.setUuid(qwUser.getUid());
+                wxWorkService.LoginOut(wxWorkGetQrCodeDTO,qwUser.getServerId());
+                updateIpadStatus(qwUser.getId(),0);
+            } catch (Exception e) {
+                System.out.println("解绑ipad报错"+e);
+
+            }
+        }
+    }
+
+
+    void updateIpadStatus(Long id ,Integer status){
+        QwUser u = new QwUser();
+        u.setId(id);
+        u.setIpadStatus(status);
+        qwUserMapper.updateQwUser(u);
+    }
+
 }

+ 30 - 39
fs-admin/src/main/java/com/fs/web/controller/system/SysConfigController.java

@@ -30,13 +30,10 @@ import com.fs.system.service.ISysConfigService;
 
 /**
  * 参数配置 信息操作处理
- *
-
  */
 @RestController
 @RequestMapping("/system/config")
-public class SysConfigController extends BaseController
-{
+public class SysConfigController extends BaseController {
     @Autowired
     private ISysConfigService configService;
     @Autowired
@@ -47,8 +44,7 @@ public class SysConfigController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:config:list')")
     @GetMapping("/list")
-    public TableDataInfo list(SysConfig config)
-    {
+    public TableDataInfo list(SysConfig config) {
         startPage();
         List<SysConfig> list = configService.selectConfigList(config);
         return getDataTable(list);
@@ -57,8 +53,7 @@ public class SysConfigController extends BaseController
     @Log(title = "参数管理", businessType = BusinessType.EXPORT)
     @PreAuthorize("@ss.hasPermi('system:config:export')")
     @GetMapping("/export")
-    public AjaxResult export(SysConfig config)
-    {
+    public AjaxResult export(SysConfig config) {
         List<SysConfig> list = configService.selectConfigList(config);
         ExcelUtil<SysConfig> util = new ExcelUtil<SysConfig>(SysConfig.class);
         return util.exportExcel(list, "参数数据");
@@ -69,8 +64,7 @@ public class SysConfigController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:config:query')")
     @GetMapping(value = "/{configId}")
-    public AjaxResult getInfo(@PathVariable Long configId)
-    {
+    public AjaxResult getInfo(@PathVariable Long configId) {
         return AjaxResult.success(configService.selectConfigById(configId));
     }
 
@@ -78,8 +72,7 @@ public class SysConfigController extends BaseController
      * 根据参数键名查询参数值
      */
     @GetMapping(value = "/configKey/{configKey}")
-    public AjaxResult getConfigKey(@PathVariable String configKey)
-    {
+    public AjaxResult getConfigKey(@PathVariable String configKey) {
         return AjaxResult.success(configService.selectConfigByKey(configKey));
     }
 
@@ -90,10 +83,8 @@ public class SysConfigController extends BaseController
     @Log(title = "参数管理", businessType = BusinessType.INSERT)
     @PostMapping
     @RepeatSubmit
-    public AjaxResult add(@Validated @RequestBody SysConfig config)
-    {
-        if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config)))
-        {
+    public AjaxResult add(@Validated @RequestBody SysConfig config) {
+        if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) {
             return AjaxResult.error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
         }
         config.setCreateBy(getUsername());
@@ -106,10 +97,8 @@ public class SysConfigController extends BaseController
     @PreAuthorize("@ss.hasPermi('system:config:edit')")
     @Log(title = "参数管理", businessType = BusinessType.UPDATE)
     @PutMapping
-    public AjaxResult edit(@Validated @RequestBody SysConfig config)
-    {
-        if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config)))
-        {
+    public AjaxResult edit(@Validated @RequestBody SysConfig config) {
+        if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) {
             return AjaxResult.error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
         }
         config.setUpdateBy(getUsername());
@@ -122,8 +111,7 @@ public class SysConfigController extends BaseController
     @PreAuthorize("@ss.hasPermi('system:config:remove')")
     @Log(title = "参数管理", businessType = BusinessType.DELETE)
     @DeleteMapping("/{configIds}")
-    public AjaxResult remove(@PathVariable Long[] configIds)
-    {
+    public AjaxResult remove(@PathVariable Long[] configIds) {
         configService.deleteConfigByIds(configIds);
         return success();
     }
@@ -134,50 +122,53 @@ public class SysConfigController extends BaseController
     @PreAuthorize("@ss.hasPermi('system:config:remove')")
     @Log(title = "参数管理", businessType = BusinessType.CLEAN)
     @DeleteMapping("/refreshCache")
-    public AjaxResult refreshCache()
-    {
+    public AjaxResult refreshCache() {
         configService.resetConfigCache();
         return AjaxResult.success();
     }
 
     @GetMapping(value = "/getConfigByKey/{configKey}")
-    public AjaxResult getConfigByKey(@PathVariable String configKey)
-    {
-        SysConfig config=configService.selectConfigByConfigKey(configKey);
+    public AjaxResult getConfigByKey(@PathVariable String configKey) {
+        SysConfig config = configService.selectConfigByConfigKey(configKey);
         return AjaxResult.success(config);
     }
 
     @PostMapping(value = "/updateConfigByKey")
     @Log(title = "更改参数", businessType = BusinessType.UPDATE)
     @RepeatSubmit
-    public AjaxResult updateConfigByKey(@Validated @RequestBody SysConfig config)
-    {
+    public AjaxResult updateConfigByKey(@Validated @RequestBody SysConfig config) {
         config.setCreateBy(SecurityUtils.getUsername());
-        return toAjax(configService.updateConfig(config));
+        //修复只能更新的BUG
+        if (null != config.getConfigId()) {
+            return toAjax(configService.updateConfig(config));
+        } else {
+            return toAjax(configService.insertConfig(config));
+        }
+
     }
 
 
     /**
      * 启用-关闭小程序销售管理
+     *
      * @param bock
      * @return
      */
     @GetMapping("/updateIsTownOn")
-    public R queryIsTownOn(String bock, String appId)
-    {
-        String key = appId+"start_status_001";
+    public R queryIsTownOn(String bock, String appId) {
+        String key = appId + "start_status_001";
         String start = redisCache.getCacheObject(key);
-        if (ObjectUtil.isNotEmpty(bock)){
-            if (bock.equals("001")){
-                redisCache.setCacheObject(key,bock);
+        if (ObjectUtil.isNotEmpty(bock)) {
+            if (bock.equals("001")) {
+                redisCache.setCacheObject(key, bock);
                 return R.ok("调整成功");
-            }else if (bock.equals("002")){
-                redisCache.setCacheObject(key,bock);
+            } else if (bock.equals("002")) {
+                redisCache.setCacheObject(key, bock);
                 return R.ok("调整成功");
             }
 
         }
-        return R.ok().put("date",start);
+        return R.ok().put("date", start);
     }
 
 }

+ 5 - 0
fs-company/src/main/java/com/fs/company/controller/qw/SopUserLogsController.java

@@ -195,4 +195,9 @@ public class SopUserLogsController extends BaseController
         sopUserLogsService.replaceUser(vo);
         return R.ok();
     }
+
+    @GetMapping("/getShortLink")
+    public R getShortLink(String id, String sopId, String appId){
+        return sopUserLogsService.getShortLink(id, sopId, appId);
+    }
 }

+ 1 - 6
fs-doctor-app/src/main/java/com/fs/app/controller/FsUserInformationCollectionController.java

@@ -2,11 +2,8 @@ package com.fs.app.controller;
 
 import com.fs.common.core.domain.R;
 import com.fs.his.domain.FsUserInformationCollection;
-import com.fs.his.dto.FsUserInformationCollectionDTO;
-import com.fs.his.param.CollectionInfoConfirmParam;
 import com.fs.his.param.UserInformationDoctorType2Param;
 import com.fs.his.service.IFsUserInformationCollectionService;
-import com.fs.his.vo.FsInquiryOrderListPDVO;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -21,10 +18,8 @@ public class FsUserInformationCollectionController extends  AppBaseController {
     private IFsUserInformationCollectionService fsUserInformationCollectionService;
     @GetMapping("/getUserInformation")
     public R getUserInformation(@RequestParam("id") Long id) {
-        FsUserInformationCollectionDTO fsUserInformationCollection = fsUserInformationCollectionService.selectFsUserInformationCollectionDTOById(id);
 
-
-        return R.ok().put("data", fsUserInformationCollection);
+        return R.ok().put("data", fsUserInformationCollectionService.selectFsUserInformationCollectionVoById(id));
     }
     //医生确认
     @PostMapping("/doctorConfirm")

+ 45 - 13
fs-ipad-task/src/main/java/com/fs/app/service/IpadSendServer.java

@@ -12,6 +12,8 @@ import com.fs.company.domain.CompanyMiniapp;
 import com.fs.company.service.ICompanyMiniappService;
 import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.domain.FsCourseWatchLog;
+import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
+import com.fs.course.service.IFsCoursePlaySourceConfigService;
 import com.fs.course.service.IFsCourseWatchLogService;
 import com.fs.his.domain.FsUser;
 import com.fs.his.mapper.FsUserMapper;
@@ -39,6 +41,7 @@ import java.time.LocalDateTime;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 @Slf4j
@@ -55,34 +58,63 @@ public class IpadSendServer {
     private final IQwUserVideoService qwUserVideoService;
     private final RedisCache redisCache;
     private final ICompanyMiniappService companyMiniappService;
+    private final IFsCoursePlaySourceConfigService playSourceConfigService;
     private final FsUserMapper fsUserMapper;
     private static final List<String> PROJECT_NAMES = Arrays.asList("济南联志健康", "北京存在文化");
     private void sendMiniProgram(BaseVo vo, QwSopCourseFinishTempSetting.Setting content, Map<String, FsCoursePlaySourceConfig> miniMap, Long companyId) {
+        // 发送参数原本的appid
         String appid = content.getMiniprogramAppid();
+        // 判断销售工时ID不为空并且有小程序类型
         if(companyId != null && content.getMiniType() != null){
-            List<CompanyMiniapp> list = companyMiniappService.list(new QueryWrapper<CompanyMiniapp>().eq("company_id", companyId));
-            List<CompanyMiniapp> collect = list.stream().filter(e -> e.getType().equals(content.getMiniType())).collect(Collectors.toList());
-            if(!collect.isEmpty() && collect.get(0) != null && StringUtils.isNotEmpty(collect.get(0).getAppId())){
-                appid = collect.get(0).getAppId();
+            // 获取销售公司下面绑定的主备小程序,并且根据当前应该发送的主备类型查询出数据
+            List<CompanyMiniapp> list = companyMiniappService.list(new QueryWrapper<CompanyMiniapp>().eq("company_id", companyId).eq("type", content.getMiniType()));
+            // 判断当前绑定的最新的小程序,并且覆盖以前的值(可以达到实时替换小程序的功能)
+            if(!list.isEmpty() && list.get(0) != null && StringUtils.isNotEmpty(list.get(0).getAppId())){
+                appid = list.get(0).getAppId();
             }
+            // 获取配置文件里面的项目名称
             String signProjectName = SpringUtils.getProperty("cloud_host.company_name");
-            //区分新老用户,新用户发送备用小程序,老用户发送主小程序
+            //区分新老用户,新用户发送备用小程序,老用户发送主小程序,TODO 需要使用的项目在参数里面加上
             if(PROJECT_NAMES.contains(signProjectName)){
                 log.info("ID:{}, qwUserId:{},externalId:{},进入区分发小程序逻辑", vo.getId(), vo.getQwUserId(), vo.getExId());
+                // 判断消息是否是群聊,不是群聊再进去,TODO 当权无法判断群聊是否可以发送对应的小程序
                 if(!vo.isRoom()){
                     log.info("qwUserId:{},externalId:{},不是群聊", vo.getQwUserId(), vo.getExId());
                     try {
+                        // 获取当前外部联系人
                         QwExternalContact qwExternalContact = qwExternalContactMapper.selectOne(new LambdaQueryWrapper<QwExternalContact>().eq(QwExternalContact::getQwUserId,vo.getQwUserId()).eq(QwExternalContact::getExternalUserId,vo.getExId()).last(" limit 1"));
+                        // 当前外部联系是否绑定用户数据,如果数据为空则是没看过小程序的新用户,不用去判断小程序,跳过判断
                         if(qwExternalContact.getFsUserId() != null){
+                            // 根据用户绑定信息去查询用户信息
                             FsUser fsUser = fsUserMapper.selectFsUserByUserId(qwExternalContact.getFsUserId());
-                            LocalDateTime createTime = DateUtil.dateToLocalDateTime(fsUser.getCreateTime());
-                            log.info("ID:{}, qwUserId:{},externalId:{},已绑定小程序,判断时间:{}", vo.getId(), vo.getQwUserId(), vo.getExId(), createTime);
-                            LocalDateTime lastTime = LocalDateTime.of(2025, 11, 6, 23, 59, 59);
-                            int listIndex = createTime.isAfter(lastTime) ? 1 : 0 ;
-                            List<CompanyMiniapp> collect2 = list.stream().filter(e -> e.getType().equals(listIndex)).collect(Collectors.toList());
-                            if(!collect2.isEmpty() && collect2.get(0) != null && StringUtils.isNotEmpty(collect2.get(0).getAppId())){
-                                appid = collect2.get(0).getAppId();
-                                log.info("ID:{}, qwUserId:{},externalId:{},发送小程序:{}", vo.getId(), vo.getQwUserId(), vo.getExId(), appid);
+                            // 判断用户是否有看过其他的小程序多个
+                            if(StringUtils.isNotEmpty(fsUser.getAppId())){
+                                // 获取用户看过的小程序ID集合
+                                List<String> miniAppList = Arrays.asList(fsUser.getAppId().split(","));
+                                // 根据小程序ID查询小程序列表
+                                List<FsCoursePlaySourceConfig> configList = playSourceConfigService.selectByAppIds(miniAppList);
+                                // 筛选出半封禁的小程序数据,得到这个数据然后优先发这个小程序
+                                Optional<FsCoursePlaySourceConfig> optional = configList.stream().filter(e -> e.getStatus() != null && e.getStatus() == 1).findFirst();
+                                // 判断是否找到
+                                if(optional.isPresent()){
+                                    // 找到半封禁并且在appid里面存在证明这个客户是打开过小程序,优先发送这个
+                                    appid = optional.get().getAppid();
+                                }
+                            }else{
+                                // 获取用户的创建时间
+                                LocalDateTime createTime = DateUtil.dateToLocalDateTime(fsUser.getCreateTime());
+                                log.info("ID:{}, qwUserId:{},externalId:{},已绑定小程序,判断时间:{}", vo.getId(), vo.getQwUserId(), vo.getExId(), createTime);
+                                // 这个时间是写死的,目前判断的芳华封禁的时间,可以更具项目调整
+                                LocalDateTime lastTime = LocalDateTime.of(2025, 11, 6, 23, 59, 59);
+                                // 判断客户创建时间是在这个之前还是之后
+                                int listIndex = createTime.isAfter(lastTime) ? 1 : 0 ;
+                                // 获取公司里面的主备小程序,根据用户创建时间来发送主备,如果创建时间大于上看的时间就发送备用小程序,如果小于就发送主要小程序
+                                List<CompanyMiniapp> collect2 = list.stream().filter(e -> e.getType().equals(listIndex)).collect(Collectors.toList());
+                                // 判断是否获取到了配置
+                                if(!collect2.isEmpty() && collect2.get(0) != null && StringUtils.isNotEmpty(collect2.get(0).getAppId())){
+                                    appid = collect2.get(0).getAppId();
+                                    log.info("ID:{}, qwUserId:{},externalId:{},发送小程序:{}", vo.getId(), vo.getQwUserId(), vo.getExId(), appid);
+                                }
                             }
                         }else{
                             log.info("ID:{}, qwUserId:{},externalId:{},未绑定小程序用户", vo.getId(), vo.getQwUserId(), vo.getExId());

+ 2 - 1
fs-quartz/src/main/java/com/fs/quartz/config/ScheduleConfig.java

@@ -8,7 +8,7 @@ import java.util.Properties;
 
 /**
  * 定时任务配置
- * 
+ *
 
  */
 @Configuration
@@ -51,6 +51,7 @@ public class ScheduleConfig
         factory.setOverwriteExistingJobs(true);
         // 设置自动启动,默认为true
         factory.setAutoStartup(true);
+//        factory.setAutoStartup(false);
 
         return factory;
     }

+ 76 - 3
fs-qw-task/src/main/java/com/fs/app/controller/CommonController.java

@@ -21,10 +21,11 @@ import com.fs.his.service.IFsInquiryOrderService;
 import com.fs.his.utils.qrcode.QRCodeUtils;
 import com.fs.qw.domain.QwCompany;
 import com.fs.qw.domain.QwExternalContact;
+import com.fs.qw.domain.QwIpadServerLog;
+import com.fs.qw.domain.QwUser;
 import com.fs.qw.mapper.QwExternalContactMapper;
-import com.fs.qw.service.IQwCompanyService;
-import com.fs.qw.service.IQwExternalContactService;
-import com.fs.qw.service.IQwMaterialService;
+import com.fs.qw.mapper.QwUserMapper;
+import com.fs.qw.service.*;
 import com.fs.qwApi.domain.QwExternalContactResult;
 import com.fs.qwApi.service.QwApiService;
 import com.fs.sop.mapper.QwSopLogsMapper;
@@ -33,6 +34,8 @@ import com.fs.sop.mapper.SopUserLogsMapper;
 import com.fs.sop.service.*;
 import com.fs.sop.vo.QwSopLogsDoSendListTVO;
 import com.fs.store.service.IFsUserCourseCountService;
+import com.fs.wxwork.dto.WxWorkGetQrCodeDTO;
+import com.fs.wxwork.service.WxWorkService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
@@ -48,6 +51,7 @@ import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Date;
 import java.util.List;
 
 @Api("公共接口")
@@ -134,8 +138,77 @@ public class CommonController {
     @Autowired
     public RedisCache redisCache;
 
+    @Autowired
+    private QwUserMapper qwUserMapper;
+
+
+    @Autowired
+    IQwIpadServerService ipadServerService;
+
+    @Autowired
+    IQwIpadServerLogService qwIpadServerLogService;
+    @Autowired
+    IQwIpadServerUserService qwIpadServerUserService;
+
+    @Autowired
+    IQwExternalContactService externalContactService;
+    @Autowired
+    WxWorkService wxWorkService;
+
+    /**
+     *
+     */
+    @GetMapping("/selectQwUserByTest")
+    public void selectQwUserByTest() {
+        try {
+            List<QwUser> list = qwUserMapper.selectQwUserByTest();
+            for (QwUser qwUser : list) {
+                try {
+                    Integer serverStatus = qwUser.getServerStatus();
+                    Long serverId = qwUser.getServerId();
+                    if (serverStatus==0){
+                        log.error("不需要解绑");
+                    }
+                    if (serverId==null){
+                        log.error("serverId不存在");
+                    }
+                    QwUser u = new QwUser();
+                    u.setId(qwUser.getId());
+                    u.setServerId(null);
+                    u.setServerStatus(0);
+                    qwUserMapper.updateQwUser(u);
+                    ipadServerService.addServer(serverId);
+                    QwIpadServerLog qwIpadServerLog = new QwIpadServerLog();
+                    qwIpadServerLog.setType(2);
+                    qwIpadServerLog.setTilie("解绑");
+                    qwIpadServerLog.setServerId(serverId);
+                    qwIpadServerLog.setQwUserId(qwUser.getId());
+                    qwIpadServerLog.setCompanyUserId(qwUser.getCompanyUserId());
+                    qwIpadServerLog.setCompanyId(qwUser.getCompanyId());
+                    qwIpadServerLog.setCreateTime(new Date());
+                    qwIpadServerLogService.insertQwIpadServerLog(qwIpadServerLog);
+                    qwIpadServerUserService.deleteQwIpadServerUserByQwUserId(qwUser.getId());
+                    WxWorkGetQrCodeDTO wxWorkGetQrCodeDTO = new WxWorkGetQrCodeDTO();
+                    wxWorkGetQrCodeDTO.setUuid(qwUser.getUid());
+                    wxWorkService.LoginOut(wxWorkGetQrCodeDTO,qwUser.getServerId());
+                    updateIpadStatus(qwUser.getId(),0);
+                } catch (Exception e) {
+                    log.error("解绑ipad报错",e);
+                }
+            }
+        } catch (Exception e) {
+            log.error("定时处理未绑定员工企微异常",e);
+        }
 
+    }
 
+
+    void updateIpadStatus(Long id ,Integer status){
+        QwUser u = new QwUser();
+        u.setId(id);
+        u.setIpadStatus(status);
+        qwUserMapper.updateQwUser(u);
+    }
     /**
      *
      */

+ 4 - 1
fs-service/src/main/java/com/fs/company/mapper/CompanyMapper.java

@@ -155,7 +155,10 @@ public interface CompanyMapper
 
 
     @Select({"<script> " +
-            "select c.*,cu.user_name,qu.used_num FROM company c LEFT JOIN company_user cu ON c.user_id =cu.user_id  " +
+            "select c.*,cu.user_name,qu.used_num," +
+            "CASE WHEN JSON_VALID(t1.config_value) THEN t1.config_value->>'$.mchId' ELSE NULL END as mchId" +
+            " FROM company c LEFT JOIN company_user cu ON c.user_id =cu.user_id  " +
+            " left join company_config t1 on t1.config_key = 'redPacket:config' and t1.company_id = c.company_id " +
             "LEFT JOIN (select company_id, count(id) as used_num from qw_user where server_id is not null and server_status = 1 group by company_id) qu ON qu.company_id = c.company_id " +
             "where c.is_del=0 " +
             "            <if test=\"companyName != null  and companyName != ''\"> and c.company_name like concat('%', #{companyName}, '%')</if>\n" +

+ 5 - 0
fs-service/src/main/java/com/fs/company/vo/CompanyVO.java

@@ -99,4 +99,9 @@ public class CompanyVO implements Serializable
     private BigDecimal redPackageMoney;
 
     private Integer liveShow;
+
+    /**
+     * 新增展示商户号(分公司配置时有值)
+     */
+    private String mchId;
 }

+ 19 - 0
fs-service/src/main/java/com/fs/course/config/RandomRedPacketConfig.java

@@ -0,0 +1,19 @@
+package com.fs.course.config;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author MixLiu
+ * @date 2025/11/27 下午2:07)
+ */
+@Data
+public class RandomRedPacketConfig {
+    /**
+     * 是否开启随机红包
+     */
+    private Boolean enableRandomRedpacket;
+
+    private List<RandomRedPacketRule> rules;
+}

+ 28 - 0
fs-service/src/main/java/com/fs/course/config/RandomRedPacketRule.java

@@ -0,0 +1,28 @@
+package com.fs.course.config;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @author MixLiu
+ * @date 2025/11/27 下午2:08)
+ */
+
+@Data
+public class RandomRedPacketRule {
+    /**
+     * 最小金额
+     */
+    private BigDecimal minAmount;
+
+    /**
+     * 最大金额
+     */
+    private BigDecimal maxAmount;
+
+    /**
+     * 权重
+     */
+    private Integer weight;
+}

+ 6 - 0
fs-service/src/main/java/com/fs/course/domain/FsUserCourseVideo.java

@@ -78,6 +78,12 @@ public class FsUserCourseVideo extends BaseEntity
     private Integer uploadType;
 
     private BigDecimal redPacketMoney;
+
+    /**
+     * 随机红包配置
+     */
+    private String randomRedPacketRules;
+
     private Long fileSize;//文件大小  字节
     private String fileKey;//文件key 对用存储桶
     private String round;//轮次

+ 1 - 1
fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java

@@ -62,7 +62,7 @@ public interface FsUserCourseVideoMapper
     public int updateFsUserCourseVideo(FsUserCourseVideo fsUserCourseVideo);
 
     @Update("<script> " +
-            "update fs_user_course_video set red_packet_money=#{data.redPacketMoney} where course_id=#{data.courseId} " +
+            "update fs_user_course_video set red_packet_money=#{data.redPacketMoney}, random_red_packet_rules = #{data.randomRedPacketRules} where course_id=#{data.courseId} " +
             "</script>")
     public int updateFsUserCourseRedPage(@Param("data") FsUserCourseRedPageParam courseRedPageParam);
 

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

@@ -13,4 +13,6 @@ public interface IFsCoursePlaySourceConfigService extends IService<FsCoursePlayS
      * 查询点播配置列表
      */
     List<FsCoursePlaySourceConfigVO> selectCoursePlaySourceConfigVOListByMap(Map<String, Object> params);
+
+    List<FsCoursePlaySourceConfig> selectByAppIds(List<String> miniAppList);
 }

+ 0 - 5
fs-service/src/main/java/com/fs/course/service/impl/FsCourseLinkServiceImpl.java

@@ -898,14 +898,9 @@ public class FsCourseLinkServiceImpl implements IFsCourseLinkService
                             }else {
                                 return R.error("获取失败:"+jsonObject.getString("errmsg"));
                             }
-                        }else {
-                            return R.error("未配置小程序id");
                         }
                     }
                 }
-
-
-
             } else {
                 return R.error("页面链接错误,获取失败");
             }

+ 6 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsCoursePlaySourceConfigServiceImpl.java

@@ -1,5 +1,6 @@
 package com.fs.course.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
@@ -24,4 +25,9 @@ public class FsCoursePlaySourceConfigServiceImpl extends ServiceImpl<FsCoursePla
     public List<FsCoursePlaySourceConfigVO> selectCoursePlaySourceConfigVOListByMap(Map<String, Object> params) {
         return baseMapper.selectCoursePlaySourceConfigVOListByMap(params);
     }
+
+    @Override
+    public List<FsCoursePlaySourceConfig> selectByAppIds(List<String> miniAppList) {
+        return baseMapper.selectList(new QueryWrapper<FsCoursePlaySourceConfig>().in("appid", miniAppList));
+    }
 }

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

@@ -506,7 +506,8 @@ public class FsCourseProductOrderServiceImpl extends ServiceImpl<FsCourseProduct
                     }
                 }
             } else {
-                //TODO 支付金额为0的业务
+                this.payConfirm(courseProductOrder.getOrderCode(),"","","",2,null,null);
+                return R.ok().put("isPay",1);
             }
 
         } else {

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

@@ -15,6 +15,7 @@ import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
+import com.fs.common.utils.CloudHostUtils;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.CompanyTag;
@@ -776,6 +777,11 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
         link.setUpdateTime(calendar.getTime());
         int i = fsCourseLinkMapper.insertFsCourseLink(link);
         if (i > 0){
+            if (CloudHostUtils.hasCloudHostName("中康")){
+                String domainName = getDomainName(param.getCompanyUserId(), config);
+                String sortLink = domainName + link.getRealLink().replace("/#","");
+                return R.ok().put("url", sortLink).put("link", random);
+            }
             String domainName = getDomainName(param.getCompanyUserId(), config);
             String sortLink = domainName + appShortLink + link.getLink();
             return R.ok().put("url", sortLink).put("link", random);
@@ -783,6 +789,9 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
         return R.error("生成链接失败!");
     }
 
+    public static void main(String[] args) {
+        System.out.println(appRealLink.replace("/#", ""));
+    }
     /**
      * 修改课堂配置
      */

+ 313 - 3
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -2,6 +2,7 @@ package com.fs.course.service.impl;
 
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -33,6 +34,8 @@ import com.fs.company.mapper.CompanyUserMapper;
 import com.fs.company.service.ICompanyService;
 import com.fs.config.cloud.CloudHostProper;
 import com.fs.course.config.CourseConfig;
+import com.fs.course.config.RandomRedPacketConfig;
+import com.fs.course.config.RandomRedPacketRule;
 import com.fs.course.domain.*;
 import com.fs.course.dto.CoursePackageDTO;
 import com.fs.course.mapper.*;
@@ -495,8 +498,234 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         // 设置 Redis 记录的过期时间(例如 5 分钟)
         redisCache.expire(redisKey, 300, TimeUnit.SECONDS);
     }
-
     @Override
+    public R isAddKf(FsUserCourseVideoAddKfUParam param) {
+
+        logger.info("zyp \n【判断添加客服】:{}",param);
+        //查询用户
+        FsUser fsUser = fsUserMapper.selectFsUserByUserId(param.getUserId());
+
+        //用户不存在唤起重新授权
+        if (fsUser==null){
+            return R.error(401,"会员不存在");
+        }
+        if (fsUser.getStatus()==0){
+            return R.error("会员被停用,无权限,请联系客服!");
+        }
+
+        if (param.getIsRoom()!=null&& param.getIsRoom()== 1) {
+            // 当 isRoom 为 1 时走 handleRoom
+            return handleRoom(param,fsUser);
+        }
+
+
+        if (param.getLinkType()!=null&&param.getLinkType()==1){
+            if (param.getLinkId()!=null){
+                // 从数据库中查找短链对应的真实链接
+                FsCourseLink courseLink = courseLinkMapper.selectFsCourseLinkByLinkId(param.getLinkId());
+                if (courseLink != null) {
+                    // 获取当前时间
+                    Date currentTime = new Date();
+                    // 获取链接的更新时间(假设这个字段代表过期时间)
+                    Date updateTime = courseLink.getUpdateTime();
+
+                    // 判断是否过期
+                    if (currentTime.after(updateTime)) {
+                        // 链接已过期
+                        return R.error("链接已过期");
+                    }else {
+                        return R.ok();
+                    }
+                }
+            }
+            return R.error("链接过期");
+        }
+        FsCourseLink courseLink = courseLinkMapper.selectFsCourseLinkByLink(param.getLink());
+//        if(StringUtils.isNotEmpty(courseLink.getUNo())){
+//            if(!courseLink.getUNo().equals(param.getUNo())){
+//                log.error("看课链接uNO不一致,linkUNo:{}, param-uNo:{}", courseLink.getUNo(), param.getUNo());
+//            }else{
+//                log.info("看课链接uNO一致,uno:{}", courseLink.getUNo());
+//            }
+//        }
+
+        //未注册提示
+        String noRegisterMsg = "由于您还未完成注册,请联系伴学助手完成注册即可观看!";
+        //非独属链接提示
+        String noMemberMsg = "此链接已被绑定,请联系伴学助手领取您的专属链接,专属链接请勿分享哦!";
+
+        // 群聊逻辑
+        if(courseLink != null && StringUtils.isNotEmpty(courseLink.getChatId())){
+            QwGroupChat qwGroupChat = qwGroupChatMapper.selectQwGroupChatByChatId(courseLink.getChatId());
+            if(qwGroupChat == null){
+                return R.error("群参数异常!");
+            }
+            SopUserLogsInfo sopUserLogsInfo =  new SopUserLogsInfo();
+            sopUserLogsInfo.setChatId(courseLink.getChatId());
+            List<QwGroupChatUser> qwGroupChatUsers = qwGroupChatUserMapper.selectByChatId(sopUserLogsInfo);
+            if(qwGroupChatUsers == null || qwGroupChatUsers.isEmpty()){
+                return R.error("群参数异常!");
+            }
+            QwExternalContact qwExternalContact =
+                    qwExternalContactMapper.selectOne(new QueryWrapper<QwExternalContact>()
+                            .eq("user_id", qwGroupChat.getOwner())
+                            .eq("fs_user_id", param.getUserId())
+                            .eq("corp_id", param.getCorpId())
+                            .eq("status",0));
+            if(qwExternalContact==null){
+                return R.error(noRegisterMsg);
+            }
+            if(qwGroupChatUsers.stream().noneMatch(e -> e.getUserId().equals(qwExternalContact.getExternalUserId()))){
+                log.error("客户不在群:{},里面:{}", qwGroupChat.getChatId(), qwExternalContact.getExternalUserId());
+                return R.error(noRegisterMsg);
+            }
+            Long qwExternalId = qwExternalContact.getId();
+            log.info("外部联系人数据:{}", qwExternalContact);
+            addCompanyCompanyFsUser(param);
+            FsCourseWatchLog log = courseWatchLogMapper.getWatchCourseVideoByExt(qwExternalId, param.getVideoId(),param.getQwUserId());
+            if (log==null ){
+                return R.error(noRegisterMsg);
+            }
+            boolean isDebug = false;
+            //判断外部联系人有没有绑定userId
+            if (qwExternalContact.getFsUserId()!=null && isDebug){
+                //有客户有小程序id  但 登录的小程序id和根据外部联系人id查出来的小程序id不一致
+                if (!qwExternalContact.getFsUserId().equals(param.getUserId())) {
+                    return R.error(noMemberMsg);
+                }
+                List<QwExternalContact> qwExternalContacts = qwExternalContactMapper.selectQwExternalContactByMiniUserId(param.getUserId());
+                //匹配客户公司id
+                if (qwExternalContacts.stream().noneMatch(contact -> contact.getCorpId().equals(param.getCorpId()))){
+                    return R.error(noRegisterMsg);
+                }
+
+                //看课记录中userId为0绑定userId
+                if (log.getUserId()==null||log.getUserId().equals(0L) || !log.getUserId().equals(param.getUserId())){
+                    log.setUserId(param.getUserId());
+                }
+
+                log.setUpdateTime(new Date());
+                fsUserCompanyBindService.bindFsUser(fsUser.getUserId(), qwExternalId, log.getLogId());
+                courseWatchLogMapper.updateFsCourseWatchLog(log);
+
+            }else {
+                //没绑定fsUser直接绑定fsUser
+                QwExternalContact contact = new QwExternalContact();
+                contact.setId(qwExternalId);
+                contact.setFsUserId(param.getUserId());
+                qwExternalContactMapper.updateQwExternalContact(contact);
+                FsUser user = new FsUser();
+                user.setUserId(fsUser.getUserId());
+                user.setIsAddQw(1);
+                fsUserMapper.updateFsUser(user);
+                //绑定上之后 更新观看记录
+                //看课记录中userId为0绑定userId
+                log.setUserId(param.getUserId());
+                log.setUpdateTime(new Date());
+                courseWatchLogMapper.updateFsCourseWatchLog(log);
+            }
+            fsUserCompanyBindService.bindFsUser(fsUser.getUserId(), qwExternalId, log.getLogId());
+            return R.error(567,"群聊通用链接").put("qwExternalId", qwExternalContact.getId());
+        }
+        else{
+            Long qwExternalId = param.getQwExternalId();
+
+            FsCourseWatchLog log=new FsCourseWatchLog();
+
+            //如果是官方的则查真正的外部联系人id
+            if (param.getLinkType()!=null&&param.getLinkType()==5) {
+
+                log = courseWatchLogMapper.selectFsCourseWatchLogByCourseSopIdAndVideoId(param.getUserId(), param.getVideoId(), param.getQwUserId());
+                if (log == null) {
+                    return R.error(noRegisterMsg);
+                }else {
+                    qwExternalId=log.getQwExternalContactId();
+                }
+
+            }else {
+                log = courseWatchLogMapper.getWatchCourseVideoByExt(qwExternalId, param.getVideoId(),param.getQwUserId());
+                if (log==null ){
+                    return R.error(noRegisterMsg);
+                }
+            }
+
+
+            //查询是否有添加客服
+            QwExternalContact externalContact = qwExternalContactMapper.selectQwExternalContactById(qwExternalId);
+
+            //用小程序id查询外部联系人
+            List<QwExternalContact> qwExternalContacts = qwExternalContactMapper.selectQwExternalContactByMiniUserId(param.getUserId());
+
+
+            //如果查不出来客户信息,加好友
+            if(externalContact==null){
+                return R.error(noRegisterMsg);
+            }
+
+            //2025.04.10 绑定公司码
+            addCompanyCompanyFsUser(param);
+
+            //判断外部联系人有没有绑定userId
+            if (externalContact.getFsUserId()!=null){
+                //有客户有小程序id  但 登录的小程序id和根据外部联系人id查出来的小程序id不一致
+                if (!externalContact.getFsUserId().equals(param.getUserId())) {
+                    return R.error(noMemberMsg);
+                }
+                //匹配客户公司id
+                if (qwExternalContacts.stream().noneMatch(contact -> contact.getCorpId().equals(param.getCorpId()))){
+                    return R.error(noMemberMsg);
+                }
+
+                //看课记录中userId为0绑定userId
+                if (log.getUserId()==null||log.getUserId().equals(0L) || !log.getUserId().equals(param.getUserId())){
+                    log.setUserId(param.getUserId());
+                }
+
+                log.setUpdateTime(new Date());
+                courseWatchLogMapper.updateFsCourseWatchLog(log);
+
+                iSopUserLogsInfoService.updateSopUserInfoByExternalId(qwExternalId,param.getUserId());
+
+                fsUserCompanyBindService.bindFsUser(fsUser.getUserId(), qwExternalId, log.getLogId());
+                if (param.getLinkType()!=null&&param.getLinkType()==5){
+                    FsCourseLink fsCourseLink = fsCourseLinkMapper.selectExpireLinkByQwExternalId(param.getQwUserId(), param.getVideoId(), qwExternalId);
+                    return R.error(566,"官方群发通用链接").put("courseLink",fsCourseLink);
+                }
+                return R.ok();
+
+            }else {
+                //没绑定fsUser直接绑定fsUser
+                QwExternalContact contact = new QwExternalContact();
+                contact.setId(qwExternalId);
+                contact.setFsUserId(param.getUserId());
+//            adHtmlClickLogService.upload(contact.getState(), AdUploadType.REGISTERED, e -> contact.setUploadRegisterStatus(1));
+                qwExternalContactMapper.updateQwExternalContact(contact);
+
+                iSopUserLogsInfoService.updateSopUserInfoByExternalId(qwExternalId,param.getUserId());
+
+                FsUser user = new FsUser();
+                user.setUserId(fsUser.getUserId());
+                user.setIsAddQw(1);
+                fsUserMapper.updateFsUser(user);
+
+                //绑定上之后 更新观看记录
+                //看课记录中userId为0绑定userId
+                if (log.getUserId()==null||log.getUserId().equals(0L) || !log.getUserId().equals(param.getUserId())){
+                    log.setUserId(param.getUserId());
+                }
+
+                log.setUpdateTime(new Date());
+                courseWatchLogMapper.updateFsCourseWatchLog(log);
+                fsUserCompanyBindService.bindFsUser(fsUser.getUserId(), qwExternalId, log.getLogId());
+                if (param.getLinkType()!=null&&param.getLinkType()==5){
+                    FsCourseLink fsCourseLink = fsCourseLinkMapper.selectExpireLinkByQwExternalId(param.getQwUserId(), param.getVideoId(), qwExternalId);
+                    return R.error(566,"官方群发通用链接").put("courseLink",fsCourseLink);
+                }
+                return R.ok();
+            }
+        }
+    }
+  /*  @Override
     public R isAddKf(FsUserCourseVideoAddKfUParam param) {
         logger.info("【判断添加客服】:{}",param);
         //查询用户
@@ -589,7 +818,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             return R.error("参数错误!");
         }
 
-    }
+    }*/
     private R handleQwRoom(FsUserCourseVideoAddKfUParam param,FsUser user) {
         FsCourseLink courseLink = courseLinkMapper.selectFsCourseLinkByLink(param.getLink());
         String msg = "<div style=\"color: red;margin-bottom: 15px;font-weight: bold;\">本课程为群会员独享<br>请长按二维码</div>\n" +
@@ -1400,7 +1629,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
         // 判断来源是否是app,如是app,则发放积分奖励
         int sourceApp = 3;
-        if(sourceApp == param.getSource()){
+        if(sourceApp == param.getSource()&&!CloudHostUtils.hasCloudHostName("中康")){
             return sendIntegralReward(param, user, log, config);
         }
 
@@ -1444,6 +1673,33 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             amount = redPackage.getRedPacketMoney();
         } else if (video != null) {
             amount = video.getRedPacketMoney();
+            //是否开启了随机红包
+            String json = configService.selectConfigByKey("randomRedpacket:config");
+            if(StringUtils.isNotBlank(json)){
+                RandomRedPacketConfig randomRedPacket = JSONUtil.toBean(json, RandomRedPacketConfig.class);
+                //是否开启拼手气红包
+                if(null != randomRedPacket && randomRedPacket.getEnableRandomRedpacket()){
+                    BigDecimal randomMoney = BigDecimal.ZERO;
+                    //优先读取课程配置随机红包规则
+                    String randomRedPacketRules = video.getRandomRedPacketRules();
+                    if(StringUtils.isNotBlank(randomRedPacketRules) ){
+                        JSONArray array = JSONObject.parseArray(randomRedPacketRules);
+                        List<RandomRedPacketRule> rules = new ArrayList<>();
+                        for (Object o : array) {
+                            rules.add(JSONObject.toJavaObject((JSONObject) o, RandomRedPacketRule.class));
+                        }
+                        randomMoney = getRandomMoneyByRules(rules);
+                    }
+                    //如果课程没有配置 读取后台默认随机规则
+                    else{
+                        randomMoney = getRandomMoneyByRules(randomRedPacket.getRules());
+                    }
+                    //兼容拼手气红包报错情况的发放红包情况
+                    if(BigDecimal.ZERO.compareTo(randomMoney) < 0){
+                        amount = randomMoney;
+                    }
+                }
+            }
         }
 
         // 准备发送红包参数
@@ -3613,6 +3869,60 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         return R.ok();
     }
 
+    /**
+     * 根据匹配规则返回随机红包值(需求是概率独立计算)
+     * @param rules
+     * @return
+     */
+    private BigDecimal getRandomMoneyByRules(List<RandomRedPacketRule> rules) {
+        try {
+
+            if (CollectionUtils.isEmpty(rules)) {
+                logger.error("随机红包规则列表为空,不予处理");
+//            throw new ServiceException("随机红包规则列表为空");
+            }
+            // 计算总权重
+            int totalWeight = rules.stream()
+                    .mapToInt(RandomRedPacketRule::getWeight)
+                    .sum();
+            // 根据权重随机选择规则
+            Random random = new Random();
+            int randomPoint = random.nextInt(totalWeight);
+
+            RandomRedPacketRule selectedRule = null;
+            int currentWeight = 0;
+
+            for (RandomRedPacketRule rule : rules) {
+                currentWeight += rule.getWeight();
+                if (randomPoint < currentWeight) {
+                    selectedRule = rule;
+                    break;
+                }
+            }
+
+            // 如果因为计算精度问题没有选中规则,默认选第一个
+            if (selectedRule == null) {
+                selectedRule = rules.get(0);
+            }
+            // 在选中规则的范围内生成随机金额
+            BigDecimal maxAmount = selectedRule.getMaxAmount();
+            BigDecimal minAmount = selectedRule.getMinAmount();
+            // 如果最大最小金额相等,直接返回该金额
+            if (maxAmount.compareTo(minAmount) == 0) {
+                return maxAmount;
+            }
+            // 生成随机金额
+            BigDecimal range = maxAmount.subtract(minAmount);
+            BigDecimal randomValue = range.multiply(BigDecimal.valueOf(random.nextDouble()));
+            BigDecimal result = minAmount.add(randomValue);
+            // 保留两位小数,四舍五入
+            return result.setScale(2, RoundingMode.HALF_UP);
+        } catch (Exception e) {
+            logger.error("获取拼手气红包金额异常:{}",rules, e);
+        }
+
+        return BigDecimal.ZERO;
+    }
 
 
 }

+ 6 - 0
fs-service/src/main/java/com/fs/course/vo/FsUserCourseVideoQVO.java

@@ -68,6 +68,12 @@ public class FsUserCourseVideoQVO extends BaseEntity {
     private String lineThree; //线路三 华为云obs
     private Integer uploadType;
     private String redPacketMoney;
+
+    /**
+     * 随机红包配置
+     */
+    private String randomRedPacketRules;
+
     private Long fileSize;//文件大小  字节
     private String fileKey;//文件key 对用存储桶
     private String round;//轮次

+ 4 - 0
fs-service/src/main/java/com/fs/erp/dto/sdk/df/DfClient.java

@@ -85,6 +85,10 @@ public class DfClient {
 
 	public String execute(RequestUrlEnum request, Map<String, Object> params,Long dfAccountId) throws IOException {
 		FsDfAccount dfAccount = fsDfAccountMapper.selectFsDfAccountById(dfAccountId);
+		if (dfAccount == null){
+			log.error("未查询到代服账户,传参:请求={},参数-{},代服id-{}",JSON.toJSONString(request),JSON.toJSONString(params),dfAccountId);
+			return null;
+		}
 		String appkey = dfAccount.getDfAppKey();
 		String appsecret = dfAccount.getDfAppsecret();
 		String timestamp = String.valueOf(System.currentTimeMillis());

+ 48 - 0
fs-service/src/main/java/com/fs/erp/service/impl/DfOrderServiceImpl.java

@@ -200,6 +200,9 @@ public class DfOrderServiceImpl implements IErpOrderService {
             //2.请求
             log.info("开始推送订单,参数: {}", JSON.toJSONString(map));
             String response = client.execute(RequestUrlEnum.CREAT_ORDER, map, dfAccountId);
+            if (StringUtils.isBlank(response)) {
+                return new ErpOrderResponse();
+            }
             DFApiResponse dfApiResponse = JSON.parseObject(response, DFApiResponse.class);
             //3.处理请求结果
             if (dfApiResponse != null && "ok".equals(dfApiResponse.getCode())) {
@@ -256,6 +259,9 @@ public class DfOrderServiceImpl implements IErpOrderService {
             //2.请求
             log.info("开始取消订单,参数: {}", JSON.toJSONString(map));
             String response = client.execute(RequestUrlEnum.ORDER_CANCEL, map, dfAccountId);
+            if (StringUtils.isBlank(response)) {
+                return new ErpOrderResponse();
+            }
             DFApiResponse dfApiResponse = JSON.parseObject(response, DFApiResponse.class);
             //3.处理请求结果
             if (dfApiResponse != null && "ok".equals(dfApiResponse.getCode())) {
@@ -311,6 +317,9 @@ public class DfOrderServiceImpl implements IErpOrderService {
             //2.请求
             log.info("开始取消订单,参数: {}", JSON.toJSONString(map));
             String response = client.execute(RequestUrlEnum.ORDER_CANCEL, map, dfAccountId);
+            if (StringUtils.isBlank(response)) {
+                return new ErpOrderResponse();
+            }
             DFApiResponse dfApiResponse = JSON.parseObject(response, DFApiResponse.class);
             //3.处理请求结果
             if (dfApiResponse != null && "ok".equals(dfApiResponse.getCode())) {
@@ -360,6 +369,9 @@ public class DfOrderServiceImpl implements IErpOrderService {
             //2.请求
             log.info("开始取消订单,参数: {}", JSON.toJSONString(map));
             String response = client.execute(RequestUrlEnum.ORDER_CANCEL, map, dfAccountId);
+            if (StringUtils.isBlank(response)) {
+                return new ErpOrderResponse();
+            }
             DFApiResponse dfApiResponse = JSON.parseObject(response, DFApiResponse.class);
             //3.处理请求结果
             if (dfApiResponse != null && "ok".equals(dfApiResponse.getCode())) {
@@ -412,6 +424,9 @@ public class DfOrderServiceImpl implements IErpOrderService {
                         map.put("mailNumber", mailNumber);
                         log.info("开始查询路由结果,参数为: {}", JSON.toJSONString(map));
                         String response = client.execute(RequestUrlEnum.ORDER_DELIVERY, map, dfAccountId);
+                        if (StringUtils.isBlank(response)) {
+                            return erpDeliverysResponse;
+                        }
                         DFApiResponse dfApiResponse = JSON.parseObject(response, DFApiResponse.class);
                         if (dfApiResponse != null && "ok".equals(dfApiResponse.getCode())) {
                             dfApiResponse.setCode(mailNumber);
@@ -595,10 +610,16 @@ public class DfOrderServiceImpl implements IErpOrderService {
         Map<String, Object> map = new HashMap<>();
         Long orderId = order.getOrderId();
         Long dfAccountId = getSFAccountIndex(orderId);
+        if (dfAccountId == null){
+            log.info("代服管家 getOrderDeliveryStatus-订单id: {}", orderId);
+        }
         map.put("orderNumber", order.getOrderCode());
         map.put("mailNumber", order.getDeliverySn());
         try {
             String response = client.execute(RequestUrlEnum.ORDER_DELIVERY_STATUS, map, dfAccountId);
+            if (StringUtils.isBlank(response)) {
+                return;
+            }
             DFApiResponse dfApiResponse = JSON.parseObject(response, DFApiResponse.class);
             if ("运单不存在".equals(dfApiResponse.getMsg())) {
 
@@ -832,6 +853,9 @@ public class DfOrderServiceImpl implements IErpOrderService {
         map.put("mailNumber", order.getDeliveryId());
         try {
             String response = client.execute(RequestUrlEnum.ORDER_DELIVERY_STATUS, map, dfAccountId);
+            if (StringUtils.isBlank(response)) {
+                return;
+            }
             DFApiResponse dfApiResponse = JSON.parseObject(response, DFApiResponse.class);
             if ("运单不存在".equals(dfApiResponse.getMsg())) {
 
@@ -927,6 +951,9 @@ public class DfOrderServiceImpl implements IErpOrderService {
         map.put("mailNumber", order.getDeliverySn());
         try {
             String response = client.execute(RequestUrlEnum.ORDER_DELIVERY_STATUS, map, dfAccountId);
+            if (StringUtils.isBlank(response)) {
+                return;
+            }
             DFApiResponse dfApiResponse = JSON.parseObject(response, DFApiResponse.class);
             if ("运单不存在".equals(dfApiResponse.getMsg())) {
                 //查看原来物流状态
@@ -1128,6 +1155,9 @@ public class DfOrderServiceImpl implements IErpOrderService {
             //2.请求
             log.info("开始推送订单,参数: {}", JSON.toJSONString(map));
             String response = client.execute(RequestUrlEnum.CREAT_ORDER, map, dfAccountId);
+            if (StringUtils.isBlank(response)) {
+                return new ErpOrderResponse();
+            }
             DFApiResponse dfApiResponse = JSON.parseObject(response, DFApiResponse.class);
             //3.处理请求结果
             if (dfApiResponse != null && "ok".equals(dfApiResponse.getCode())) {
@@ -1179,6 +1209,9 @@ public class DfOrderServiceImpl implements IErpOrderService {
             //2.请求
             log.info("开始推送订单,参数: {}", JSON.toJSONString(map));
             String response = client.execute(RequestUrlEnum.CREAT_ORDER, map, dfAccountId);
+            if (StringUtils.isBlank(response)) {
+                return new ErpOrderResponse();
+            }
             DFApiResponse dfApiResponse = JSON.parseObject(response, DFApiResponse.class);
             //3.处理请求结果
             if (dfApiResponse != null && "ok".equals(dfApiResponse.getCode())) {
@@ -1226,6 +1259,9 @@ public class DfOrderServiceImpl implements IErpOrderService {
             //2.请求
             log.info("开始推送订单,参数: {}", JSON.toJSONString(map));
             String response = client.execute(RequestUrlEnum.CREAT_ORDER, map, dfAccountId);
+            if (StringUtils.isBlank(response)) {
+                return new ErpOrderResponse();
+            }
             DFApiResponse dfApiResponse = JSON.parseObject(response, DFApiResponse.class);
             //3.处理请求结果
             if (dfApiResponse != null && "ok".equals(dfApiResponse.getCode())) {
@@ -1688,6 +1724,9 @@ public class DfOrderServiceImpl implements IErpOrderService {
             String status = map.get("exInterfaceType").toString();
             log.info("开始查询订单结果,参数为: {}", JSON.toJSONString(map));
             String response = client.execute(RequestUrlEnum.ORDER_RESULT, map, dfAccountId);
+            if (StringUtils.isBlank(response)) {
+                return ;
+            }
             DFApiResponse dfApiResponse = JSON.parseObject(response, DFApiResponse.class);
             if (dfApiResponse != null && "ok".equals(dfApiResponse.getCode())) {
                 log.info("查询订单结果,结果: {}", JSON.toJSONString(dfApiResponse));
@@ -1741,6 +1780,9 @@ public class DfOrderServiceImpl implements IErpOrderService {
             String status = map.get("exInterfaceType").toString();
             log.info("开始查询订单结果,参数为: {}", JSON.toJSONString(map));
             String response = client.execute(RequestUrlEnum.ORDER_RESULT, map, dfAccountId);
+            if (StringUtils.isBlank(response)) {
+                return;
+            }
             DFApiResponse dfApiResponse = JSON.parseObject(response, DFApiResponse.class);
             if (dfApiResponse != null && "ok".equals(dfApiResponse.getCode())) {
                 log.info("查询订单结果,结果: {}", JSON.toJSONString(dfApiResponse));
@@ -1794,6 +1836,9 @@ public class DfOrderServiceImpl implements IErpOrderService {
             String status = map.get("exInterfaceType").toString();
             log.info("开始查询订单结果,参数为: {}", JSON.toJSONString(map));
             String response = client.execute(RequestUrlEnum.ORDER_RESULT, map, dfAccountId);
+            if (StringUtils.isBlank(response)) {
+                return;
+            }
             DFApiResponse dfApiResponse = JSON.parseObject(response, DFApiResponse.class);
             if (dfApiResponse != null && "ok".equals(dfApiResponse.getCode())) {
                 log.info("查询订单结果,结果: {}", JSON.toJSONString(dfApiResponse));
@@ -2204,6 +2249,9 @@ public class DfOrderServiceImpl implements IErpOrderService {
             String status = map.get("exInterfaceType").toString();
             log.info("开始查询订单结果,参数为: {}", JSON.toJSONString(map));
             String response = client.execute(RequestUrlEnum.ORDER_RESULT, map, dfAccountId);
+            if (StringUtils.isBlank(response)) {
+                return;
+            }
             DFApiResponse dfApiResponse = JSON.parseObject(response, DFApiResponse.class);
             if (dfApiResponse != null && "ok".equals(dfApiResponse.getCode())) {
                 log.info("查询订单结果,结果: {}", JSON.toJSONString(dfApiResponse));

+ 6 - 4
fs-service/src/main/java/com/fs/erp/service/impl/JSTErpOrderServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.fs.common.utils.StringUtils;
 import com.fs.erp.constant.AfterSalesOrderStatusEnum;
 import com.fs.erp.constant.ErpQueryOrderStatusEnum;
 import com.fs.erp.constant.OrderStatusEnum;
@@ -44,10 +45,7 @@ import org.springframework.util.CollectionUtils;
 
 import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @Slf4j
@@ -543,6 +541,7 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
         // 1. 构建查询请求DTO
         OrderQueryRequestDTO requestDTO = new OrderQueryRequestDTO();
         requestDTO.setOIds(Collections.singletonList(Long.valueOf(param.getCode())));
+        requestDTO.setOrderItemFlds(Arrays.asList("status"));
 
         // 2. 调用ERP服务查询订单
         OrderQueryResponseDTO query = jstErpHttpService.query(requestDTO);
@@ -742,6 +741,9 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
                     .sum();
             erpOrder.setQty(totalQty);
         }
+        if (StringUtils.isNotEmpty(order.getStatus()) && "Cancelled".equals(order.getStatus())) {
+            erpOrder.setCancle(true);
+        }
 
         // 设置金额相关信息
         erpOrder.setAmount(order.getAmount() != null ? order.getAmount().doubleValue() : null);

+ 2 - 0
fs-service/src/main/java/com/fs/his/service/IFsUserInformationCollectionService.java

@@ -112,4 +112,6 @@ public interface IFsUserInformationCollectionService extends IService<FsUserInfo
     FsUserInformationCollectionDTO selectFsUserInformationCollectionDTOById(Long id);
 
     int updatePackageOrderCode(FsUserInformationCollection fsUserInformationCollection);
+
+    FsUserInformationCollectionAndPatientVO selectFsUserInformationCollectionVoById(Long id);
 }

+ 8 - 2
fs-service/src/main/java/com/fs/his/service/impl/FsPrescribeServiceImpl.java

@@ -21,6 +21,7 @@ import com.fs.his.service.IFsPrescribeDrugService;
 import com.fs.his.service.IFsPrescribeService;
 import com.fs.his.service.IFsStoreOrderService;
 import com.fs.his.utils.ConfigUtil;
+import com.fs.his.utils.IdCardUtil;
 import com.fs.his.utils.qrcode.QRCodeUtils;
 import com.fs.his.vo.*;
 import com.fs.im.dto.MsgCustomDTO;
@@ -517,7 +518,12 @@ public class FsPrescribeServiceImpl implements IFsPrescribeService
             return null;
         }
         long currentTimeMillis = System.currentTimeMillis();
-        long ageInMillis = currentTimeMillis - patJson.getBirthday();
+        Long birthday = patJson.getBirthday();
+        if (birthday == null) {
+            birthday = IdCardUtil.getBirthdayFromIdCard(patJson.getIdCard());
+            patJson.setBirthday(birthday);
+        }
+        long ageInMillis = currentTimeMillis - birthday;
         long ageInSeconds = ageInMillis / 1000;
         long ageInYears = ageInSeconds / (365 * 24 * 3600);
         fsPrescribe.setPatientAge(ageInYears+"");
@@ -525,7 +531,7 @@ public class FsPrescribeServiceImpl implements IFsPrescribeService
         fsPrescribe.setPatientName(patJson.getPatientName());
         fsPrescribe.setPatientTel(patJson.getMobile());
         fsPrescribe.setPatientGender(patJson.getSex().toString());
-        fsPrescribe.setPatientBirthday(new SimpleDateFormat("yyyy-MM-dd").format(new Date(patJson.getBirthday())));
+        fsPrescribe.setPatientBirthday(new SimpleDateFormat("yyyy-MM-dd").format(new Date(birthday)));
         fsPrescribe.setDoctorId(packageOrder.getDoctorId());
         FsDoctor fsDoctor = doctorMapper.selectFsDoctorByDoctorId(packageOrder.getDoctorId());
         if (fsDoctor==null){

+ 27 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsStoreOrderServiceImpl.java

@@ -60,6 +60,7 @@ import com.fs.huifuPay.sdk.opps.core.utils.HuiFuUtils;
 import com.fs.huifuPay.service.HuiFuService;
 import com.fs.im.dto.*;
 import com.fs.im.service.IImService;
+import com.fs.im.service.OpenIMService;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.domain.QwUser;
 import com.fs.qw.mapper.QwExternalContactMapper;
@@ -293,6 +294,11 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
     @Autowired
     private com.fs.gtPush.service.uniPush2Service uniPush2Service;
 
+    @Autowired
+    private FsUserInformationCollectionMapper fsUserInformationCollectionMapper;
+    @Autowired
+    private OpenIMService openIMService;
+
     //ERP 类型到服务的映射
     private Map<Integer, IErpOrderService> erpServiceMap;
 
@@ -1036,6 +1042,10 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
         }
 
         if (fsStoreOrderMapper.insertFsStoreOrder(order) > 0) {
+            if(CloudHostUtils.hasCloudHostName("金牛明医")){
+                //信息采集 发送药师im
+                doctorSendIm(packageOrder);
+            }
             if (packageOrder.getCycle() >= followRate) {
                 FsFollow fsFollow = new FsFollow();
                 fsFollow.setTempId(FollowTempId + 0L);
@@ -1120,6 +1130,23 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
         return R.ok();
     }
 
+    private void doctorSendIm(FsPackageOrder packageOrder) {
+        try {
+            //信息采集 发送药师im
+            FsUserInformationCollection fsUserInformationCollectionParam = new FsUserInformationCollection();
+            fsUserInformationCollectionParam.setPackageOrderId(packageOrder.getOrderId());
+            fsUserInformationCollectionParam.setPackageOrderCode(packageOrder.getOrderSn());
+            List<FsUserInformationCollection> fsUserInformationCollections = fsUserInformationCollectionMapper.selectFsUserInformationCollectionList(fsUserInformationCollectionParam);
+            if (!fsUserInformationCollections.isEmpty()) {
+                for (FsUserInformationCollection collection : fsUserInformationCollections) {
+                    openIMService.sendUserInformation(collection.getUserId(),collection.getDoctorType2Id(),collection.getId());
+                }
+            }
+        } catch (Exception e) {
+            log.error("信息采集 通知药师发送失败:{}",e.getMessage());
+        }
+    }
+
     @SuppressWarnings("all")
     @Override
     public String importSroreOrder(List<FsStoreProductDeliverExcelVO> list, Long storeId, Long companyId) {

+ 36 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsUserInformationCollectionServiceImpl.java

@@ -25,6 +25,7 @@ import com.fs.core.utils.OrderCodeUtils;
 import com.fs.his.config.FsSysConfig;
 import com.fs.his.domain.*;
 import com.fs.his.dto.FsUserInformationCollectionDTO;
+import com.fs.his.enums.FsPackageOrderStatusEnum;
 import com.fs.his.enums.FsStoreOrderStatusEnum;
 import com.fs.his.mapper.*;
 import com.fs.his.param.*;
@@ -59,6 +60,7 @@ import com.google.gson.Gson;
 import me.chanjar.weixin.common.error.WxErrorException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -131,6 +133,8 @@ public class FsUserInformationCollectionServiceImpl extends ServiceImpl<FsUserIn
 
     @Autowired
     private FsPackageOrderMapper packageOrderMapper;
+    @Autowired
+    private FsPatientMapper fsPatientMapper;
 
     @Autowired
     private FsPrescribeMapper fsPrescribeMapper;
@@ -971,6 +975,38 @@ public class FsUserInformationCollectionServiceImpl extends ServiceImpl<FsUserIn
         return fsUserInformationCollectionMapper.updateFsUserInformationCollection(fsUserInformationCollection);
     }
 
+    @Override
+    public FsUserInformationCollectionAndPatientVO selectFsUserInformationCollectionVoById(Long id) {
+        FsUserInformationCollection info = baseMapper.selectFsUserInformationCollectionById(id);
+        FsUserInformationCollectionAndPatientVO vo = new FsUserInformationCollectionAndPatientVO();
+        BeanUtils.copyProperties(info, vo);
+        Long patientId = info.getPatientId();
+        if(patientId != null){
+            FsPatient fsPatient = fsPatientMapper.selectFsPatientByPatientId(patientId);
+            if (fsPatient != null){
+
+                vo.setPatientInfo(fsPatient);
+                //查询是否支付
+                Integer isPay = 0;
+                Long packageOrderId = info.getPackageOrderId();
+                if (packageOrderId != null){
+                    FsPackageOrder order = packageOrderMapper.selectFsPackageOrderByOrderId(packageOrderId);
+                    if (order != null && order.getStatus() > 1){
+                        isPay = 1;
+                        vo.setStoreOrderId(order.getStoreOrderId());
+                        Integer status = order.getStatus();
+                        vo.setOrderStatus(FsPackageOrderStatusEnum.toType(status).getDesc()); //订单状态
+                        vo.setPackageJson(order.getPackageJson());
+                    }
+                }
+                vo.setIsPay(isPay);
+            }
+        }
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(info.getCompanyUserId());
+        info.setCompanyId(companyUser.getCompanyId());
+        return vo;
+    }
+
     private List<AnswerVO> getAnswerVOs(List<AnswerVO> target,List<AnswerVO> source) {
         target.addAll(source);
         return target.stream()

+ 20 - 0
fs-service/src/main/java/com/fs/his/utils/IdCardUtil.java

@@ -140,4 +140,24 @@ public class IdCardUtil {
             throw new RuntimeException("匹配请求异常", e);
         }
     }
+
+    /**
+     * 从身份证号码提取出生日期时间戳
+     * @param idCard 身份证号码
+     * @return 出生日期时间戳(毫秒)
+     */
+    public static Long getBirthdayFromIdCard(String idCard) {
+        if (idCard == null || idCard.length() != 18) {
+            throw new IllegalArgumentException("身份证号码格式不正确");
+        }
+
+        try {
+            String birthdayStr = idCard.substring(6, 14);
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
+            Date birthday = sdf.parse(birthdayStr);
+            return birthday.getTime();
+        } catch (Exception e) {
+            throw new IllegalArgumentException("身份证出生日期解析失败", e);
+        }
+    }
 }

+ 2 - 0
fs-service/src/main/java/com/fs/his/vo/FsUserInformationCollectionAndPatientVO.java

@@ -15,6 +15,8 @@ public class FsUserInformationCollectionAndPatientVO extends FsUserInformationCo
     private FsPatient patientInfo; //病人信息
     private Integer isPay;
     private Long storeOrderId;
+    private String orderStatus;
+    private String packageJson;
 
 
 }

+ 3 - 1
fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreOrderItemScrmMapper.java

@@ -76,7 +76,9 @@ public interface FsStoreOrderItemScrmMapper
 
     @Select({"<script> " +
             "select i.*,o.user_id,psps.cost,o.pay_postage,o.total_num,o.status,fspcs.cate_name, o.real_name,o.user_phone,o.user_address,o.create_time,o.pay_time,o.delivery_sn,o.delivery_name,o.delivery_id, c.company_name ,cu.nick_name as company_user_nick_name ,cu.phonenumber as company_usere_phonenumber,o.upload_time ,CASE WHEN o.certificates IS NULL OR o.certificates = '' THEN 0 ELSE 1 END AS is_upload   " +
-            " ,p.title as package_name,cts.name as scheduleName from fs_store_order_item_scrm i left join fs_store_order_scrm o on o.id=i.order_id left join fs_user u on o.user_id=u.user_id  " +
+            " ,p.title as package_name,cts.name as scheduleName, os.bank_transaction_id as bankTransactionId from fs_store_order_item_scrm i left join fs_store_order_scrm o on o.id=i.order_id" +
+            " left join fs_store_payment_scrm os on os.business_order_id = o.id " +
+            " left join fs_user u on o.user_id=u.user_id  " +
             " left join fs_store_product_package_scrm p on o.package_id=p.package_id left join company c on c.company_id=o.company_id left join company_user cu on cu.user_id=o.company_user_id left join company_tcm_schedule cts on cts.id = o.schedule_id " +
             " left join fs_store_product_scrm psps on i.product_id=psps.product_id left join fs_store_product_category_scrm fspcs on fspcs.cate_id=psps.cate_id " +
             "where 1=1 " +

+ 3 - 0
fs-service/src/main/java/com/fs/hisStore/param/FsStoreOrderParam.java

@@ -113,4 +113,7 @@ public class FsStoreOrderParam extends BaseEntity implements Serializable
 
     private String appId;
 
+    //银行交易流水号
+    private String bankTransactionId;
+
 }

+ 2 - 1
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreAfterSalesScrmServiceImpl.java

@@ -1427,7 +1427,8 @@ public class FsStoreAfterSalesScrmServiceImpl implements IFsStoreAfterSalesScrmS
         }
         if (payments != null && payments.size() > 0) {
             FsStorePaymentScrm payment = payments.get(0);
-            String json = configService.selectConfigByKey("store.pay");
+//            String json = configService.selectConfigByKey("store.pay");
+            String json = configService.selectConfigByKey("his.pay");
             FsPayConfigScrm fsPayConfig = JSON.parseObject(json, FsPayConfigScrm.class);
             if (payment.getPayMode().equals("wx")) {
                 WxPayConfig payConfig = new WxPayConfig();

+ 6 - 5
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java

@@ -3045,10 +3045,10 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                     TemplateDTO templateDTO = TemplateDTO.builder()
                             .number(num)
                             .price(price)
-                            .first(shippingTemplatesRegion.getFirst().doubleValue())
-                            .firstPrice(shippingTemplatesRegion.getFirstPrice())
-                            .continues(shippingTemplatesRegion.getContinues().doubleValue())
-                            .continuePrice(shippingTemplatesRegion.getContinuePrice())
+                            .first(ObjectUtil.isNotEmpty(shippingTemplatesRegion)?shippingTemplatesRegion.getFirst().doubleValue():0.0)
+                            .firstPrice(ObjectUtil.isNotEmpty(shippingTemplatesRegion)?shippingTemplatesRegion.getFirstPrice():new BigDecimal(0.0))
+                            .continues(ObjectUtil.isNotEmpty(shippingTemplatesRegion)?shippingTemplatesRegion.getContinues().doubleValue():0.0)
+                            .continuePrice(ObjectUtil.isNotEmpty(shippingTemplatesRegion)?shippingTemplatesRegion.getContinuePrice():new BigDecimal(0.0))
                             .tempId(tempId)
                             .cityId(cityId)
                             .build();
@@ -5008,7 +5008,8 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 // 获取未结算订单
                 List<FsStoreOrderScrm> orderScrmList = fsStoreOrderMapper.getUnsettledOrder();
 
-                String payConfig = configService.selectConfigByKey("store.pay");
+//                String payConfig = configService.selectConfigByKey("store.pay");
+                String payConfig = configService.selectConfigByKey("his.pay");
                 JSONObject js = JSON.parseObject(payConfig);
                 String appId = js.getString("appId");
 

+ 3 - 0
fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderItemExportVO.java

@@ -107,5 +107,8 @@ public class FsStoreOrderItemExportVO implements Serializable
     @Excel(name = "归属档期")
     private String scheduleName;
 
+    //银行交易流水号
+    @Excel(name = "银行交易流水号")
+    private String bankTransactionId;
 
 }

+ 4 - 0
fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderVO.java

@@ -267,5 +267,9 @@ public class FsStoreOrderVO implements Serializable
     //erp推送账号
     private String erpAccount;
 
+    /** 银行交易流水号 */
+    @Excel(name = "银行交易流水号")
+    private String bankTransactionId;
+
 
 }

+ 2 - 0
fs-service/src/main/java/com/fs/live/domain/Live.java

@@ -124,5 +124,7 @@ public class   Live extends BaseEntity {
     private Date createTime;
     private String companyName;
     private Long fileSize;
+    private Long videoFileSize;
+    private Long videoDuration;
     private Integer globalVisible;
 }

+ 3 - 0
fs-service/src/main/java/com/fs/live/mapper/LiveCouponMapper.java

@@ -125,4 +125,7 @@ public interface LiveCouponMapper
     @Select("select * from live_coupon_issue_relation where live_id = #{liveId}")
     List<LiveCouponIssueRelation> selectCouponRelationByLiveId(@Param("liveId") Long liveId);
 
+    @Select("select * from live_coupon_issue_relation where coupon_issue_id = #{couponIssueId}")
+    List<LiveCouponIssueRelation> selectCouponRelationByCouponIssueId(@Param("couponIssueId") Long couponIssueId);
+
 }

+ 4 - 1
fs-service/src/main/java/com/fs/live/mapper/LiveOrderMapper.java

@@ -107,7 +107,7 @@ public interface LiveOrderMapper {
     @Select("select * from live_order where `status` = 1 and extend_order_id is not null and delivery_sn is null ")
     List<LiveOrder> selectUpdateExpress();
 
-    @Select("select order_id from live_order where `status` = 2")
+    @Select("select order_id from live_order where `status` = 2 and delivery_code is not null and delivery_sn is not null and is_pay = 1")
     List<Long> selectSyncExpressIds();
 
     @Select("select order_id from live_order where `status` = 1 and extend_order_id is null and is_pay='1'")
@@ -444,4 +444,7 @@ public interface LiveOrderMapper {
      * @param dtoList 物流信息列表
      */
     void batchUpdateInOrderCode(@Param("list") List<LiveOrderDeliveryNoteDTO> dtoList);
+
+    @Select("SELECT * FROM live_order WHERE user_id=#{userId} LIMIT 1")
+    LiveOrder selectOrderByUserIdLimit1(@Param("userId") Long userId);
 }

+ 21 - 0
fs-service/src/main/java/com/fs/live/param/LiveNotifyParam.java

@@ -0,0 +1,21 @@
+package com.fs.live.param;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.HashMap;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class LiveNotifyParam {
+
+    private String liveId;
+    private String templateId;
+    private String maOpenId;
+    private Long userId;
+    private String appId;
+
+    HashMap<String,String> data;
+}

+ 3 - 0
fs-service/src/main/java/com/fs/live/param/LiveOrderParam.java

@@ -111,4 +111,7 @@ public class LiveOrderParam extends BaseEntity implements Serializable
     //导出字段
     private String filter;
 
+    //银行交易流水号
+    private String bankTransactionId;
+
 }

+ 7 - 0
fs-service/src/main/java/com/fs/live/service/ILiveAutoTaskService.java

@@ -89,4 +89,11 @@ public interface ILiveAutoTaskService {
     List<LiveAutoTask> selectLiveAutoTaskConsoleList(LiveAutoTask liveAutoTask);
 
     List<LiveAutoTask> consoleList(Long liveId);
+
+    void deleteAutoTasksByCouponId(Long couponId, Long liveId);
+    void deleteAutoTasksByRedId(Long redId, Long liveId);
+    void deleteAutoTasksByLotteryId(Long lotteryId, Long liveId);
+    void deleteAutoTasksByGoodsId(Long goodsId, Long liveId);
+    void deleteLotteryCache(Long lotteryId, Long liveId);
+    void deleteRedCache(Long redId, Long liveId);
 }

+ 3 - 1
fs-service/src/main/java/com/fs/live/service/ILiveOrderService.java

@@ -100,7 +100,7 @@ public interface ILiveOrderService {
      * @param orderId
      * @return
      */
-    int getGoods(Long orderId);
+    int finishishOrder(Long orderId);
 
     /**
      * 修改物流信息
@@ -255,4 +255,6 @@ public interface ILiveOrderService {
      * @return list
      * **/
     List<LiveOrderDeliveryNoteExportVO> getDeliveryNote(LiveOrderParam param);
+
+    LiveOrder selectOrderByUserIdLimit1(Long userId);
 }

+ 2 - 1
fs-service/src/main/java/com/fs/live/service/ILiveService.java

@@ -2,6 +2,7 @@ package com.fs.live.service;
 
 
 import com.fs.common.core.page.PageRequest;
+import com.fs.live.param.LiveNotifyParam;
 import com.fs.live.vo.LiveVo;
 import com.fs.common.core.domain.R;
 import com.fs.live.domain.Live;
@@ -181,7 +182,7 @@ public interface ILiveService
 
     List<Live> liveCompanyList(Long companyId);
 
-    R subNotifyLive(HashMap<String, Object> param);
+    R subNotifyLive(LiveNotifyParam liveNotifyParam);
 
     Integer updateLiveIsAudit(Live live);
 

+ 14 - 5
fs-service/src/main/java/com/fs/live/service/impl/LiveAfterSalesServiceImpl.java

@@ -25,6 +25,8 @@ import com.fs.config.cloud.CloudHostProper;
 import com.fs.erp.constant.AfterSalesOrderStatusEnum;
 import com.fs.erp.domain.FsJstAftersalePush;
 import com.fs.erp.dto.BaseResponse;
+import com.fs.erp.dto.ErpOrderQueryRequert;
+import com.fs.erp.dto.ErpOrderQueryResponse;
 import com.fs.erp.dto.ErpRefundUpdateRequest;
 import com.fs.erp.mapper.FsJstAftersalePushMapper;
 import com.fs.erp.service.IErpOrderService;
@@ -424,9 +426,16 @@ public class LiveAfterSalesServiceImpl implements ILiveAfterSalesService {
         request.setRefund_state(1);
         request.setStoreAfterSalesId(storeAfterSales.getId());
         if (StringUtils.isNotBlank(order.getExtendOrderId())){
-            BaseResponse response=erpOrderService.refundUpdateLive(request);
-            if(response.getSuccess()){
-                return R.ok();
+            ErpOrderQueryRequert queryRequest = new ErpOrderQueryRequert();
+            queryRequest.setCode(order.getExtendOrderId());
+            ErpOrderQueryResponse response = erpOrderService.getLiveOrder(queryRequest);
+            if (response.getOrders() != null && response.getOrders().size() > 0) {
+                if (response.getOrders().get(0).getCancle() != null && !response.getOrders().get(0).getCancle()) {
+                    BaseResponse res = erpOrderService.refundUpdateLive(request);
+                    if(res.getSuccess()){
+                        return R.ok();
+                    }
+                }
             }
             else{
                 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
@@ -542,7 +551,7 @@ public class LiveAfterSalesServiceImpl implements ILiveAfterSalesService {
     @Override
     public int updateLiveAfterSales(LiveAfterSales liveAfterSales)
     {
-        if (!"".equals(liveAfterSales.getDeliveryName()) && !"".equals(liveAfterSales.getDeliverySn())){
+        if (StringUtils.isNotEmpty(liveAfterSales.getDeliveryName()) && StringUtils.isNotEmpty(liveAfterSales.getDeliverySn()) && StringUtils.isNotEmpty(liveAfterSales.getDeliveryCode())) {
             liveAfterSales.setStatus(2);
         }
 
@@ -882,7 +891,7 @@ public class LiveAfterSalesServiceImpl implements ILiveAfterSalesService {
                 orderMap.setOrderCode(orderSn);
                 liveOrderService.updateLiveOrder(orderMap);
                 //生成新的订单
-                List<LiveOrderPayment> payments = liveOrderPaymentMapper.selectLiveOrderPaymentByPay(2, order.getOrderId());
+                List<LiveOrderPayment> payments = liveOrderPaymentMapper.selectLiveOrderPaymentByPay(5, order.getOrderId());
                 for (LiveOrderPayment payment : payments) {
                     LiveOrderPayment livePayment = new LiveOrderPayment();
                     livePayment.setPaymentId(payment.getPaymentId());

+ 242 - 4
fs-service/src/main/java/com/fs/live/service/impl/LiveAutoTaskServiceImpl.java

@@ -3,10 +3,7 @@ package com.fs.live.service.impl;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.ZoneId;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
 
 import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
@@ -333,6 +330,13 @@ public class LiveAutoTaskServiceImpl implements ILiveAutoTaskService {
     @Override
     public int deleteLiveAutoTaskByIds(Long[] ids)
     {
+        // 先从缓存中删除所有任务
+        for (Long id : ids) {
+            LiveAutoTask task = baseMapper.selectLiveAutoTaskById(id);
+            if (task != null) {
+                removeTaskFromCache(task);
+            }
+        }
         return baseMapper.deleteLiveAutoTaskByIds(ids);
     }
 
@@ -345,6 +349,12 @@ public class LiveAutoTaskServiceImpl implements ILiveAutoTaskService {
     @Override
     public int deleteLiveAutoTaskById(Long id)
     {
+        // 先查询任务信息
+        LiveAutoTask task = baseMapper.selectLiveAutoTaskById(id);
+        if (task != null) {
+            // 从缓存中删除
+            removeTaskFromCache(task);
+        }
         return baseMapper.deleteLiveAutoTaskById(id);
     }
 
@@ -414,4 +424,232 @@ public class LiveAutoTaskServiceImpl implements ILiveAutoTaskService {
     public List<LiveAutoTask> consoleList(Long liveId) {
         return baseMapper.consoleList(liveId, DateUtils.getNowDate());
     }
+
+    /**
+     * 删除与优惠券相关的自动化任务(taskType=5)
+     * @param couponId 优惠券ID
+     * @param liveId 直播间ID(可为null,null表示所有直播间)
+     */
+    @Override
+    public void deleteAutoTasksByCouponId(Long couponId, Long liveId) {
+        try {
+            List<LiveAutoTask> allTasks;
+            if (liveId != null) {
+                allTasks = baseMapper.selectLiveAutoTaskByLiveId(liveId);
+            } else {
+                // 查询所有直播间的任务
+                LiveAutoTask queryTask = new LiveAutoTask();
+                queryTask.setTaskType(5L); // 优惠券任务
+                allTasks = baseMapper.selectLiveAutoTaskList(queryTask);
+            }
+
+            List<Long> taskIdsToDelete = new ArrayList<>();
+            for (LiveAutoTask task : allTasks) {
+                if (task.getTaskType() != null && task.getTaskType() == 5L) {
+                    try {
+                        LiveCoupon liveCoupon = JSON.parseObject(task.getContent(), LiveCoupon.class);
+                        if (liveCoupon != null && couponId.equals(liveCoupon.getCouponId())) {
+                            taskIdsToDelete.add(task.getId());
+                            // 从缓存中删除
+                            removeTaskFromCache(task);
+                        }
+                    } catch (Exception e) {
+                        log.warn("解析自动化任务content失败,taskId: {}, error: {}", task.getId(), e.getMessage());
+                    }
+                }
+            }
+
+            if (!taskIdsToDelete.isEmpty()) {
+                Long[] ids = taskIdsToDelete.toArray(new Long[0]);
+                baseMapper.deleteLiveAutoTaskByIds(ids);
+                log.info("删除与优惠券ID {} 相关的自动化任务 {} 个", couponId, taskIdsToDelete.size());
+            }
+        } catch (Exception e) {
+            log.error("删除优惠券相关自动化任务失败,couponId: {}", couponId, e);
+        }
+    }
+
+    /**
+     * 删除与红包相关的自动化任务(taskType=2)
+     * @param redId 红包ID
+     * @param liveId 直播间ID
+     */
+    @Override
+    public void deleteAutoTasksByRedId(Long redId, Long liveId) {
+        try {
+            List<LiveAutoTask> allTasks = baseMapper.selectLiveAutoTaskByLiveId(liveId);
+            List<Long> taskIdsToDelete = new ArrayList<>();
+
+            for (LiveAutoTask task : allTasks) {
+                if (task.getTaskType() != null && task.getTaskType() == 2L) {
+                    try {
+                        LiveRedConf liveRedConf = JSON.parseObject(task.getContent(), LiveRedConf.class);
+                        if (liveRedConf != null && redId.equals(liveRedConf.getRedId())) {
+                            taskIdsToDelete.add(task.getId());
+                            // 从缓存中删除
+                            removeTaskFromCache(task);
+                        }
+                    } catch (Exception e) {
+                        log.warn("解析自动化任务content失败,taskId: {}, error: {}", task.getId(), e.getMessage());
+                    }
+                }
+            }
+
+            if (!taskIdsToDelete.isEmpty()) {
+                Long[] ids = taskIdsToDelete.toArray(new Long[0]);
+                baseMapper.deleteLiveAutoTaskByIds(ids);
+                log.info("删除与红包ID {} 相关的自动化任务 {} 个", redId, taskIdsToDelete.size());
+            }
+        } catch (Exception e) {
+            log.error("删除红包相关自动化任务失败,redId: {}, liveId: {}", redId, liveId, e);
+        }
+    }
+
+    /**
+     * 删除与抽奖相关的自动化任务(taskType=4)
+     * @param lotteryId 抽奖ID
+     * @param liveId 直播间ID
+     */
+    @Override
+    public void deleteAutoTasksByLotteryId(Long lotteryId, Long liveId) {
+        try {
+            List<LiveAutoTask> allTasks = baseMapper.selectLiveAutoTaskByLiveId(liveId);
+            List<Long> taskIdsToDelete = new ArrayList<>();
+
+            for (LiveAutoTask task : allTasks) {
+                if (task.getTaskType() != null && task.getTaskType() == 4L) {
+                    try {
+                        LiveLotteryConf liveLotteryConf = JSON.parseObject(task.getContent(), LiveLotteryConf.class);
+                        if (liveLotteryConf != null && lotteryId.equals(liveLotteryConf.getLotteryId())) {
+                            taskIdsToDelete.add(task.getId());
+                            // 从缓存中删除
+                            removeTaskFromCache(task);
+                        }
+                    } catch (Exception e) {
+                        log.warn("解析自动化任务content失败,taskId: {}, error: {}", task.getId(), e.getMessage());
+                    }
+                }
+            }
+
+            if (!taskIdsToDelete.isEmpty()) {
+                Long[] ids = taskIdsToDelete.toArray(new Long[0]);
+                baseMapper.deleteLiveAutoTaskByIds(ids);
+                log.info("删除与抽奖ID {} 相关的自动化任务 {} 个", lotteryId, taskIdsToDelete.size());
+            }
+        } catch (Exception e) {
+            log.error("删除抽奖相关自动化任务失败,lotteryId: {}, liveId: {}", lotteryId, liveId, e);
+        }
+    }
+
+    /**
+     * 删除与商品相关的自动化任务(taskType=1或6)
+     * @param goodsId 商品ID
+     * @param liveId 直播间ID
+     */
+    @Override
+    public void deleteAutoTasksByGoodsId(Long goodsId, Long liveId) {
+        try {
+            List<LiveAutoTask> allTasks = baseMapper.selectLiveAutoTaskByLiveId(liveId);
+            List<Long> taskIdsToDelete = new ArrayList<>();
+
+            for (LiveAutoTask task : allTasks) {
+                if (task.getTaskType() != null && (task.getTaskType() == 1L || task.getTaskType() == 6L)) {
+                    try {
+                        if (task.getTaskType() == 1L) {
+                            // 商品推荐任务
+                            LiveGoodsVo liveGoodsVo = JSON.parseObject(task.getContent(), LiveGoodsVo.class);
+                            if (liveGoodsVo != null && goodsId.equals(liveGoodsVo.getGoodsId())) {
+                                taskIdsToDelete.add(task.getId());
+                                removeTaskFromCache(task);
+                            }
+                        } else if (task.getTaskType() == 6L) {
+                            // 商品上下架任务
+                            com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(task.getContent());
+                            Long taskGoodsId = jsonObject.getLong("goodsId");
+                            if (taskGoodsId != null && goodsId.equals(taskGoodsId)) {
+                                taskIdsToDelete.add(task.getId());
+                                removeTaskFromCache(task);
+                            }
+                        }
+                    } catch (Exception e) {
+                        log.warn("解析自动化任务content失败,taskId: {}, error: {}", task.getId(), e.getMessage());
+                    }
+                }
+            }
+
+            if (!taskIdsToDelete.isEmpty()) {
+                Long[] ids = taskIdsToDelete.toArray(new Long[0]);
+                baseMapper.deleteLiveAutoTaskByIds(ids);
+                log.info("删除与商品ID {} 相关的自动化任务 {} 个", goodsId, taskIdsToDelete.size());
+            }
+        } catch (Exception e) {
+            log.error("删除商品相关自动化任务失败,goodsId: {}, liveId: {}", goodsId, liveId, e);
+        }
+    }
+
+    /**
+     * 从缓存中删除自动化任务
+     * @param task 自动化任务
+     */
+    private void removeTaskFromCache(LiveAutoTask task) {
+        try {
+            if (task.getLiveId() != null && task.getId() != null) {
+                String cacheKey = "live:auto_task:" + task.getLiveId();
+                // 获取ZSet中的所有任务
+                Set<String> allTasks = redisCache.redisTemplate.opsForZSet().range(cacheKey, 0, -1);
+                if (allTasks != null && !allTasks.isEmpty()) {
+                    // 遍历找到匹配的任务ID
+                    for (String taskJson : allTasks) {
+                        try {
+                            LiveAutoTask cachedTask = JSON.parseObject(taskJson, LiveAutoTask.class);
+                            if (cachedTask != null && task.getId().equals(cachedTask.getId())) {
+                                // 找到匹配的任务,从ZSet中删除
+                                redisCache.redisTemplate.opsForZSet().remove(cacheKey, taskJson);
+                                log.debug("从缓存中删除自动化任务,liveId: {}, taskId: {}", task.getLiveId(), task.getId());
+                                break;
+                            }
+                        } catch (Exception e) {
+                            log.warn("解析缓存中的任务失败,taskJson: {}, error: {}", taskJson, e.getMessage());
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            log.warn("从缓存删除自动化任务失败,taskId: {}, error: {}", task.getId(), e.getMessage());
+        }
+    }
+
+    /**
+     * 删除抽奖缓存
+     * @param lotteryId 抽奖ID
+     * @param liveId 直播间ID
+     */
+    public void deleteLotteryCache(Long lotteryId, Long liveId) {
+        try {
+            String cacheKey = "live:lottery_task:" + liveId;
+            // 从ZSet中删除指定的抽奖ID
+            redisCache.redisTemplate.opsForZSet().remove(cacheKey, String.valueOf(lotteryId));
+            log.info("删除抽奖缓存,lotteryId: {}, liveId: {}", lotteryId, liveId);
+        } catch (Exception e) {
+            log.error("删除抽奖缓存失败,lotteryId: {}, liveId: {}", lotteryId, liveId, e);
+        }
+    }
+
+    /**
+     * 删除红包缓存
+     * @param redId 红包ID
+     * @param liveId 直播间ID
+     */
+    public void deleteRedCache(Long redId, Long liveId) {
+        try {
+            String cacheKey = "live:red_task:" + liveId;
+            // 从ZSet中删除指定的红包ID
+            redisCache.redisTemplate.opsForZSet().remove(cacheKey, String.valueOf(redId));
+            // 同时删除剩余红包数的缓存
+            redisCache.deleteObject("live:red:remainingLots:" + redId);
+            log.info("删除红包缓存,redId: {}, liveId: {}", redId, liveId);
+        } catch (Exception e) {
+            log.error("删除红包缓存失败,redId: {}, liveId: {}", redId, liveId, e);
+        }
+    }
 }

+ 52 - 0
fs-service/src/main/java/com/fs/live/service/impl/LiveCouponIssueServiceImpl.java

@@ -3,7 +3,11 @@ package com.fs.live.service.impl;
 import java.util.Collections;
 import java.util.List;
 import com.fs.common.utils.DateUtils;
+import com.fs.live.domain.LiveCouponIssueRelation;
+import com.fs.live.mapper.LiveCouponMapper;
 import com.fs.live.param.CouponPO;
+import com.fs.live.service.ILiveAutoTaskService;
+import com.fs.live.vo.LiveCouponListVo;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.fs.live.mapper.LiveCouponIssueMapper;
@@ -21,6 +25,10 @@ public class LiveCouponIssueServiceImpl implements ILiveCouponIssueService
 {
     @Autowired
     private LiveCouponIssueMapper liveCouponIssueMapper;
+    @Autowired
+    private LiveCouponMapper liveCouponMapper;
+    @Autowired
+    private ILiveAutoTaskService liveAutoTaskService;
 
     /**
      * 查询优惠券领取
@@ -79,8 +87,31 @@ public class LiveCouponIssueServiceImpl implements ILiveCouponIssueService
      * @return 结果
      */
     @Override
+    @org.springframework.transaction.annotation.Transactional
     public int deleteLiveCouponIssueByIds(Long[] ids)
     {
+        // 联动删除:删除所有直播间存在的优惠券、定时任务和缓存
+        for (Long couponIssueId : ids) {
+            // 查询优惠券发布信息,获取couponId
+            LiveCouponIssue issue = liveCouponIssueMapper.selectLiveCouponIssueById(couponIssueId);
+            if (issue != null && issue.getCouponId() != null) {
+                // 删除所有直播间相关的自动化任务(liveId为null表示所有直播间)
+                liveAutoTaskService
+                        .deleteAutoTasksByCouponId(issue.getCouponId(), null);
+
+                // 查询所有使用该优惠券发布的直播间关联关系
+                List<LiveCouponIssueRelation> relations =
+                        liveCouponMapper.selectCouponRelationByCouponIssueId(couponIssueId);
+
+                // 删除所有直播间的关联关系
+                for (LiveCouponIssueRelation relation : relations) {
+                    LiveCouponListVo listVo = new LiveCouponListVo();
+                    listVo.setCouponIds(java.util.Arrays.asList(couponIssueId));
+                    listVo.setLiveId(relation.getLiveId().intValue());
+                    liveCouponMapper.handleDeleteSelectedAdmin(listVo);
+                }
+            }
+        }
         return liveCouponIssueMapper.deleteLiveCouponIssueByIds(ids);
     }
 
@@ -91,8 +122,29 @@ public class LiveCouponIssueServiceImpl implements ILiveCouponIssueService
      * @return 结果
      */
     @Override
+    @org.springframework.transaction.annotation.Transactional
     public int deleteLiveCouponIssueById(Long id)
     {
+        // 联动删除:删除所有直播间存在的优惠券、定时任务和缓存
+        // 查询优惠券发布信息,获取couponId
+        LiveCouponIssue issue = liveCouponIssueMapper.selectLiveCouponIssueById(id);
+        if (issue != null && issue.getCouponId() != null) {
+            // 删除所有直播间相关的自动化任务(liveId为null表示所有直播间)
+            liveAutoTaskService
+                    .deleteAutoTasksByCouponId(issue.getCouponId(), null);
+
+            // 查询所有使用该优惠券发布的直播间关联关系
+            List<LiveCouponIssueRelation> relations =
+                    liveCouponMapper.selectCouponRelationByCouponIssueId(id);
+
+            // 删除所有直播间的关联关系
+            for (LiveCouponIssueRelation relation : relations) {
+                LiveCouponListVo listVo = new LiveCouponListVo();
+                listVo.setCouponIds(java.util.Arrays.asList(id));
+                listVo.setLiveId(relation.getLiveId().intValue());
+                liveCouponMapper.handleDeleteSelectedAdmin(listVo);
+            }
+        }
         return liveCouponIssueMapper.deleteLiveCouponIssueById(id);
     }
 

+ 84 - 4
fs-service/src/main/java/com/fs/live/service/impl/LiveCouponServiceImpl.java

@@ -11,19 +11,17 @@ import com.fs.common.core.redis.RedisCache;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.live.domain.*;
+import com.fs.live.mapper.LiveCouponIssueMapper;
 import com.fs.live.mapper.LiveCouponIssueUserMapper;
 import com.fs.live.mapper.LiveMapper;
 import com.fs.live.param.CouponPO;
-import com.fs.live.service.ILiveCouponIssueService;
-import com.fs.live.service.ILiveCouponIssueUserService;
-import com.fs.live.service.ILiveCouponUserService;
+import com.fs.live.service.*;
 import com.fs.live.vo.LiveCouponListVo;
 
 import org.checkerframework.checker.units.qual.A;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.fs.live.mapper.LiveCouponMapper;
-import com.fs.live.service.ILiveCouponService;
 import org.springframework.transaction.annotation.Transactional;
 
 /**
@@ -51,6 +49,10 @@ public class LiveCouponServiceImpl implements ILiveCouponService
     private ILiveCouponIssueService liveCouponIssueService;
     @Autowired
     private LiveCouponIssueUserMapper liveCouponIssueUserMapper;
+    @Autowired
+    private ILiveAutoTaskService liveAutoTaskService;
+    @Autowired
+    private LiveCouponIssueMapper liveCouponIssueMapper;
 
     /**
      * 查询优惠券
@@ -109,8 +111,34 @@ public class LiveCouponServiceImpl implements ILiveCouponService
      * @return 结果
      */
     @Override
+    @Transactional
     public int deleteLiveCouponByIds(Long[] couponIds)
     {
+        // 联动删除:删除所有直播间存在的优惠券、定时任务和缓存
+        for (Long couponId : couponIds) {
+            // 删除所有直播间相关的自动化任务(liveId为null表示所有直播间)
+            liveAutoTaskService
+                    .deleteAutoTasksByCouponId(couponId, null);
+
+            // 查询所有使用该优惠券的优惠券发布记录
+            LiveCouponIssue queryIssue = new LiveCouponIssue();
+            queryIssue.setCouponId(couponId);
+            List<LiveCouponIssue> couponIssues = liveCouponIssueMapper.selectLiveCouponIssueList(queryIssue);
+
+            // 删除所有直播间的关联关系
+            for (LiveCouponIssue issue : couponIssues) {
+                if (issue.getId() != null) {
+                    // 查询所有使用该优惠券发布的直播间关联关系
+                    List<LiveCouponIssueRelation> relations = liveCouponMapper.selectCouponRelationByCouponIssueId(issue.getId());
+                    for (LiveCouponIssueRelation relation : relations) {
+                        LiveCouponListVo listVo = new LiveCouponListVo();
+                        listVo.setCouponIds(java.util.Arrays.asList(issue.getId()));
+                        listVo.setLiveId(relation.getLiveId().intValue());
+                        liveCouponMapper.handleDeleteSelectedAdmin(listVo);
+                    }
+                }
+            }
+        }
         return liveCouponMapper.deleteLiveCouponByIds(couponIds);
     }
 
@@ -121,8 +149,32 @@ public class LiveCouponServiceImpl implements ILiveCouponService
      * @return 结果
      */
     @Override
+    @Transactional
     public int deleteLiveCouponById(Long couponId)
     {
+        // 联动删除:删除所有直播间存在的优惠券、定时任务和缓存
+        // 删除所有直播间相关的自动化任务(liveId为null表示所有直播间)
+        liveAutoTaskService
+                .deleteAutoTasksByCouponId(couponId, null);
+
+        // 查询所有使用该优惠券的优惠券发布记录
+        LiveCouponIssue queryIssue = new LiveCouponIssue();
+        queryIssue.setCouponId(couponId);
+        List<LiveCouponIssue> couponIssues = liveCouponIssueMapper.selectLiveCouponIssueList(queryIssue);
+
+        // 删除所有直播间的关联关系
+        for (LiveCouponIssue issue : couponIssues) {
+            if (issue.getId() != null) {
+                // 查询所有使用该优惠券发布的直播间关联关系
+                List<LiveCouponIssueRelation> relations = liveCouponMapper.selectCouponRelationByCouponIssueId(issue.getId());
+                for (LiveCouponIssueRelation relation : relations) {
+                    LiveCouponListVo listVo = new LiveCouponListVo();
+                    listVo.setCouponIds(java.util.Arrays.asList(issue.getId()));
+                    listVo.setLiveId(relation.getLiveId().intValue());
+                    liveCouponMapper.handleDeleteSelectedAdmin(listVo);
+                }
+            }
+        }
         return liveCouponMapper.deleteLiveCouponById(couponId);
     }
 
@@ -185,13 +237,41 @@ public class LiveCouponServiceImpl implements ILiveCouponService
     }
 
     @Override
+    @Transactional
     public R handleDeleteSelectedAdmin(LiveCouponListVo listVo) {
+        // 在删除前,查询关联关系,获取couponId和liveId,用于联动删除
+        if (listVo.getCouponIds() != null && !listVo.getCouponIds().isEmpty() && listVo.getLiveId() != null) {
+            Long liveId = Long.valueOf(listVo.getLiveId());
+            for (Long couponIssueId : listVo.getCouponIds()) {
+                // 查询优惠券发布信息
+                LiveCouponIssue liveCouponIssue = liveCouponIssueMapper.selectLiveCouponIssueById(couponIssueId);
+                if (liveCouponIssue != null && liveCouponIssue.getCouponId() != null) {
+                    // 删除相关的自动化任务
+                    liveAutoTaskService
+                            .deleteAutoTasksByCouponId(liveCouponIssue.getCouponId(), liveId);
+                }
+            }
+        }
         liveCouponMapper.handleDeleteSelectedAdmin(listVo);
         return R.ok();
     }
 
     @Override
+    @Transactional
     public int delLiveCoupon(LiveCouponListVo vo) {
+        // 在删除前,查询关联关系,获取couponId和liveId,用于联动删除
+        if (vo.getCouponIds() != null && !vo.getCouponIds().isEmpty() && vo.getLiveId() != null) {
+            Long liveId = Long.valueOf(vo.getLiveId());
+            for (Long couponIssueId : vo.getCouponIds()) {
+                // 查询优惠券发布信息
+                LiveCouponIssue liveCouponIssue = liveCouponIssueMapper.selectLiveCouponIssueById(couponIssueId);
+                if (liveCouponIssue != null && liveCouponIssue.getCouponId() != null) {
+                    // 删除相关的自动化任务
+                    liveAutoTaskService
+                            .deleteAutoTasksByCouponId(liveCouponIssue.getCouponId(), liveId);
+                }
+            }
+        }
         liveCouponMapper.handleDeleteSelectedAdmin(vo);
         return 1;
     }

+ 43 - 0
fs-service/src/main/java/com/fs/live/service/impl/LiveGoodsServiceImpl.java

@@ -11,6 +11,7 @@ import com.fs.hisStore.domain.FsStoreProductScrm;
 import com.fs.hisStore.mapper.FsStoreProductScrmMapper;
 import com.fs.live.domain.LiveGoods;
 import com.fs.live.mapper.LiveGoodsMapper;
+import com.fs.live.service.ILiveAutoTaskService;
 import com.fs.live.service.ILiveGoodsService;
 import com.fs.live.vo.LiveGoodsListVo;
 import com.fs.live.vo.LiveGoodsVo;
@@ -37,6 +38,8 @@ public class LiveGoodsServiceImpl  implements ILiveGoodsService {
 
     @Autowired
     private LiveGoodsMapper baseMapper;
+    @Autowired
+    private ILiveAutoTaskService liveAutoTaskService;
 
     /**
      * 查询直播商品
@@ -105,8 +108,17 @@ public class LiveGoodsServiceImpl  implements ILiveGoodsService {
      * @return 结果
      */
     @Override
+    @org.springframework.transaction.annotation.Transactional
     public int deleteLiveGoodsByGoodsIds(Long[] goodsIds)
     {
+        // 联动删除:删除相关的自动化任务
+        for (Long goodsId : goodsIds) {
+            LiveGoods goods = baseMapper.selectLiveGoodsByGoodsId(goodsId);
+            if (goods != null && goods.getLiveId() != null) {
+                liveAutoTaskService
+                        .deleteAutoTasksByGoodsId(goodsId, goods.getLiveId());
+            }
+        }
         return baseMapper.deleteLiveGoodsByGoodsIds(goodsIds);
     }
 
@@ -117,8 +129,16 @@ public class LiveGoodsServiceImpl  implements ILiveGoodsService {
      * @return 结果
      */
     @Override
+    @org.springframework.transaction.annotation.Transactional
     public int deleteLiveGoodsByGoodsId(Long goodsId)
     {
+        // 先查询商品信息,获取liveId
+        LiveGoods goods = baseMapper.selectLiveGoodsByGoodsId(goodsId);
+        if (goods != null && goods.getLiveId() != null) {
+            // 删除相关的自动化任务
+            liveAutoTaskService
+                    .deleteAutoTasksByGoodsId(goodsId, goods.getLiveId());
+        }
         return baseMapper.deleteLiveGoodsByGoodsId(goodsId);
     }
 
@@ -276,7 +296,18 @@ public class LiveGoodsServiceImpl  implements ILiveGoodsService {
     }
 
     @Override
+    @org.springframework.transaction.annotation.Transactional
     public R handleDeleteSelected(LiveGoodsListVo listVo) {
+        // 联动删除:删除相关的自动化任务
+        if (listVo.getGoodsIds() != null && !listVo.getGoodsIds().isEmpty()) {
+            Long liveId = listVo.getLiveId() != null ? Long.valueOf(listVo.getLiveId()) : null;
+            for (Long goodsId : listVo.getGoodsIds()) {
+                if (liveId != null) {
+                    liveAutoTaskService
+                            .deleteAutoTasksByGoodsId(goodsId, liveId);
+                }
+            }
+        }
         int deleteCount = baseMapper.deleteBatchList(listVo);
         if (deleteCount > 0) {
             return R.ok("操作成功");
@@ -306,7 +337,19 @@ public class LiveGoodsServiceImpl  implements ILiveGoodsService {
     }
 
     @Override
+    @org.springframework.transaction.annotation.Transactional
     public R handleDeleteSelectedAdmin(LiveGoodsListVo listVo) {
+        // 联动删除:删除相关的自动化任务
+        if (listVo.getGoodsIds() != null && !listVo.getGoodsIds().isEmpty()) {
+            // 需要查询每个商品的liveId
+            for (Long goodsId : listVo.getGoodsIds()) {
+                LiveGoods goods = baseMapper.selectLiveGoodsByGoodsId(goodsId);
+                if (goods != null && goods.getLiveId() != null) {
+                    liveAutoTaskService
+                            .deleteAutoTasksByGoodsId(goodsId, goods.getLiveId());
+                }
+            }
+        }
         baseMapper.handleDeleteSelectedAdmin(listVo);
         return R.ok();
     }

+ 36 - 0
fs-service/src/main/java/com/fs/live/service/impl/LiveLotteryConfServiceImpl.java

@@ -12,6 +12,7 @@ import com.fs.live.mapper.LiveLotteryRegistrationMapper;
 import com.fs.live.param.LiveLotteryProduct;
 import com.fs.live.param.LiveLotteryProductSaveParam;
 import com.fs.live.param.LotteryPO;
+import com.fs.live.service.ILiveAutoTaskService;
 import com.fs.live.service.ILiveLotteryConfService;
 import com.fs.live.vo.LiveLotteryConfVo;
 import com.fs.live.vo.LiveLotteryProductListVo;
@@ -46,6 +47,8 @@ public class LiveLotteryConfServiceImpl implements ILiveLotteryConfService {
 
     @Autowired
     private LiveLotteryConfMapper baseMapper;
+    @Autowired
+    private ILiveAutoTaskService liveAutoTaskService;
     /**
      * 查询直播抽奖配置
      *
@@ -117,8 +120,21 @@ public class LiveLotteryConfServiceImpl implements ILiveLotteryConfService {
      * @return 结果
      */
     @Override
+    @Transactional
     public int deleteLiveLotteryConfByLotteryIds(Long[] lotteryIds)
     {
+        // 联动删除:删除相关的自动化任务和缓存
+        for (Long lotteryId : lotteryIds) {
+            LiveLotteryConf conf = baseMapper.selectLiveLotteryConfByLotteryId(lotteryId);
+            if (conf != null && conf.getLiveId() != null) {
+                // 删除相关的自动化任务
+                liveAutoTaskService
+                        .deleteAutoTasksByLotteryId(lotteryId, conf.getLiveId());
+                // 删除抽奖缓存
+                liveAutoTaskService
+                        .deleteLotteryCache(lotteryId, conf.getLiveId());
+            }
+        }
         return baseMapper.deleteLiveLotteryConfByLotteryIds(lotteryIds);
     }
 
@@ -132,6 +148,16 @@ public class LiveLotteryConfServiceImpl implements ILiveLotteryConfService {
     @Transactional
     public int deleteLiveLotteryConfByLotteryId(Long lotteryId)
     {
+        // 先查询抽奖配置,获取liveId
+        LiveLotteryConf conf = baseMapper.selectLiveLotteryConfByLotteryId(lotteryId);
+        if (conf != null && conf.getLiveId() != null) {
+            // 删除相关的自动化任务
+            liveAutoTaskService
+                    .deleteAutoTasksByLotteryId(lotteryId, conf.getLiveId());
+            // 删除抽奖缓存
+            liveAutoTaskService
+                    .deleteLotteryCache(lotteryId, conf.getLiveId());
+        }
         return baseMapper.deleteLiveLotteryConfByLotteryId(lotteryId);
     }
 
@@ -162,6 +188,16 @@ public class LiveLotteryConfServiceImpl implements ILiveLotteryConfService {
     @Override
     @Transactional
     public void delete(Long lotteryId) {
+        // 先查询抽奖配置,获取liveId
+        LiveLotteryConf conf = mapper.selectById(lotteryId);
+        if (conf != null && conf.getLiveId() != null) {
+            // 删除相关的自动化任务
+            liveAutoTaskService
+                    .deleteAutoTasksByLotteryId(lotteryId, conf.getLiveId());
+            // 删除抽奖缓存
+            liveAutoTaskService
+                    .deleteLotteryCache(lotteryId, conf.getLiveId());
+        }
         mapper.deleteById(lotteryId);
     }
 

+ 63 - 13
fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java

@@ -91,6 +91,7 @@ import com.fs.live.dto.LiveOrderComputeDTO;
 import com.fs.live.dto.LiveOrderCustomerExportDTO;
 import com.fs.live.dto.LiveOrderDeliveryNoteDTO;
 import com.fs.live.dto.LiveOrderItemDTO;
+import com.fs.live.enums.LiveAfterSalesStatusEnum;
 import com.fs.live.mapper.*;
 import com.fs.live.param.*;
 import com.fs.live.service.*;
@@ -656,7 +657,10 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
             log.info("组合码为空,订单ID:" + order.getOrderCode());
             return ;
         }
-
+        // 上面getErpOrder(order) 会更新掉订单信息
+        order.setDeliverySn(null);
+        order.setDeliveryCode(null);
+        order.setDeliveryName(null);
         if (erpOrderService == jSTOrderService) {
             erpOrder.setShop_code(erpConfig.getErpJstShopCode());
         }
@@ -1133,6 +1137,15 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
         IErpOrderService erpOrderService = getErpService();
         FsErpConfig erpConfig = configUtil.generateStructConfigByKey("his.config", FsErpConfig.class);
         LiveOrder order = baseMapper.selectLiveOrderByOrderId(String.valueOf(orderId));
+        LiveAfterSales updateSales = liveAfterSalesMapper.getLiveAfterSalesByOrderId(orderId);
+        if (updateSales == null) {
+            return R.error("售后单不存在");
+        }
+        LiveAfterSales liveMp = new LiveAfterSales();
+        liveMp.setId(updateSales.getId());
+        liveMp.setStatus(LiveAfterSalesStatusEnum.STATUS_4.getValue());
+        liveMp.setSalesStatus(3);
+        liveAfterSalesMapper.updateLiveAfterSales(liveMp);
         if (order == null) {
             return R.error("订单不存在");
         }
@@ -1171,15 +1184,23 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                 }
                 return liveAfterSalesService.applyForAfterSales(order.getUserId(), param);
             } else {
-                jSTOrderService.refundUpdateLive(request);
+                ErpOrderQueryRequert queryRequest = new ErpOrderQueryRequert();
+                queryRequest.setCode(order.getExtendOrderId());
+                ErpOrderQueryResponse response = erpOrderService.getLiveOrder(queryRequest);
+                if (response.getOrders() != null && response.getOrders().size() > 0) {
+                    if (response.getOrders().get(0).getCancle() != null && !response.getOrders().get(0).getCancle()) {
+                        jSTOrderService.refundUpdateLive(request);
+                    }
+                }
             }
         }
-        order.setStatus(OrderInfoEnum.STATUS_2.getValue());
+        order.setStatus(OrderInfoEnum.STATUS_NE2.getValue());
         order.setRefundMoney(order.getPayMoney());
         order.setRefundStatus(String.valueOf(OrderInfoEnum.REFUND_STATUS_2.getValue()));
         liveUserLotteryRecordMapper.updateOrderStatusByOrderId(order.getOrderId(), -2);
         baseMapper.updateLiveOrder(order);
 
+
         //退库存
         //获取订单下的商品
         List<LiveOrderItem> orderItemVOS = liveOrderItemMapper.selectLiveOrderItemByOrderId(order.getOrderId());
@@ -1294,6 +1315,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                 userService.subTuiMoney(storeOrder);
             }
         }
+
         return R.ok();
     }
 
@@ -1345,7 +1367,14 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                 }
                 return liveAfterSalesService.applyForAfterSales(order.getUserId(), param);
             } else {
-                jSTOrderService.refundUpdateLive(request);
+                ErpOrderQueryRequert queryRequest = new ErpOrderQueryRequert();
+                queryRequest.setCode(order.getExtendOrderId());
+                ErpOrderQueryResponse response = erpOrderService.getLiveOrder(queryRequest);
+                if (response.getOrders() != null && response.getOrders().size() > 0) {
+                    if (response.getOrders().get(0).getCancle() != null && !response.getOrders().get(0).getCancle()) {
+                        jSTOrderService.refundUpdateLive(request);
+                    }
+                }
             }
         }
         order.setStatus(OrderInfoEnum.STATUS_NE2.getValue());
@@ -1468,6 +1497,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                 userService.subLiveTuiMoney(liveOrder);
             }
         }
+
         return R.ok();
     }
 
@@ -1581,7 +1611,10 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
             erpOrder.setShop_code(erpConfig.getErpJstShopCode());
         }
         ErpOrderResponse response = erpOrderService.addLiveOrder(erpOrder);
-
+        // 上面getErpOrder(order) 会更新掉订单信息
+        order.setDeliverySn(null);
+        order.setDeliveryCode(null);
+        order.setDeliveryName(null);
         //写入日志
         log.info("ErpCreate:" + order.getOrderCode() + ":" + JSONUtil.toJsonStr(response));
         //支付成功后 将订单号写入待发货的REDIS中
@@ -2661,17 +2694,19 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
         baseMapper.updateLiveOrder(updateEntity);
         //如果是正常签收,更新订单状态
         if(dto.getState().equals("3")&&(dto.getStateEx().equals("301")||dto.getStateEx().equals("302")||dto.getStateEx().equals("304")||dto.getStateEx().equals("311"))){
-            this.getGoods(order.getOrderId());
+            this.finishishOrder(order.getOrderId());
         }
         return R.ok();
     }
 
     @Override
-    public int getGoods(Long orderId) {
+    public int finishishOrder(Long orderId) {
 
         LiveOrder order = baseMapper.selectLiveOrderByOrderId(String.valueOf(orderId));
         if (order==null)throw new CustomException("订单不存在");
-        if (order.getStatus()!= OrderInfoEnum.STATUS_3.getValue())throw new CustomException("非法更改");
+        if (!Objects.equals(order.getStatus(), OrderInfoEnum.STATUS_2.getValue()))throw new CustomException("非法更改");
+        liveOrderLogsService.create(order.getOrderId(), OrderLogEnum.FINISH_ORDER.getValue(),
+                OrderLogEnum.FINISH_ORDER.getDesc());
         LiveOrder updateEntity = new LiveOrder();
         updateEntity.setOrderId(order.getOrderId());
         updateEntity.setUpdateTime(new DateTime());
@@ -2690,8 +2725,16 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
 //                OrderLogEnum.FINISH_ORDER.getDesc());
 
         int i = baseMapper.updateLiveOrder(updateEntity);
-        liveUserLotteryRecordMapper.updateOrderStatusByOrderId(order.getOrderId(), OrderInfoEnum.STATUS_3.getValue());
-
+        //模板消息支付成功发布事件
+        TemplateBean templateBean = TemplateBean.builder()
+                .orderId(order.getOrderId().toString())
+                .orderCode(order.getOrderCode().toString())
+                .remark("您的订单已签收成功")
+                .finishTime(order.getFinishTime())
+                .userId(Long.valueOf(order.getUserId()))
+                .templateType(TemplateListenEnum.TYPE_3.getValue())
+                .build();
+        publisher.publishEvent(new TemplateEvent(this, templateBean));
         return i;
     }
 
@@ -2769,7 +2812,8 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
             }
             FsUserScrm user = userMapper.selectFsUserById(Long.valueOf(liveOrder.getUserId()));
             if(user == null) return R.error("用户不存在");
-            String json = configService.selectConfigByKey("store.pay");
+//            String json = configService.selectConfigByKey("store.pay");
+            String json = configService.selectConfigByKey("his.pay");
             FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);
             String payCode =  OrderCodeUtils.getOrderSn();
             if(StringUtils.isEmpty(payCode)){
@@ -3017,7 +3061,8 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                 // 获取未结算订单
                 List<LiveOrder> orderScrmList = liveOrderMapper.getUnsettledOrder();
 
-                String payConfig = configService.selectConfigByKey("store.pay");
+//                String payConfig = configService.selectConfigByKey("store.pay");
+                String payConfig = configService.selectConfigByKey("his.pay");
                 JSONObject js = JSON.parseObject(payConfig);
                 String appId = js.getString("appId");
 
@@ -3262,6 +3307,11 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
         return baseMapper.getDeliveryNote(param);
     }
 
+    @Override
+    public LiveOrder selectOrderByUserIdLimit1(Long userId) {
+        return baseMapper.selectOrderByUserIdLimit1(userId);
+    }
+
 
     @Override
     @Transactional(rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)
@@ -3294,7 +3344,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
 
         // 更改店铺库存
         fsStoreProduct.setStock(fsStoreProduct.getStock()-Integer.parseInt(liveOrder.getTotalNum()));
-        fsStoreProduct.setSales(fsStoreProduct.getSales()+Long.parseLong(liveOrder.getTotalNum()));
+        fsStoreProduct.setSales(fsStoreProduct.getSales()+Integer.parseInt(liveOrder.getTotalNum()));
         fsStoreProductService.updateFsStoreProduct(fsStoreProduct);
         // 更新直播间库存
         goods.setStock(goods.getStock()-Integer.parseInt(liveOrder.getTotalNum()));

+ 36 - 0
fs-service/src/main/java/com/fs/live/service/impl/LiveRedConfServiceImpl.java

@@ -16,6 +16,7 @@ import com.fs.live.mapper.LiveRedConfMapper;
 import com.fs.live.mapper.LiveRewardRecordMapper;
 import com.fs.live.mapper.LiveUserRedRecordMapper;
 import com.fs.live.param.RedPO;
+import com.fs.live.service.ILiveAutoTaskService;
 import com.fs.live.service.ILiveRedConfService;
 
 import org.slf4j.Logger;
@@ -54,6 +55,8 @@ public class LiveRedConfServiceImpl implements ILiveRedConfService {
     private LiveMapper liveMapper;
     @Autowired
     private LiveRewardRecordMapper liveRewardRecordMapper;
+    @Autowired
+    private ILiveAutoTaskService liveAutoTaskService;
 
     private static final String REDPACKET_REMAININGLOTS_KEY = "live:red:remainingLots:";
     private static final String REDPACKET_REMAININGNUM_KEY = "live:red:remainingNum:";
@@ -133,8 +136,20 @@ public class LiveRedConfServiceImpl implements ILiveRedConfService {
      * @return 结果
      */
     @Override
+    @Transactional
     public int deleteLiveRedConfByRedIds(Long[] redIds)
     {
+        // 联动删除:删除相关的自动化任务和缓存
+        for (Long redId : redIds) {
+            LiveRedConf conf = baseMapper.selectLiveRedConfByRedId(redId);
+            if (conf != null && conf.getLiveId() != null) {
+                // 删除相关的自动化任务
+                liveAutoTaskService.deleteAutoTasksByRedId(redId, conf.getLiveId());
+                // 删除红包缓存
+                liveAutoTaskService
+                        .deleteRedCache(redId, conf.getLiveId());
+            }
+        }
         return baseMapper.deleteLiveRedConfByRedIds(redIds);
     }
 
@@ -145,8 +160,19 @@ public class LiveRedConfServiceImpl implements ILiveRedConfService {
      * @return 结果
      */
     @Override
+    @Transactional
     public int deleteLiveRedConfByRedId(Long redId)
     {
+        // 先查询红包配置,获取liveId
+        LiveRedConf conf = baseMapper.selectLiveRedConfByRedId(redId);
+        if (conf != null && conf.getLiveId() != null) {
+            // 删除相关的自动化任务
+            liveAutoTaskService
+                    .deleteAutoTasksByRedId(redId, conf.getLiveId());
+            // 删除红包缓存
+            liveAutoTaskService
+                    .deleteRedCache(redId, conf.getLiveId());
+        }
         return baseMapper.deleteLiveRedConfByRedId(redId);
     }
 
@@ -177,6 +203,16 @@ public class LiveRedConfServiceImpl implements ILiveRedConfService {
     @Override
     @Transactional
     public void delete(Long redId) {
+        // 先查询红包配置,获取liveId
+        LiveRedConf conf = baseMapper.selectById(redId);
+        if (conf != null && conf.getLiveId() != null) {
+            // 删除相关的自动化任务
+            liveAutoTaskService
+                    .deleteAutoTasksByRedId(redId, conf.getLiveId());
+            // 删除红包缓存
+            liveAutoTaskService
+                    .deleteRedCache(redId, conf.getLiveId());
+        }
         baseMapper.deleteById(redId);
     }
 

+ 23 - 13
fs-service/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java

@@ -22,6 +22,7 @@ import com.fs.hisStore.domain.FsStoreProductScrm;
 import com.fs.hisStore.mapper.FsStoreProductScrmMapper;
 import com.fs.live.dto.TemplateMessageSendRequestDTO;
 import com.fs.live.enums.MiniAppNotifyTaskStatusEnum;
+import com.fs.live.param.LiveNotifyParam;
 import com.fs.live.vo.LiveVo;
 import com.fs.common.constant.LiveKeysConstant;
 import com.fs.common.core.domain.R;
@@ -144,6 +145,8 @@ public class LiveServiceImpl implements ILiveService
             byId.setDuration(liveVideo.getDuration());
             byId.setVideoId(liveVideo.getVideoId());
             byId.setVideoType(liveVideo.getVideoType());
+            byId.setVideoFileSize(liveVideo.getFileSize());
+            byId.setVideoDuration(liveVideo.getDuration());
         }
         return byId;
     }
@@ -245,20 +248,20 @@ public class LiveServiceImpl implements ILiveService
     }
 
     @Override
-    public R subNotifyLive(HashMap<String, Object> param) {
+    public R subNotifyLive(LiveNotifyParam param) {
         LiveMiniprogramSubNotifyTask notifyTask = new LiveMiniprogramSubNotifyTask();
-        notifyTask.setPage("/pages_course/living?liveId=" + param.get("liveId"));
+        notifyTask.setPage("/pages_course/living?liveId=" + param.getLiveId());
         notifyTask.setTaskName("直播间预约提醒");
-        notifyTask.setTemplateId((String) param.get("templateId"));
-        Long userId = Long.valueOf((Integer) param.get("userId"));
+        notifyTask.setTemplateId(param.getTemplateId());
+        Long userId = param.getUserId();
         Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
                 .eq(FsUserWx::getFsUserId, userId)
-                .eq(FsUserWx::getAppId, param.getOrDefault("appid", "wx44beed5640bcb1ba"));
+                .eq(FsUserWx::getAppId, StringUtils.isEmpty(param.getAppId()) ? "wx44beed5640bcb1ba" : param.getAppId()); // 卓美小程序
         FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
         String maOpenId = fsUserWx.getOpenId();
-//        if (StringUtils.isEmpty(maOpenId)) {
-//            maOpenId = (String) param.get("maOpenId");
-//        }
+        if (StringUtils.isEmpty(maOpenId)) {
+            maOpenId = param.getMaOpenId();
+        }
         notifyTask.setTouser(maOpenId);
         notifyTask.setPage(String.valueOf(1));
 
@@ -268,7 +271,7 @@ public class LiveServiceImpl implements ILiveService
         notifyTask.setRetryCount(0);
         notifyTask.setMaxRetries(3);
         Map<String, TemplateMessageSendRequestDTO.TemplateDataValue> data = new HashMap<>();
-        HashMap<String,String> mapData = (HashMap<String, String>) param.get("data");
+        HashMap<String,String> mapData =  param.getData();
         // 定义日期时间格式器,注意与字符串格式完全匹配
         DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
 
@@ -280,7 +283,7 @@ public class LiveServiceImpl implements ILiveService
         });
         notifyTask.setData(JSON.toJSONString(data));
 //        return R.ok("success");
-        liveMiniprogramSubNotifyTaskMapper.insert(notifyTask);
+//        liveMiniprogramSubNotifyTaskMapper.insert(notifyTask);
 
         return R.ok("success");
     }
@@ -387,6 +390,7 @@ public class LiveServiceImpl implements ILiveService
     @Override
     @Transactional
     public int updateLiveEntity(Live live) {
+        log.error("updateLiveEntity:"+ live.getLiveId());
         return baseMapper.updateLive( live);
     }
 
@@ -524,6 +528,7 @@ public class LiveServiceImpl implements ILiveService
             live.setLiveConfig(JSON.toJSONString(liveReplayParam));
 
         }
+        log.error("updateLive:" + live.getLiveId());
         int result = baseMapper.updateLive(live);
         liveAutoTaskService.recalcLiveAutoTask(live);
 
@@ -659,6 +664,7 @@ public class LiveServiceImpl implements ILiveService
         live.setStatus(1);
         live.setFinishTime(LocalDateTime.now());
         live.setLiveType(2);
+        log.error("closeLiving:" + live.getLiveId());
         baseMapper.updateLive(live);
         return R.ok();
     }
@@ -694,7 +700,7 @@ public class LiveServiceImpl implements ILiveService
             curLive.setRtmpUrl("rtmp://your-srs-server/live/" + streamKey);
             curLive.setUpdateTime(now);
 
-
+            log.error("startLoopPlay:" + live.getLiveId());
             baseMapper.updateLive(curLive);
 
             return R.ok();
@@ -722,6 +728,7 @@ public class LiveServiceImpl implements ILiveService
             // 更新流状态
             curLive.setStatus(2);
             curLive.setUpdateTime(new Date());
+            log.error("stopLoopPlay:" + live.getLiveId());
             baseMapper.updateLive(curLive);
 
             return R.ok();
@@ -733,6 +740,7 @@ public class LiveServiceImpl implements ILiveService
     @Override
     public R handleShelfOrUn(LiveListVo listVo) {
         int updatedCount = baseMapper.updateBatchLiveList(listVo);
+        log.error("有人下架了视频:" + listVo.getLiveIds());
         if (updatedCount > 0) {
             return R.ok("操作成功");
         }
@@ -757,7 +765,7 @@ public class LiveServiceImpl implements ILiveService
         if (exist.getStatus() == 3) {
             return R.error("直播已结束");
         }
-
+        log.error("finishLive:" + live.getLiveId());
         exist.setStatus(3);
         exist.setFinishTime(LocalDateTime.now());
         exist.setUpdateTime(new Date());
@@ -787,7 +795,7 @@ public class LiveServiceImpl implements ILiveService
         Date now = new Date();
         exist.setRtmpUrl(rtmpPushUrl);
         exist.setFlvHlsUrl(hlvPlayUrl);
-
+        log.error("startLive:" + live.getLiveId());
         exist.setStatus(2);
         exist.setUpdateTime(now);
         exist.setFinishTime( null);
@@ -808,6 +816,7 @@ public class LiveServiceImpl implements ILiveService
     @Override
     public R handleShelfOrUnAdmin(LiveListVo listVo) {
         baseMapper.handleShelfOrUnAdmin(listVo);
+        log.error("有人下架了视频:" + listVo.getLiveIds());
         return R.ok();
     }
 
@@ -1208,6 +1217,7 @@ public class LiveServiceImpl implements ILiveService
             JSONObject jsonObject = JSONObject.parseObject(result);
             if (200 == jsonObject.getIntValue("code") && jsonObject.getBooleanValue("success")) {
                 live.setIdCardUrl(payload.get("idCardUrl"));
+                log.error("verifyIdInfo:" + live.getLiveId());
                 baseMapper.updateLive(live);
                 return R.ok();
             }

+ 4 - 0
fs-service/src/main/java/com/fs/live/vo/LiveOrderVO.java

@@ -255,5 +255,9 @@ public class LiveOrderVO implements Serializable
     //erp推送账号
     private String erpAccount;
 
+    /** 银行交易流水号 */
+    @Excel(name = "银行交易流水号")
+    private String bankTransactionId;
+
 
 }

+ 3 - 0
fs-service/src/main/java/com/fs/live/vo/LiveOrderVoZm.java

@@ -476,6 +476,9 @@ public class LiveOrderVoZm{
     private String createTimeStart;
     private String createTimeEnd;
 
+    /** 银行交易流水号 */
+    @Excel(name = "银行交易流水号")
+    private String bankTransactionId;
 
 
 }

+ 2 - 0
fs-service/src/main/java/com/fs/live/vo/LiveVo.java

@@ -37,6 +37,8 @@ public class LiveVo {
     private String videoUrl;
     private Long videoId;
     private Integer videoType;
+    private Long videoFileSize;
+    private Long videoDuration;
 
     private String flvHlsUrl;
 

+ 1 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java

@@ -487,4 +487,5 @@ public interface QwUserMapper extends BaseMapper<QwUser>
             "</script>")
     List<QwUser> selectQwUserByIds(@Param("qwUserIdList") List<Long> qwUserIdList);
 
+    List<QwUser> selectQwUserByTest();
 }

+ 5 - 0
fs-service/src/main/java/com/fs/qw/param/FsUserCourseRedPageParam.java

@@ -11,5 +11,10 @@ public class FsUserCourseRedPageParam {
     private Long courseId;
     //红包
     private BigDecimal redPacketMoney;
+
+    /**
+     * 新增配置 随机红包配置
+     */
+    private String randomRedPacketRules;
 }
 

+ 2 - 2
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java

@@ -984,7 +984,7 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
     //递归
     public R  syncMyQwExternalContactRecursion(QwUser qwUser,String getNextCursor )  {
 
-
+        int i=0;
         String qwUserId = qwUser.getQwUserId();
         String corpId = qwUser.getCorpId();
         Long companyId = qwUser.getCompanyId();
@@ -1061,7 +1061,7 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
                         qwExternalContactMapper.insertQwExternalContact(qwExternalContact);
                     }
 
-                    logger.info("成功同步一个用户");
+                    logger.info("成功同步一个用户"+i++);
                 }
 
             }else {

+ 3 - 0
fs-service/src/main/java/com/fs/sop/service/IQwSopTempContentService.java

@@ -1,5 +1,6 @@
 package com.fs.sop.service;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.common.annotation.DataSource;
 import com.fs.common.enums.DataSourceType;
@@ -90,4 +91,6 @@ public interface IQwSopTempContentService extends IService<QwSopTempContent>{
     void removeByTempIds(Collection<String> tempIds);
 
     List<QwSopTempContent> listByTempIds(Collection<String> tempIds);
+
+    void removeByWrapper(LambdaQueryWrapper<QwSopTempContent> wrapper);
 }

+ 11 - 0
fs-service/src/main/java/com/fs/sop/service/IQwSopTempDayService.java

@@ -1,10 +1,15 @@
 package com.fs.sop.service;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.sop.domain.QwSopTempDay;
 
+import java.sql.Wrapper;
 import java.util.Collection;
 import java.util.List;
+import java.util.Set;
 
 /**
  * sop任务模板规则Service接口
@@ -35,4 +40,10 @@ public interface IQwSopTempDayService extends IService<QwSopTempDay> {
     int getDayNumByIdLimitOne(String tempId);
 
     void removeByTempIds(Collection<String> tempIds);
+
+    void removeByWrapper(LambdaQueryWrapper<QwSopTempDay> wrapper);
+
+    List<QwSopTempDay> listByTempIds(LambdaQueryWrapper<QwSopTempDay> wrapper);
+
+    void updateByWrapper(UpdateWrapper<QwSopTempDay> wrapper);
 }

+ 5 - 0
fs-service/src/main/java/com/fs/sop/service/IQwSopTempRulesService.java

@@ -1,5 +1,6 @@
 package com.fs.sop.service;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.common.annotation.DataSource;
 import com.fs.common.enums.DataSourceType;
@@ -94,4 +95,8 @@ public interface IQwSopTempRulesService extends IService<QwSopTempRules>{
     List<QwSopTempRules> listByCourseId(Long courseId);
 
     void removeByTempIds(Collection<String> tempIds);
+
+    void removeByWrapper(LambdaQueryWrapper<QwSopTempRules> wrapper);
+
+    List<QwSopTempRules> selectListByDayId(Long id);
 }

+ 2 - 0
fs-service/src/main/java/com/fs/sop/service/ISopUserLogsService.java

@@ -66,4 +66,6 @@ public interface ISopUserLogsService {
     public List<SopUserLogs> meetsTherestoreByIsDaysNotStudy(int offset,int pageSize,Integer notStudyDays);
 
     void replaceUser(ReplaceUserDto vo);
+
+    R getShortLink(String id, String sopId, String appId);
 }

+ 7 - 0
fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempContentServiceImpl.java

@@ -1,5 +1,6 @@
 package com.fs.sop.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.common.annotation.DataSource;
@@ -163,4 +164,10 @@ public class QwSopTempContentServiceImpl extends ServiceImpl<QwSopTempContentMap
     public List<QwSopTempContent> listByTempIds(Collection<String> tempIds) {
         return baseMapper.selectList(new QueryWrapper<QwSopTempContent>().in("temp_id", tempIds));
     }
+
+    @Override
+    @DataSource(DataSourceType.SOP)
+    public void removeByWrapper(LambdaQueryWrapper<QwSopTempContent> wrapper) {
+        this.remove(wrapper);
+    }
 }

+ 23 - 0
fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempDayServiceImpl.java

@@ -2,6 +2,7 @@ package com.fs.sop.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.common.annotation.DataSource;
@@ -13,7 +14,9 @@ import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.sql.Wrapper;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -24,6 +27,7 @@ import java.util.List;
  */
 @Service
 @AllArgsConstructor
+@DataSource(DataSourceType.SOP)
 public class QwSopTempDayServiceImpl extends ServiceImpl<QwSopTempDayMapper, QwSopTempDay> implements IQwSopTempDayService {
 
 
@@ -92,4 +96,23 @@ public class QwSopTempDayServiceImpl extends ServiceImpl<QwSopTempDayMapper, QwS
     public void removeByTempIds(Collection<String> tempIds) {
         this.remove(new QueryWrapper<QwSopTempDay>().in("temp_id", tempIds));
     }
+
+    @Override
+    @DataSource(DataSourceType.SOP)
+    public void removeByWrapper(LambdaQueryWrapper<QwSopTempDay> wrapper) {
+        this.remove(wrapper);
+    }
+
+    @Override
+    @DataSource(DataSourceType.SOP)
+    public List<QwSopTempDay> listByTempIds(LambdaQueryWrapper<QwSopTempDay> wrapper) {
+        return this.list(wrapper);
+    }
+
+    @Override
+    @DataSource(DataSourceType.SOP)
+    public void updateByWrapper(UpdateWrapper<QwSopTempDay> wrapper) {
+        this.update(wrapper);
+    }
+
 }

+ 13 - 0
fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempRulesServiceImpl.java

@@ -1,6 +1,7 @@
 package com.fs.sop.service.impl;
 
 import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.common.annotation.DataSource;
@@ -252,4 +253,16 @@ public class QwSopTempRulesServiceImpl extends ServiceImpl<QwSopTempRulesMapper,
     public void removeByTempIds(Collection<String> tempIds) {
         this.remove(new QueryWrapper<QwSopTempRules>().in("temp_id", tempIds));
     }
+
+    @Override
+    @DataSource(DataSourceType.SOP)
+    public List<QwSopTempRules> selectListByDayId(Long id) {
+        return list(new QueryWrapper<QwSopTempRules>().eq("day_id", id));
+    }
+
+    @Override
+    @DataSource(DataSourceType.SOP)
+    public void removeByWrapper(LambdaQueryWrapper<QwSopTempRules> wrapper) {
+        this.remove(wrapper);
+    }
 }

+ 60 - 45
fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempServiceImpl.java

@@ -2,7 +2,10 @@ package com.fs.sop.service.impl;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.annotation.DataSource;
 import com.fs.common.enums.DataSourceType;
 import com.fs.common.exception.base.BaseException;
@@ -46,7 +49,6 @@ import java.text.SimpleDateFormat;
 import java.time.LocalTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
@@ -425,6 +427,10 @@ public class QwSopTempServiceImpl implements IQwSopTempService {
         temp.setProject(fsUserCourse.getProject());
         qwSopTempMapper.updateQwSopTemp(temp);
         List<FsUserCourseVideo> videoList = fsUserCourseVideoMapper.selectVideoByCourseId(fsUserCourse.getCourseId());
+        createSopTempRules(temp, videoList, fsUserCourse);
+    }
+
+    private void createSopTempRules(QwSopTemp temp, List<FsUserCourseVideo> videoList, FsUserCourse fsUserCourse) {
         AtomicInteger i = new AtomicInteger(1);
         Integer gap = temp.getGap();
         List<QwSopTempDay> collect = videoList.stream().map(e -> {
@@ -627,67 +633,76 @@ public class QwSopTempServiceImpl implements IQwSopTempService {
         if (CollectionUtils.isEmpty(rulesList)) {
             return;
         }
-
         // 获取这些规则关联的模板ID集合
         Set<String> tempIds = rulesList.stream()
                 .map(QwSopTempRules::getTempId)
                 .filter(Objects::nonNull)
                 .collect(Collectors.toSet());
 
-        // 查询相关联的sop模板
-        if (CollectionUtils.isEmpty(tempIds)) {
-            return;
-        }
-        // 只弄课程模板的
+        FsUserCourse fsUserCourse = fsUserCourseMapper.selectFsUserCourseByCourseId(courseId);
+        List<FsUserCourseVideo> videoList = fsUserCourseVideoMapper.selectVideoByCourseId(fsUserCourse.getCourseId());
         List<QwSopTemp> tempList = qwSopTempMapper.selectListByIds(tempIds);
-        tempList = tempList.stream().filter(f -> Objects.equals(f.getStatus(), "1")).collect(Collectors.toList());
-        if (CollectionUtils.isEmpty(tempList)) {
-            return;
+        List<QwSopTempContent> contentList = qwSopTempContentService.listByTempIds(tempIds);
+        List<QwSopTempDay> dayList = qwSopTempDayService.listByTempIds(new LambdaQueryWrapper<QwSopTempDay>().in(QwSopTempDay::getTempId, tempIds));
+        List<Long> videoIdList = videoList.stream().map(FsUserCourseVideo::getVideoId).collect(Collectors.toList());
+        // videoList转Map key 为videoId value 为 courseSort
+        Map<Long, Long> videoSortMap = videoList.stream().collect(Collectors.toMap(FsUserCourseVideo::getVideoId, FsUserCourseVideo::getCourseSort));
+
+        // 将课程中已删除的视频在规则和日期中删除
+        Set<Long> dayIdList = rulesList.stream().filter(e -> !videoIdList.contains(e.getVideoId())).map(QwSopTempRules::getDayId).collect(Collectors.toSet());
+        if (CollectionUtils.isNotEmpty(dayIdList)) {
+            qwSopTempDayService.removeByWrapper(new LambdaQueryWrapper<QwSopTempDay>().in(QwSopTempDay::getId, dayIdList));
+            qwSopTempRulesService.removeByWrapper(new LambdaQueryWrapper<QwSopTempRules>().in(QwSopTempRules::getDayId, dayIdList));
+            qwSopTempContentService.removeByWrapper(new LambdaQueryWrapper<QwSopTempContent>().in(QwSopTempContent::getDayId, dayIdList));
         }
 
-        // 获取这些规则关联的模板ID集合
-        Set<String> sopTempIds = tempList.stream()
-                .map(QwSopTemp::getId)
-                .filter(Objects::nonNull)
-                .collect(Collectors.toSet());
+        // 需要添加的课程视频
+        List<FsUserCourseVideo> addVideoList = videoList.stream()
+                .filter(e -> rulesList.stream().noneMatch(f -> f.getVideoId().equals(e.getVideoId()))).collect(Collectors.toList());
 
-        List<QwSopTempContent> contentList = qwSopTempContentService.listByTempIds(sopTempIds);
+        if (CollectionUtils.isNotEmpty(addVideoList)) {
+            for (QwSopTemp temp : tempList) {
+                // 通过历史中的第一课的数据来构建
+                Optional<QwSopTempDay> first = dayList.stream().filter(e -> e.getTempId().equals(temp.getId())).findFirst();
+                if (!first.isPresent()) {
+                    break;
+                }
+                QwSopTempDay qwSopTempDay = first.get();
+                // 构造timeList timeDesc time
+                temp.setTime(LocalTime.now());
+
+                temp.setTimeList(rulesList.stream()
+                        .filter(e -> e.getTempId().equals(temp.getId()) && Objects.equals(e.getIsOfficial(), "0")
+                                && Objects.equals(e.getDayId(), qwSopTempDay.getId())
+                        ).map(QwSopTempRules::getTime)
+                        .collect(Collectors.toList()));
 
-        qwSopTempDayService.removeByTempIds(tempIds);
-        qwSopTempRulesService.removeByTempIds(tempIds);
-        qwSopTempContentService.removeByTempIds(tempIds);
-        // 对每个模板执行同步操作
-        for (QwSopTemp temp : tempList) {
-            // 构造timeList timeDesc time
-            rulesList.stream().filter(e -> e.getTempId().equals(temp.getId())).findFirst()
-                    .ifPresent(first -> temp.setTime(LocalTime.parse(first.getTime() + ":00")));
-
-            temp.setTimeList(rulesList.stream()
-                    .filter(e -> e.getTempId().equals(temp.getId()) && Objects.equals(e.getIsOfficial(), "0")
-                            && Objects.equals(e.getName(), "第1天")).map(QwSopTempRules::getTime)
-                    .collect(Collectors.toList()));
-            // 过滤并找到 dayId 最小的元素
-            Optional<QwSopTempContent> minDayEntity = contentList.stream()
-                    // 1. 过滤条件:tempId匹配 + isBindUrl为null
-                    .filter(e -> e.getTempId().equals(temp.getId())
-                            && Objects.isNull(e.getIsBindUrl()))
-                    // 2. 按 dayId 升序排序,取第一个(最小)
-                    .min(Comparator.comparingLong(QwSopTempContent::getDayId)); // 若dayId是Long,用comparingLong
-
-            if (minDayEntity.isPresent()) {
-                QwSopTempContent qwSopTempContent = minDayEntity.get();
                 temp.setTimeDesc(contentList.stream().filter(e -> e.getTempId().equals(temp.getId())
                                 && Objects.isNull(e.getIsBindUrl())
-                                && Objects.equals(qwSopTempContent.getDayId(), e.getDayId())
+                                && Objects.equals(qwSopTempDay.getId(), e.getDayId())
                         )
                         .map(m -> JSONObject.parseObject(m.getContent()).getString("value")).collect(Collectors.toList()));
+                temp.setProject(fsUserCourse.getProject());
+                temp.setCourseId(courseId);
+                temp.setOpenOfficial("1");
+                qwSopTempMapper.updateQwSopTemp(temp);
+                createSopTempRules(temp, addVideoList, fsUserCourse);
             }
+        }
 
-            // 插入课程id
-            temp.setCourseId(courseId);
-            temp.setOpenOfficial("1");
-            // 重新生成该模板的规则和内容
-            threadPoolTaskExecutor.execute(() -> createSopTempRules(temp));
+        // 整理排序
+        List<QwSopTempRules> afterRuleList = qwSopTempRulesService.listByCourseId(courseId);
+        for (QwSopTemp temp : tempList) {
+            Long[] dayIdArray = afterRuleList.stream().filter(e -> e.getTempId().equals(temp.getId())).sorted(Comparator.comparing(a -> videoSortMap.get(a.getVideoId())))
+                    .map(QwSopTempRules::getDayId).distinct().toArray(Long[]::new);
+            for (int i = 0; i < dayIdArray.length; i++) {
+                qwSopTempDayService.updateByWrapper(new UpdateWrapper<QwSopTempDay>()
+                        .eq("id", dayIdArray[i])
+                        .set("sorts", i + 1)
+                        .set("name", "第" + (i + 1) + "天")
+                        .set("day_num", i + 1)
+                );
+            }
         }
     }
 

+ 2 - 2
fs-service/src/main/java/com/fs/sop/service/impl/SopUserLogsInfoServiceImpl.java

@@ -1547,7 +1547,7 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
     }
 
     //插入观看记录
-    private void addWatchLogIfNeeded(String sopId, Integer videoId, Integer courseId,
+    public void addWatchLogIfNeeded(String sopId, Integer videoId, Integer courseId,
                                      Long fsUserId, String qwUserId, String companyUserId,
                                      String companyId, Long externalId, String startTime,Date createTime) {
 
@@ -1603,7 +1603,7 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
         return sortLink.replaceAll("^[\\s\\u2005]+", "");
     }
 
-    private String createLinkByMiniApp(QwSopCourseFinishTempSetting.Setting setting, String corpId, Date sendTime,
+    public String createLinkByMiniApp(QwSopCourseFinishTempSetting.Setting setting, String corpId, Date sendTime,
                                      Integer courseId, Integer videoId, Long qwUserId,
                                      String companyUserId, String companyId, Long externalId,CourseConfig config, String chatId) {
 

+ 147 - 91
fs-service/src/main/java/com/fs/sop/service/impl/SopUserLogsServiceImpl.java

@@ -8,6 +8,7 @@ import com.fs.common.exception.base.BaseException;
 import com.fs.common.utils.PubFun;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.date.DateUtil;
+import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsCourseWatchLog;
 import com.fs.course.mapper.FsCourseWatchLogMapper;
 import com.fs.course.param.FsCourseLinkCreateParam;
@@ -16,18 +17,17 @@ import com.fs.crm.domain.CrmMsg;
 import com.fs.crm.mapper.CrmMsgMapper;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.domain.QwGroupChat;
+import com.fs.qw.domain.QwGroupChatUser;
 import com.fs.qw.domain.QwUser;
 import com.fs.qw.mapper.QwExternalContactMapper;
+import com.fs.qw.mapper.QwGroupChatMapper;
+import com.fs.qw.mapper.QwGroupChatUserMapper;
 import com.fs.qw.mapper.QwUserMapper;
 import com.fs.qw.param.SopUserLogsVO;
 import com.fs.qw.service.IQwGroupChatService;
 import com.fs.qw.service.IQwUserService;
 import com.fs.qw.vo.*;
-import com.fs.qwApi.service.QwApiService;
-import com.fs.sop.domain.QwSop;
-import com.fs.sop.domain.QwSopLogs;
-import com.fs.sop.domain.SopUserLogs;
-import com.fs.sop.domain.SopUserLogsInfo;
+import com.fs.sop.domain.*;
 import com.fs.sop.mapper.QwSopMapper;
 import com.fs.sop.mapper.SopUserLogsInfoMapper;
 import com.fs.sop.mapper.SopUserLogsMapper;
@@ -35,9 +35,7 @@ import com.fs.sop.params.QwRatingConfig;
 import com.fs.sop.params.SopUserLogsList;
 import com.fs.sop.params.SopUserLogsParam;
 import com.fs.sop.params.SopUserLogsParamByDate;
-import com.fs.sop.service.IQwSopLogsService;
-import com.fs.sop.service.IQwSopTempDayService;
-import com.fs.sop.service.ISopUserLogsService;
+import com.fs.sop.service.*;
 import com.fs.sop.vo.QwRatingVO;
 import com.fs.sop.vo.ReplaceUserDto;
 import com.fs.sop.vo.SopUserLogsInfoVo;
@@ -69,7 +67,7 @@ import java.util.stream.Collectors;
 
 @Slf4j
 @Service
-public class SopUserLogsServiceImpl  implements ISopUserLogsService {
+public class SopUserLogsServiceImpl implements ISopUserLogsService {
 
     private static final Logger logger = LoggerFactory.getLogger(SopUserLogsServiceImpl.class);
 
@@ -85,7 +83,7 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
     @Autowired
     private QwSopMapper sopMapper;
     @Autowired
-    private QwApiService qwApiService;
+    private IFsCourseLinkService linkService;
 
     @Autowired
     private RedisCache redisCache;
@@ -99,6 +97,17 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
     @Autowired
     private IQwSopTempDayService qwSopTempDayService;
 
+    @Autowired
+    private SopUserLogsInfoServiceImpl sopUserLogsInfoService;
+    @Autowired
+    private IQwSopTempService sopTempService;
+    @Autowired
+    private IQwSopTempRulesService qwSopTempRulesService;
+    @Autowired
+    private QwGroupChatUserMapper qwGroupChatUserMapper;
+    @Autowired
+    private QwGroupChatMapper qwGroupChatMapper;
+
 
     @Autowired
     private ISysConfigService configService;
@@ -143,7 +152,7 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
 //        return sopUserLogsMapper.updateSopUserLogsDistinctByList(userLogsList);
 //    }
 
-//    @Override
+    //    @Override
 //    public int updateSopUserLogsDistinctByList(SopUserLogsArray userLogsArray) {
 //        return sopUserLogsMapper.updateSopUserLogsDistinctByList(userLogsArray);
 //    }
@@ -152,6 +161,57 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
         sopUserLogsMapper.replaceUser(vo);
     }
 
+    @Override
+    public R getShortLink(String id, String sopId, String appId) {
+        QwSop qwSop = sopMapper.selectQwSopById(sopId);
+        QwSopTemp qwSopTemp = sopTempService.selectQwSopTempById(qwSop.getTempId());
+        SopUserLogs sopUserLogs = sopUserLogsMapper.selectSopUserLogsById(id);
+        String[] userKey = sopUserLogs.getUserId().split("\\|");
+        String qwUserId = userKey[0].trim();
+        QwUser qwUser = qwUserMapper.selectById(qwUserId);
+        Optional<QwSopTempDay> dayOptional = qwSopTemp.getList().stream().filter(e -> Objects.equals(e.getDayNum(), sopUserLogs.getCountDays())).findFirst();
+        if (dayOptional.isPresent()) {
+            List<QwSopTempRules> rulesList = qwSopTempRulesService.selectListByDayId(dayOptional.get().getId());
+            Optional<QwSopTempRules> rulesOptional = rulesList.stream().filter(r -> r.getCourseId() != null).findFirst();
+            if (rulesOptional.isPresent()) {
+                QwSopTempRules rules = rulesOptional.get();
+                QwGroupChat groupChat = qwGroupChatMapper.selectQwGroupChatByChatId(sopUserLogs.getChatId());
+                List<QwGroupChatUser> groupUserList = qwGroupChatUserMapper.selectQwGroupChatUserByChatIds(new String[]{sopUserLogs.getChatId()});
+                List<String> groupChatUserIds = PubFun.listToNewList(groupUserList, QwGroupChatUser::getUserId);
+                if (!groupChatUserIds.isEmpty()) {
+                    List<GroupUserExternalVo> userList = qwExternalContactMapper.selectByGroupUser(groupChatUserIds);
+                    Map<String, List<GroupUserExternalVo>> userMap = PubFun.listToMapByGroupList(userList, GroupUserExternalVo::getExternalUserId);
+                    groupUserList.forEach(e -> {
+                        e.setUserList(userMap.getOrDefault(e.getUserId(), Collections.emptyList()));
+                    });
+                }
+                try {
+                    groupUserList.stream().filter(e -> e.getUserList() != null && !e.getUserList().isEmpty()).forEach(e -> {
+                        Map<String, GroupUserExternalVo> userMap = PubFun.listToMapByGroupObject(e.getUserList(), GroupUserExternalVo::getUserId);
+                        GroupUserExternalVo vo = userMap.get(groupChat.getOwner());
+                        if (vo != null && vo.getId() != null) {
+                            sopUserLogsInfoService.addWatchLogIfNeeded(sopId, rules.getVideoId().intValue(), rules.getCourseId().intValue(), vo.getFsUserId(), qwUser.getId().toString(), qwUser.getCompanyUserId().toString(), qwUser.getCompanyId().toString(), vo.getId(), sopUserLogs.getStartTime(), new Date());
+                        }
+                    });
+                } catch (Exception e) {
+                    log.error("群聊创建看课记录失败!", e);
+                }
+                QwSopCourseFinishTempSetting.Setting st = new QwSopCourseFinishTempSetting.Setting();
+                st.setExpiresDays(1);
+                String json = configService.selectConfigByKey("course.config");
+                CourseConfig config = JSON.parseObject(json, CourseConfig.class);
+                String linkByMiniApp = sopUserLogsInfoService.createLinkByMiniApp(st, sopUserLogs.getCorpId(), new Date(), rules.getCourseId().intValue(), rules.getVideoId().intValue(),
+                        qwUser.getId(), qwUser.getCompanyUserId().toString(), qwUser.getCompanyId().toString(), null, config, sopUserLogs.getChatId());
+                if(StringUtils.isNotEmpty(linkByMiniApp)){
+                    linkByMiniApp = linkByMiniApp.replaceAll(".html", "");
+                }
+                String link = linkService.getGotoWxAppLink(linkByMiniApp, appId);
+                return R.ok().put("urlLink", link);
+            }
+        }
+        return R.error("系统错误❌");
+    }
+
     @Override
     public int deleteSopUserLogsBySopId(String sopId) {
         return sopUserLogsMapper.deleteSopUserLogsBySopId(sopId);
@@ -181,20 +241,20 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
             //如果为空,则任务删除了 ,则全部营期删除
             if (ruleTimeVO == null) {
                 sopUserLogsMapper.deleteSopUserLogsBySopId(key);
-            }else if (ruleTimeVO.getStatus()==0){
+            } else if (ruleTimeVO.getStatus() == 0) {
                 SopUserLogs sopUserLogs = new SopUserLogs();
                 sopUserLogs.setSopId(key);
                 sopUserLogs.setStatus(2);
                 sopUserLogsMapper.updateSopUserLogsByStatus(sopUserLogs);
-            }else {
+            } else {
 
                 //如果模板停用了,也改这个营期记录
-                if (ruleTimeVO.getTempStatus().equals("0")){
+                if (ruleTimeVO.getTempStatus().equals("0")) {
                     SopUserLogs sopUserLogs = new SopUserLogs();
                     sopUserLogs.setSopId(key);
                     sopUserLogs.setStatus(2);
                     sopUserLogsMapper.updateSopUserLogsByStatus(sopUserLogs);
-                }else {
+                } else {
 
                     // 分组的 key
                     List<SopUserLogsVo> userLogsVos = entry.getValue(); // 分组对应的日志列表
@@ -202,24 +262,24 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
                     // 处理日志数据
                     userLogsVos.forEach(log -> {
 
-                            // 获取开始时间和间隔天数
-                            Date startTime = null; // 假设 startTime 是 java.util.Date 类型
-                            try {
-                                startTime = formatter.parse(log.getStartTime());
-                            } catch (ParseException e) {
-                                logger.error("selectSopUserLogsListByTime解析开始时间失败: {}", e.getMessage());
-                            }
+                        // 获取开始时间和间隔天数
+                        Date startTime = null; // 假设 startTime 是 java.util.Date 类型
+                        try {
+                            startTime = formatter.parse(log.getStartTime());
+                        } catch (ParseException e) {
+                            logger.error("selectSopUserLogsListByTime解析开始时间失败: {}", e.getMessage());
+                        }
 
-                            Integer tempGap = ruleTimeVO.getTempGap();
+                        Integer tempGap = ruleTimeVO.getTempGap();
 
-                            // 将 startTime 转换为 LocalDate
-                            LocalDate startLocalDate = startTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+                        // 将 startTime 转换为 LocalDate
+                        LocalDate startLocalDate = startTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
 
-                            // 计算当前时间距离开始时间的天数差
-                            long daysBetween = ChronoUnit.DAYS.between(startLocalDate, currentDate);
+                        // 计算当前时间距离开始时间的天数差
+                        long daysBetween = ChronoUnit.DAYS.between(startLocalDate, currentDate);
 
-                            // TODO 修改
-                            // 获取 QwSopTempSetting 内容
+                        // TODO 修改
+                        // 获取 QwSopTempSetting 内容
 //                            List<QwSopTempSetting> qwSopTempSettings = JSON.parseArray(ruleTimeVO.getTempSetting(), QwSopTempSetting.class);
 //
 //                            // 计算当前天数属于第几天,第一天就是 startLocalDate,后续递增
@@ -293,9 +353,6 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
             }
 
 
-
-
-
         }
 
         // 遍历分组数据
@@ -454,7 +511,8 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
 //        }
     }
 
-    private void insertSopUserLogs(List<SopUserLogsInfo> list,SopUserLogsVo log,Date sendTime,QwSopRuleTimeVO ruleTimeVO,QwSopTempSetting.Content element) {
+    private void insertSopUserLogs(List<SopUserLogsInfo> list, SopUserLogsVo log, Date sendTime, QwSopRuleTimeVO
+            ruleTimeVO, QwSopTempSetting.Content element) {
 
         QwSopLogs sopLogs = new QwSopLogs();
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@@ -574,7 +632,7 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
 
 
                             //如果要推短链-则必须要绑定了小程序-才会有观看记录
-                            if (sopLogs.getFsUserId() != null && sopLogs.getFsUserId()!= 0 ) {
+                            if (sopLogs.getFsUserId() != null && sopLogs.getFsUserId() != 0) {
 
                                 FsCourseWatchLog watchLog = new FsCourseWatchLog();
                                 watchLog.setUserId(sopLogs.getFsUserId());
@@ -643,9 +701,9 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
         return resultSopUserLogsList(list);
     }
 
-    private List<SopUserLogsVO> resultSopUserLogsList( List<SopUserLogsVO> list){
+    private List<SopUserLogsVO> resultSopUserLogsList(List<SopUserLogsVO> list) {
         List<String> chatIdList = PubFun.listToNewList(list, SopUserLogsVO::getChatId);
-        if(!chatIdList.isEmpty()){
+        if (!chatIdList.isEmpty()) {
             List<QwGroupChat> qwGroupChatList = qwGroupChatService.selectQwGroupChatByChatIds(chatIdList.toArray(new String[0]));
             Map<String, QwGroupChat> groupChatMap = PubFun.listToMapByGroupObject(qwGroupChatList, QwGroupChat::getChatId);
             list.stream().filter(e -> groupChatMap.containsKey(e.getChatId())).forEach(e -> {
@@ -703,9 +761,9 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
                 // 获取名称
                 String names = voList.stream().peek(v -> {
                     // 标识那些是发送了,发送了到时候要更新状态不会查出数据进入此方法
-                    if(type == 0){
+                    if (type == 0) {
                         v.setMinIsSend(true);
-                    }else{
+                    } else {
                         v.setMaxIsSend(true);
                     }
                 }).map(SopUserLogsInfoVo::getExternalUserName).collect(Collectors.joining(","));
@@ -726,11 +784,11 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
         // 打转换消息
         List<CrmMsg> maxList = toFun.apply(list, 1);
         // 不为空添加
-        if(!minList.isEmpty()){
+        if (!minList.isEmpty()) {
             msgList.addAll(minList);
         }
         // 不为空添加
-        if(!maxList.isEmpty()){
+        if (!maxList.isEmpty()) {
             msgList.addAll(maxList);
         }
         msgList.forEach(crmMsgMapper::insertCrmMsg);
@@ -756,8 +814,7 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
      * @return sopUserLogs
      */
     @Override
-    public SopUserLogs selectSopUserLogsById(String id)
-    {
+    public SopUserLogs selectSopUserLogsById(String id) {
         return sopUserLogsMapper.selectSopUserLogsById(id);
     }
 
@@ -768,14 +825,14 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
         if (qwUser != null) {
             Long companyUserId = qwUser.getCompanyUserId();
             Long companyId = qwUser.getCompanyId();
-            if (companyUserId==null) {
+            if (companyUserId == null) {
                 return R.error("用户未绑定销售,请先绑定");
             }
-            if (companyId==null) {
+            if (companyId == null) {
                 return R.error("用户未绑定销售公司,请先绑定");
             }
 
-            param.setUserId(qwUser.getId()+"|"+companyUserId+"|"+companyId);
+            param.setUserId(qwUser.getId() + "|" + companyUserId + "|" + companyId);
             sopUserLogsMapper.updateSopUserLogsByCompanyInfo(param);
         }
 
@@ -789,26 +846,26 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
 
             Map<String, QwUser> qwUserMap = sopUserLogs.stream()
                     .collect(Collectors.toMap(
-                            item -> item.getCorpId() + "|" + item.getQwUserId()+"|"+item.getId(),
+                            item -> item.getCorpId() + "|" + item.getQwUserId() + "|" + item.getId(),
                             item -> Optional.ofNullable(qwUserMapper.selectQwUserByCorpIdAndUserId(item.getCorpId(), item.getQwUserId()))
                                     .orElse(new QwUser())
                     ));
             List<String> errorMessages = new ArrayList<>();
 
             sopUserLogs.forEach(item -> {
-                String key = item.getCorpId() + "|" + item.getQwUserId()+"|"+item.getId();
+                String key = item.getCorpId() + "|" + item.getQwUserId() + "|" + item.getId();
                 QwUser qwUser = qwUserMap.get(key);
 
-                if (qwUser != null && qwUser.getId()!=null) {
+                if (qwUser != null && qwUser.getId() != null) {
                     Long companyUserId = qwUser.getCompanyUserId();
                     Long companyId = qwUser.getCompanyId();
 
                     if (companyUserId == null) {
-                        errorMessages.add("用户 " + item.getQwUserId() +"|"+item.getCorpId()+ " 未绑定销售,请先绑定");
+                        errorMessages.add("用户 " + item.getQwUserId() + "|" + item.getCorpId() + " 未绑定销售,请先绑定");
                         return;
                     }
                     if (companyId == null) {
-                        errorMessages.add("用户 " + item.getQwUserId()+"|" +item.getCorpId()+ " 未绑定销售公司,请先绑定");
+                        errorMessages.add("用户 " + item.getQwUserId() + "|" + item.getCorpId() + " 未绑定销售公司,请先绑定");
                         return;
                     }
 
@@ -826,10 +883,10 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
             });
 
             if (!errorMessages.isEmpty()) {
-                logger.error("定时处理 营期异常的数据 出错:"+String.join(";", errorMessages));
+                logger.error("定时处理 营期异常的数据 出错:" + String.join(";", errorMessages));
             }
-        }catch (Exception e){
-            logger.error("定时处理 营期异常的数据 出错2:"+e.getMessage());
+        } catch (Exception e) {
+            logger.error("定时处理 营期异常的数据 出错2:" + e.getMessage());
         }
 
 
@@ -842,21 +899,21 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
         QwRatingConfig config = JSON.parseObject(json, QwRatingConfig.class);
 
         List<SopUserLogs> sopUserLogs = sopUserLogsMapper.meetsTheRatingByUserInfoBySopId(sopId);
-        sopUserLogs.stream().forEach(item->{
+        sopUserLogs.stream().forEach(item -> {
 
             Integer countDays = item.getCountDays();
 
-           Integer sopTemIdNum=redisCache.getCacheObject("sop-tempId:"+item.getSopTempId());
+            Integer sopTemIdNum = redisCache.getCacheObject("sop-tempId:" + item.getSopTempId());
 
-           if (sopTemIdNum==null){
-               sopTemIdNum= qwSopTempDayService.getDayNumByIdLimitOne(item.getSopTempId());
-               redisCache.setCacheObject("sop-tempId:"+item.getSopTempId(),sopTemIdNum,3, TimeUnit.HOURS);
-           }
+            if (sopTemIdNum == null) {
+                sopTemIdNum = qwSopTempDayService.getDayNumByIdLimitOne(item.getSopTempId());
+                redisCache.setCacheObject("sop-tempId:" + item.getSopTempId(), sopTemIdNum, 3, TimeUnit.HOURS);
+            }
 
 
             //如果当前营期的伦次中,模板天数不足。则不评级
-            if (sopTemIdNum< countDays){
-                logger.info("当前营期的伦次中,模板天数不足。不评级:"+item.getSopTempId()+"|sopId:"+item.getSopId());
+            if (sopTemIdNum < countDays) {
+                logger.info("当前营期的伦次中,模板天数不足。不评级:" + item.getSopTempId() + "|sopId:" + item.getSopId());
                 return;
             }
 
@@ -864,7 +921,7 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
             List<SopUserLogsInfo> sopUserLogsInfosList = sopUserLogsInfoMapper.selectSopUserLogsInfoListBySopId(item.getSopId(), item.getId());
             if (sopUserLogsInfosList != null && !sopUserLogsInfosList.isEmpty()) {
 
-                List<QwExternalContact> batchQwExternalContact=new ArrayList<>();
+                List<QwExternalContact> batchQwExternalContact = new ArrayList<>();
 
                 sopUserLogsInfosList.forEach(logsInfo -> {
                     try {
@@ -875,8 +932,8 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
                                     .selectFsCourseWatchLogByExtIdRating(externalId, config.getLevelDay());
 
                             if (ratingVOS.isEmpty()) {
-                                log.error("没有看课记录不评级。则不评级:"+externalId);
-                                return ;
+                                log.error("没有看课记录不评级。则不评级:" + externalId);
+                                return;
                             }
 
                             int scoreLevel = getScoreLevel(ratingVOS, config);
@@ -894,17 +951,15 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
                             batchQwExternalContact.add(externalContact);
 
 
-
-
                         }
-                    }catch (Exception e){
+                    } catch (Exception e) {
                         logger.error("计算用户积分异常,用户id:{}", logsInfo, e);
                     }
                 });
 
                 batchUpdateQwExternalContact(batchQwExternalContact);
 
-            }else {
+            } else {
                 logger.error("当前营期没有客户-sopId:{},营期id:{}", item.getSopId(), item.getId());
             }
         });
@@ -915,10 +970,10 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
 
     @Override
     public R updateLogDate(UpdateSopUserLogDateVo vo) {
-        if(vo.getDate() == null){
+        if (vo.getDate() == null) {
             throw new BaseException("修改时间不能为空");
         }
-        if(vo.getIds() == null || vo.getIds().isEmpty()){
+        if (vo.getIds() == null || vo.getIds().isEmpty()) {
             throw new BaseException("营期ID不能为空");
         }
 //        sopUserLogsMapper.updateSopuserLogsDateById(vo);
@@ -948,16 +1003,17 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
 
         // 记录剔除的重复ID
         if (!duplicateIds.isEmpty()) {
-            log.error("根据sopId、qwUserId、corpId、startTime组合检查,剔除重复ID: {},时间:{}", duplicateIds,targetDateStr);
+            log.error("根据sopId、qwUserId、corpId、startTime组合检查,剔除重复ID: {},时间:{}", duplicateIds, targetDateStr);
         }
 
-        return  R.ok().put("data",duplicateIds);
+        return R.ok().put("data", duplicateIds);
     }
 
     /**
      * 检查是否存在相同组合的数据
      */
-    private boolean checkDuplicateCombination(SopUserLogs currentLog, List<SopUserLogs> allLogs, String targetDate) {
+    private boolean checkDuplicateCombination(SopUserLogs currentLog, List<SopUserLogs> allLogs, String
+            targetDate) {
         for (SopUserLogs log : allLogs) {
             // 跳过自身比较
             if (log.getId().equals(currentLog.getId())) {
@@ -1003,7 +1059,7 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
             sopUserLogs.setStartTime(qwSop.getStartTime());
             sopUserLogs.setStatus(1);
             QwUserVO qwUserVO = qwUserMap.get(groupChat.getOwner());
-            if(qwUserVO != null){
+            if (qwUserVO != null) {
                 sopUserLogs.setUserId(qwUserVO.getId() + "|" + qwUserVO.getCompanyUserId() + "|" + qwUserVO.getCompanyId());
             }
             return sopUserLogs;
@@ -1013,7 +1069,7 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
 
     @Override
     public List<SopUserLogs> meetsTherestoreByIsDaysNotStudy(int offset, int pageSize, Integer notStudyDays) {
-        return sopUserLogsMapper.meetsTherestoreByIsDaysNotStudy(offset,pageSize,notStudyDays);
+        return sopUserLogsMapper.meetsTherestoreByIsDaysNotStudy(offset, pageSize, notStudyDays);
     }
 
     //批量更新
@@ -1030,7 +1086,7 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
             // 直接使用批次数据进行批量更新,不需要额外的 List
             try {
                 qwExternalContactMapper.batchUpdateQwExternalContact(batchList);
-                logger.info("成功更新了评级批次数据,起始索引为:{},数量:{} ", i,batchList.size());
+                logger.info("成功更新了评级批次数据,起始索引为:{},数量:{} ", i, batchList.size());
             } catch (Exception e) {
                 // 记录异常日志,方便后续排查问题
                 logger.error("批量更新数据时发生异常,处理的批次起始索引为: " + i, e);
@@ -1041,7 +1097,7 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
     //评级
     public int getScoreLevel(List<QwRatingVO> qwRatingVOS, QwRatingConfig config) {
 
-        AtomicDouble watchCount= new AtomicDouble();
+        AtomicDouble watchCount = new AtomicDouble();
 
         qwRatingVOS.forEach(vo -> {
             // 计算 watchDuration 除以 allDuration,并保留2位小数,四舍五入
@@ -1080,20 +1136,21 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
             throw new IllegalArgumentException("分数不在任何等级范围内: " + score);
         }
     }
+
     //升降等级
-    public int getLevelUpFall(int scoreLevel,int levelUpFall){
+    public int getLevelUpFall(int scoreLevel, int levelUpFall) {
 
         if (scoreLevel > levelUpFall) {
-            return  1;//升级
-        }else if (scoreLevel < levelUpFall) {
-            return  2;//降级
-        }else {
-            return  3;//不变
+            return 1;//升级
+        } else if (scoreLevel < levelUpFall) {
+            return 2;//降级
+        } else {
+            return 3;//不变
         }
     }
 
     //计算最晚看课时间
-    public int getLatestTime(List<QwRatingVO> qwRatingVOS){
+    public int getLatestTime(List<QwRatingVO> qwRatingVOS) {
 
         // 定义日期时间格式
         DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@@ -1102,21 +1159,21 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
         // 用于存储提取出的时分
         List<String> timeOnlyList = new ArrayList<>();
 
-        qwRatingVOS.forEach(vos->{
+        qwRatingVOS.forEach(vos -> {
 
             String finishTime = vos.getFinishTime();
 
-            if (!StringUtil.strIsNullOrEmpty(finishTime)){
+            if (!StringUtil.strIsNullOrEmpty(finishTime)) {
                 LocalTime localTime = LocalTime.parse(finishTime, formatter);
                 String formattedTime = localTime.format(outputFormatter);
                 timeOnlyList.add(formattedTime);
             }
 
         });
-        String latestTime=null;
-        if (!timeOnlyList.isEmpty()){
-            latestTime  = Collections.max(timeOnlyList);
-        }else {
+        String latestTime = null;
+        if (!timeOnlyList.isEmpty()) {
+            latestTime = Collections.max(timeOnlyList);
+        } else {
             latestTime = "0";
         }
 
@@ -1125,5 +1182,4 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
     }
 
 
-
 }

+ 7 - 0
fs-service/src/main/resources/application-config-dev-jnlzjk.yml

@@ -57,6 +57,13 @@ watch:
 fs :
   commonApi: http://127.0.0.1:7771
   h5CommonApi: http://127.0.0.1:7771
+  jwt:
+    # 加密秘钥
+    secret: f4e2e52034348f86b67cde581c0f9eb5
+    # token有效时长,7天,单位秒
+    expire: 31536000
+    header: AppToken
+
 nuonuo:
   key: 10924508
   secret: A2EB20764D304D16

+ 15 - 11
fs-service/src/main/resources/application-config-druid-bjczwh.yml

@@ -37,8 +37,8 @@ wx:
       port: 6379
       timeout: 2000
     configs:
-      - appId: wx090xxxx5456e # 第一个公众号的appid  //公众号名称:德瑞康
-        secret: dc70e9xxxx0aea6b7c52b7 # 公众号的appsecret--德瑞康
+      - appId: wx014d7c4fff877ea0 # 第一个公众号的appid  //公众号名称:食养美好生活
+        secret: ef574e8c66433cac1b158ea3a901650c # 公众号的appsecret--食养美好生活
         token: PPKOdAlCoMO # 接口配置里的Token值
         aesKey: Eswa6VjwtVMCcw03qZy6fWllgrv5aytIA1SZPEU0kU2 # 接口配置里的EncodingAESKey值
 aifabu:  #爱链接
@@ -55,8 +55,14 @@ watch:
   password3: v9xsKuqn_$d2y
 
 fs :
-  commonApi: http://127.0.0.1:7771
-  h5CommonApi: http://127.0.0.1:7771
+  commonApi: http://192.168.0.194:7771
+  h5CommonApi: http://192.168.0.194:7771
+  jwt:
+    # 加密秘钥
+    secret: bjczwh-bcdefg
+    # token有效时长,7天,单位秒
+    expire: 31536000
+    header: AppToken
 nuonuo:
   key: 10924508
   secret: A2EB20764D304D16
@@ -78,17 +84,15 @@ tmp_secret_config:
   proxy: fs
 cloud_host:
   company_name: 北京存在文化
-  projectCode: BJCZWH
+  projectCode: CZWH
 headerImg:
   imgUrl:
 
 ipad:
-  ipadUrl: http://ipad.cdwjyyh.com
-  aiApi: 1212121212
-  voiceApi:
-  commonApi:
+  ipadUrl: http://aipad.moonxiang.com
+  aiApi: http://49.232.181.28:3000/api
+  voiceApi: http://81.70.193.34:8667
+  commonApi: http://81.70.193.34:7771
 wx_miniapp_temp:
   pay_order_temp_id:
   inquiry_temp_id:
-
-

+ 6 - 0
fs-service/src/main/resources/application-config-druid-hzyy.yml

@@ -62,6 +62,12 @@ watch:
 fs :
   commonApi: http://127.0.0.1:7771
   h5CommonApi: http://127.0.0.1:7771
+  jwt:
+    # 加密秘钥
+    secret: f4h2z52034348y86y67cde581c0f9eb5
+    # token有效时长,7天,单位秒
+    expire: 31536000
+    header: AppToken
 nuonuo:
   key: 10924508
   secret: A2EB20764D304D16

+ 3 - 0
fs-service/src/main/resources/application-dev.yml

@@ -178,6 +178,9 @@ headerImg:
 ipad:
     ipadUrl: http://admin.test.ylrztop.com/ipad
     aiApi: http://1.95.196.10:3000/api
+    voiceApi:
+    commonApi:
+    url:
 wx_miniapp_temp:
     pay_order_temp_id:
     inquiry_temp_id:

+ 159 - 150
fs-service/src/main/resources/application-druid-bjczwh.yml

@@ -1,158 +1,167 @@
 # 数据源配置
 spring:
-    profiles:
-        include: config-druid-bjczwh,common
-    # redis 配置
-    redis:
-        host: r-bp1ylqods7sqn8gs4b.redis.rds.aliyuncs.com
-        port: 6379
-        # 数据库索引
-        database: 0
-        # 密码
-        password: Ylrz_1q2w3e4r5t6y
-        # 连接超时时间
-        timeout: 10s
-        lettuce:
-            pool:
-                # 连接池中的最小空闲连接
-                min-idle: 0
-                # 连接池中的最大空闲连接
-                max-idle: 8
-                # 连接池的最大数据库连接数
-                max-active: 100
-                # #连接池最大阻塞等待时间(使用负值表示没有限制)
-                max-wait: -1ms
-    datasource:
-#        clickhouse:
-#            type: com.alibaba.druid.pool.DruidDataSource
-#            driverClassName: com.clickhouse.jdbc.ClickHouseDriver
-#            url: jdbc:clickhouse://1.14.104.71:8123/sop_test?compress=0&use_server_time_zone=true&use_client_time_zone=false&timezone=Asia/Shanghai
-#            username: rt_2024
-#            password: Yzx_19860213
-#            initialSize: 10
-#            maxActive: 100
-#            minIdle: 10
-#            maxWait: 6000
-        mysql:
-            type: com.alibaba.druid.pool.DruidDataSource
-            driverClassName: com.mysql.cj.jdbc.Driver
-            druid:
-                # 主库数据源
-                master:
-                  url: jdbc:mysql://rm-bp10925iw97l3b2hb.mysql.rds.aliyuncs.com:3306/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                  username: root
-                  password: Ylrz_1q2w3e4r5t6y
-                # 从库数据源
-                slave:
-                    # 从数据源开关/默认关闭
-                    enabled: false
-                    url:
-                    username:
-                    password:
-                # 初始连接数
-                initialSize: 5
-                # 最小连接池数量
-                minIdle: 10
-                # 最大连接池数量
-                maxActive: 20
-                # 配置获取连接等待超时的时间
-                maxWait: 60000
-                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
-                timeBetweenEvictionRunsMillis: 60000
-                # 配置一个连接在池中最小生存的时间,单位是毫秒
-                minEvictableIdleTimeMillis: 300000
-                # 配置一个连接在池中最大生存的时间,单位是毫秒
-                maxEvictableIdleTimeMillis: 900000
-                # 配置检测连接是否有效
-                validationQuery: SELECT 1 FROM DUAL
-                testWhileIdle: true
-                testOnBorrow: false
-                testOnReturn: false
-                webStatFilter:
-                    enabled: true
-                statViewServlet:
-                    enabled: true
-                    # 设置白名单,不填则允许所有访问
-                    allow:
-                    url-pattern: /druid/*
-                    # 控制台管理用户名和密码
-                    login-username: fs
-                    login-password: 123456
-                filter:
-                    stat:
-                        enabled: true
-                        # 慢SQL记录
-                        log-slow-sql: true
-                        slow-sql-millis: 1000
-                        merge-sql: true
-                    wall:
-                        config:
-                            multi-statement-allow: true
-        sop:
-            type: com.alibaba.druid.pool.DruidDataSource
-            driverClassName: com.mysql.cj.jdbc.Driver
-            druid:
-                # 主库数据源
-                master:
-                    url: jdbc:mysql://rm-bp10925iw97l3b2hb.mysql.rds.aliyuncs.com:3306/fs_his_sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: root
-                    password: Ylrz_1q2w3e4r5t6y
-                # 初始连接数
-                initialSize: 5
-                # 最小连接池数量
-                minIdle: 10
-                # 最大连接池数量
-                maxActive: 20
-                # 配置获取连接等待超时的时间
-                maxWait: 60000
-                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
-                timeBetweenEvictionRunsMillis: 60000
-                # 配置一个连接在池中最小生存的时间,单位是毫秒
-                minEvictableIdleTimeMillis: 300000
-                # 配置一个连接在池中最大生存的时间,单位是毫秒
-                maxEvictableIdleTimeMillis: 900000
-                # 配置检测连接是否有效
-                validationQuery: SELECT 1 FROM DUAL
-                testWhileIdle: true
-                testOnBorrow: false
-                testOnReturn: false
-                webStatFilter:
-                    enabled: true
-                statViewServlet:
-                    enabled: true
-                    # 设置白名单,不填则允许所有访问
-                    allow:
-                    url-pattern: /druid/*
-                    # 控制台管理用户名和密码
-                    login-username: fs
-                    login-password: 123456
-                filter:
-                    stat:
-                        enabled: true
-                        # 慢SQL记录
-                        log-slow-sql: true
-                        slow-sql-millis: 1000
-                        merge-sql: true
-                    wall:
-                        config:
-                            multi-statement-allow: true
+  profiles:
+    include: config-druid-bjczwh,common
+  # redis 配置
+  redis:
+    host: redis-b6d80cf4-3df9-43c8-8182-bfe3ace0098b.cn-southwest-2.dcs.myhuaweicloud.com
+    port: 6379
+    # 数据库索引
+    database: 0
+    # 密码
+    password:
+    # 连接超时时间
+    timeout: 10s
+    lettuce:
+      pool:
+        # 连接池中的最小空闲连接
+        min-idle: 0
+        # 连接池中的最大空闲连接
+        max-idle: 8
+        # 连接池的最大数据库连接数
+        max-active: 100
+        # #连接池最大阻塞等待时间(使用负值表示没有限制)
+        max-wait: -1ms
+  datasource:
+    #        clickhouse:
+    #            type: com.alibaba.druid.pool.DruidDataSource
+    #            driverClassName: com.clickhouse.jdbc.ClickHouseDriver
+    #            url: jdbc:clickhouse://1.14.104.71:8123/sop_test?compress=0&use_server_time_zone=true&use_client_time_zone=false&timezone=Asia/Shanghai
+    #            username: rt_2024
+    #            password: Yzx_19860213
+    #            initialSize: 10
+    #            maxActive: 100
+    #            minIdle: 10
+    #            maxWait: 6000
+    mysql:
+      type: com.alibaba.druid.pool.DruidDataSource
+      driverClassName: com.mysql.cj.jdbc.Driver
+      druid:
+        # 主库数据源
+        master:
+          url: jdbc:mysql://rds.czwh.lan:3306/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+          username: czwh
+          password: Ylrz_1q2w3e4r5t6y
+        # 从库数据源
+        slave:
+          # 从数据源开关/默认关闭
+          enabled: false
+          url:
+          username:
+          password:
+        # 初始连接数
+        initialSize: 5
+        # 最小连接池数量
+        minIdle: 10
+        # 最大连接池数量
+        maxActive: 20
+        # 配置获取连接等待超时的时间
+        maxWait: 60000
+        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+        timeBetweenEvictionRunsMillis: 60000
+        # 配置一个连接在池中最小生存的时间,单位是毫秒
+        minEvictableIdleTimeMillis: 300000
+        # 配置一个连接在池中最大生存的时间,单位是毫秒
+        maxEvictableIdleTimeMillis: 900000
+        # 配置检测连接是否有效
+        validationQuery: SELECT 1 FROM DUAL
+        testWhileIdle: true
+        testOnBorrow: false
+        testOnReturn: false
+        webStatFilter:
+          enabled: true
+        statViewServlet:
+          enabled: true
+          # 设置白名单,不填则允许所有访问
+          allow:
+          url-pattern: /druid/*
+          # 控制台管理用户名和密码
+          login-username: fs
+          login-password: 123456
+        filter:
+          stat:
+            enabled: true
+            # 慢SQL记录
+            log-slow-sql: true
+            slow-sql-millis: 1000
+            merge-sql: true
+          wall:
+            config:
+              multi-statement-allow: true
+    sop:
+      type: com.alibaba.druid.pool.DruidDataSource
+      driverClassName: com.mysql.cj.jdbc.Driver
+      druid:
+        # 主库数据源
+        master:
+          url: jdbc:mysql://rds.czwh.lan:3306/fs_his_sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+          username: czwh
+          password: Ylrz_1q2w3e4r5t6y
+        # 初始连接数
+        initialSize: 5
+        # 最小连接池数量
+        minIdle: 10
+        # 最大连接池数量
+        maxActive: 20
+        # 配置获取连接等待超时的时间
+        maxWait: 60000
+        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+        timeBetweenEvictionRunsMillis: 60000
+        # 配置一个连接在池中最小生存的时间,单位是毫秒
+        minEvictableIdleTimeMillis: 300000
+        # 配置一个连接在池中最大生存的时间,单位是毫秒
+        maxEvictableIdleTimeMillis: 900000
+        # 配置检测连接是否有效
+        validationQuery: SELECT 1 FROM DUAL
+        testWhileIdle: true
+        testOnBorrow: false
+        testOnReturn: false
+        webStatFilter:
+          enabled: true
+        statViewServlet:
+          enabled: true
+          # 设置白名单,不填则允许所有访问
+          allow:
+          url-pattern: /druid/*
+          # 控制台管理用户名和密码
+          login-username: fs
+          login-password: 123456
+        filter:
+          stat:
+            enabled: true
+            # 慢SQL记录
+            log-slow-sql: true
+            slow-sql-millis: 1000
+            merge-sql: true
+          wall:
+            config:
+              multi-statement-allow: true
 rocketmq:
-    name-server: rmq-16xj8o92zp.rocketmq.cd.qcloud.tencenttdmq.com:8080
-    producer:
-        group: my-producer-group
-        access-key: ak16xj8o92zp984557f83ba2 # 替换为实际的 accessKey
-        secret-key: sk2ff1c6b15b74b888 # 替换为实际的 secretKey
-    consumer:
-        group: common-group
-        access-key: ak16xj8o92zp984557f83ba2 # 替换为实际的 accessKey
-        secret-key: sk2ff1c6b15b74b888 # 替换为实际的 secretKey
+  name-server: 192.168.0.124:8100
+  producer:
+    group: my-producer-group
+    access-key: default # 替换为实际的 accessKey
+    secret-key: O1VnW98G8Rmn0PoZ # 替换为实际的 secretKey
+  consumer:
+    topic: course-finish-notes
+    group: course-finish-group
+    access-key: default # 替换为实际的 accessKey
+    secret-key: O1VnW98G8Rmn0PoZ # 替换为实际的 secretKey
 openIM:
-    secret: openIM123
-    userID: imAdmin
-    url: https://web.im.fbylive.com/api
+  secret: openIM123
+  userID: imAdmin
+  url: https://web.im.fbylive.com/api
 #是否为新商户,新商户不走mpOpenId
-isNewWxMerchant: true
+isNewWxMerchant: false
 #是否使用新im
 im:
-    type: NONE
+  type: NONE
+
+qw:
+  enableAutoTag: 1
+tag:
+  thread:
+    num: 5
+  rate:
+    limit: 30
 

+ 3 - 0
fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml

@@ -163,6 +163,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.qwUserName != null  and maps.qwUserName != '' ">
                 and qu.qw_user_name = #{maps.qwUserName}
             </if>
+            <if test="maps.deptId != null  and maps.deptId != '' ">
+                and cu.dept_id = #{maps.deptId}
+            </if>
             <if test='maps.cuDeptIdList != null and !maps.cuDeptIdList.isEmpty() and  maps.userType != "00" '>
                 AND cu.dept_id IN
                 <foreach collection='maps.cuDeptIdList' item='item' open='(' separator=',' close=')'>

+ 1 - 1
fs-service/src/main/resources/mapper/course/FsUserCourseTrainingCampMapper.xml

@@ -18,7 +18,7 @@
             left join fs_course_watch_log cu on cu.period_id = ctp.period_id
         </if>
         <where>
-            ctc.del_flag ='0'
+            ctc.del_flag ='0'  and (ctp.del_flag != '1' or ctp.del_flag is null)
             <if test="params.trainingCampName != null and params.trainingCampName != ''">
                 and ctc.training_camp_name like concat('%',#{params.trainingCampName},'%')
             </if>

+ 3 - 0
fs-service/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml

@@ -92,6 +92,7 @@
             <if test="lineThree != null">line_three,</if>
             <if test="uploadType != null">upload_type,</if>
             <if test="redPacketMoney != null">red_packet_money,</if>
+            <if test="randomRedPacketRules != null">random_red_packet_rules,</if>
             <if test="fileSize != null">file_size,</if>
             <if test="fileKey != null">file_key,</if>
             <if test="round != null">round,</if>
@@ -130,6 +131,7 @@
             <if test="lineThree != null">#{lineThree},</if>
             <if test="uploadType != null">#{uploadType},</if>
             <if test="redPacketMoney != null">#{redPacketMoney},</if>
+            <if test="randomRedPacketRules != null">#{randomRedPacketRules},</if>
             <if test="fileSize != null">#{fileSize},</if>
             <if test="fileKey != null">#{fileKey},</if>
             <if test="round != null">#{round},</if>
@@ -218,6 +220,7 @@
             <if test="lineThree != null">line_three = #{lineThree},</if>
             <if test="uploadType != null">upload_type = #{uploadType},</if>
             <if test="redPacketMoney != null">red_packet_money = #{redPacketMoney},</if>
+            <if test="randomRedPacketRules != null">random_red_packet_rules = #{randomRedPacketRules},</if>
             <if test="fileSize != null">file_size = #{fileSize},</if>
             <if test="fileKey != null">file_key = #{fileKey},</if>
             <if test="round != null">round = #{round},</if>

+ 2 - 1
fs-service/src/main/resources/mapper/his/FsUserInformationCollectionMapper.xml

@@ -97,7 +97,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 <if test="maps.doctorType2Confirm != null"> and fui.doctor_type2_confirm = #{maps.doctorType2Confirm}</if>
                 <if test="maps.packageOrderCode != null  and maps.packageOrderCode != ''"> and fui.package_order_code = #{maps.packageOrderCode}</if>
             </where>
-
+        order by id desc
     </select>
     <select id="selectFsUserInformationCollectionByDoctorType1"
             resultType="com.fs.his.domain.FsUserInformationCollection">
@@ -107,6 +107,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.doctorConfirm != null"> and fui.doctor_confirm = #{maps.doctorConfirm}</if>
             <if test="maps.packageOrderCode != null  and maps.packageOrderCode != ''"> and fui.package_order_code = #{maps.packageOrderCode}</if>
         </where>
+        order by id desc
     </select>
     <select id="selectFsUserInformationCollectionByOrderCode"
             resultType="com.fs.his.domain.FsUserInformationCollection">

+ 1 - 1
fs-service/src/main/resources/mapper/his/FsUserMapper.xml

@@ -94,7 +94,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isShow != null  ">and is_show = #{isShow}</if>
             <!--<if test="qwRepeat != null  ">and qw_repeat = #{qwRepeat}</if>
             <if test="userRepeat != null  ">and user_repeat = #{userRepeat}</if>-->
-            <if test="payOrder != null  ">and pay_order = #{payOrder}</if>
+<!--            <if test="payOrder != null  ">and pay_order = #{payOrder}</if>-->
         </where>
     </select>
 

+ 24 - 3
fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml

@@ -985,7 +985,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </foreach>
     </select>
     <select id="selectFsStoreOrderListVOByErpAccount" resultType="com.fs.hisStore.vo.FsStoreOrderVO">
-        select o.*,u.phone,u.register_code,u.register_date,u.source, c.company_name ,cu.nick_name as company_user_nick_name ,cu.phonenumber as company_usere_phonenumber,,df.login_account as erp_account,
+        select o.*,u.phone,u.register_code,u.register_date,u.source, c.company_name ,cu.nick_name as company_user_nick_name ,cu.phonenumber as company_usere_phonenumber,df.login_account as erp_account,
+        sp_latest.bank_transaction_id as bankTransactionId
         from fs_store_order_scrm o
             left join fs_user u on o.user_id=u.user_id
             left join company c on c.company_id=o.company_id
@@ -1000,6 +1001,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         sp.*,
         ROW_NUMBER() OVER (PARTITION BY sp.business_code ORDER BY sp.create_time DESC) as rn
         FROM fs_store_payment_scrm sp
+        WHERE sp.business_code IS NOT NULL
         ) sp_latest ON sp_latest.business_code = o.order_code AND sp_latest.rn = 1
         LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp_latest.app_id
         <where>
@@ -1015,6 +1017,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.orderCode != null and  maps.orderCode !=''">
                 and o.order_code like CONCAT('%',#{maps.orderCode},'%')
             </if>
+            <if test="maps.bankTransactionId != null and  maps.bankTransactionId !=''">
+                and sp_latest.bank_transaction_id like CONCAT('%',#{maps.bankTransactionId},'%')
+            </if>
             <if test="maps.isPayRemain != null">
                 and o.is_pay_remain =#{maps.isPayRemain}
             </if>
@@ -1181,6 +1186,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.orderCode != null and  maps.orderCode !=''">
                 and o.order_code like CONCAT('%',#{maps.orderCode},'%')
             </if>
+            <if test="maps.bankTransactionId != null and  maps.bankTransactionId !=''">
+                and sp_latest.bank_transaction_id like CONCAT('%',#{maps.bankTransactionId},'%')
+            </if>
             <if test="maps.isPayRemain != null">
                 and o.is_pay_remain =#{maps.isPayRemain}
             </if>
@@ -1324,6 +1332,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.orderCode != null and  maps.orderCode !=''">
                 and o.order_code like CONCAT('%',#{maps.orderCode},'%')
             </if>
+            <if test="maps.bankTransactionId != null and  maps.bankTransactionId !=''">
+                and sp_latest.bank_transaction_id like CONCAT('%',#{maps.bankTransactionId},'%')
+            </if>
             <if test="maps.isPayRemain != null">
                 and o.is_pay_remain =#{maps.isPayRemain}
             </if>
@@ -1468,6 +1479,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.orderCode != null and  maps.orderCode !=''">
                 and o.order_code like CONCAT('%',#{maps.orderCode},'%')
             </if>
+            <if test="maps.bankTransactionId != null and  maps.bankTransactionId !=''">
+                and sp_latest.bank_transaction_id like CONCAT('%',#{maps.bankTransactionId},'%')
+            </if>
             <if test="maps.isPayRemain != null">
                 and o.is_pay_remain =#{maps.isPayRemain}
             </if>
@@ -1574,8 +1588,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </select>
 <!--    商城订单查询接口-->
     <select id="selectFsStoreOrderListVO" resultType="com.fs.hisStore.vo.FsStoreOrderVO">
-        select o.*,u.phone,u.register_code,u.register_date,u.source, c.company_name ,cu.nick_name as company_user_nick_name ,cu.phonenumber as company_usere_phonenumber
-        , csc.name miniProgramName,fsp.cost as cost, fspc.cate_name,spavs.bar_code
+        select o.id,o.order_code,o.extend_order_id,o.pay_order_id,o.bank_order_id,o.user_id,o.real_name,o.user_phone,o.user_address,o.cart_id,o.freight_price,o.total_num,o.total_price,o.total_postage,o.pay_price,o.pay_postage,o.pay_delivery,o.pay_money,o.deduction_price,o.coupon_id,o.coupon_price,o.paid,o.pay_time,o.pay_type,o.create_time,o.update_time,o.status,o.refund_status,o.refund_reason_wap_img,o.refund_reason_wap_explain,o.refund_reason_time,o.refund_reason_wap,o.refund_reason,o.refund_price,o.delivery_sn,o.delivery_name,o.delivery_type,o.delivery_id,o.gain_integral,o.use_integral,o.pay_integral,o.back_integral,o.mark,o.is_del,o.remark,o.verify_code,o.store_id,o.shipping_type,o.is_channel,o.is_remind,o.is_sys_del,o.is_prescribe,o.prescribe_id,o.company_id,o.company_user_id,o.is_package,o.package_json,o.order_type,o.package_id,o.finish_time,o.delivery_status,o.delivery_pay_status,o.delivery_time,o.delivery_pay_time,o.delivery_pay_money,o.tui_money,o.tui_money_status,o.delivery_import_time,o.tui_user_id,o.tui_user_money_status,o.order_create_type,o.store_house_code,o.dept_id,o.is_edit_money,o.customer_id,o.is_pay_remain,o.delivery_send_time,o.certificates,o.upload_time,o.item_json,o.schedule_id,o.delivery_pay_type,o.order_visit,o.service_fee,o.cycle,o.prescribe_price,o.follow_doctor_id,o.follow_time,o.user_coupon_id,o.order_medium,o.erp_phone
+        ,u.phone,u.register_code,u.register_date,u.source, c.company_name ,cu.nick_name as company_user_nick_name ,cu.phonenumber as company_usere_phonenumber
+        , csc.name miniProgramName,fsp.cost, fspc.cate_name,spavs.bar_code, sp_latest.bank_transaction_id as bankTransactionId
         from fs_store_order_scrm o
         left join fs_user u on o.user_id=u.user_id
         left join company c on c.company_id=o.company_id
@@ -1610,6 +1625,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.orderCode != null and  maps.orderCode !=''">
                 and o.order_code like CONCAT('%',#{maps.orderCode},'%')
             </if>
+            <if test="maps.bankTransactionId != null and  maps.bankTransactionId !=''">
+                and sp_latest.bank_transaction_id like CONCAT('%',#{maps.bankTransactionId},'%')
+            </if>
             <if test="maps.isPayRemain != null">
                 and o.is_pay_remain =#{maps.isPayRemain}
             </if>
@@ -1765,6 +1783,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.orderCode != null and  maps.orderCode !=''">
                 and o.order_code like CONCAT('%',#{maps.orderCode},'%')
             </if>
+            <if test="maps.bankTransactionId != null and  maps.bankTransactionId !=''">
+                and sp_latest.bank_transaction_id like CONCAT('%',#{maps.bankTransactionId},'%')
+            </if>
             <if test="maps.isPayRemain != null">
                 and o.is_pay_remain =#{maps.isPayRemain}
             </if>

+ 19 - 7
fs-service/src/main/resources/mapper/live/LiveOrderMapper.xml

@@ -482,7 +482,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="selectLiveOrderListVO" resultType="com.fs.live.vo.LiveOrderVO">
 
     select o.*,u.phone,u.register_code,u.register_date,u.source, c.company_name ,cu.nick_name as company_user_nick_name ,cu.phonenumber as company_usere_phonenumber
-    , csc.name miniProgramName
+    , csc.name miniProgramName, sp_latest.bank_transaction_id as bankTransactionId
     from live_order o
     left join fs_user u on o.user_id=u.user_id
     left join company c on c.company_id=o.company_id
@@ -516,6 +516,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <if test="maps.orderCode != null and  maps.orderCode !=''">
             and o.order_code like CONCAT('%',#{maps.orderCode},'%')
         </if>
+        <if test="maps.bankTransactionId != null and  maps.bankTransactionId !=''">
+            and sp_latest.bank_transaction_id like CONCAT('%',#{maps.bankTransactionId},'%')
+        </if>
         <if test="maps.isPayRemain != null">
             and o.is_pay_remain =#{maps.isPayRemain}
         </if>
@@ -1002,7 +1005,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
             <!-- 门店信息 -->
             spavs.bar_code,
-            spcs.cate_name
+            spcs.cate_name,
+            <!-- 支付信息 -->
+            lop.bank_transaction_id AS bankTransactionId
 
         FROM
             live_order o
@@ -1012,9 +1017,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             LEFT JOIN fs_store_scrm s ON p.store_id = s.store_id
             LEFT JOIN fs_store_product_attr_value_scrm spavs ON p.product_id = spavs.product_id
             LEFT JOIN fs_store_product_category_scrm spcs ON p.cate_id = spcs.cate_id
+            LEFT JOIN (
+                SELECT
+                    sp.*,
+                    ROW_NUMBER() OVER (PARTITION BY sp.business_code ORDER BY sp.create_time DESC) as rn
+                FROM live_order_payment sp
+                WHERE sp.business_code IS NOT NULL
+            ) lop ON lop.business_code = o.order_code AND lop.rn = 1
 
         <where>
-            o.is_del = 0
+            o.is_del = 0 and p.product_id IS NOT NULL
             <if test="orderId != null">
                 AND o.order_id = #{orderId}
             </if>
@@ -1107,7 +1119,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <select id="getDeliveryNote" resultType="com.fs.live.vo.LiveOrderDeliveryNoteExportVO">
         SELECT
-        CONCAT('AC', o.id) AS orderNumber,
+        CONCAT('AC', o.order_id) AS orderNumber,
         o.user_name AS recipient,
         o.user_phone AS recipientPhone,
         o.user_address AS recipientAddress,
@@ -1133,11 +1145,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LEFT JOIN company_user cu
         ON cu.user_id = o.company_user_id
         LEFT JOIN (
-        SELECT DISTINCT order_id
+        SELECT DISTINCT business_id as order_id
         FROM live_order_payment
-        WHERE is_pay_remain != 0 AND STATUS != 0
+        WHERE  STATUS != 0
         ) fp
-        ON o.id = fp.order_id
+        ON o.order_id = fp.order_id
         WHERE
         o.is_del = 0 and
         1 = 1

+ 5 - 0
fs-service/src/main/resources/mapper/qw/QwUserMapper.xml

@@ -304,4 +304,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         SELECT dept_id FROM sub_dept
     </select>
 
+    <select id="selectQwUserByTest" resultMap="QwUserResult">
+        <include refid="selectQwUserVo"/>
+        where status = 0 and server_status = 1
+    </select>
+
 </mapper>

+ 2 - 0
fs-service/src/main/resources/mapper/sop/SopUserLogsMapper.xml

@@ -14,6 +14,7 @@
         <result property="startTime"    column="start_time"  jdbcType="TIMESTAMP"   />
         <result property="status"    column="status"    />
         <result property="userId"    column="user_id"    />
+        <result property="chatId"    column="chat_id"    />
         <result property="countDays" column="count_days" />
     </resultMap>
 
@@ -25,6 +26,7 @@
             qw_user_id,
             corp_id,
             start_time,
+            chat_id,
             status,
             user_id,
             DATEDIFF(CURRENT_DATE, start_time) + 1 AS count_days

+ 2 - 18
fs-user-app/src/main/java/com/fs/app/controller/CompanyUserController.java

@@ -37,10 +37,7 @@ import com.fs.fastgptApi.vo.AudioVO;
 import com.fs.his.domain.FsPatient;
 import com.fs.his.domain.FsUserInformationCollection;
 import com.fs.his.param.*;
-import com.fs.his.service.IFsPatientService;
-import com.fs.his.service.IFsPrescribeService;
-import com.fs.his.service.IFsQuestionAndAnswerService;
-import com.fs.his.service.IFsUserInformationCollectionService;
+import com.fs.his.service.*;
 import com.fs.his.vo.*;
 import com.fs.sop.domain.QwSopTempVoice;
 import com.fs.sop.service.IQwSopTempVoiceService;
@@ -98,8 +95,6 @@ public class CompanyUserController extends  AppBaseController {
     private IFsUserInformationCollectionService fsUserInformationCollectionService;
     @Autowired
     private IFsQuestionAndAnswerService fsQuestionAndAnswerService;
-    @Autowired
-    private IFsPatientService fsPatientService;
 
     public static final String SOP_TEMP_VOICE_KEY = "sop:tempVoice";
     @PostMapping("/login")
@@ -430,18 +425,7 @@ public class CompanyUserController extends  AppBaseController {
     @GetMapping(value = "/informationCollection/{id}")
     public R getInformationCollectionInfo(@PathVariable("id") Long id)
     {
-        FsUserInformationCollection info = fsUserInformationCollectionService.selectFsUserInformationCollectionById(id);
-        Long patientId = info.getPatientId();
-        if(patientId != null){
-            FsPatient fsPatient = fsPatientService.selectFsPatientByPatientId(patientId);
-            if (fsPatient != null){
-                FsUserInformationCollectionAndPatientVO vo = new FsUserInformationCollectionAndPatientVO();
-                BeanUtils.copyProperties(info, vo);
-                vo.setPatientInfo(fsPatient);
-                return R.ok().put("data", vo);
-            }
-        }
-        return R.ok().put("data",info);
+        return R.ok().put("data", fsUserInformationCollectionService.selectFsUserInformationCollectionVoById(id));
     }
 
     /**

+ 5 - 38
fs-user-app/src/main/java/com/fs/app/controller/FsUserInformationCollectionController.java

@@ -35,12 +35,6 @@ public class FsUserInformationCollectionController extends AppBaseController
 {
     @Autowired
     private IFsUserInformationCollectionService fsUserInformationCollectionService;
-    @Autowired
-    private IFsPatientService fsPatientService;
-    @Autowired
-    private ICompanyUserService companyUserService;
-    @Autowired
-    private IFsPackageOrderService fsPackageOrderService;
 
 
     /**
@@ -51,44 +45,17 @@ public class FsUserInformationCollectionController extends AppBaseController
     public R getInfo(@PathVariable("id") Long id)
     {
 
-        FsUserInformationCollection info = fsUserInformationCollectionService.selectFsUserInformationCollectionById(id);
-
-        if (info == null){
+        FsUserInformationCollectionAndPatientVO vo = fsUserInformationCollectionService.selectFsUserInformationCollectionVoById(id);
+        if (vo == null){
             return R.error("未查询到信息!");
         }
         String userId = getUserId();
-        if (info.getUserId() != Long.parseLong(userId)){
+        if (vo.getUserId() != Long.parseLong(userId)){
             return R.error("未查询您的采集信息!");
         }
-        if (info.getDoctorConfirm() == 0){
-            info.setPackageId(null);
-        }
-        CompanyUser companyUser = companyUserService.selectCompanyUserById(info.getCompanyUserId());
-        info.setCompanyId(companyUser.getCompanyId());
-        Long patientId = info.getPatientId();
-
-        FsUserInformationCollectionAndPatientVO vo = new FsUserInformationCollectionAndPatientVO();
-        BeanUtils.copyProperties(info, vo);
-
-        if(patientId != null){
-            FsPatient fsPatient = fsPatientService.selectFsPatientByPatientId(patientId);
-            if (fsPatient != null){
-
-                vo.setPatientInfo(fsPatient);
-                //查询是否支付
-                Integer isPay = 0;
-                Long packageOrderId = info.getPackageOrderId();
-                if (packageOrderId != null){
-                    FsPackageOrder order = fsPackageOrderService.selectFsPackageOrderByOrderId(packageOrderId);
-                    if (order != null && order.getStatus() > 1){
-                        isPay = 1;
-                        vo.setStoreOrderId(order.getStoreOrderId());
-                    }
-                }
-                vo.setIsPay(isPay);
-            }
+        if (vo.getDoctorConfirm() == 0){
+            vo.setPackageId(null);
         }
-
         return R.ok().put("data", vo);
     }
 

+ 2 - 2
fs-user-app/src/main/java/com/fs/app/controller/UserController.java

@@ -201,7 +201,7 @@ public class UserController extends  AppBaseController {
     public R editUser(@RequestBody @Valid FsUserEditParam param, HttpServletRequest request){
         param.setUserId(Long.parseLong(getUserId()));
         log.info("【修改用户头像昵称】:{}",param);
-        if (param.getNickName().length()>50){
+        if (param.getNickname().length()>50){
             return R.error("请授权正确的昵称!");
         }
         if (StringUtils.isEmpty(param.getAvatar())){
@@ -211,7 +211,7 @@ public class UserController extends  AppBaseController {
         user.setUserId(Long.parseLong(getUserId()));
         user.setAvatar(param.getAvatar());
         // 前端传了nickname 和 nickName 但是只有nickName是正确的
-        user.setNickName(StringUtils.isNotEmpty(param.getNickName())?param.getNickName():param.getNickName());
+        user.setNickName(StringUtils.isNotEmpty(param.getNickName())?param.getNickName():param.getNickname());
         if (ObjectUtils.isNotEmpty(param.getIsWeixinAuth())){
             user.setIsWeixinAuth(param.getIsWeixinAuth());
         }

+ 3 - 2
fs-user-app/src/main/java/com/fs/app/controller/live/LiveController.java

@@ -13,6 +13,7 @@ import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.bean.BeanUtils;
 import com.fs.live.domain.Live;
 import com.fs.live.domain.LiveMsg;
+import com.fs.live.param.LiveNotifyParam;
 import com.fs.live.service.*;
 import com.fs.live.vo.LiveVo;
 import com.github.pagehelper.PageHelper;
@@ -266,8 +267,8 @@ public class LiveController extends AppBaseController {
 
 	@PostMapping("/subNotifyLive")
 	@Transactional
-	@Login
-	public R subNotifyLive(@RequestBody HashMap<String,Object> param) {
+//	@Login
+	public R subNotifyLive(@RequestBody LiveNotifyParam param) {
 /*		String userId = getUserId();
 		return liveService.currentActivities(liveId,userId);*/
 		return liveService.subNotifyLive(param);

+ 38 - 0
fs-user-app/src/main/java/com/fs/app/controller/store/IndexScrmController.java

@@ -6,6 +6,7 @@ import com.fs.app.annotation.Login;
 import com.fs.app.controller.AppBaseController;
 import com.fs.app.vo.IndexVO;
 import com.fs.common.core.domain.R;
+import com.fs.his.config.AgreementConfig;
 import com.fs.hisStore.domain.*;
 import com.fs.hisStore.param.*;
 import com.fs.hisStore.service.*;
@@ -22,6 +23,7 @@ import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.ModelAndView;
 import springfox.documentation.annotations.Cacheable;
 
 import javax.servlet.http.HttpServletRequest;
@@ -249,5 +251,41 @@ public class IndexScrmController extends AppBaseController {
 		return R.ok().put("data",chineseMedicine);
 	}
 
+	/**
+	 * 用户协议
+	 * @return
+	 */
+	@GetMapping("/getAgreementConfig")
+	public R getAgreementConfig(@RequestParam("name") String name)
+	{
+		String json=configService.selectConfigByKey("his.agreementConfig");
+		AgreementConfig config= JSONUtil.toBean(json, AgreementConfig.class);
+		String data = null;
+		switch (name){
+			case "userRegister":
+				data = config.getUserRegister();
+				break;
+			case "userPrivacy":
+				data = config.getUserPrivacy();
+				break;
+			case "userHealth":
+				data = config.getUserHealth();
+				break;
+			case "vipService":
+				data = config.getVipService();
+				break;
+			case "vipAutomaticService":
+				data = config.getVipAutomaticService();
+				break;
+			case "userRemoveService":
+				data = config.getUserRemoveService();
+				break;
+			default:
+				break;
+		}
+
+		return R.ok().put("data",data);
+	}
+
 
 }

+ 12 - 1
fs-user-app/src/main/java/com/fs/app/controller/store/UserScrmController.java

@@ -28,6 +28,8 @@ import com.fs.hisStore.vo.FsStoreOrderTuiVO;
 import com.fs.hisStore.vo.FsStoreProductRelationQueryVO;
 import com.fs.hisStore.vo.FsUserExtractVO;
 import com.fs.hisStore.vo.FsUserTuiVO;
+import com.fs.live.domain.LiveOrder;
+import com.fs.live.service.ILiveOrderService;
 import com.fs.utils.FileCacheService;
 import com.fs.wx.miniapp.config.WxMaProperties;
 import com.github.pagehelper.PageHelper;
@@ -90,6 +92,9 @@ public class UserScrmController extends AppBaseController {
     private FileCacheService fileCacheService;
     @Autowired
     private WxMaProperties maProperties;
+    @Autowired
+    private ILiveOrderService liveOrderService;
+
     /**
      * 获取用户信息
      * @param request
@@ -102,9 +107,15 @@ public class UserScrmController extends AppBaseController {
             FsUserScrm user=userService.selectFsUserById(Long.parseLong(getUserId()));
             if (user.getIsShow() !=null && user.getIsShow() == 0){
                 FsStoreOrderScrm order = orderService.selectOrderByUserIdLimit1(user.getUserId());
-                if (order!=null){
+                if (order != null) {
                     user.setIsShow(1);
+                } else {
+                    LiveOrder liveOrder = liveOrderService.selectOrderByUserIdLimit1(user.getUserId());
+                    if (liveOrder!=null){
+                        user.setIsShow(1);
+                    }
                 }
+
             }
             return R.ok().put("user",user);
         } catch (Exception e){

+ 21 - 21
fs-user-app/src/main/java/com/fs/app/param/FsUserEditParam.java

@@ -12,13 +12,13 @@ import java.io.Serializable;
 
 @JsonIgnoreProperties(ignoreUnknown = true)
 public class FsUserEditParam implements Serializable {
-//    @NotNull(message = "用户昵称不能为空!")
-//    @JsonAlias("nickname")
-//    private String nickname;
+    @NotNull(message = "用户昵称不能为空!")
+    @JsonAlias("nickname")
+    private String nickname;
 
     //    @NotBlank(message = "用户头像不能为空!")
     private String avatar;
-    @NotNull(message = "用户昵称不能为空!")
+
     @JsonAlias("nickName")
     private String nickName;
 
@@ -26,13 +26,13 @@ public class FsUserEditParam implements Serializable {
     private Integer isWeixinAuth;
 
 
-//    public @NotNull(message = "用户昵称不能为空!") String getNickname() {
-//        return nickname;
-//    }
-//
-//    public void setNickname(@NotNull(message = "用户昵称不能为空!") String nickname) {
-//        this.nickname = nickname;
-//    }
+    public @NotNull(message = "用户昵称不能为空!") String getNickname() {
+        return nickname;
+    }
+
+    public void setNickname(@NotNull(message = "用户昵称不能为空!") String nickname) {
+        this.nickname = nickname;
+    }
 
     public String getAvatar() {
         return avatar;
@@ -66,14 +66,14 @@ public class FsUserEditParam implements Serializable {
         this.isWeixinAuth = isWeixinAuth;
     }
 
-//    @Override
-//    public String toString() {
-//        return "FsUserEditParam{" +
-//                "nickname='" + nickname + '\'' +
-//                ", avatar='" + avatar + '\'' +
-//                ", nickName='" + nickName + '\'' +
-//                ", userId=" + userId +
-//                ", isWeixinAuth=" + isWeixinAuth +
-//                '}';
-//    }
+    @Override
+    public String toString() {
+        return "FsUserEditParam{" +
+                "nickname='" + nickname + '\'' +
+                ", avatar='" + avatar + '\'' +
+                ", nickName='" + nickName + '\'' +
+                ", userId=" + userId +
+                ", isWeixinAuth=" + isWeixinAuth +
+                '}';
+    }
 }