Explorar o código

Merge remote-tracking branch 'origin/master'

xyx hai 5 días
pai
achega
177d0ffc79
Modificáronse 100 ficheiros con 2710 adicións e 462 borrados
  1. 43 31
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseCompanyStatisticsController.java
  2. 24 7
      fs-admin/src/main/java/com/fs/his/controller/FsIntegralOrderController.java
  3. 109 0
      fs-admin/src/main/java/com/fs/his/controller/FsIntegralOrderLogsController.java
  4. 9 0
      fs-admin/src/main/java/com/fs/his/controller/FsStoreOrderController.java
  5. 38 0
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreHealthOrderScrmController.java
  6. 35 0
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java
  7. 8 8
      fs-admin/src/main/java/com/fs/hisStore/task/LiveTask.java
  8. 10 0
      fs-admin/src/main/java/com/fs/live/controller/LiveAfterSalesController.java
  9. 1 1
      fs-admin/src/main/java/com/fs/live/controller/LiveAutoTaskController.java
  10. 14 5
      fs-admin/src/main/java/com/fs/live/controller/LiveOrderController.java
  11. 2 2
      fs-admin/src/main/java/com/fs/qw/controller/IpadAllocationRecordsController.java
  12. 93 6
      fs-admin/src/main/java/com/fs/qw/qwTask/qwTask.java
  13. 21 1
      fs-company-app/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java
  14. 5 0
      fs-company-app/src/main/java/com/fs/app/param/FsUserLoginByMpParam.java
  15. 6 0
      fs-company/src/main/java/com/fs/company/controller/live/LiveAfterSalesController.java
  16. 1 1
      fs-company/src/main/java/com/fs/company/controller/live/LiveAutoTaskController.java
  17. 8 0
      fs-company/src/main/java/com/fs/company/controller/store/FsPackageOrderController.java
  18. 1 1
      fs-company/src/main/java/com/fs/user/FsUserAdminController.java
  19. 44 4
      fs-ipad-task/src/main/java/com/fs/app/service/IpadSendServer.java
  20. 12 0
      fs-live-app/src/main/java/com/fs/live/websocket/service/WebSocketServer.java
  21. 2 1
      fs-quartz/src/main/java/com/fs/quartz/config/ScheduleConfig.java
  22. 94 5
      fs-qw-task/src/main/java/com/fs/app/controller/CommonController.java
  23. 2 2
      fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java
  24. 5 0
      fs-service/src/main/java/com/fs/course/domain/FsCoursePlaySourceConfig.java
  25. 11 23
      fs-service/src/main/java/com/fs/course/domain/FsUserCourseCompanyStatistics.java
  26. 3 0
      fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigCreateParam.java
  27. 3 0
      fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigEditParam.java
  28. 9 0
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java
  29. 7 3
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  30. 3 0
      fs-service/src/main/java/com/fs/course/vo/FsCoursePlaySourceConfigVO.java
  31. 38 23
      fs-service/src/main/java/com/fs/erp/service/impl/DfOrderServiceImpl.java
  32. 1 1
      fs-service/src/main/java/com/fs/gtPush/service/impl/uniPush2ServiceImpl.java
  33. 2 0
      fs-service/src/main/java/com/fs/his/config/FsSmsConfig.java
  34. 47 0
      fs-service/src/main/java/com/fs/his/domain/FsIntegralOrderLogs.java
  35. 5 0
      fs-service/src/main/java/com/fs/his/domain/FsUser.java
  36. 62 0
      fs-service/src/main/java/com/fs/his/mapper/FsIntegralOrderLogsMapper.java
  37. 1 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserInformationCollectionMapper.java
  38. 4 0
      fs-service/src/main/java/com/fs/his/param/FsUserInformationCollectionParam.java
  39. 62 0
      fs-service/src/main/java/com/fs/his/service/IFsIntegralOrderLogsService.java
  40. 2 0
      fs-service/src/main/java/com/fs/his/service/IFsPackageOrderService.java
  41. 92 0
      fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderLogsServiceImpl.java
  42. 19 0
      fs-service/src/main/java/com/fs/his/service/impl/FsPackageOrderServiceImpl.java
  43. 64 30
      fs-service/src/main/java/com/fs/his/service/impl/FsUserInformationCollectionServiceImpl.java
  44. 2 0
      fs-service/src/main/java/com/fs/his/vo/FsUserInformationCollectionAndPatientVO.java
  45. 13 0
      fs-service/src/main/java/com/fs/hisStore/domain/FsUserScrm.java
  46. 2 1
      fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreOrderItemScrmMapper.java
  47. 6 0
      fs-service/src/main/java/com/fs/hisStore/service/IFsUserScrmService.java
  48. 17 10
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsMenuScrmServiceImpl.java
  49. 4 3
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java
  50. 27 2
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStorePaymentScrmServiceImpl.java
  51. 27 0
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsUserScrmServiceImpl.java
  52. 15 0
      fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderExportVO.java
  53. 10 0
      fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderItemExportVO.java
  54. 13 0
      fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderVO.java
  55. 3 2
      fs-service/src/main/java/com/fs/im/service/impl/OpenIMServiceImpl.java
  56. 2 1
      fs-service/src/main/java/com/fs/ipad/vo/BaseVo.java
  57. 3 0
      fs-service/src/main/java/com/fs/live/mapper/LiveAfterSalesMapper.java
  58. 1 1
      fs-service/src/main/java/com/fs/live/mapper/LiveOrderMapper.java
  59. 2 0
      fs-service/src/main/java/com/fs/live/service/ILiveAfterSalesService.java
  60. 2 0
      fs-service/src/main/java/com/fs/live/service/ILiveOrderPaymentService.java
  61. 224 6
      fs-service/src/main/java/com/fs/live/service/impl/LiveAfterSalesServiceImpl.java
  62. 5 0
      fs-service/src/main/java/com/fs/live/service/impl/LiveOrderPaymentServiceImpl.java
  63. 160 85
      fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java
  64. 16 2
      fs-service/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java
  65. 11 3
      fs-service/src/main/java/com/fs/live/vo/LiveOrderVoZm.java
  66. 46 0
      fs-service/src/main/java/com/fs/qw/domain/QwApiSopLogToken.java
  67. 61 0
      fs-service/src/main/java/com/fs/qw/mapper/QwApiSopLogTokenMapper.java
  68. 1 0
      fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java
  69. 61 0
      fs-service/src/main/java/com/fs/qw/service/IQwApiSopLogTokenService.java
  70. 91 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwApiSopLogTokenServiceImpl.java
  71. 22 0
      fs-service/src/main/java/com/fs/sop/mapper/QwSopLogsMapper.java
  72. 2 0
      fs-service/src/main/java/com/fs/sop/service/IQwSopLogsService.java
  73. 11 1
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopLogsServiceImpl.java
  74. 3 2
      fs-service/src/main/resources/application-config-dev.yml
  75. 15 11
      fs-service/src/main/resources/application-config-druid-bjczwh.yml
  76. 98 0
      fs-service/src/main/resources/application-config-druid-gzzdy.yml
  77. 1 0
      fs-service/src/main/resources/application-config-druid-heyantang.yml
  78. 1 1
      fs-service/src/main/resources/application-config-druid-hzyy.yml
  79. 2 0
      fs-service/src/main/resources/application-config-druid-jnmy.yml
  80. 1 0
      fs-service/src/main/resources/application-config-druid-knt.yml
  81. 1 0
      fs-service/src/main/resources/application-config-druid-knt2.yml
  82. 6 5
      fs-service/src/main/resources/application-config-druid-sft.yml
  83. 1 1
      fs-service/src/main/resources/application-config-druid-sxjz.yml
  84. 1 0
      fs-service/src/main/resources/application-config-zkzh.yml
  85. 159 150
      fs-service/src/main/resources/application-druid-bjczwh.yml
  86. 151 0
      fs-service/src/main/resources/application-druid-gzzdy.yml
  87. 73 0
      fs-service/src/main/resources/application-druid-jnmy-test.yml
  88. 0 3
      fs-service/src/main/resources/application-druid-jnmy.yml
  89. 4 0
      fs-service/src/main/resources/application-druid-kyt.yml
  90. 1 2
      fs-service/src/main/resources/mapper/course/FsUserCompanyBindMapper.xml
  91. 1 1
      fs-service/src/main/resources/mapper/course/FsUserCourseCompanyStatisticsMapper.xml
  92. 76 0
      fs-service/src/main/resources/mapper/his/FsIntegralOrderLogsMapper.xml
  93. 8 6
      fs-service/src/main/resources/mapper/his/FsUserInformationCollectionMapper.xml
  94. 5 1
      fs-service/src/main/resources/mapper/his/FsUserMapper.xml
  95. 7 5
      fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml
  96. 5 1
      fs-service/src/main/resources/mapper/hisStore/FsUserScrmMapper.xml
  97. 9 1
      fs-service/src/main/resources/mapper/live/LiveOrderMapper.xml
  98. 78 0
      fs-service/src/main/resources/mapper/qw/QwApiSopLogTokenMapper.xml
  99. 5 0
      fs-service/src/main/resources/mapper/qw/QwUserMapper.xml
  100. 116 0
      fs-user-app/src/main/java/com/fs/app/controller/AppLoginController.java

+ 43 - 31
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseCompanyStatisticsController.java

@@ -89,44 +89,56 @@ public class FsUserCourseCompanyStatisticsController extends BaseController
     @PreAuthorize("@ss.hasPermi('course:statistics:export')")
     @Log(title = "会员每日看课统计", businessType = BusinessType.EXPORT)
     @GetMapping("/export")
-    public AjaxResult export(FsUserCourseCompanyStatistics fsUserCourseCompanyStatistics)
-    {
+    public AjaxResult export(FsUserCourseCompanyStatistics fsUserCourseCompanyStatistics) {
+
         List<FsUserCourseCompanyStatistics> list =
                 fsUserCourseCompanyStatisticsService.selectFsUserCourseCompanyStatisticsTotal(fsUserCourseCompanyStatistics);
 
-        Optional.ofNullable(list).orElse(Collections.emptyList())
-                .forEach(item -> {
-                    // 计算完播率 (完播次数 / 观看次数 * 100)
-                    item.setCompleteRate(
-                            Optional.ofNullable(item.getWatchCount())
-                                    .filter(watchCount -> watchCount > 0)
-                                    .map(watchCount -> BigDecimal.valueOf(
-                                                    Optional.ofNullable(item.getCompleteWatchCount()).orElse(0L))
-                                            .multiply(BigDecimal.valueOf(100))
-                                            .divide(BigDecimal.valueOf(watchCount), 2, RoundingMode.HALF_UP)
-                                            .longValue()
-                                    )
-                                    .orElse(0L)
-                    );
-
-                    // 计算正确率 (正确人次 / 答题人次 * 100)
-                    item.setCorrectRate(
-                            Optional.ofNullable(item.getAnswerCount())
-                                    .filter(answerCount -> answerCount > 0)
-                                    .map(answerCount -> BigDecimal.valueOf(
-                                                    Optional.ofNullable(item.getCorrectCount()).orElse(0L))
-                                            .multiply(BigDecimal.valueOf(100))
-                                            .divide(BigDecimal.valueOf(answerCount), 2, RoundingMode.HALF_UP)
-                                            .longValue()
-                                    )
-                                    .orElse(0L)
-                    );
-                });
+        if (list == null) {
+            list = Collections.emptyList();
+        }
+
+        for (FsUserCourseCompanyStatistics item : list) {
 
-        ExcelUtil<FsUserCourseCompanyStatistics> util = new ExcelUtil<FsUserCourseCompanyStatistics>(FsUserCourseCompanyStatistics.class);
+            Long watchCount = item.getWatchCount();
+            Long completeWatchCount = Optional.ofNullable(item.getCompleteWatchCount()).orElse(0L);
+
+            // 完播率 = 完播次数 / 观看次数 * 100  (放大100倍存入long,再格式化两位小数)
+            if (watchCount != null && watchCount > 0) {
+                Long rateValue = BigDecimal.valueOf(completeWatchCount)
+                        .multiply(BigDecimal.valueOf(10000)) // 100*100
+                        .divide(BigDecimal.valueOf(watchCount), 0, RoundingMode.HALF_UP)
+                        .longValue();
+                item.setCompleteRate(rateValue);
+                item.setCompleteRateStr(String.format("%.2f%%", rateValue / 100.0));  // Excel 格式化
+            } else {
+                item.setCompleteRate(0L);
+                item.setCompleteRateStr("0.00%");
+            }
+
+            Long answerCount = item.getAnswerCount();
+            Long correctCount = Optional.ofNullable(item.getCorrectCount()).orElse(0L);
+
+            // 正确率 = 正确人次 / 答题人次 * 100
+            if (answerCount != null && answerCount > 0) {
+                Long rateValue = BigDecimal.valueOf(correctCount)
+                        .multiply(BigDecimal.valueOf(10000))
+                        .divide(BigDecimal.valueOf(answerCount), 0, RoundingMode.HALF_UP)
+                        .longValue();
+                item.setCorrectRate(rateValue);
+                item.setCorrectRateStr(String.format("%.2f%%", rateValue / 100.0));
+            } else {
+                item.setCorrectRate(0L);
+                item.setCorrectRateStr("0.00%");
+            }
+        }
+
+        ExcelUtil<FsUserCourseCompanyStatistics> util = new ExcelUtil<>(FsUserCourseCompanyStatistics.class);
         return util.exportExcel(list, "会员每日看课统计数据");
     }
 
+
+
     /**
      * 获取会员每日看课统计详细信息
      */

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

@@ -12,10 +12,8 @@ import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.CloudHostUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.his.domain.FsDfAccount;
-import com.fs.his.domain.FsIntegralOrder;
-import com.fs.his.domain.FsIntegralOrderDf;
-import com.fs.his.domain.FsStoreOrder;
+import com.fs.common.utils.uuid.IdUtils;
+import com.fs.his.domain.*;
 import com.fs.his.dto.ExpressInfoDTO;
 import com.fs.his.enums.ShipperCodeEnum;
 import com.fs.his.mapper.FsIntegralOrderMapper;
@@ -59,6 +57,8 @@ public class FsIntegralOrderController extends BaseController
     @Autowired
     private IFsStoreOrderService fsStoreOrderService;
 
+    @Autowired
+    private IFsIntegralOrderLogsService integralOrderLogsService;
 
     @Autowired
     private IFsIntegralOrderDfService integralOrderDfService;
@@ -314,12 +314,20 @@ public class FsIntegralOrderController extends BaseController
             } else {
                 integralOrderDfService.insertFsIntegralOrderDf(df);
             }
-            //积分订单操作日志暂定
+            // 添加积分订单操作记录
+            FsIntegralOrderLogs logs = new FsIntegralOrderLogs();
+            logs.setLogsId(IdUtils.fastUUID());
+            logs.setOrderId(item.getOrderId());
+            logs.setChangeType("set_erp_account");
+            logs.setChangeMessage(nickName+"设置ERP账户为:" + loginAccount);
+            logs.setChangeTime(LocalDateTime.now());
+            logs.setOperator(nickName);
+            integralOrderLogsService.insertFsIntegralOrderLogs(logs);
         });
         return R.ok();
     }
 
-//    @Log(title = "手动推管易", businessType = BusinessType.INSERT)
+    //    @Log(title = "手动推管易", businessType = BusinessType.INSERT)
     @ApiOperation("批量创建ERP订单")
 //    @PreAuthorize("@ss.hasPermi('his:storeOrder:createErpOrder')")
     @Log(title = "积分商品订单", businessType = BusinessType.UPDATE)
@@ -354,9 +362,18 @@ public class FsIntegralOrderController extends BaseController
                     integralOrderDfService.getBaseMapper().insert(df);
                     order.setLoginAccount(df.getLoginAccount());
                     integralOrderMapper.updateById(order);
-                    //日志表,待定
                 }
                 fsIntegralOrderService.createErpOrder(order.getOrderId());
+
+                // 添加积分订单操作记录
+                FsIntegralOrderLogs logs = new FsIntegralOrderLogs();
+                logs.setLogsId(IdUtils.fastUUID());
+                logs.setOrderId(order.getOrderId());
+                logs.setChangeType("create_erp_order");
+                logs.setChangeMessage(getLoginUser().getUser().getNickName()+"创建ERP订单,账户:" + loginAccount);
+                logs.setChangeTime(LocalDateTime.now());
+                logs.setOperator(getLoginUser().getUser().getNickName());
+                integralOrderLogsService.insertFsIntegralOrderLogs(logs);
             }
         }
         return R.ok("推送成功");

+ 109 - 0
fs-admin/src/main/java/com/fs/his/controller/FsIntegralOrderLogsController.java

@@ -0,0 +1,109 @@
+package com.fs.his.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.his.domain.FsIntegralOrderLogs;
+import com.fs.his.service.IFsIntegralOrderLogsService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 订单操作记录Controller
+ *
+ * @author fs
+ * @date 2025-11-25
+ */
+@RestController
+@RequestMapping("/his/logs")
+public class FsIntegralOrderLogsController extends BaseController
+{
+    @Autowired
+    private IFsIntegralOrderLogsService fsIntegralOrderLogsService;
+
+    /**
+     * 查询订单操作记录列表
+     */
+//    @PreAuthorize("@ss.hasPermi('his:logs:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsIntegralOrderLogs fsIntegralOrderLogs)
+    {
+        startPage();
+        List<FsIntegralOrderLogs> list = fsIntegralOrderLogsService.selectFsIntegralOrderLogsList(fsIntegralOrderLogs);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出订单操作记录列表
+     */
+//    @PreAuthorize("@ss.hasPermi('his:logs:export')")
+    @Log(title = "订单操作记录", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsIntegralOrderLogs fsIntegralOrderLogs)
+    {
+        List<FsIntegralOrderLogs> list = fsIntegralOrderLogsService.selectFsIntegralOrderLogsList(fsIntegralOrderLogs);
+        ExcelUtil<FsIntegralOrderLogs> util = new ExcelUtil<FsIntegralOrderLogs>(FsIntegralOrderLogs.class);
+        return util.exportExcel(list, "订单操作记录数据");
+    }
+
+    /**
+     * 获取订单操作记录详细信息
+     */
+//    @PreAuthorize("@ss.hasPermi('his:logs:query')")
+    @GetMapping(value = "/{logsId}")
+    public AjaxResult getInfo(@PathVariable("logsId") String logsId)
+    {
+        return AjaxResult.success(fsIntegralOrderLogsService.selectFsIntegralOrderLogsByLogsId(logsId));
+    }
+
+    /**
+     * 新增订单操作记录
+     */
+//    @PreAuthorize("@ss.hasPermi('his:logs:add')")
+    @Log(title = "订单操作记录", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsIntegralOrderLogs fsIntegralOrderLogs)
+    {
+        return toAjax(fsIntegralOrderLogsService.insertFsIntegralOrderLogs(fsIntegralOrderLogs));
+    }
+
+    /**
+     * 修改订单操作记录
+     */
+//    @PreAuthorize("@ss.hasPermi('his:logs:edit')")
+    @Log(title = "订单操作记录", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsIntegralOrderLogs fsIntegralOrderLogs)
+    {
+        return toAjax(fsIntegralOrderLogsService.updateFsIntegralOrderLogs(fsIntegralOrderLogs));
+    }
+
+    /**
+     * 根据订单ID查询操作记录
+     */
+//    @PreAuthorize("@ss.hasPermi('his:logs:query')")
+    @GetMapping("/order/{orderId}")
+    public AjaxResult getLogsByOrderId(@PathVariable("orderId") Long orderId)
+    {
+        FsIntegralOrderLogs queryParam = new FsIntegralOrderLogs();
+        queryParam.setOrderId(orderId);
+        List<FsIntegralOrderLogs> list = fsIntegralOrderLogsService.selectFsIntegralOrderLogsList(queryParam);
+        return AjaxResult.success(list);
+    }
+
+    /**
+     * 删除订单操作记录
+     */
+//    @PreAuthorize("@ss.hasPermi('his:logs:remove')")
+    @Log(title = "订单操作记录", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{logsIds}")
+    public AjaxResult remove(@PathVariable String[] logsIds)
+    {
+        return toAjax(fsIntegralOrderLogsService.deleteFsIntegralOrderLogsByLogsIds(logsIds));
+    }
+}

+ 9 - 0
fs-admin/src/main/java/com/fs/his/controller/FsStoreOrderController.java

@@ -34,6 +34,7 @@ import com.fs.his.dto.TracesDTO;
 import com.fs.his.enums.FsStoreOrderLogEnum;
 import com.fs.his.enums.FsStoreOrderStatusEnum;
 import com.fs.his.enums.ShipperCodeEnum;
+import com.fs.his.mapper.FsUserInformationCollectionMapper;
 import com.fs.his.param.FsFollowMsgParam;
 import com.fs.his.param.FsStoreOrderParam;
 import com.fs.his.param.FsStoreOrderSalesParam;
@@ -125,6 +126,8 @@ public class FsStoreOrderController extends BaseController
 
     @Autowired
     private IFsDfAccountService fsDfAccountService;
+    @Autowired
+    private FsUserInformationCollectionMapper userInformationCollectionMapper;
     /**
      * 查询订单列表
      */
@@ -648,6 +651,12 @@ public class FsStoreOrderController extends BaseController
     public AjaxResult sendGoods(@RequestBody FsStoreOrder fsStoreOrder)
     {
         String nickName = getLoginUser().getUser().getNickName();
+        if(CloudHostUtils.hasCloudHostName("金牛明医")){
+            FsUserInformationCollection fsUserInformationCollection = userInformationCollectionMapper.selectFsUserInformationCollectionByOrderCode(fsStoreOrder.getOrderCode());
+            if (fsUserInformationCollection != null&&fsUserInformationCollection.getDoctorType2Confirm()!=1) {
+                return AjaxResult.error("药师未确认");
+            }
+        }
         return toAjax(fsStoreOrderService.sendGoods(fsStoreOrder,nickName));
     }
     /**

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

@@ -7,14 +7,17 @@ import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
+import com.fs.common.core.domain.model.LoginUser;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.CloudHostUtils;
+import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.service.ICompanyMoneyLogsService;
 import com.fs.course.dto.FsOrderDeliveryNoteDTO;
 import com.fs.erp.service.IErpOrderService;
+import com.fs.framework.web.service.TokenService;
 import com.fs.his.domain.FsStoreOrderDf;
 import com.fs.his.service.IFsStoreOrderDfService;
 import com.fs.his.service.IFsUserService;
@@ -48,6 +51,8 @@ public class FsStoreHealthOrderScrmController extends BaseController {
 
     @Autowired
     private IFsStoreOrderStatusScrmService orderStatusService;
+    @Autowired
+    private TokenService tokenService;
 
     @Autowired
     IErpOrderService erpOrderService;
@@ -93,6 +98,7 @@ public class FsStoreHealthOrderScrmController extends BaseController {
             dataTable.setMsg("knt");
         }
         if (list != null) {
+            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
             for (FsStoreOrderVO vo : list) {
                 if(vo.getPhone()!=null){
                     vo.setPhone(vo.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
@@ -105,6 +111,17 @@ public class FsStoreHealthOrderScrmController extends BaseController {
                         vo.setErpAccount(df.getLoginAccount());
                     }
                 }
+                //
+                if (loginUser.getPermissions().contains("his:storeAfterSales:finance") || loginUser.getPermissions().contains("*:*:*")) {
+                    vo.setFPrice(vo.getCost().multiply(BigDecimal.valueOf(vo.getTotalNum())));
+                } else {
+                    vo.setPayPostage(BigDecimal.ZERO);
+                    vo.setCost(BigDecimal.ZERO);
+                    vo.setFPrice(BigDecimal.ZERO);
+                    vo.setPayDelivery(BigDecimal.ZERO);
+                    vo.setBarCode("");
+                    vo.setCateName("");
+                }
 
             }
         }
@@ -269,6 +286,7 @@ public class FsStoreHealthOrderScrmController extends BaseController {
         List<FsStoreOrderItemExportVO> list = orderItemService.selectFsStoreOrderItemListExportVO(param);
         //对手机号脱敏
         if (list != null) {
+            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
             for (FsStoreOrderItemExportVO vo : list) {
                 if (vo.getUserPhone() != null) {
                     String phone = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{1})", "$1****$2");
@@ -281,6 +299,16 @@ public class FsStoreHealthOrderScrmController extends BaseController {
                     } catch (Exception e) {
                     }
                 }
+                //
+                if (loginUser.getPermissions().contains("his:storeAfterSales:finance") || loginUser.getPermissions().contains("*:*:*")) {
+                    vo.setFPrice(vo.getCost().multiply(BigDecimal.valueOf(vo.getTotalNum())));
+                } else {
+                    vo.setPayPostage(BigDecimal.ZERO);
+                    vo.setCost(BigDecimal.ZERO);
+                    vo.setFPrice(BigDecimal.ZERO);
+                    vo.setBarCode("");
+                    vo.setCateName("");
+                }
             }
         }
         ExcelUtil<FsStoreOrderItemExportVO> util = new ExcelUtil<FsStoreOrderItemExportVO>(FsStoreOrderItemExportVO.class);
@@ -314,6 +342,7 @@ public class FsStoreHealthOrderScrmController extends BaseController {
         List<FsStoreOrderItemExportVO> list = orderItemService.selectFsStoreOrderItemListExportVO(param);
         //对手机号脱敏
         if (list != null) {
+            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
             for (FsStoreOrderItemExportVO vo : list) {
                 if (!StringUtils.isEmpty(vo.getJsonInfo())) {
                     try {
@@ -322,6 +351,15 @@ public class FsStoreHealthOrderScrmController extends BaseController {
                     } catch (Exception e) {
                     }
                 }
+                if (loginUser.getPermissions().contains("his:storeAfterSales:finance") || loginUser.getPermissions().contains("*:*:*")) {
+                    vo.setFPrice(vo.getCost().multiply(BigDecimal.valueOf(vo.getTotalNum())));
+                } else {
+                    vo.setPayPostage(BigDecimal.ZERO);
+                    vo.setCost(BigDecimal.ZERO);
+                    vo.setFPrice(BigDecimal.ZERO);
+                    vo.setBarCode("");
+                    vo.setCateName("");
+                }
             }
         }
         ExcelUtil<FsStoreOrderItemExportVO> util = new ExcelUtil<FsStoreOrderItemExportVO>(FsStoreOrderItemExportVO.class);

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

@@ -194,6 +194,7 @@ public class FsStoreOrderScrmController extends BaseController {
             dataTable.setMsg("knt");
         }
         if (list != null) {
+            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
             for (FsStoreOrderVO vo : list) {
                 if(vo.getPhone()!=null){
                     vo.setPhone(vo.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
@@ -206,6 +207,17 @@ public class FsStoreOrderScrmController extends BaseController {
                         vo.setErpAccount(df.getLoginAccount());
                     }
                 }
+                //
+                if (loginUser.getPermissions().contains("his:storeAfterSales:finance") || loginUser.getPermissions().contains("*:*:*")) {
+                    vo.setFPrice(vo.getCost().multiply(BigDecimal.valueOf(vo.getTotalNum())));
+                } else {
+                    vo.setPayPostage(BigDecimal.ZERO);
+                    vo.setCost(BigDecimal.ZERO);
+                    vo.setFPrice(BigDecimal.ZERO);
+                    vo.setPayDelivery(BigDecimal.ZERO);
+                    vo.setBarCode("");
+                    vo.setCateName("");
+                }
             }
         }
         FsStoreOrderListAndStatisticsVo vo = new FsStoreOrderListAndStatisticsVo();
@@ -435,6 +447,8 @@ public class FsStoreOrderScrmController extends BaseController {
         List<FsStoreOrderItemExportVO> list = orderItemService.selectFsStoreOrderItemListExportVO(param);
         //对手机号脱敏
         if (list != null) {
+            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+
             for (FsStoreOrderItemExportVO vo : list) {
                 if (vo.getUserPhone() != null) {
                     String phone = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{1})", "$1****$2");
@@ -450,6 +464,16 @@ public class FsStoreOrderScrmController extends BaseController {
                     } catch (Exception e) {
                     }
                 }
+                //
+                if (loginUser.getPermissions().contains("his:storeAfterSales:finance") || loginUser.getPermissions().contains("*:*:*")) {
+                    vo.setFPrice(vo.getCost().multiply(BigDecimal.valueOf(vo.getTotalNum())));
+                } else {
+                    vo.setPayPostage(BigDecimal.ZERO);
+                    vo.setCost(BigDecimal.ZERO);
+                    vo.setFPrice(BigDecimal.ZERO);
+                    vo.setBarCode("");
+                    vo.setCateName("");
+                }
             }
         }
         ExcelUtil<FsStoreOrderItemExportVO> util = new ExcelUtil<FsStoreOrderItemExportVO>(FsStoreOrderItemExportVO.class);
@@ -486,6 +510,7 @@ public class FsStoreOrderScrmController extends BaseController {
         List<FsStoreOrderItemExportVO> list = orderItemService.selectFsStoreOrderItemListExportVO(param);
         //对手机号脱敏
         if (list != null) {
+            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
             for (FsStoreOrderItemExportVO vo : list) {
                 if (!StringUtils.isEmpty(vo.getJsonInfo())) {
                     try {
@@ -494,6 +519,16 @@ public class FsStoreOrderScrmController extends BaseController {
                     } catch (Exception e) {
                     }
                 }
+                //
+                if (loginUser.getPermissions().contains("his:storeAfterSales:finance") || loginUser.getPermissions().contains("*:*:*")) {
+                    vo.setFPrice(vo.getCost().multiply(BigDecimal.valueOf(vo.getTotalNum())));
+                } else {
+                    vo.setPayPostage(BigDecimal.ZERO);
+                    vo.setCost(BigDecimal.ZERO);
+                    vo.setFPrice(BigDecimal.ZERO);
+                    vo.setBarCode("");
+                    vo.setCateName("");
+                }
             }
         }
         ExcelUtil<FsStoreOrderItemExportVO> util = new ExcelUtil<FsStoreOrderItemExportVO>(FsStoreOrderItemExportVO.class);

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

@@ -150,10 +150,10 @@ 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();
+//        for (Long id : ids) {
+//            liveOrderService.createOmsOrder(id);
+//        }
     }
 
     public void redPacketSubMoney() throws Exception {
@@ -317,10 +317,10 @@ public class LiveTask {
     }
 
     public void updateOrderItem() throws ParseException {
-        List<Long> ids = liveOrderService.selectOrderIdByNoErp();
-        for (Long id : ids) {
-            liveOrderService.createOmsOrder(id);
-        }
+//        List<Long> ids = liveOrderService.selectOrderIdByNoErp();
+//        for (Long id : ids) {
+//            liveOrderService.createOmsOrder(id);
+//        }
     }
 
     //每天执行一次

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

@@ -180,4 +180,14 @@ public class LiveAfterSalesController extends BaseController
         param.setOperator(loginUser.getUser().getNickName());
         return liveAfterSalesService.cancel(param);
     }
+
+    @PreAuthorize("@ss.hasPermi('store:storeAfterSales:refund')")
+    @PostMapping("/handleImmediatelyRefund")
+    public R handleImmediatelyRefund(@RequestBody LiveAfterSalesRefundParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setOperator(loginUser.getUser().getNickName());
+        return liveAfterSalesService.handleImmediatelyRefund(param.getOrderId());
+    }
+
 }

+ 1 - 1
fs-admin/src/main/java/com/fs/live/controller/LiveAutoTaskController.java

@@ -66,7 +66,7 @@ public class LiveAutoTaskController extends BaseController
         return getDataTable(list);
     }
 
-    @PreAuthorize("@ss.hasPermi('live:task:list')")
+//    @PreAuthorize("@ss.hasPermi('live:task:list')")
     @GetMapping("/consoleList")
     public TableDataInfo consoleList(LiveAutoTask liveAutoTask)
     {

+ 14 - 5
fs-admin/src/main/java/com/fs/live/controller/LiveOrderController.java

@@ -178,6 +178,9 @@ public class LiveOrderController extends BaseController
             } else {
                 vo.setCostPrice(BigDecimal.ZERO);
                 vo.setFPrice(BigDecimal.ZERO);
+                vo.setPayDelivery(BigDecimal.ZERO);
+                vo.setBarCode("");
+                vo.setCateName("");
             }
             vo.setCost(vo.getCostPrice());
 
@@ -484,8 +487,12 @@ public class LiveOrderController extends BaseController
     {
         logger.info("手动推管易 订单号: {}",orderCode);
         LiveOrder order=liveOrderService.selectOrderIdByOrderCode(orderCode);
-        liveOrderService.createOmsOrder(order.getOrderId());
-        return R.ok();
+        if (orderPaymentService.selectByBussinessId(order.getOrderId()) != null) {
+            liveOrderService.createOmsOrder(order.getOrderId());
+            return R.ok();
+        }
+        return R.error("订单未支付!");
+
     }
 
     @Log(title = "同步管易物流单号", businessType = BusinessType.UPDATE)
@@ -636,9 +643,11 @@ public class LiveOrderController extends BaseController
                     orderLogsService.create(orderId, FsStoreOrderLogEnum.SET_PUSH_ACCOUNT.getValue(),
                             nickName + " " +FsStoreOrderLogEnum.SET_PUSH_ACCOUNT.getDesc() + ":" + df.getLoginAccount());
                 }
-                liveOrderService.createOmsOrder(orderId);
-                orderLogsService.create(orderId, FsStoreOrderLogEnum.PUSH_ORDER_ERP.getValue(),
-                        nickName + " " +FsStoreOrderLogEnum.PUSH_ORDER_ERP.getDesc() + ":" + df.getLoginAccount());
+                if (orderPaymentService.selectByBussinessId(orderId) != null) {
+                    liveOrderService.createOmsOrder(orderId);
+                    orderLogsService.create(orderId, FsStoreOrderLogEnum.PUSH_ORDER_ERP.getValue(),
+                            nickName + " " +FsStoreOrderLogEnum.PUSH_ORDER_ERP.getDesc() + ":" + df.getLoginAccount());
+                }
             } catch (ParseException e) {
                 throw new RuntimeException(e);
             }

+ 2 - 2
fs-admin/src/main/java/com/fs/qw/controller/IpadAllocationRecordsController.java

@@ -52,7 +52,7 @@ public class IpadAllocationRecordsController extends BaseController {
 
     @Autowired
     private IpadAllocationRecordsMapper ipadAllocationRecordsMapper;
-    @Value("${ipad.url}")
+    @Value("${ipad.watchUrl:https://manwatch.ylrzcloud.com/prod-api}")
     private String ipadServerUrl;
 
     /**
@@ -128,7 +128,7 @@ public class IpadAllocationRecordsController extends BaseController {
         return AjaxResult.success(detailsList);
     }
 
-    @Value("${ipad.companyId:13}")
+    @Value("${ipad.fsCompanyId:13}")
     private Long companyId;
     //发起申请ipad服务器
     @GetMapping("/apply")

+ 93 - 6
fs-admin/src/main/java/com/fs/qw/qwTask/qwTask.java

@@ -1,21 +1,24 @@
 package com.fs.qw.qwTask;
 
 import com.fs.course.service.IFsUserCourseService;
-import com.fs.qw.service.IQwExternalContactService;
-import com.fs.qw.service.IQwGroupMsgService;
-import com.fs.qw.service.IQwMaterialService;
-import com.fs.qw.service.IQwUserService;
+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 org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+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 {
@@ -51,6 +54,25 @@ 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;
+
+
     //正在使用
     public void qwExternalContact()
     {
@@ -199,4 +221,69 @@ public class qwTask {
     public void updateMaterialByTwoDays(){
         iQwMaterialService.updateQwMaterialByQw();
     }
+
+    /**
+     * 统计 每天的官方群发统计
+     */
+    public void countQwApiAopLogToken(){
+        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        // 获取当前日期(只包含年月日)
+        LocalDate currentDate = LocalDate.now();
+
+        String todayStr = currentDate.format(dateFormatter);
+         qwSopLogsService.countQwApiAopLogToken(todayStr);
+
+
+    }
+
+    /**
+     * 定时清除 占着茅坑不拉屎的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);
+    }
+
 }

+ 21 - 1
fs-company-app/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java

@@ -9,9 +9,11 @@ import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.StringUtils;
+import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyMiniapp;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.ICompanyMiniappService;
+import com.fs.company.service.ICompanyService;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.course.domain.FsUserCoursePeriod;
 import com.fs.course.dto.BatchSendCourseDTO;
@@ -39,6 +41,7 @@ import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -57,6 +60,9 @@ public class FsUserCourseVideoController extends AppBaseController {
     @Autowired
     private IFsUserCourseVideoService fsUserCourseVideoService;
 
+    @Autowired
+    private ICompanyService iCompanyService;
+
     @Autowired
     private IFsUserCourseService fsUserCourseService;
 
@@ -290,6 +296,20 @@ public class FsUserCourseVideoController extends AppBaseController {
         return ResponseResult.ok(courseLinkService.getGotoWxAppLink(linkStr,appid));
     }
 
+    @GetMapping("/getGotoAppLink")
+    @ApiOperation("获取跳转微信小程序的链接地址")
+    public ResponseResult<String> getGotoWxAppLink(String linkStr, Long companyId) {
+        Company company = iCompanyService.selectCompanyById(companyId);
+        String appid = null;
+        if (CollectionUtils.isNotEmpty(company.getMiniAppMaster())){
+            appid = company.getMiniAppMaster().get(0);
+        }else if (CollectionUtils.isNotEmpty(company.getMiniAppServer())){
+            appid = company.getMiniAppServer().get(0);
+        }else {
+            return ResponseResult.fail(500,"请在后台配置主备小程序!");
+        }
+        return ResponseResult.ok(courseLinkService.getGotoWxAppLink(linkStr,appid));
+    }
     /**
      * 获取跳转微信小程序的链接地址
      */
@@ -309,7 +329,7 @@ public class FsUserCourseVideoController extends AppBaseController {
         R courseSortLink = fsUserCourseService.createAppCourseSortLink(fsCourseLinkCreateParam);
         String url = courseSortLink.get("url").toString();
         batchSendCourseDTO.setUrl(url);
-
+        batchSendCourseDTO.setIsUrgeCourse(false);
         return openIMService.batchSendCourse(batchSendCourseDTO);
     }
 

+ 5 - 0
fs-company-app/src/main/java/com/fs/app/param/FsUserLoginByMpParam.java

@@ -9,4 +9,9 @@ import java.io.Serializable;
 public class FsUserLoginByMpParam implements Serializable {
     @NotBlank(message = "code参数缺失")
     private String code;
+    
+    /**
+     * 小程序appId
+     */
+    private String appId;
 }

+ 6 - 0
fs-company/src/main/java/com/fs/company/controller/live/LiveAfterSalesController.java

@@ -8,6 +8,8 @@ import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.company.domain.CompanyUser;
+import com.fs.framework.security.SecurityUtils;
 import com.fs.his.domain.FsUser;
 import com.fs.his.service.IFsUserService;
 import com.fs.live.domain.LiveAfterSales;
@@ -55,6 +57,8 @@ public class LiveAfterSalesController extends BaseController
     public TableDataInfo list(LiveAfterSalesVo liveAfterSales)
     {
         startPage();
+        CompanyUser user = SecurityUtils.getLoginUser().getUser();
+        liveAfterSales.setCompanyId(user.getCompanyId());
         List<LiveAfterSalesVo> list = liveAfterSalesService.selectLiveAfterSalesVoList(liveAfterSales);
         for (LiveAfterSalesVo liveAfterSalesVo : list) {
             liveAfterSalesVo.setUserPhone(ParseUtils.parsePhone(liveAfterSalesVo.getUserPhone()));
@@ -71,6 +75,8 @@ public class LiveAfterSalesController extends BaseController
     public AjaxResult export(LiveAfterSalesVo liveAfterSales)
     {
         PageHelper.startPage(1, 10000, "");
+        CompanyUser user = SecurityUtils.getLoginUser().getUser();
+        liveAfterSales.setCompanyId(user.getCompanyId());
         List<LiveAfterSalesVo> list = liveAfterSalesService.selectLiveAfterSalesVoList(liveAfterSales);
         for (LiveAfterSalesVo liveAfterSalesVo : list) {
             liveAfterSalesVo.setUserPhone(liveAfterSalesVo.getUserPhone() == null ? "" : liveAfterSalesVo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));

+ 1 - 1
fs-company/src/main/java/com/fs/company/controller/live/LiveAutoTaskController.java

@@ -55,7 +55,7 @@ public class LiveAutoTaskController extends BaseController
         return getDataTable(list);
     }
 
-    @PreAuthorize("@ss.hasPermi('live:task:list')")
+//    @PreAuthorize("@ss.hasPermi('live:task:list')")
     @GetMapping("/consoleList")
     public TableDataInfo consoleList(LiveAutoTask liveAutoTask)
     {

+ 8 - 0
fs-company/src/main/java/com/fs/company/controller/store/FsPackageOrderController.java

@@ -20,6 +20,7 @@ import com.fs.his.service.IFsPackageOrderService;
 import com.fs.his.utils.PhoneUtil;
 import com.fs.his.vo.FsPackageOrderListVO;
 import com.fs.his.vo.FsPackageOrderVO;
+import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
@@ -260,4 +261,11 @@ public class FsPackageOrderController extends BaseController
         return fsPackageOrderService.getWxaCodePackageOrderUnLimit(orderId);
 
     }
+
+    @ApiOperation("修改或者添加患者首诊图片")
+    @PostMapping("/editPatientImages")
+    public R editPatientImages(@RequestParam("orderId")Long orderId,
+                               @RequestParam("imagesList")String imagesList){
+        return fsPackageOrderService.editPatientImages(orderId,imagesList);
+    }
 }

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

@@ -167,7 +167,7 @@ public class FsUserAdminController extends BaseController {
         R courseSortLink = fsUserCourseService.createAppCourseSortLink(fsCourseLinkCreateParam);
         String url = courseSortLink.get("url").toString();
         batchSendCourseDTO.setUrl(url);
-
+        batchSendCourseDTO.setIsUrgeCourse(false);
         return openIMService.batchSendCourse(batchSendCourseDTO);
     }
 

+ 44 - 4
fs-ipad-task/src/main/java/com/fs/app/service/IpadSendServer.java

@@ -1,18 +1,23 @@
 package com.fs.app.service;
 
 import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.exception.base.BaseException;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.date.DateUtil;
+import com.fs.common.utils.spring.SpringUtils;
 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.service.IFsCourseWatchLogService;
+import com.fs.his.domain.FsUser;
+import com.fs.his.mapper.FsUserMapper;
 import com.fs.ipad.IpadSendUtils;
 import com.fs.ipad.vo.*;
+import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.domain.QwUser;
 import com.fs.qw.domain.QwUserVideo;
 import com.fs.qw.mapper.QwExternalContactMapper;
@@ -27,11 +32,14 @@ import com.fs.sop.service.impl.QwSopLogsServiceImpl;
 import com.fs.wxwork.dto.*;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 @Slf4j
 @Service
@@ -47,13 +55,44 @@ public class IpadSendServer {
     private final IQwUserVideoService qwUserVideoService;
     private final RedisCache redisCache;
     private final ICompanyMiniappService companyMiniappService;
-
+    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) {
         String appid = content.getMiniprogramAppid();
         if(companyId != null && content.getMiniType() != null){
-            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();
+            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();
+            }
+            String signProjectName = SpringUtils.getProperty("cloud_host.company_name");
+            //区分新老用户,新用户发送备用小程序,老用户发送主小程序
+            if(PROJECT_NAMES.contains(signProjectName)){
+                log.info("ID:{}, qwUserId:{},externalId:{},进入区分发小程序逻辑", vo.getId(), vo.getQwUserId(), vo.getExId());
+                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);
+                            }
+                        }else{
+                            log.info("ID:{}, qwUserId:{},externalId:{},未绑定小程序用户", vo.getId(), vo.getQwUserId(), vo.getExId());
+                        }
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        log.error("6.输出外部联系人ID-------------->{}",vo.getExId());
+                        log.error("7.数据异常----------------------》{}",e.getMessage());
+                    }
+                }
             }
         }
         FsCoursePlaySourceConfig courseMaConfig = miniMap.get(appid);
@@ -341,6 +380,7 @@ public class IpadSendServer {
         vo.setServerId(qwUser.getServerId());
         vo.setCorpCode(parentVo.getCorpCode());
         vo.setCorpId(parentVo.getCorpId());
+        vo.setQwUserId(qwUser.getId());
         try {
             content.setSendStatus(1);
             switch (content.getContentType()) {

+ 12 - 0
fs-live-app/src/main/java/com/fs/live/websocket/service/WebSocketServer.java

@@ -365,6 +365,9 @@ public class WebSocketServer {
                 case "goods":
                     sendGoodsMessage(msg);
                     break;
+                case "deleteMsg":
+                    deleteMsg(liveId,msg);
+                    break;
                 case "red":
                     processRed(liveId, msg);
                     break;
@@ -385,6 +388,15 @@ public class WebSocketServer {
         }
     }
 
+    private void deleteMsg(long liveId,SendMsgVo msg) {
+        SendMsgVo sendMsgVo = new SendMsgVo();
+        sendMsgVo.setLiveId(liveId);
+        sendMsgVo.setUserType(0L);
+        sendMsgVo.setCmd("deleteMsg");
+        sendMsgVo.setMsg(msg.getMsg());
+        broadcastMessage(liveId, JSONObject.toJSONString(R.ok().put("data", sendMsgVo)));
+    }
+
     private void processCoupon(long liveId, SendMsgVo msg) {
         JSONObject jsonObject = JSON.parseObject(msg.getData());
         Integer status = jsonObject.getInteger("status");

+ 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;
     }

+ 94 - 5
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,11 +138,96 @@ 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);
+    }
+    /**
+     *
+     */
+    @GetMapping("/countQwApiAopLogToken")
+    public void countQwApiAopLogToken() {
+
+        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        // 获取当前日期(只包含年月日)
+        LocalDate currentDate = LocalDate.now();
+
+        String todayStr = currentDate.format(dateFormatter);
+        qwSopLogsService.countQwApiAopLogToken(todayStr);
+
+    }
+
+    /**
+     * 查询视频时长
      */
     @GetMapping("/getVideoDuration")
-    @ApiOperation("获取跳转微信小程序的链接地址")
     public Long getVideoDuration(Long videoId) {
 
             String redisKey = "h5user:video:duration:" + videoId;

+ 2 - 2
fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java

@@ -1127,9 +1127,9 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
         }
         clonedContent.getSetting().stream().filter(e -> "1".equals(e.getIsBindUrl())).forEach(e -> {
             e.setIsBindUrl("0");
-            e.setLinkDescribe(null);
+//            e.setLinkDescribe(null);
             e.setLinkUrl(null);
-            e.setLinkImageUrl(null);
+//            e.setLinkImageUrl(null);
         });
         sopLogs.setContentJson(JSON.toJSONString(clonedContent));
         enqueueQwSopLogs(sopLogs);

+ 5 - 0
fs-service/src/main/java/com/fs/course/domain/FsCoursePlaySourceConfig.java

@@ -99,4 +99,9 @@ public class FsCoursePlaySourceConfig {
      * 是否是互医/商城小程序
      */
     private Integer isMall;
+
+    /**
+     * 小程序状态:0正常,1半封禁,2封禁
+     */
+    private Integer status;
 }

+ 11 - 23
fs-service/src/main/java/com/fs/course/domain/FsUserCourseCompanyStatistics.java

@@ -17,67 +17,55 @@ import lombok.EqualsAndHashCode;
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-public class FsUserCourseCompanyStatistics extends BaseEntity{
+public class FsUserCourseCompanyStatistics extends BaseEntity {
 
-    /** 主键ID */
     private Long id;
 
-    /** 项目ID */
-//    @Excel(name = "项目ID")
     private Long projectId;
 
-    /** 完播次数(人次) */
-    @Excel(name = "完播次数", readConverterExp = "人=次")
+    @Excel(name = "完播次数")
     private Long completeWatchCount;
 
-    /** 观看次数(人次) */
-    @Excel(name = "观看次数", readConverterExp = "人=次")
+    @Excel(name = "观看次数")
     private Long watchCount;
 
-    /** 完播率(完播次数/观看次数) */
-    @Excel(name = "完播率", readConverterExp = "完=播次数/观看次数")
+    /** DB字段,存放放大100倍后的比例整数值,例 12.34% -> 1234 */
     private Long completeRate;
 
-    /** 答题人次 */
     @Excel(name = "答题人次")
     private Long answerCount;
 
-    /** 正确人次 */
     @Excel(name = "正确人次")
     private Long correctCount;
 
-    /** 正确率(正确人次/答题人次) */
-    @Excel(name = "正确率", readConverterExp = "正=确人次/答题人次")
+    /** DB字段,同样放大100倍后存储 */
     private Long correctRate;
 
-    /** 领取次数 */
     @Excel(name = "领取次数")
     private Long receiveCount;
 
-    /** 领取金额(元) */
-    @Excel(name = "领取金额", readConverterExp = "元=")
+    @Excel(name = "领取金额(元)")
     private BigDecimal receiveAmount;
 
-    /** 会员数量 */
     @Excel(name = "会员数量")
     private Long userCount;
 
-    /** 会员黑名单数量 */
     @Excel(name = "会员黑名单数量")
     private Long userBlacklistCount;
 
-    /** 公司ID */
-//    @Excel(name = "公司ID")
     private Long companyId;
 
-    /** 公司名称 */
     @Excel(name = "公司名称")
     private String companyName;
 
-    /** 统计日期 */
     @JsonFormat(pattern = "yyyy-MM-dd")
     @Excel(name = "统计日期", width = 30, dateFormat = "yyyy-MM-dd")
     private Date createDate;
 
+    /** 用于 Excel 导出显示的字符串,不入库 */
+    @Excel(name = "完播率(%)")
+    private String completeRateStr;
 
+    @Excel(name = "正确率(%)")
+    private String correctRateStr;
 }

+ 3 - 0
fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigCreateParam.java

@@ -54,4 +54,7 @@ public class FsCoursePlaySourceConfigCreateParam {
     @ApiModelProperty("是否是互医/商城小程序")
     private Integer isMall;
     private Long createDeptId;
+
+    @ApiModelProperty("小程序状态:0正常,1半封禁,2封禁")
+    private Integer status;
 }

+ 3 - 0
fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigEditParam.java

@@ -52,4 +52,7 @@ public class FsCoursePlaySourceConfigEditParam {
     @ApiModelProperty("是否是互医/商城小程序")
     private Integer isMall;
     private Long createDeptId;
+
+    @ApiModelProperty("小程序状态:0正常,1半封禁,2封禁")
+    private Integer status;
 }

+ 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("/#", ""));
+    }
     /**
      * 修改课堂配置
      */

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

@@ -1400,7 +1400,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);
         }
 
@@ -1498,7 +1498,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             // 更新观看记录的奖励类型
             log.setRewardType(config.getRewardType());
             courseWatchLogMapper.updateFsCourseWatchLog(log);
-            return R.ok("红包发送成功");
+            return R.ok("答题成功!");
         }
 
     }
@@ -1833,7 +1833,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             // 更新观看记录的奖励类
             log.setRewardType(config.getRewardType());
             courseWatchLogMapper.updateFsCourseWatchLog(log);
-            return R.ok("红包发送成功");
+            return R.ok("答题成功!");
         }
 
     }
@@ -2302,6 +2302,10 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
                 companyUserEndDateTime : periodDays.getEndDateTime();
         // 检查时间范围和状态
         log.error("传入参数:开始时间:{},结束时间:{},periodDays={}",effectiveStartTime,effectiveEndTime,periodDays);
+        if (ObjectUtils.isEmpty(effectiveStartTime)||ObjectUtils.isEmpty(effectiveEndTime)){
+            log.error("请检查营期时间!");
+            return false;
+        }
         return DateUtil.isWithinRangeSafe(LocalDateTime.now(), effectiveStartTime, effectiveEndTime)&& periodDays.getStatus() == 1;
     }
 

+ 3 - 0
fs-service/src/main/java/com/fs/course/vo/FsCoursePlaySourceConfigVO.java

@@ -61,4 +61,7 @@ public class FsCoursePlaySourceConfigVO {
      */
     private Integer isMall;
     private Long createDeptId;
+
+    @ApiModelProperty("小程序状态:0正常,1半封禁,2封禁")
+    private Integer status;
 }

+ 38 - 23
fs-service/src/main/java/com/fs/erp/service/impl/DfOrderServiceImpl.java

@@ -162,6 +162,8 @@ public class DfOrderServiceImpl implements IErpOrderService {
     @Autowired
     private LiveOrderMapper liveOrderMapper;
 
+    @Autowired
+    private FsIntegralOrderLogsMapper fsIntegralOrderLogsMapper;
     @Autowired
     private LiveOrderItemMapper liveOrderItemMapper;
 
@@ -659,7 +661,7 @@ public class DfOrderServiceImpl implements IErpOrderService {
                     case 9:
                         //已签收
                         deliveryStatus = 3;
-                        stateEx = "301"; //退货签收
+                        stateEx = "301";
                         SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.store");
                         Map<String, Object> config = (Map<String, Object>) JSON.parse(sysConfig.getConfigValue());
                         Object isUpdateOrder = config.get("isUpdateOrder");
@@ -760,34 +762,43 @@ public class DfOrderServiceImpl implements IErpOrderService {
                                         case 1:
                                             break;
                                         case 2:
-                                            sBuilder.append("您好,您有一个包裹正在准备发货,请耐心等待;\n");
-                                            if (order.getDeliverySn() != null && !order.getDeliverySn().isEmpty()) {
-                                                sBuilder.append(" 物流单号为:").append(order.getDeliverySn()).append("\n");
-                                            }
-                                            sBuilder.append("\uD83C\uDF39\uD83C\uDF39\uD83C\uDF39");
                                             break;
                                         case 3:
-                                            if ("202".equals(stateEx)) {
-                                                //211
-                                                //你好,这边查询到您购买的XXX(购买套餐)在XXX(时间)已经送到了,送货员电话为XXX(送货员信息)
-                                                ErpDeliverysRequest erpDeliverysRequest = new ErpDeliverysRequest();
-                                                erpDeliverysRequest.setCode(order.getOrderCode());
-                                                ErpDeliverysResponse express = null;
-                                                express = getDeliver(erpDeliverysRequest);
-                                                sBuilder.append("这边查询到您有一个包裹 ");
-                                                if (express != null && express.getDeliverys() != null && !express.getDeliverys().isEmpty()) {
-                                                    List<ErpDeliverys> deliverys = express.getDeliverys();
-                                                    ErpDeliverys tracesDTO = deliverys.get(deliverys.size() - 1);
-                                                    String remark = tracesDTO.getRemark();
-                                                    if ("派送至".equals(remark)) {
-                                                        sBuilder.append(" 在").append(tracesDTO.getAcceptTime()).append("已经送到了\n");
+                                            //你好,这边查询到您购买的XXX(购买套餐)在XXX(时间)已经送到了,送货员电话为XXX(送货员信息)
+                                            ErpDeliverysRequest erpDeliverysRequest = new ErpDeliverysRequest();
+                                            erpDeliverysRequest.setCode(order.getOrderCode());
+                                            ErpDeliverysResponse express = null;
+                                            express = getDeliver(erpDeliverysRequest);
+                                            if (express != null && express.getDeliverys() != null && !express.getDeliverys().isEmpty()) {
+                                                List<ErpDeliverys> deliverys = express.getDeliverys();
+                                                ErpDeliverys tracesDTO = deliverys.get(deliverys.size() - 1);
+                                                String remark = tracesDTO.getRemark();
+
+                                                if ("0".equals(stateEx) || "1".equals(stateEx) || "2".equals(stateEx)) {
+                                                    if (remark.contains("已收取快件")){
+                                                        sBuilder.append("您好,您有一个包裹正在准备发货,请耐心等待;\n");
+                                                        if (order.getDeliverySn() != null && !order.getDeliverySn().isEmpty()) {
+                                                            sBuilder.append(" 物流单号为:").append(order.getDeliverySn()).append("\n");
+                                                        }
+                                                        sBuilder.append("\uD83C\uDF39\uD83C\uDF39\uD83C\uDF39");
+                                                    }
+                                                } else if ("202".equals(stateEx)) {
+                                                    if (remark.contains("正在派送")) {
+                                                        sBuilder.append("这边查询到您有一个包裹 ");
+                                                        sBuilder.append("正在派送中\n");
+                                                        sBuilder.append(" 物流单号为:").append(order.getDeliverySn()).append("\n");
+                                                        sBuilder.append("物流信息:").append(remark).append("\n");
+                                                        sBuilder.append("\uD83C\uDF39\uD83C\uDF39\uD83C\uDF39");
+                                                    }
+
+                                                } else if ("301".equals(stateEx)){
+                                                    if (remark.contains("派送至本人") || remark.contains("签收")) {
+                                                        sBuilder.append("这边查询到您有一个包裹 ");
+                                                        sBuilder.append(" 在").append(tracesDTO.getAcceptTime()).append("已经签收了\n");
                                                         sBuilder.append(" 物流单号为:").append(order.getDeliverySn()).append("\n");
                                                         sBuilder.append("物流信息:").append(remark).append("\n");
                                                     }
-                                                } else {
-                                                    sBuilder.append(" 已经送到了\n");
                                                 }
-                                                sBuilder.append("\uD83C\uDF39\uD83C\uDF39\uD83C\uDF39");
                                             }
                                             break;
                                         case 4:
@@ -1048,10 +1059,12 @@ public class DfOrderServiceImpl implements IErpOrderService {
             order.setStatus(1);//设置待发货状态
             order.setDeliverySn("");
             integralOrderMapper.updateById(order);
+            fsIntegralOrderLogsMapper.insert(FsIntegralOrderLogs.builder().orderId(order.getOrderId()).changeType(FsStoreOrderLogEnum.UPDATE_ORDER_DF.getValue()).changeMessage("运单不存在," + FsStoreOrderLogEnum.UPDATE_ORDER_DF.getDesc()).build());
         } else {
             log.info("积分订单物流被取消,退款积分订单{}",order.getOrderCode());
             //以前查询到过物流信息,现在查不到,物流被人为取消
             integralOrderService.mandatoryRefunds(order.getOrderCode());
+            fsIntegralOrderLogsMapper.insert(FsIntegralOrderLogs.builder().orderId(order.getOrderId()).changeType(FsStoreOrderLogEnum.REFUND_ORDER_DF.getValue()).changeMessage("运单不存在," + FsStoreOrderLogEnum.REFUND_ORDER_DF.getDesc()).build());
         }
         log.info("取消订单代服记录更新id{}",order.getOrderCode());
         FsIntegralOrderDf df = new FsIntegralOrderDf();
@@ -1974,6 +1987,8 @@ public class DfOrderServiceImpl implements IErpOrderService {
                                             order.setStatus(2);//修改积分订单为待收货状态
                                             order.setDeliveryTime(DateUtils.getNowDate()); //更新发货时间
                                             fsIntegralOrderMapper.updateById(order);
+                                            //订单发货日志
+                                            fsIntegralOrderLogsMapper.insert(FsIntegralOrderLogs.builder().orderId(order.getOrderId()).changeType("delivery_goods").changeMessage(FsStoreOrderLogEnum.DELIVERY_GOODS.getDesc()).build());
 //                                            fsStoreOrderLogsService.create(order.getOrderId(), FsStoreOrderLogEnum.DELIVERY_GOODS.getValue(), FsStoreOrderLogEnum.DELIVERY_GOODS.getDesc());
 //                                            redisCache.deleteObject(DELIVERY+":"+order.getOrderCode());
 //                                            if (order.getCompanyId() != null && order.getCompanyId() > 0) {

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

@@ -46,7 +46,7 @@ public class uniPush2ServiceImpl implements uniPush2Service {
     public void pushSopAppLinkMsgByExternalIM(String cropId, String linkTile, String linkDescribe,String linkImageUrl, String link, Long companyUserId,Long fsUserId) throws JsonProcessingException {
 
         if (companyUserId!=null&&fsUserId!=null && fsUserId!=0){
-            openIMService.sendCourse(fsUserId,companyUserId,link,linkTile,linkImageUrl,cropId);
+            openIMService.sendCourse(fsUserId,companyUserId,link,linkDescribe,linkImageUrl,cropId);
         }
 
     }

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

@@ -21,4 +21,6 @@ public class FsSmsConfig {
     private String dhPassword2;
     private String dhSign;
 
+    private Integer isSmsVerification; //是否开启短信验证
+
 }

+ 47 - 0
fs-service/src/main/java/com/fs/his/domain/FsIntegralOrderLogs.java

@@ -0,0 +1,47 @@
+package com.fs.his.domain;
+
+import com.fs.common.annotation.Excel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+
+/**
+ * 订单操作记录对象 fs_integral_order_logs
+ *
+ * @author fs
+ * @date 2025-11-25
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class FsIntegralOrderLogs{
+
+    /** $column.columnComment */
+    private String logsId;
+
+    /** 订单id */
+    @Excel(name = "订单id")
+    private Long orderId;
+
+    /** 操作类型 */
+    @Excel(name = "操作类型")
+    private String changeType;
+
+    /** 操作备注 */
+    @Excel(name = "操作备注")
+    private String changeMessage;
+
+    /** 操作时间 */
+    private LocalDateTime changeTime;
+
+    /** 操作员 */
+    @Excel(name = "操作员")
+    private String operator;
+
+
+}

+ 5 - 0
fs-service/src/main/java/com/fs/his/domain/FsUser.java

@@ -174,6 +174,11 @@ public class FsUser extends BaseEntity
      * **/
     private Long qwUserId;
 
+    /**
+     * 小程序appId,多个用逗号分隔
+     */
+    private String appId;
+
 
     /** 推广上级用户ID */
     private Long spreadUserId;

+ 62 - 0
fs-service/src/main/java/com/fs/his/mapper/FsIntegralOrderLogsMapper.java

@@ -0,0 +1,62 @@
+package com.fs.his.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.his.domain.FsIntegralOrderLogs;
+
+import java.util.List;
+
+/**
+ * 订单操作记录Mapper接口
+ *
+ * @author fs
+ * @date 2025-11-25
+ */
+public interface FsIntegralOrderLogsMapper extends BaseMapper<FsIntegralOrderLogs> {
+    /**
+     * 查询订单操作记录
+     *
+     * @param logsId 订单操作记录主键
+     * @return 订单操作记录
+     */
+    FsIntegralOrderLogs selectFsIntegralOrderLogsByLogsId(String logsId);
+
+    /**
+     * 查询订单操作记录列表
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 订单操作记录集合
+     */
+    List<FsIntegralOrderLogs> selectFsIntegralOrderLogsList(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 新增订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    int insertFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 修改订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    int updateFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 删除订单操作记录
+     *
+     * @param logsId 订单操作记录主键
+     * @return 结果
+     */
+    int deleteFsIntegralOrderLogsByLogsId(String logsId);
+
+    /**
+     * 批量删除订单操作记录
+     *
+     * @param logsIds 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsIntegralOrderLogsByLogsIds(String[] logsIds);
+}

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

@@ -99,4 +99,5 @@ public interface FsUserInformationCollectionMapper extends BaseMapper<FsUserInfo
 
     List<FsUserInformationCollection>selectFsUserInformationCollectionByDoctorType2(@Param("maps") UserInformationDoctorType2Param userInformationDoctorType2Param);
     List<FsUserInformationCollection>selectFsUserInformationCollectionByDoctorType1(@Param("maps") UserInformationDoctorType2Param userInformationDoctorType2Param);
+    FsUserInformationCollection selectFsUserInformationCollectionByOrderCode(String orderCode);
 }

+ 4 - 0
fs-service/src/main/java/com/fs/his/param/FsUserInformationCollectionParam.java

@@ -48,5 +48,9 @@ public class FsUserInformationCollectionParam {
 
     private String doctorSign;
 
+    private Long doctorId;
+
+    private Long doctorType2Id;
+
     private String packageOrderCode;
 }

+ 62 - 0
fs-service/src/main/java/com/fs/his/service/IFsIntegralOrderLogsService.java

@@ -0,0 +1,62 @@
+package com.fs.his.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.his.domain.FsIntegralOrderLogs;
+
+import java.util.List;
+
+/**
+ * 订单操作记录Service接口
+ *
+ * @author fs
+ * @date 2025-11-25
+ */
+public interface IFsIntegralOrderLogsService extends IService<FsIntegralOrderLogs> {
+    /**
+     * 查询订单操作记录
+     *
+     * @param logsId 订单操作记录主键
+     * @return 订单操作记录
+     */
+    FsIntegralOrderLogs selectFsIntegralOrderLogsByLogsId(String logsId);
+
+    /**
+     * 查询订单操作记录列表
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 订单操作记录集合
+     */
+    List<FsIntegralOrderLogs> selectFsIntegralOrderLogsList(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 新增订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    int insertFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 修改订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    int updateFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 批量删除订单操作记录
+     *
+     * @param logsIds 需要删除的订单操作记录主键集合
+     * @return 结果
+     */
+    int deleteFsIntegralOrderLogsByLogsIds(String[] logsIds);
+
+    /**
+     * 删除订单操作记录信息
+     *
+     * @param logsId 订单操作记录主键
+     * @return 结果
+     */
+    int deleteFsIntegralOrderLogsByLogsId(String logsId);
+}

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

@@ -144,4 +144,6 @@ public interface IFsPackageOrderService
     R getPackageOrder(String createOrderKey);
 
     List<FsPackageOrder> selectOutTimeOrderList(Integer unPayTime);
+
+    R editPatientImages(Long orderId, String imagesList);
 }

+ 92 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderLogsServiceImpl.java

@@ -0,0 +1,92 @@
+package com.fs.his.service.impl;
+
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.his.domain.FsIntegralOrderLogs;
+import com.fs.his.mapper.FsIntegralOrderLogsMapper;
+import com.fs.his.service.IFsIntegralOrderLogsService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 订单操作记录Service业务层处理
+ *
+ * @author fs
+ * @date 2025-11-25
+ */
+@Service
+public class FsIntegralOrderLogsServiceImpl extends ServiceImpl<FsIntegralOrderLogsMapper, FsIntegralOrderLogs> implements IFsIntegralOrderLogsService {
+
+    /**
+     * 查询订单操作记录
+     *
+     * @param logsId 订单操作记录主键
+     * @return 订单操作记录
+     */
+    @Override
+    public FsIntegralOrderLogs selectFsIntegralOrderLogsByLogsId(String logsId)
+    {
+        return baseMapper.selectFsIntegralOrderLogsByLogsId(logsId);
+    }
+
+    /**
+     * 查询订单操作记录列表
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 订单操作记录
+     */
+    @Override
+    public List<FsIntegralOrderLogs> selectFsIntegralOrderLogsList(FsIntegralOrderLogs fsIntegralOrderLogs)
+    {
+        return baseMapper.selectFsIntegralOrderLogsList(fsIntegralOrderLogs);
+    }
+
+    /**
+     * 新增订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    @Override
+    public int insertFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs)
+    {
+        return baseMapper.insertFsIntegralOrderLogs(fsIntegralOrderLogs);
+    }
+
+    /**
+     * 修改订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    @Override
+    public int updateFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs)
+    {
+        return baseMapper.updateFsIntegralOrderLogs(fsIntegralOrderLogs);
+    }
+
+    /**
+     * 批量删除订单操作记录
+     *
+     * @param logsIds 需要删除的订单操作记录主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsIntegralOrderLogsByLogsIds(String[] logsIds)
+    {
+        return baseMapper.deleteFsIntegralOrderLogsByLogsIds(logsIds);
+    }
+
+    /**
+     * 删除订单操作记录信息
+     *
+     * @param logsId 订单操作记录主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsIntegralOrderLogsByLogsId(String logsId)
+    {
+        return baseMapper.deleteFsIntegralOrderLogsByLogsId(logsId);
+    }
+}

+ 19 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsPackageOrderServiceImpl.java

@@ -16,6 +16,7 @@ import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.constant.FsConstants;
@@ -1851,4 +1852,22 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
     public List<FsPackageOrder> selectOutTimeOrderList(Integer unPayTime) {
         return fsPackageOrderMapper.selectOutTimeOrderList(unPayTime);
     }
+
+    @Override
+    public R editPatientImages(Long orderId, String imagesList) {
+        FsPackageOrder fsPackageOrder = fsPackageOrderMapper.selectFsPackageOrderByOrderId(orderId);
+        if(fsPackageOrder==null){
+            return R.error("订单不存在");
+        }
+        String patientJson = fsPackageOrder.getPatientJson();
+        JSONObject jsonObject = JSONObject.parseObject(patientJson);
+        //后台编辑直接覆盖之前的图片
+        jsonObject.put("firstVisitImages",imagesList);
+        fsPackageOrder.setPatientJson(jsonObject.toJSONString());
+        int i = fsPackageOrderMapper.updateFsPackageOrder(fsPackageOrder);
+        if(i<=0){
+            return R.error("更新失败");
+        }
+        return R.ok();
+    }
 }

+ 64 - 30
fs-service/src/main/java/com/fs/his/service/impl/FsUserInformationCollectionServiceImpl.java

@@ -14,8 +14,11 @@ import com.fs.common.exception.CustomException;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.CompanyUser;
+import com.fs.company.domain.CompanyUserUser;
 import com.fs.company.mapper.CompanyUserMapper;
+import com.fs.company.mapper.CompanyUserUserMapper;
 import com.fs.company.service.ICompanyService;
+import com.fs.company.service.ICompanyUserService;
 import com.fs.core.config.WxMaConfiguration;
 import com.fs.core.config.WxPayProperties;
 import com.fs.core.utils.OrderCodeUtils;
@@ -149,6 +152,11 @@ public class FsUserInformationCollectionServiceImpl extends ServiceImpl<FsUserIn
     private IFsInquiryOrderService fsInquiryOrderService;
     @Autowired
     private OpenIMService openIMService;
+    @Autowired
+    private CompanyUserUserMapper companyUserUserMapper;
+    @Autowired
+    private FsPackageMapper fsPackageMapper;
+
     /**
      * 查询用户信息采集
      *
@@ -219,6 +227,9 @@ public class FsUserInformationCollectionServiceImpl extends ServiceImpl<FsUserIn
         if (collection.getUserConfirm() == 1 && collection.getUserConfirm2() == 0) {
             throw new CustomException("确认中,暂无法修改");
         }
+        param.setDoctorId(collection.getDoctorId());
+        param.setDoctorType2Id(collection.getDoctorType2Id());
+        param.setPackageId(collection.getPackageId());
         FsUserInformationCollection fsUserInformationCollection = getFsUserInformationCollection(param);
         fsUserInformationCollection.setUpdateTime(DateUtils.getNowDate());
         baseMapper.updateFsUserInformationCollection(fsUserInformationCollection);
@@ -246,6 +257,9 @@ public class FsUserInformationCollectionServiceImpl extends ServiceImpl<FsUserIn
         }
         //清空订单号
         fsUserInformationCollectionMapper.collectionOderCodeNULL(param.getId());
+        param.setDoctorId(collection.getDoctorId());
+        param.setDoctorType2Id(collection.getDoctorType2Id());
+        param.setPackageId(collection.getPackageId());
         FsUserInformationCollection fsUserInformationCollection = getFsUserInformationCollection(param);
         fsUserInformationCollection.setUserConfirm2(0);
         fsUserInformationCollection.setUserConfirm(0);
@@ -574,7 +588,7 @@ public class FsUserInformationCollectionServiceImpl extends ServiceImpl<FsUserIn
             map.setJsonInfo(JSON.toJSONString(answerVOS));
         }
 //
-
+        openIMService.doctorSendMsgToUser(collection.getUserId(),collection.getDoctorType2Id());
         if (fsUserInformationCollectionMapper.updateFsUserInformationCollection(map) > 0) {
             FsPackageOrder fsPackageOrder = packageOrderMapper.selectFsPackageOrderByOrderSn(collection.getPackageOrderCode());
             if(fsPackageOrder.getStoreOrderId()==null||fsPackageOrder.getStoreOrderId()==0){
@@ -674,6 +688,20 @@ public class FsUserInformationCollectionServiceImpl extends ServiceImpl<FsUserIn
         if (!Objects.equals(collection.getUserId(), param.getUserId())) {
             return R.error("用户信息不匹配,无法确认");
         }
+        //绑定用户
+        CompanyUserUser companyUserUserMap=new CompanyUserUser();
+        companyUserUserMap.setCompanyUserId(collection.getCompanyUserId());
+        companyUserUserMap.setUserId(collection.getUserId());
+        List<CompanyUserUser> list= companyUserUserMapper.selectCompanyUserUserList(companyUserUserMap);
+        if(list==null|| list.isEmpty()){
+            CompanyUser companyUser=companyUserMapper.selectCompanyUserById(collection.getCompanyUserId());
+            if(companyUser!=null&&companyUser.getStatus().equals("0")){
+                companyUserUserMap.setCompanyId(companyUser.getCompanyId());
+                companyUserUserMap.setCreateTime(new Date());
+                companyUserUserMapper.insertCompanyUserUser(companyUserUserMap);
+            }
+        }
+
         FsUserInformationCollection map = new FsUserInformationCollection();
         map.setId(param.getId());
         map.setUserConfirm(1);
@@ -982,37 +1010,43 @@ public class FsUserInformationCollectionServiceImpl extends ServiceImpl<FsUserIn
         if (companyUser == null) {
             throw new CustomException("销售不存在");
         }
-        Long doctorId = null;
-        if (companyUser.getDoctorId() != null) {
-            FsDoctor doctor = doctorMapper.selectFsDoctorByDoctorId(companyUser.getDoctorId());
-            if (doctor != null) {
-                doctorId = doctor.getDoctorId();
-            }
-        } else {
-            //随机获取医生id
-            doctorId = iFsDoctorService.selectFsDoctorDoctorByPackage();
-        }
-        fsUserInformationCollection.setDoctorId(doctorId);
-
+        //医生
+        Long doctorId = companyUser.getDoctorId();
+        fsUserInformationCollection.setDoctorId(getDoctorId(doctorId,1,param.getPackageId()));
+        //药师
+        Long doctorType2Id = param.getDoctorType2Id();
+        fsUserInformationCollection.setDoctorType2Id(getDoctorId(doctorType2Id,2,param.getPackageId()));
         return fsUserInformationCollection;
     }
 
-    public static void main(String[] args) {
-//        String str1 = "[{\"options\":[{\"flag\":false,\"name\":\"通天\",\"value\":0},{\"flag\":false,\"name\":\"哈哈\",\"value\":1}],\"title\":\"测试标题1\",\"value\":1},{\"options\":[{\"flag\":false,\"name\":\"呼呼\",\"value\":0},{\"flag\":false,\"name\":\"嘻嘻\",\"value\":1}],\"title\":\"测试标题2\",\"value\":1},{\"options\":[{\"flag\":false,\"name\":\"胸痛\",\"value\":0},{\"flag\":false,\"name\":\"胸闷\",\"value\":1},{\"flag\":false,\"name\":\"头晕\",\"value\":2},{\"flag\":false,\"name\":\"肢体麻木\",\"value\":3},{\"flag\":false,\"name\":\"无\",\"value\":4}],\"title\":\"您目前是否有心脑血管相关症状,如胸痛、胸闷、头晕、肢体麻木等?\",\"value\":1}]";
-//        String str2 = "[{\"options\":[{\"flag\":true,\"name\":\"胸痛\",\"value\":0},{\"flag\":true,\"name\":\"胸闷\",\"value\":1},{\"flag\":true,\"name\":\"头晕\",\"value\":2},{\"flag\":true,\"name\":\"肢体麻木\",\"value\":3},{\"flag\":true,\"name\":\"无\",\"value\":4}],\"title\":\"您目前是否有心脑血管相关症状,如胸痛、胸闷、头晕、肢体麻木等?\",\"value\":1},{\"options\":[{\"flag\":false,\"name\":\"胃疼\",\"value\":0},{\"flag\":false,\"name\":\"反酸\",\"value\":1},{\"flag\":false,\"name\":\"恶心\",\"value\":2},{\"flag\":false,\"name\":\"呕吐\",\"value\":3},{\"flag\":false,\"name\":\"黑便\",\"value\":4},{\"flag\":false,\"name\":\"无\",\"value\":5}],\"title\":\"您近期是否出现胃部不适症状,如胃痛、反酸、恶心、呕吐或黑便?\",\"value\":1}]";
-//        List<AnswerVO> vo1 = null;
-//        List<AnswerVO> vo2 = JSON.parseArray(str2, AnswerVO.class);
-//        System.out.println(vo1);
-//        System.out.println(vo2);
-//        vo2.addAll(vo1);
-//        Map<String, List<AnswerVO>> collect = vo2.stream()
-//                .collect(Collectors.groupingBy(AnswerVO::getTitle));
-//        List<AnswerVO> collect1 = vo2.stream()
-//                .collect(Collectors.groupingBy(AnswerVO::getTitle))
-//                .values().stream()
-//                .map(group -> group.stream().reduce((a, b) -> a).orElse(null)).collect(Collectors.toList());
-//        System.out.println(JSON.toJSONString(collect));
-//        System.out.println(JSON.toJSONString(collect1));
-        boolean contains = "是否有糖尿病相关疾病?".contains("糖尿病");
+    /**
+     *  如果是药师 需要根据套餐类型查询药师
+     * @param doctorId
+     * @param doctorType 1医生 2药师
+     * @return
+     */
+    private Long getDoctorId(Long doctorId,Integer doctorType,Long packageId) {
+        FsDoctor doctor = null;
+        if (doctorId != null) {
+            doctor = doctorMapper.selectFsDoctorByDoctorId(doctorId);
+        }
+        if (doctorId == null || doctor == null) {
+            if (doctorType == 1){
+                //随机获取医生id
+                doctorId = iFsDoctorService.selectFsDoctorDoctorByPackage();
+            } else if (doctorType == 2){
+                //随机获取药师id
+                FsPackage fsPackage = fsPackageMapper.selectFsPackageByPackageId(packageId);
+                if (fsPackage != null){
+                    doctor =doctorMapper.selectPackageFsDoctorType2Ids(fsPackage.getProductType());
+                }
+                if (doctor != null) {
+                    doctorId = doctor.getDoctorId();
+                }
+            }
+
+        }
+        return doctorId;
     }
+
 }

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

@@ -13,6 +13,8 @@ import java.util.List;
 @Data
 public class FsUserInformationCollectionAndPatientVO extends FsUserInformationCollection {
     private FsPatient patientInfo; //病人信息
+    private Integer isPay;
+    private Long storeOrderId;
 
 
 }

+ 13 - 0
fs-service/src/main/java/com/fs/hisStore/domain/FsUserScrm.java

@@ -178,6 +178,19 @@ public class FsUserScrm extends BaseEntity
      * **/
     private Long qwUserId;
 
+    /**
+     * 小程序appId,多个用逗号分隔
+     */
+    private String appId;
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
     public void setNickName(String nickname)
     {
         if(StringUtils.isNotEmpty(nickname)){

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

@@ -75,9 +75,10 @@ public interface FsStoreOrderItemScrmMapper
     List<FsStoreOrderItemVO> selectFsStoreOrderItemListAndProductByOrderId(Long id);
 
     @Select({"<script> " +
-            "select i.*,o.user_id,o.status, 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   " +
+            "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  " +
             " 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 " +
             "<if test = 'maps.orderCode != null and  maps.orderCode !=\"\"    '> " +
             "and o.order_code like CONCAT('%',#{maps.orderCode},'%') " +

+ 6 - 0
fs-service/src/main/java/com/fs/hisStore/service/IFsUserScrmService.java

@@ -1,11 +1,14 @@
 package com.fs.hisStore.service;
 
+import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.param.LoginMaWxParam;
 import com.fs.course.param.newfs.FsUserCourseBeMemberParam;
 import com.fs.course.vo.newfs.FsCourseAnalysisVO;
 import com.fs.his.domain.FsStoreProductAttrValue;
+import com.fs.his.domain.FsUser;
 import com.fs.his.vo.OptionsVO;
 import com.fs.hisStore.domain.FsStoreProductAttrValueScrm;
 import com.fs.live.domain.LiveOrder;
@@ -286,4 +289,7 @@ public interface IFsUserScrmService
     void addTuiLiveMoney(LiveOrder order, List<FsStoreProductAttrValueScrm> productAttrValues);
 
     void subLiveTuiMoney(LiveOrder liveOrder);
+
+    void handleFsUserWx(FsUserScrm user, LoginMaWxParam param, WxMaJscode2SessionResult session);
+
 }

+ 17 - 10
fs-service/src/main/java/com/fs/hisStore/service/impl/FsMenuScrmServiceImpl.java

@@ -3,6 +3,8 @@ package com.fs.hisStore.service.impl;
 import java.util.List;
 import com.fs.common.utils.DateUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 import com.fs.hisStore.mapper.FsMenuScrmMapper;
 import com.fs.hisStore.domain.FsMenuScrm;
@@ -10,7 +12,7 @@ import com.fs.hisStore.service.IFsMenuScrmService;
 
 /**
  * 用户端菜单管理Service业务层处理
- * 
+ *
  * @author fs
  * @date 2022-03-15
  */
@@ -22,7 +24,7 @@ public class FsMenuScrmServiceImpl implements IFsMenuScrmService
 
     /**
      * 查询用户端菜单管理
-     * 
+     *
      * @param menuId 用户端菜单管理ID
      * @return 用户端菜单管理
      */
@@ -34,23 +36,25 @@ public class FsMenuScrmServiceImpl implements IFsMenuScrmService
 
     /**
      * 查询用户端菜单管理列表
-     * 
-     * @param fsMenu 用户端菜单管理
+     *
+     * @param param 用户端菜单管理
      * @return 用户端菜单管理
      */
     @Override
-    public List<FsMenuScrm> selectFsMenuList(FsMenuScrm fsMenu)
+    @Cacheable(value = "selectFsMenuList", key = "#param")
+    public List<FsMenuScrm> selectFsMenuList(FsMenuScrm param)
     {
-        return fsMenuMapper.selectFsMenuList(fsMenu);
+        return fsMenuMapper.selectFsMenuList(param);
     }
 
     /**
      * 新增用户端菜单管理
-     * 
+     *
      * @param fsMenu 用户端菜单管理
      * @return 结果
      */
     @Override
+    @CacheEvict(value = "selectFsMenuList",allEntries = true)
     public int insertFsMenu(FsMenuScrm fsMenu)
     {
         fsMenu.setCreateTime(DateUtils.getNowDate());
@@ -59,11 +63,12 @@ public class FsMenuScrmServiceImpl implements IFsMenuScrmService
 
     /**
      * 修改用户端菜单管理
-     * 
+     *
      * @param fsMenu 用户端菜单管理
      * @return 结果
      */
     @Override
+    @CacheEvict(value = "selectFsMenuList",allEntries = true)
     public int updateFsMenu(FsMenuScrm fsMenu)
     {
         fsMenu.setUpdateTime(DateUtils.getNowDate());
@@ -72,11 +77,12 @@ public class FsMenuScrmServiceImpl implements IFsMenuScrmService
 
     /**
      * 批量删除用户端菜单管理
-     * 
+     *
      * @param menuIds 需要删除的用户端菜单管理ID
      * @return 结果
      */
     @Override
+    @CacheEvict(value = "selectFsMenuList",allEntries = true)
     public int deleteFsMenuByIds(Long[] menuIds)
     {
         return fsMenuMapper.deleteFsMenuByIds(menuIds);
@@ -84,11 +90,12 @@ public class FsMenuScrmServiceImpl implements IFsMenuScrmService
 
     /**
      * 删除用户端菜单管理信息
-     * 
+     *
      * @param menuId 用户端菜单管理ID
      * @return 结果
      */
     @Override
+    @CacheEvict(value = "selectFsMenuList",allEntries = true)
     public int deleteFsMenuById(Long menuId)
     {
         return fsMenuMapper.deleteFsMenuById(menuId);

+ 4 - 3
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java

@@ -2966,9 +2966,8 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         BigDecimal payIntegral = this.getOrderSumPrice(cartInfo, "payIntegral");//获取订单需要的积分
 
         //如果设置满包邮0 表示全局包邮,如果设置大于0表示满这价格包邮,否则走运费模板算法
-        if (storeFreePostage.compareTo(BigDecimal.ZERO) != 0 && totalPrice.compareTo(storeFreePostage) <= 0) {
-            storePostage = this.handlePostage(cartInfo, userAddress);
-        }
+        storePostage = this.handlePostage(cartInfo, userAddress);
+
 
         FsStoreOrderPriceDTO priceGroupDTO = new FsStoreOrderPriceDTO();
         priceGroupDTO.setStorePostage(storePostage);
@@ -4209,6 +4208,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 user.setStatus(1);
                 user.setMaOpenId(session.getOpenid());
                 user.setUnionId(session.getUnionid());
+                user.setAppId(properties.getConfigs().get(0).getAppid());
                 user.setIsWeixinAuth(0);
                 user.setLastIp(ip);
                 user.setCreateTime(new Date());
@@ -4327,6 +4327,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 user.setStatus(1);
                 user.setMaOpenId(session.getOpenid());
                 user.setUnionId(session.getUnionid());
+                user.setAppId(properties.getConfigs().get(0).getAppid());
                 user.setIsWeixinAuth(0);
                 user.setLastIp(ip);
                 user.setCreateTime(new Date());

+ 27 - 2
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStorePaymentScrmServiceImpl.java

@@ -13,6 +13,8 @@ import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.TypeReference;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.annotation.DataScope;
 import com.fs.common.config.FSSysConfig;
 import com.fs.common.core.domain.R;
@@ -34,6 +36,7 @@ import com.fs.course.service.IFsCourseRedPacketLogService;
 import com.fs.his.config.FsSysConfig;
 import com.fs.his.domain.FsUser;
 import com.fs.his.domain.FsUserWx;
+import com.fs.his.mapper.FsUserWxMapper;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.service.IFsUserWxService;
 import com.fs.his.utils.ConfigUtil;
@@ -851,6 +854,8 @@ public class FsStorePaymentScrmServiceImpl implements IFsStorePaymentScrmService
 
     @Autowired
     private IFsUserService fsUserService;
+    @Autowired
+    private FsUserWxMapper fsUserWxMapper;
 
     @Override
     public R paymentByWxaCode(FsStorePaymentPayParam param) {
@@ -874,6 +879,26 @@ public class FsStorePaymentScrmServiceImpl implements IFsStorePaymentScrmService
 
         //生成支付流水
         String orderSn = IdUtil.getSnowflake(0, 0).nextIdStr();
+
+        //获取用户openid
+        String openId = null;
+        String appId = param.getAppId();
+
+        //查询fs_user_wx的openId
+        Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                .eq(FsUserWx::getFsUserId, param.getUserId())
+                .eq(FsUserWx::getAppId, appId);
+        FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+        if (fsUserWx != null) {
+            openId = fsUserWx.getOpenId();
+        }else {
+            openId = user.getMaOpenId();
+        }
+
+        if (StringUtils.isEmpty(openId)){
+            return R.error("openId参数错误!");
+        }
+
         FsStorePaymentScrm storePayment=new FsStorePaymentScrm();
         storePayment.setCompanyId(param.getCompanyId());
         //判断销售是否存在
@@ -887,7 +912,7 @@ public class FsStorePaymentScrmServiceImpl implements IFsStorePaymentScrmService
         storePayment.setPayTypeCode("weixin");
         storePayment.setBusinessType(1);//微信收款
         storePayment.setRemark(StringUtils.isNotBlank(param.getRemark()) ? param.getRemark() : "商城收款订单支付");
-        storePayment.setOpenId(user.getMaOpenId());
+        storePayment.setOpenId(openId);
         storePayment.setUserId(user.getUserId());
         storePayment.setPayMode("hf");//目前微信收款仅支持汇付
         storePayment.setAppId(param.getAppId());
@@ -896,7 +921,7 @@ public class FsStorePaymentScrmServiceImpl implements IFsStorePaymentScrmService
         //汇付支付
         HuiFuCreateOrder o = new HuiFuCreateOrder();
         o.setTradeType("T_MINIAPP");
-        o.setOpenid(user.getMaOpenId());
+        o.setOpenid(openId);
         o.setReqSeqId("payment-"+storePayment.getPayCode());
         o.setTransAmt(storePayment.getPayMoney().toString());
         o.setGoodsDesc("商城订单支付");

+ 27 - 0
fs-service/src/main/java/com/fs/hisStore/service/impl/FsUserScrmServiceImpl.java

@@ -1,5 +1,6 @@
 package com.fs.hisStore.service.impl;
 
+import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
@@ -8,6 +9,7 @@ import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.core.domain.entity.SysDictData;
 import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.param.LoginMaWxParam;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.DictUtils;
 import com.fs.common.utils.ParseUtils;
@@ -30,7 +32,10 @@ import com.fs.course.param.newfs.UserCourseVideoPageParam;
 import com.fs.course.vo.newfs.FsCourseAnalysisCountVO;
 import com.fs.course.vo.newfs.FsCourseAnalysisVO;
 import com.fs.course.vo.newfs.FsUserCourseVideoPageListVO;
+import com.fs.his.domain.FsUser;
 import com.fs.his.domain.FsUserBill;
+import com.fs.his.domain.FsUserWx;
+import com.fs.his.service.IFsUserWxService;
 import com.fs.his.vo.OptionsVO;
 import com.fs.live.domain.LiveOrder;
 import com.fs.qw.param.QwFsUserParam;
@@ -1130,4 +1135,26 @@ public class FsUserScrmServiceImpl implements IFsUserScrmService
     public List<OptionsVO> selectUserListByMap(Map<String, Object> params) {
         return fsUserMapper.selectUserListByMap(params);
     }
+
+
+    @Autowired
+    private IFsUserWxService fsUserWxService;
+
+    @Override
+    public void handleFsUserWx(FsUserScrm user, LoginMaWxParam param, WxMaJscode2SessionResult session) {
+        try {
+            FsUserWx fsUserWx = new FsUserWx();
+            fsUserWx.setType(1);
+            fsUserWx.setFsUserId(user.getUserId());
+            fsUserWx.setAppId(param.getAppId());
+            fsUserWx.setOpenId(session.getOpenid());
+            fsUserWx.setUnionId(session.getUnionid() != null ? session.getUnionid() : null);
+            fsUserWx.setCreateTime(new Date());
+            fsUserWx.setUpdateTime(new Date());
+            fsUserWxService.saveOrUpdateByUniqueKey(fsUserWx);
+            log.info("zyp \n 【更新或插入用户与小程序{}的绑定关系】:{}", param.getAppId(), user.getUserId());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
 }

+ 15 - 0
fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderExportVO.java

@@ -126,6 +126,21 @@ public class FsStoreOrderExportVO implements Serializable
     @Excel(name = "订单状态", dictType = "store_order_status")
     private String status;
 
+    @Excel(name = "成本价",cellType= Excel.ColumnType.NUMERIC)
+    private BigDecimal cost;
+
+    /** 结算价 */
+    @Excel(name = "结算价",cellType= Excel.ColumnType.NUMERIC)
+    private BigDecimal FPrice;
+
+    /** 商品编码 */
+    @Excel(name = "商品编码")
+    private String barCode;
+
+    /** 商品分类 */
+    @Excel(name = "商品分类")
+    private String cateName;
+
 //    /** 0 未退款 1 申请中 2 已退款 */
 ////    @Excel(name = "0 未退款 1 申请中 2 已退款")
 //    private Integer refundStatus;

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

@@ -41,6 +41,16 @@ public class FsStoreOrderItemExportVO implements Serializable
     @Excel(name = "产品价格")
     private BigDecimal price;
 
+    @Excel(name = "成本价")
+    private BigDecimal cost;
+    @Excel(name = "结算价")
+    private BigDecimal FPrice;
+    @Excel(name = "额外运费")
+    private BigDecimal payPostage;
+    private Integer totalNum;
+    @Excel(name = "商品分类")
+    private String cateName;
+
 
     private String jsonInfo;
 

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

@@ -194,8 +194,21 @@ public class FsStoreOrderVO implements Serializable
     private Integer isDel;
 
     /** 成本价 */
+    @Excel(name = "成本价")
     private BigDecimal cost;
 
+    /** 结算价 */
+    @Excel(name = "结算价")
+    private BigDecimal FPrice;
+
+    /** 商品编码 */
+    @Excel(name = "商品编码")
+    private String barCode;
+
+    /** 商品分类 */
+    @Excel(name = "商品分类")
+    private String cateName;
+
     /** 核销码 */
     private String verifyCode;
 

+ 3 - 2
fs-service/src/main/java/com/fs/im/service/impl/OpenIMServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.http.HttpRequest;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -1099,7 +1100,7 @@ public class OpenIMServiceImpl implements OpenIMService {
         FsUserCourse fsUserCourse = fsUserCourseMapper.selectFsUserCourseByCourseId(batchSendCourseDTO.getCourseId());
         Long project = fsUserCourse != null ? fsUserCourse.getProject() : null;
         long planSendTimeStamp;
-        if(batchSendCourseDTO.getSendType() == 1 && batchSendCourseDTO.getSendTime() != null && batchSendCourseDTO.getSendTime().compareTo(new Date()) > 0){
+        if(ObjectUtils.isNotEmpty(batchSendCourseDTO.getSendType())&&batchSendCourseDTO.getSendType() == 1 && batchSendCourseDTO.getSendTime() != null && batchSendCourseDTO.getSendTime().compareTo(new Date()) > 0){
             planSendTimeStamp = batchSendCourseDTO.getSendTime().getTime();
         } else {
             planSendTimeStamp = System.currentTimeMillis();
@@ -1109,7 +1110,7 @@ public class OpenIMServiceImpl implements OpenIMService {
         OpenImBatchMsgDTO openImBatchMsgDTO = makeOpenImBatchMsgDTO(batchSendCourseDTO, courseUrl, objectMapper, userIds, planSendTimeStamp, "发课");
 
         int sendType;
-        if(batchSendCourseDTO.getSendType() == 1 && batchSendCourseDTO.getSendTime() != null && batchSendCourseDTO.getSendTime().compareTo(new Date()) > 0) {
+        if(ObjectUtils.isNotEmpty(batchSendCourseDTO.getSendType())&&batchSendCourseDTO.getSendType() == 1 && batchSendCourseDTO.getSendTime() != null && batchSendCourseDTO.getSendTime().compareTo(new Date()) > 0) {
             sendType = 1; //定时
         } else {
             sendType = 2; //实时

+ 2 - 1
fs-service/src/main/java/com/fs/ipad/vo/BaseVo.java

@@ -15,7 +15,7 @@ public class BaseVo{
     private String corpId;
     private String corpCode;
     private boolean isRoom;
-
+    private Long qwUserId;
 
     public void setBase(BaseVo vo){
         this.uuid = vo.getUuid();
@@ -24,5 +24,6 @@ public class BaseVo{
         this.corpCode = vo.getCorpCode();
         this.exId = vo.getExId();
         this.isRoom = vo.isRoom();
+        this.qwUserId = vo.qwUserId;
     }
 }

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

@@ -130,4 +130,7 @@ public interface LiveAfterSalesMapper {
             "where user_id=#{userId}  and sales_status =#{salesStatus} " +
             "</script>"})
     Integer selectLiveAfterSalesCount(@Param("userId")long userId,@Param("salesStatus") int salesStatus);
+
+    @Select(" select  * from  live_after_sales where order_id = #{orderId} and sales_status = 0 ")
+    LiveAfterSales getLiveAfterSalesByOrderId(@Param("orderId") Long orderId);
 }

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

@@ -110,7 +110,7 @@ public interface LiveOrderMapper {
     @Select("select order_id from live_order where `status` = 2")
     List<Long> selectSyncExpressIds();
 
-    @Select("select order_id from live_order where `status` = 1 and extend_order_id is null ")
+    @Select("select order_id from live_order where `status` = 1 and extend_order_id is null and is_pay='1'")
     List<Long> selectOrderIdByNoErp();
 
     @Select("select * from live_order where extend_order_id is not null and `status`=2")

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

@@ -90,4 +90,6 @@ public interface ILiveAfterSalesService {
     List<LiveAfterSalesQueryVO> selectLiveAfterSalesListQuery(LiveAfterSalesQueryParam param);
 
     Integer selectLiveAfterSalesCount(long l, int i);
+
+    R handleImmediatelyRefund(Long orderId);
 }

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

@@ -65,4 +65,6 @@ public interface ILiveOrderPaymentService {
     LiveOrderPaymentVo selectLiveOrderPaymentByPaymentIdNew(Long paymentId);
 
     List<LiveOrderPayment> selectLiveOrderPaymentByOrderId(Long id);
+
+    LiveOrderPayment selectByBussinessId(Long orderCode);
 }

+ 224 - 6
fs-service/src/main/java/com/fs/live/service/impl/LiveAfterSalesServiceImpl.java

@@ -2,6 +2,7 @@ package com.fs.live.service.impl;
 
 import java.lang.reflect.InvocationTargetException;
 import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
 import java.util.*;
 
@@ -10,6 +11,7 @@ import cn.hutool.core.date.DateTime;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
@@ -17,6 +19,9 @@ import com.fs.common.utils.CloudHostUtils;
 import com.fs.common.utils.DateUtils;
 
 import com.fs.common.utils.StringUtils;
+import com.fs.common.utils.spring.SpringUtils;
+import com.fs.company.service.ICompanyService;
+import com.fs.config.cloud.CloudHostProper;
 import com.fs.erp.constant.AfterSalesOrderStatusEnum;
 import com.fs.erp.domain.FsJstAftersalePush;
 import com.fs.erp.dto.BaseResponse;
@@ -24,25 +29,30 @@ import com.fs.erp.dto.ErpRefundUpdateRequest;
 import com.fs.erp.mapper.FsJstAftersalePushMapper;
 import com.fs.erp.service.IErpOrderService;
 import com.fs.his.config.FsSysConfig;
+import com.fs.his.domain.FsHfpayConfig;
 import com.fs.his.domain.FsUser;
+import com.fs.his.mapper.FsHfpayConfigMapper;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.utils.ConfigUtil;
+import com.fs.hisStore.config.FsErpConfig;
 import com.fs.hisStore.domain.*;
 import com.fs.hisStore.dto.StoreOrderProductDTO;
-import com.fs.hisStore.enums.AfterSalesStatusEnum;
-import com.fs.hisStore.enums.AfterStatusEnum;
-import com.fs.hisStore.enums.OrderInfoEnum;
-import com.fs.hisStore.enums.SysConfigEnum;
+import com.fs.hisStore.enums.*;
 import com.fs.hisStore.param.FsStoreAfterSalesProductParam;
+import com.fs.hisStore.service.IFsStoreProductScrmService;
 import com.fs.hisStore.service.IFsUserScrmService;
 import com.fs.hisStore.vo.FsStoreAfterSalesQueryVO;
 import com.fs.hisStore.vo.FsStoreOrderItemVO;
+import com.fs.huifuPay.domain.HuiFuRefundResult;
+import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayRefundRequest;
+import com.fs.huifuPay.service.HuiFuService;
 import com.fs.live.domain.*;
 import com.fs.live.dto.LiveAfterSalesProductDTO;
 import com.fs.live.enums.LiveAfterSalesStatusEnum;
 import com.fs.live.mapper.*;
 import com.fs.live.param.*;
 import com.fs.live.service.ILiveOrderItemService;
+import com.fs.live.service.ILiveOrderLogsService;
 import com.fs.live.service.ILiveOrderService;
 import com.fs.live.vo.LiveAfterSalesListUVO;
 import com.fs.live.vo.LiveAfterSalesQueryVO;
@@ -52,9 +62,17 @@ import com.fs.store.config.StoreConfig;
 import com.fs.store.domain.*;
 import com.fs.store.service.cache.IFsUserCacheService;
 import com.fs.system.service.ISysConfigService;
+import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
+import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
+import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
+import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
+import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.WxPayService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.beanutils.BeanUtils;
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang.ObjectUtils;
 import org.apache.http.util.Asserts;
 import org.springframework.aop.framework.AopContext;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -864,7 +882,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());
@@ -873,7 +891,9 @@ public class LiveAfterSalesServiceImpl implements ILiveAfterSalesService {
                 }
 
                 try {
-                    liveOrderService.createOmsOrder(order.getOrderId());
+                    if (liveOrderPaymentMapper.selectByBuissnessId(Long.valueOf(order.getOrderCode())) != null) {
+                        liveOrderService.createOmsOrder(order.getOrderId());
+                    }
                 } catch (Exception e) {
                     log.error("推送ERP订单失败!",e);
                 }
@@ -885,4 +905,202 @@ public class LiveAfterSalesServiceImpl implements ILiveAfterSalesService {
     }
 
 
+    @Autowired
+    private LiveOrderItemMapper liveOrderItemMapper;
+    @Autowired
+    private LiveUserLotteryRecordMapper liveUserLotteryRecordMapper;
+    @Autowired
+    private IFsStoreProductScrmService fsStoreProductService;
+
+    @Autowired
+    private WxPayService wxPayService;
+
+
+    @Autowired
+    private HuiFuService huiFuService;
+
+    @Autowired
+    private ILiveOrderLogsService liveOrderLogsService;
+    @Autowired
+    private ICompanyService companyService;
+
+    @Autowired
+    private LiveAfterSalesMapper liveAfterSalesMapper;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
+    public R handleImmediatelyRefund(Long orderId) {
+        IErpOrderService erpOrderService = getErpService();
+        FsErpConfig erpConfig = configUtil.generateStructConfigByKey("his.config", FsErpConfig.class);
+        LiveOrder order = liveOrderService.selectLiveOrderByOrderId(String.valueOf(orderId));
+        if (order == null) {
+            return R.error("订单不存在");
+        }
+        if (order.getStatus() == -2) {
+            return R.error("已退款");
+        }
+        if (!Integer.valueOf(-1).equals(order.getStatus())) {
+            return R.error("非法操作");
+        }
+        if (erpConfig.getErpOpen() != null
+                && erpConfig.getErpOpen() == 1
+                && StringUtils.isEmpty(order.getExtendOrderId())
+                && !CloudHostUtils.hasCloudHostName("康年堂")) {
+            return R.error("暂未推送至erp,请稍后再试!");
+        }
+//        if (StringUtils.isNotEmpty(order.getExtendOrderId())) {
+//            ErpRefundUpdateRequest request = new ErpRefundUpdateRequest();
+//            request.setTid(order.getOrderCode());
+//            request.setOid(order.getOrderCode());
+//            request.setRefund_state(1);
+//
+//            if (ObjectUtils.equals(order.getStatus(), 2)) {
+//                LiveAfterSalesParam param = new LiveAfterSalesParam();
+//                param.setOrderCode(order.getOrderCode());
+//                param.setRefundAmount(order.getPayMoney());
+//                param.setServiceType(1);
+//                param.setReasons("后台手动退款流程");
+//                param.setExplainImg(null);
+//                List<FsStoreAfterSalesProductParam> productParams = new ArrayList<>();
+//                List <LiveOrderItem> items = liveOrderItemMapper.selectLiveOrderItemByOrderId(order.getOrderId());
+//                for (LiveOrderItem item : items){
+//                    FsStoreAfterSalesProductParam param1 = new FsStoreAfterSalesProductParam();
+//                    param1.setProductId(item.getProductId());
+//                    param1.setNum(Math.toIntExact(item.getNum()));
+//                    productParams.add(param1);
+//                }
+//                return liveAfterSalesService.applyForAfterSales(order.getUserId(), param);
+//            } else {
+//                jSTOrderService.refundUpdateLive(request);
+//            }
+//        }
+        order.setStatus(OrderInfoEnum.STATUS_NE2.getValue());
+        order.setRefundMoney(order.getPayMoney());
+        order.setRefundStatus(String.valueOf(OrderInfoEnum.REFUND_STATUS_2.getValue()));
+        liveUserLotteryRecordMapper.updateOrderStatusByOrderId(order.getOrderId(), -2);
+        liveOrderService.updateLiveOrder(order);
+
+        //退库存
+        //获取订单下的商品
+        List<LiveOrderItem> orderItemVOS = liveOrderItemMapper.selectLiveOrderItemByOrderId(order.getOrderId());
+        for (LiveOrderItem vo : orderItemVOS) {
+            if (vo.getIsAfterSales() == 1) {
+                fsStoreProductService.incProductStock(vo.getNum(), vo.getProductId(), vo.getProductAttrValueId());
+            }
+        }
+        if ("3".equals(order.getPayType())) {
+            //货到付款
+        } else {
+            //将钱退还给用户
+            List<LiveOrderPayment> payments = liveOrderPaymentMapper.selectLiveOrderPaymentByPay(5, order.getOrderId());
+            if (payments != null && !payments.isEmpty()) {
+                String json = configService.selectConfigByKey("his.pay");
+                FsPayConfigScrm fsPayConfig = JSON.parseObject(json, FsPayConfigScrm.class);
+                for (LiveOrderPayment payment : payments) {
+                    if (payment.getPayMode() == null || "wx".equals(payment.getPayMode())) {
+                        WxPayConfig payConfig = new WxPayConfig();
+                        payConfig.setAppId(fsPayConfig.getAppId());
+                        payConfig.setMchId(fsPayConfig.getWxMchId());
+                        payConfig.setMchKey(fsPayConfig.getWxMchKey());
+                        payConfig.setKeyPath(fsPayConfig.getKeyPath());
+                        payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                        payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                        wxPayService.setConfig(payConfig);
+                        WxPayRefundRequest refundRequest = new WxPayRefundRequest();
+                        refundRequest.setOutTradeNo("live-" + payment.getPayCode());
+                        refundRequest.setOutRefundNo("live-" + payment.getPayCode());
+                        refundRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(payment.getPayMoney().toString()));
+                        refundRequest.setRefundFee(WxPayUnifiedOrderRequest.yuanToFen(payment.getPayMoney().toString()));
+                        try {
+                            WxPayRefundResult refundResult = wxPayService.refund(refundRequest);
+                            WxPayRefundQueryResult refundQueryResult = wxPayService.refundQuery("", refundResult.getOutTradeNo(), refundResult.getOutRefundNo(), refundResult.getRefundId());
+                            if (refundQueryResult != null && "SUCCESS".equals(refundQueryResult.getResultCode())) {
+                                LiveOrderPayment paymentMap = new LiveOrderPayment();
+                                paymentMap.setPaymentId(payment.getPaymentId());
+                                paymentMap.setStatus(-1);
+                                paymentMap.setRefundTime(DateUtils.getNowDate());
+                                paymentMap.setRefundMoney(payment.getPayMoney());
+                                liveOrderPaymentMapper.updateLiveOrderPayment(paymentMap);
+                            } else {
+                                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                                return R.error("退款请求失败" + (refundQueryResult != null ? refundQueryResult.getErrCodeDes() : ""));
+                            }
+                        } catch (WxPayException e) {
+                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                            return R.error("退款请求失败" + e.getErrCodeDes());
+                        }
+                    } else if (payment.getPayMode() != null && "hf".equals(payment.getPayMode())) {
+                        String huifuId = "";
+                        FsHfpayConfigMapper fsHfpayConfigMapper = SpringUtils.getBean(FsHfpayConfigMapper.class);
+                        if (payment.getAppId() != null) {
+                            FsHfpayConfig fsHfpayConfig = fsHfpayConfigMapper.selectByAppId(payment.getAppId());
+                            if (fsHfpayConfig != null) {
+                                huifuId = fsHfpayConfig.getHuifuId();
+                            }
+                        } else {
+                            CloudHostProper cloudHostProper = SpringUtils.getBean(CloudHostProper.class);
+                            if ("益善缘".equals(cloudHostProper.getCompanyName())) {
+                                FsHfpayConfig fsPayConfig2 = fsHfpayConfigMapper.selectByAppId("wx0d1a3dd485268521");
+                                if (fsPayConfig2 != null) {
+                                    huifuId = fsPayConfig2.getHuifuId();
+                                }
+                            } else {
+                                huifuId = fsPayConfig.getHuifuId();
+                            }
+                        }
+
+                        V2TradePaymentScanpayRefundRequest request = new V2TradePaymentScanpayRefundRequest();
+                        request.setOrgHfSeqId(payment.getTradeNo());
+                        request.setHuifuId(huifuId);
+                        request.setOrdAmt(payment.getPayMoney().toString());
+                        request.setOrgReqDate(new SimpleDateFormat("yyyyMMdd").format(payment.getCreateTime()));
+                        request.setReqSeqId("refund-" + payment.getPayCode());
+                        Map<String, Object> extendInfoMap = new HashMap<>();
+                        extendInfoMap.put("org_party_order_id", payment.getBankSerialNo());
+                        request.setExtendInfo(extendInfoMap);
+                        HuiFuRefundResult refund = huiFuService.refund(request);
+                        log.info("退款:" + refund);
+                        if (refund != null && ("00000000".equals(refund.getResp_code()) || "00000100".equals(refund.getResp_code()))
+                                && ("S".equals(refund.getTrans_stat()) || "P".equals(refund.getTrans_stat()))) {
+                            payment.setRefundMoney(payment.getPayMoney());
+                            payment.setStatus(-1);
+                            payment.setRefundTime(new Date());
+                            liveOrderPaymentMapper.updateLiveOrderPayment(payment);
+                        } else {
+                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                            return R.error(refund != null ? refund.getResp_desc() : "退款失败");
+                        }
+                    } else {
+                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                        return R.error("支付类型异常");
+                    }
+                }
+            }
+        }
+        liveOrderLogsService.create(order.getOrderId(), OrderLogEnum.REFUND_ORDER_SUCCESS.getValue(),
+                OrderLogEnum.REFUND_ORDER_SUCCESS.getDesc());
+        //减去公司收入
+        if (order.getCompanyId() != null && order.getCompanyId() > 0 && order.getTuiMoneyStatus() != null && order.getTuiMoneyStatus() == 1) {
+            companyService.subLiveCompanyMoney(order);
+        }
+        // 减去用户佣金
+        if (order.getTuiUserId() != null && order.getTuiUserId() > 0) {
+            IFsUserScrmService userService = SpringUtils.getBean(IFsUserScrmService.class);
+            if (userService != null) {
+                // 需要将LiveOrder转换为FsStoreOrderScrm用于subTuiMoney方法
+                FsStoreOrderScrm storeOrder = new FsStoreOrderScrm();
+                storeOrder.setId(order.getOrderId());
+                storeOrder.setTuiUserId(order.getTuiUserId());
+                userService.subTuiMoney(storeOrder);
+            }
+        }
+        LiveAfterSales liveAfterSales = liveAfterSalesMapper.getLiveAfterSalesByOrderId(orderId);
+        LiveAfterSales liveMp = new LiveAfterSales();
+        liveMp.setId(liveAfterSales.getId());
+        liveMp.setStatus(LiveAfterSalesStatusEnum.STATUS_4.getValue());
+        liveMp.setSalesStatus(3);
+        liveAfterSalesMapper.updateLiveAfterSales(liveMp);
+
+        return R.ok();
+    }
 }

+ 5 - 0
fs-service/src/main/java/com/fs/live/service/impl/LiveOrderPaymentServiceImpl.java

@@ -62,6 +62,11 @@ public class LiveOrderPaymentServiceImpl implements ILiveOrderPaymentService {
         return baseMapper.selectLiveOrderPaymentByOrderId(id);
     }
 
+    @Override
+    public LiveOrderPayment selectByBussinessId(Long orderId) {
+        return baseMapper.selectByBuissnessId(orderId);
+    }
+
     /**
      * 新增支付明细
      *

+ 160 - 85
fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java

@@ -29,6 +29,8 @@ import com.alibaba.fastjson.JSON;
 
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.TypeReference;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.config.FSSysConfig;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
@@ -63,6 +65,7 @@ import com.fs.his.enums.FsStoreOrderLogEnum;
 import com.fs.his.mapper.FsHfpayConfigMapper;
 import com.fs.his.mapper.FsStoreProductAttrValueMapper;
 import com.fs.his.mapper.FsUserMapper;
+import com.fs.his.mapper.FsUserWxMapper;
 import com.fs.his.service.IFsExpressService;
 import com.fs.his.service.IFsStoreProductService;
 import com.fs.his.service.IFsUserService;
@@ -136,6 +139,8 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
     private final RedisCache redisCache;
     @Autowired
     private LiveOrderMapper baseMapper;
+    @Autowired
+    private FsUserWxMapper fsUserWxMapper;
 
 
 
@@ -624,6 +629,47 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
 //        return R.error();
 //
 //    }
+    private void createOmsOrderCall(LiveOrder inOrder)  throws ParseException {
+        LiveOrder order = liveOrderMapper.selectLiveOrderByOrderId(String.valueOf(inOrder.getOrderId()));
+        LiveOrderPayment liveOrderPayment = liveOrderPaymentMapper.selectByBuissnessId(order.getOrderId());
+        if (liveOrderPayment == null) {
+            log.info("订单:{},未找到支付信息,不进行推送", order.getOrderCode());
+            return ;
+        }
+        FsSysConfig erpConfig = configUtil.generateStructConfigByKey(SysConfigEnum.HIS_CONFIG.getKey(), FsSysConfig.class);
+        List<Long> noErpCompany = erpConfig.getNoErpCompany();
+        if (noErpCompany != null && noErpCompany.contains(order.getCompanyId())) {
+            log.info("订单:{},相关公司不推送erp", order.getOrderCode());
+            return ;
+        }
+        IErpOrderService erpOrderService = getErpService();
+        if (erpOrderService == null) {
+            log.info("未启用erp");
+            return;
+        }
+        if (!StringUtils.isEmpty(order.getExtendOrderId()) && order.getStatus() != 1) {
+            return ;
+        }
+        if(order.getUserName() == null || StringUtils.isEmpty(order.getUserName())) return;
+        ErpOrder erpOrder = getErpOrder(order);
+        if(erpOrder == null ){
+            log.info("组合码为空,订单ID:" + order.getOrderCode());
+            return ;
+        }
+
+        if (erpOrderService == jSTOrderService) {
+            erpOrder.setShop_code(erpConfig.getErpJstShopCode());
+        }
+        ErpOrderResponse response = erpOrderService.addLiveOrder(erpOrder);
+
+        //写入日志
+        log.info("ErpCreate:" + order.getOrderCode() + ":" + JSONUtil.toJsonStr(response));
+        //支付成功后 将订单号写入待发货的REDIS中
+        redisCache.setCacheObject(DELIVERY + ":" + response.getCode(), order.getOrderCode());
+        //写入外部订单号
+        order.setExtendOrderId(response.getCode());
+        liveOrderMapper.updateLiveOrder(order);
+    }
 
     @Override
     @Transactional(rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)
@@ -687,6 +733,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
             order.setPayTime(LocalDateTime.now());
             order.setIsPay("1");
             baseMapper.updateLiveOrder(order);
+            this.createOmsOrderCall(order);
             return "SUCCESS";
         }catch (Exception e){
             log.info("支付错误:"+e.getMessage());
@@ -1504,6 +1551,11 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
     @Override
     public R createOmsOrder(Long orderId)  throws ParseException {
         LiveOrder order = liveOrderMapper.selectLiveOrderByOrderId(String.valueOf(orderId));
+        LiveOrderPayment liveOrderPayment = liveOrderPaymentMapper.selectByBuissnessId(orderId);
+        if (liveOrderPayment == null) {
+            log.info("订单:{},未找到支付信息", order.getOrderCode());
+            return R.error("订单:" + order.getOrderCode() + ",未找到支付信息");
+        }
         FsSysConfig erpConfig = configUtil.generateStructConfigByKey(SysConfigEnum.HIS_CONFIG.getKey(), FsSysConfig.class);
         List<Long> noErpCompany = erpConfig.getNoErpCompany();
         if (noErpCompany != null && noErpCompany.contains(order.getCompanyId())) {
@@ -2317,82 +2369,86 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
 
     private BigDecimal handleDeliveryMoney(Long cityId, FsStoreProductScrm fsStoreProduct, String totalNumSize) {
         BigDecimal storePostage = BigDecimal.ZERO;
-//        List<Long> citys = new ArrayList<>();
-//        citys.add(cityId);
-//        citys.add(0l);
-//        String ids = String.valueOf(fsStoreProduct.getTempId());
-//        List<FsShippingTemplates> shippingTemplatesList = shippingTemplatesService.selectFsShippingTemplatesByIds(ids);
-//        String cityIds = String.join(",", citys.stream()
-//                .map(String::valueOf).collect(Collectors.toList()));
-//        List<FsShippingTemplatesRegion> shippingTemplatesRegionList = shippingTemplatesRegionService.selectFsShippingTemplatesRegionListByTempIdsAndCityIds(ids,cityIds);
-//        Map<Long, Integer> shippingTemplatesMap = shippingTemplatesList
-//                .stream()
-//                .collect(Collectors.toMap(FsShippingTemplates::getId,
-//                        FsShippingTemplates::getType));
-//        //提取运费模板有相同值覆盖
-//        Map<Long, FsShippingTemplatesRegion> shippingTemplatesRegionMap =
-//                shippingTemplatesRegionList.stream()
-//                        .collect(Collectors.toMap(FsShippingTemplatesRegion::getTempId,
-//                                YxShippingTemplatesRegion -> YxShippingTemplatesRegion,
-//                                (key1, key2) -> key2));
-//        Long tempId = Long.valueOf(fsStoreProduct.getTempId());
-//        double num = 0d;
-//        Integer templateType = shippingTemplatesMap.get(tempId);
-//        List<FsStoreProductAttrValue> productAttrValues = fsStoreProductAttrValueMapper.selectFsStoreProductAttrValueByProductId(fsStoreProduct.getProductId());
-//        if(productAttrValues == null || productAttrValues.isEmpty()) {
-//            return storePostage;
-//        }
-//        FsStoreProductAttrValue productAttrValue = productAttrValues.get(0);
-//        Integer totalNum = Integer.valueOf(totalNumSize);
-//        // TYPE_1: 按件数计算
-//        if (ShippingTempEnum.TYPE_1.getValue().equals(templateType)) {
-//            num = totalNum.doubleValue();
-//        }
-//        // TYPE_2: 按重量计算(数量 × 重量)
-//        else if (ShippingTempEnum.TYPE_2.getValue().equals(templateType)) {
-//            num = NumberUtil.mul(totalNum, productAttrValue.getWeight()).doubleValue();
-//        }
-//        // TYPE_3: 按体积计算(数量 × 体积)
-//        else if (ShippingTempEnum.TYPE_3.getValue().equals(templateType)) {
-//            num = NumberUtil.mul(totalNum, productAttrValue.getVolume()).doubleValue();
-//        }
-//        FsShippingTemplatesRegion shippingTemplatesRegion = shippingTemplatesRegionMap.get(tempId);
-//        if (shippingTemplatesRegion == null) {
-//            log.error("没有找到运费模板");
-//            return storePostage;
-//        }
-//        BigDecimal price = NumberUtil.round(NumberUtil.mul(totalNum, fsStoreProduct.getPrice()), 2);
-//
-//        TemplateDTO templateDTO = TemplateDTO.builder()
-//                .number(num)  // 累计数量(件数/重量/体积)
-//                .price(price)  // 累计金额
-//                .first(shippingTemplatesRegion.getFirst().doubleValue())  // 首件数量
-//                .firstPrice(shippingTemplatesRegion.getFirstPrice())  // 首件运费
-//                .continues(shippingTemplatesRegion.getContinues().doubleValue())  // 续件数量
-//                .continuePrice(shippingTemplatesRegion.getContinuePrice())  // 续件运费
-//                .tempId(tempId)  // 模板ID
-//                .cityId(cityId)  // 城市ID
-//                .build();
-//        //只满足首件
-//        if (Double.compare(templateDTO.getNumber(), templateDTO.getFirst()) <= 0) {
-//            storePostage = NumberUtil.round(NumberUtil.add(storePostage,
-//                    templateDTO.getFirstPrice()), 2);
-//        } else {
-//            BigDecimal firstPrice = NumberUtil.add(storePostage, templateDTO.getFirstPrice());
-//
-//            if (templateDTO.getContinues() <= 0) {
-//                storePostage = firstPrice;
-//            } else {
-//                //续件平均值且向上取整数
-//                double average = Math.ceil(NumberUtil.div(NumberUtil.sub(templateDTO.getNumber(),
-//                                templateDTO.getFirst()),
-//                        templateDTO.getContinues().doubleValue()));
-//                //最终邮费
-//                storePostage = NumberUtil.add(firstPrice, NumberUtil.mul(average,
-//                        templateDTO.getContinuePrice()));
-//            }
-//
-//        }
+        List<Long> citys = new ArrayList<>();
+        citys.add(cityId);
+        citys.add(0l);
+        String ids = String.valueOf(fsStoreProduct.getTempId());
+        //如果没有配置运费 直接返回
+        if(StringUtils.isBlank(ids)){
+            return storePostage;
+        }
+        List<FsShippingTemplatesScrm> shippingTemplatesList = shippingTemplatesService.selectFsShippingTemplatesByIds(ids);
+        String cityIds = String.join(",", citys.stream()
+                .map(String::valueOf).collect(Collectors.toList()));
+        List<FsShippingTemplatesRegionScrm> shippingTemplatesRegionList = shippingTemplatesRegionService.selectFsShippingTemplatesRegionListByTempIdsAndCityIds(ids,cityIds);
+        Map<Long, Integer> shippingTemplatesMap = shippingTemplatesList
+                .stream()
+                .collect(Collectors.toMap(FsShippingTemplatesScrm::getId,
+                        FsShippingTemplatesScrm::getType));
+        //提取运费模板有相同值覆盖
+        Map<Long, FsShippingTemplatesRegionScrm> shippingTemplatesRegionMap =
+                shippingTemplatesRegionList.stream()
+                        .collect(Collectors.toMap(FsShippingTemplatesRegionScrm::getTempId,
+                                YxShippingTemplatesRegion -> YxShippingTemplatesRegion,
+                                (key1, key2) -> key2));
+        Long tempId = Long.valueOf(fsStoreProduct.getTempId());
+        double num = 0d;
+        Integer templateType = shippingTemplatesMap.get(tempId);
+        List<FsStoreProductAttrValueScrm> productAttrValues = fsStoreProductAttrValueMapper.selectFsStoreProductAttrValueByProductId(fsStoreProduct.getProductId());
+        if(productAttrValues == null || productAttrValues.isEmpty()) {
+            return storePostage;
+        }
+        FsStoreProductAttrValueScrm productAttrValue = productAttrValues.get(0);
+        Integer totalNum = Integer.valueOf(totalNumSize);
+        // TYPE_1: 按件数计算
+        if (ShippingTempEnum.TYPE_1.getValue().equals(templateType)) {
+            num = totalNum.doubleValue();
+        }
+        // TYPE_2: 按重量计算(数量 × 重量)
+        else if (ShippingTempEnum.TYPE_2.getValue().equals(templateType)) {
+            num = NumberUtil.mul(totalNum, productAttrValue.getWeight()).doubleValue();
+        }
+        // TYPE_3: 按体积计算(数量 × 体积)
+        else if (ShippingTempEnum.TYPE_3.getValue().equals(templateType)) {
+            num = NumberUtil.mul(totalNum, productAttrValue.getVolume()).doubleValue();
+        }
+        FsShippingTemplatesRegionScrm shippingTemplatesRegion = shippingTemplatesRegionMap.get(tempId);
+        if (shippingTemplatesRegion == null) {
+            log.error("没有找到运费模板");
+            return storePostage;
+        }
+        BigDecimal price = NumberUtil.round(NumberUtil.mul(totalNum, fsStoreProduct.getPrice()), 2);
+
+        TemplateDTO templateDTO = TemplateDTO.builder()
+                .number(num)  // 累计数量(件数/重量/体积)
+                .price(price)  // 累计金额
+                .first(shippingTemplatesRegion.getFirst().doubleValue())  // 首件数量
+                .firstPrice(shippingTemplatesRegion.getFirstPrice())  // 首件运费
+                .continues(shippingTemplatesRegion.getContinues().doubleValue())  // 续件数量
+                .continuePrice(shippingTemplatesRegion.getContinuePrice())  // 续件运费
+                .tempId(tempId)  // 模板ID
+                .cityId(cityId.toString())  // 城市ID
+                .build();
+        //只满足首件
+        if (Double.compare(templateDTO.getNumber(), templateDTO.getFirst()) <= 0) {
+            storePostage = NumberUtil.round(NumberUtil.add(storePostage,
+                    templateDTO.getFirstPrice()), 2);
+        } else {
+            BigDecimal firstPrice = NumberUtil.add(storePostage, templateDTO.getFirstPrice());
+
+            if (templateDTO.getContinues() <= 0) {
+                storePostage = firstPrice;
+            } else {
+                //续件平均值且向上取整数
+                double average = Math.ceil(NumberUtil.div(NumberUtil.sub(templateDTO.getNumber(),
+                                templateDTO.getFirst()),
+                        templateDTO.getContinues().doubleValue()));
+                //最终邮费
+                storePostage = NumberUtil.add(firstPrice, NumberUtil.mul(average,
+                        templateDTO.getContinuePrice()));
+            }
+
+        }
 
         return storePostage;
     }
@@ -2800,9 +2856,25 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
         if(StringUtils.isNotEmpty(orderId)&&order.getOrderId().toString().equals(orderId)){
             return R.error("正在支付中...");
         }
-
         FsUserScrm user=userMapper.selectFsUserById(Long.valueOf(order.getUserId()));
-        if(user!=null&& StringUtils.isNotEmpty(user.getMaOpenId())){
+        if(user == null){
+            return R.error("未找到用户信息,请联系管理员!");
+        }
+        String json = configService.selectConfigByKey("his.pay");
+        FsPayConfigScrm fsPayConfig = JSON.parseObject(json, FsPayConfigScrm.class);
+        String openId;
+        if(StringUtils.isNotEmpty(user.getMaOpenId())){
+            log.info("用户信息有openid:{}", user.getMaOpenId());
+            openId = user.getMaOpenId();
+        }else{
+            Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                    .eq(FsUserWx::getFsUserId, order.getUserId())
+                    .eq(FsUserWx::getAppId, fsPayConfig.getAppId());
+            FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+            log.info("查到的openId信息:{}", fsUserWx);
+            openId = fsUserWx.getOpenId();
+        }
+        if(StringUtils.isNotEmpty(openId)){
             //已改价处理
             if(order.getIsEditMoney()!=null&&order.getIsEditMoney()==1){
                 //改过价不做处理
@@ -2841,8 +2913,6 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
 //            order.setOrderCode(orderCode);
 //            if(order.getPayType().equals("1")||order.getPayType().equals("2")){
             if((order.getPayType().equals("1")||order.getPayType().equals("2")||order.getPayType().equals("3")) && order.getPayMoney().compareTo(new BigDecimal(0))>0){
-                String json = configService.selectConfigByKey("his.pay");
-                FsPayConfigScrm fsPayConfig = JSON.parseObject(json, FsPayConfigScrm.class);
                 LiveOrderPayment storePayment=new LiveOrderPayment();
                 storePayment.setCompanyId(order.getCompanyId());
                 storePayment.setCompanyUserId(order.getCompanyUserId());
@@ -2852,9 +2922,9 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                 storePayment.setPayMoney(order.getPayMoney());
                 storePayment.setCreateTime(new Date());
                 storePayment.setPayTypeCode("weixin");
-                storePayment.setBusinessType(2);
+                storePayment.setBusinessType(5);
                 storePayment.setRemark("直播订单支付");
-                storePayment.setOpenId(user.getRealName());
+                storePayment.setOpenId(openId);
                 storePayment.setUserId(user.getUserId());
                 storePayment.setBusinessId(String.valueOf(order.getOrderId()));
                 storePayment.setAppId(fsPayConfig.getAppId() == null ? "" : fsPayConfig.getAppId());
@@ -2863,11 +2933,11 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                 if (fsPayConfig.getType().equals("hf")){
                     HuiFuCreateOrder o = new HuiFuCreateOrder();
                     o.setTradeType("T_MINIAPP");
-                    o.setOpenid(user.getMaOpenId());
+                    o.setOpenid(storePayment.getOpenId());
                     o.setReqSeqId("live-"+storePayment.getPayCode());
                     o.setTransAmt(storePayment.getPayMoney().toString());
                     o.setGoodsDesc("直播订单支付");
-                    if (param != null && StringUtils.isNotBlank(param.getAppId())) {
+                    if (StringUtils.isNotBlank(param.getAppId())) {
                         o.setAppId(param.getAppId());
                     }
                     HuifuCreateOrderResult result = huiFuService.createOrder(o);
@@ -2879,6 +2949,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                         mt.setBusinessCode(order.getOrderCode());
                         liveOrderPaymentMapper.updateLiveOrderPayment(mt);
                         redisCache.setCacheObject("isPaying:"+order.getOrderId(),order.getOrderId().toString(),1, TimeUnit.MINUTES);
+                        log.info("汇付支付");
                         Map<String, Object> resultMap = JSON.parseObject(result.getPay_info(), new TypeReference<Map<String, Object>>() {});
                         String s = (String) resultMap.get("package");
                         resultMap.put("packageValue",s);
@@ -2898,7 +2969,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                     payConfig.setNotifyUrl(fsPayConfig.getNotifyUrlScrm());
                     wxPayService.setConfig(payConfig);
                     WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
-                    orderRequest.setOpenid(user.getMaOpenId());//公众号支付提供用户openid
+                    orderRequest.setOpenid(storePayment.getOpenId());
                     orderRequest.setBody("直播订单支付");
                     orderRequest.setOutTradeNo("live-" + storePayment.getPayCode());
                     orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));//测试
@@ -3223,9 +3294,11 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
 
         // 更改店铺库存
         fsStoreProduct.setStock(fsStoreProduct.getStock()-Integer.parseInt(liveOrder.getTotalNum()));
+        fsStoreProduct.setSales(fsStoreProduct.getSales()+Long.parseLong(liveOrder.getTotalNum()));
         fsStoreProductService.updateFsStoreProduct(fsStoreProduct);
         // 更新直播间库存
         goods.setStock(goods.getStock()-Integer.parseInt(liveOrder.getTotalNum()));
+        goods.setSales(goods.getSales()+Integer.parseInt(liveOrder.getTotalNum()));
         liveGoodsMapper.updateLiveGoods(goods);
 
         //判断是否是三种特定产品
@@ -3419,6 +3492,8 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
 
         }
 
+        liveOrder.setPayDelivery(storePostage);
+
         return storePostage;
     }
 

+ 16 - 2
fs-service/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java

@@ -6,13 +6,18 @@ import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.core.page.PageRequest;
 import com.fs.common.exception.base.BaseException;
 import com.fs.company.mapper.CompanyMapper;
 import com.fs.core.config.WxMaConfiguration;
 import com.fs.his.domain.FsStoreProduct;
 import com.fs.his.domain.FsUser;
+import com.fs.his.domain.FsUserWx;
 import com.fs.his.mapper.FsUserMapper;
+import com.fs.his.mapper.FsUserWxMapper;
 import com.fs.hisStore.domain.FsStoreProductScrm;
 import com.fs.hisStore.mapper.FsStoreProductScrmMapper;
 import com.fs.live.dto.TemplateMessageSendRequestDTO;
@@ -111,6 +116,8 @@ public class LiveServiceImpl implements ILiveService
     @Autowired
     private FsUserMapper fsUserMapper;
     @Autowired
+    private FsUserWxMapper fsUserWxMapper;
+    @Autowired
     private CompanyMapper companyMapper;
     @Autowired
     private LiveCouponMapper liveCouponMapper;
@@ -243,8 +250,15 @@ public class LiveServiceImpl implements ILiveService
         notifyTask.setPage("/pages_course/living?liveId=" + param.get("liveId"));
         notifyTask.setTaskName("直播间预约提醒");
         notifyTask.setTemplateId((String) param.get("templateId"));
-        FsUser fsUser = fsUserMapper.selectFsUserById(Long.valueOf((Integer) param.get("userId")));
-        String maOpenId = fsUser.getMaOpenId();
+        Long userId = Long.valueOf((Integer) param.get("userId"));
+        Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                .eq(FsUserWx::getFsUserId, userId)
+                .eq(FsUserWx::getAppId, param.getOrDefault("appid", "wx44beed5640bcb1ba"));
+        FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+        String maOpenId = fsUserWx.getOpenId();
+//        if (StringUtils.isEmpty(maOpenId)) {
+//            maOpenId = (String) param.get("maOpenId");
+//        }
         notifyTask.setTouser(maOpenId);
         notifyTask.setPage(String.valueOf(1));
 

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

@@ -98,6 +98,7 @@ public class LiveOrderVoZm{
     @Excel(name = "所属店铺名称")
     private String storeName;
 
+
     @Excel(name = "商品ID")
     private Long productId;
 
@@ -123,6 +124,16 @@ public class LiveOrderVoZm{
     @Excel(name = "结算价格")
     private BigDecimal fPrice;
 
+    /** 支付运费 */
+    @Excel(name = "支付运费")
+    private BigDecimal payDelivery;
+
+    @Excel(name = "商品编码")
+    private String barCode;
+
+    @Excel(name = "商品分类")
+    private String cateName;
+
     /** 支付金额 */
     @Excel(name = "支付金额")
     private BigDecimal payMoney;
@@ -311,9 +322,6 @@ public class LiveOrderVoZm{
 //    @Excel(name = "扩展订单ID")
     private String extendOrderId;
 
-    /** 支付运费 */
-//    @Excel(name = "支付运费")
-    private BigDecimal payDelivery;
 
     /** 剩余金额 */
 //    @Excel(name = "剩余金额")

+ 46 - 0
fs-service/src/main/java/com/fs/qw/domain/QwApiSopLogToken.java

@@ -0,0 +1,46 @@
+package com.fs.qw.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * 企业微信账号 发官方群发的统计对象 qw_api_sop_log_token
+ *
+ * @author fs
+ * @date 2025-11-26
+ */
+@Data
+public class QwApiSopLogToken {
+
+    /** $column.columnComment */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /** $column.columnComment */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private String qwUserId;
+
+    /** $column.columnComment */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private Long companyId;
+
+    /** $column.columnComment */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private Date sendTime;
+
+    /** $column.columnComment */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private Long sendCount;
+
+    /** $column.columnComment */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private Long sendCountToken;
+
+
+}

+ 61 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwApiSopLogTokenMapper.java

@@ -0,0 +1,61 @@
+package com.fs.qw.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.qw.domain.QwApiSopLogToken;
+
+/**
+ * 企业微信账号 发官方群发的统计Mapper接口
+ * 
+ * @author fs
+ * @date 2025-11-26
+ */
+public interface QwApiSopLogTokenMapper extends BaseMapper<QwApiSopLogToken>{
+    /**
+     * 查询企业微信账号 发官方群发的统计
+     * 
+     * @param id 企业微信账号 发官方群发的统计主键
+     * @return 企业微信账号 发官方群发的统计
+     */
+    QwApiSopLogToken selectQwApiSopLogTokenById(Long id);
+
+    /**
+     * 查询企业微信账号 发官方群发的统计列表
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 企业微信账号 发官方群发的统计集合
+     */
+    List<QwApiSopLogToken> selectQwApiSopLogTokenList(QwApiSopLogToken qwApiSopLogToken);
+
+    /**
+     * 新增企业微信账号 发官方群发的统计
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 结果
+     */
+    int insertQwApiSopLogToken(QwApiSopLogToken qwApiSopLogToken);
+
+    /**
+     * 修改企业微信账号 发官方群发的统计
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 结果
+     */
+    int updateQwApiSopLogToken(QwApiSopLogToken qwApiSopLogToken);
+
+    /**
+     * 删除企业微信账号 发官方群发的统计
+     * 
+     * @param id 企业微信账号 发官方群发的统计主键
+     * @return 结果
+     */
+    int deleteQwApiSopLogTokenById(Long id);
+
+    /**
+     * 批量删除企业微信账号 发官方群发的统计
+     * 
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteQwApiSopLogTokenByIds(Long[] ids);
+}

+ 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();
 }

+ 61 - 0
fs-service/src/main/java/com/fs/qw/service/IQwApiSopLogTokenService.java

@@ -0,0 +1,61 @@
+package com.fs.qw.service;
+
+import java.util.List;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.qw.domain.QwApiSopLogToken;
+
+/**
+ * 企业微信账号 发官方群发的统计Service接口
+ * 
+ * @author fs
+ * @date 2025-11-26
+ */
+public interface IQwApiSopLogTokenService extends IService<QwApiSopLogToken>{
+    /**
+     * 查询企业微信账号 发官方群发的统计
+     * 
+     * @param id 企业微信账号 发官方群发的统计主键
+     * @return 企业微信账号 发官方群发的统计
+     */
+    QwApiSopLogToken selectQwApiSopLogTokenById(Long id);
+
+    /**
+     * 查询企业微信账号 发官方群发的统计列表
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 企业微信账号 发官方群发的统计集合
+     */
+    List<QwApiSopLogToken> selectQwApiSopLogTokenList(QwApiSopLogToken qwApiSopLogToken);
+
+    /**
+     * 新增企业微信账号 发官方群发的统计
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 结果
+     */
+    int insertQwApiSopLogToken(QwApiSopLogToken qwApiSopLogToken);
+
+    /**
+     * 修改企业微信账号 发官方群发的统计
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 结果
+     */
+    int updateQwApiSopLogToken(QwApiSopLogToken qwApiSopLogToken);
+
+    /**
+     * 批量删除企业微信账号 发官方群发的统计
+     * 
+     * @param ids 需要删除的企业微信账号 发官方群发的统计主键集合
+     * @return 结果
+     */
+    int deleteQwApiSopLogTokenByIds(Long[] ids);
+
+    /**
+     * 删除企业微信账号 发官方群发的统计信息
+     * 
+     * @param id 企业微信账号 发官方群发的统计主键
+     * @return 结果
+     */
+    int deleteQwApiSopLogTokenById(Long id);
+}

+ 91 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwApiSopLogTokenServiceImpl.java

@@ -0,0 +1,91 @@
+package com.fs.qw.service.impl;
+
+import java.util.List;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.fs.qw.mapper.QwApiSopLogTokenMapper;
+import com.fs.qw.domain.QwApiSopLogToken;
+import com.fs.qw.service.IQwApiSopLogTokenService;
+
+/**
+ * 企业微信账号 发官方群发的统计Service业务层处理
+ * 
+ * @author fs
+ * @date 2025-11-26
+ */
+@Service
+public class QwApiSopLogTokenServiceImpl extends ServiceImpl<QwApiSopLogTokenMapper, QwApiSopLogToken> implements IQwApiSopLogTokenService {
+
+    /**
+     * 查询企业微信账号 发官方群发的统计
+     * 
+     * @param id 企业微信账号 发官方群发的统计主键
+     * @return 企业微信账号 发官方群发的统计
+     */
+    @Override
+    public QwApiSopLogToken selectQwApiSopLogTokenById(Long id)
+    {
+        return baseMapper.selectQwApiSopLogTokenById(id);
+    }
+
+    /**
+     * 查询企业微信账号 发官方群发的统计列表
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 企业微信账号 发官方群发的统计
+     */
+    @Override
+    public List<QwApiSopLogToken> selectQwApiSopLogTokenList(QwApiSopLogToken qwApiSopLogToken)
+    {
+        return baseMapper.selectQwApiSopLogTokenList(qwApiSopLogToken);
+    }
+
+    /**
+     * 新增企业微信账号 发官方群发的统计
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 结果
+     */
+    @Override
+    public int insertQwApiSopLogToken(QwApiSopLogToken qwApiSopLogToken)
+    {
+        return baseMapper.insertQwApiSopLogToken(qwApiSopLogToken);
+    }
+
+    /**
+     * 修改企业微信账号 发官方群发的统计
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 结果
+     */
+    @Override
+    public int updateQwApiSopLogToken(QwApiSopLogToken qwApiSopLogToken)
+    {
+        return baseMapper.updateQwApiSopLogToken(qwApiSopLogToken);
+    }
+
+    /**
+     * 批量删除企业微信账号 发官方群发的统计
+     * 
+     * @param ids 需要删除的企业微信账号 发官方群发的统计主键
+     * @return 结果
+     */
+    @Override
+    public int deleteQwApiSopLogTokenByIds(Long[] ids)
+    {
+        return baseMapper.deleteQwApiSopLogTokenByIds(ids);
+    }
+
+    /**
+     * 删除企业微信账号 发官方群发的统计信息
+     * 
+     * @param id 企业微信账号 发官方群发的统计主键
+     * @return 结果
+     */
+    @Override
+    public int deleteQwApiSopLogTokenById(Long id)
+    {
+        return baseMapper.deleteQwApiSopLogTokenById(id);
+    }
+}

+ 22 - 0
fs-service/src/main/java/com/fs/sop/mapper/QwSopLogsMapper.java

@@ -3,6 +3,7 @@ package com.fs.sop.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.common.annotation.DataSource;
 import com.fs.common.enums.DataSourceType;
+import com.fs.qw.domain.QwApiSopLogToken;
 import com.fs.qw.param.SopMsgParam;
 import com.fs.sop.domain.QwSopLogs;
 import com.fs.sop.params.*;
@@ -332,4 +333,25 @@ public interface QwSopLogsMapper extends BaseMapper<QwSopLogs> {
 
     @DataSource(DataSourceType.SOP)
     void batchUpdateQwSopLogsNewUserById(@Param("data")List<QwSopLogs> qwSopLogsList);
+
+    @DataSource(DataSourceType.SOP)
+    @Select("<script>" +
+            "SELECT\n" +
+            "  qw_user_key as qw_user_id,\n" +
+            "  company_id,\n" +
+            "  send_time,\n" +
+            "  count(*) as send_count," +
+            "  count(*)  * 150 as send_count_token \n" +
+            "FROM\n" +
+            "  `qw_sop_logs`\n" +
+            "WHERE\n" +
+            "  send_type = 1\n" +
+            "  AND send_status = 1\n" +
+            "  AND DATE(send_time) = #{data}\n" +
+            "GROUP BY\n" +
+            "  qw_user_key,\n" +
+            "  company_id\n" +
+            "ORDER BY qw_user_key" +
+            "</script>")
+    List<QwApiSopLogToken> countQwApiAopLogToken(@Param("data") String dateStr);
 }

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

@@ -132,4 +132,6 @@ public interface IQwSopLogsService extends IService<QwSopLogs>
 
 
     void updateBatch(List<QwSopLogs> collect);
+
+    void countQwApiAopLogToken(String dateStr);
 }

+ 11 - 1
fs-service/src/main/java/com/fs/sop/service/impl/QwSopLogsServiceImpl.java

@@ -17,14 +17,15 @@ import com.fs.company.service.ICompanyUserService;
 import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsCourseWatchLog;
 import com.fs.course.service.IFsCourseWatchLogService;
-import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.fastGpt.service.IFastGptChatSessionService;
+import com.fs.qw.domain.QwApiSopLogToken;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.domain.QwUser;
 import com.fs.qw.mapper.QwExternalContactMapper;
 import com.fs.qw.mapper.QwUserMapper;
 import com.fs.qw.param.SopMsgParam;
 import com.fs.qw.result.QwExternalContactByQwResult;
+import com.fs.qw.service.IQwApiSopLogTokenService;
 import com.fs.qw.service.impl.AsyncSopTestService;
 import com.fs.qw.service.impl.QwExternalContactServiceImpl;
 import com.fs.qw.vo.QwSopTempSetting;
@@ -109,6 +110,9 @@ public class QwSopLogsServiceImpl extends ServiceImpl<QwSopLogsMapper, QwSopLogs
 
     private AsyncSopTestService asyncSopTestService;
 
+    @Autowired
+    private IQwApiSopLogTokenService sopLogTokenService;
+
     @Autowired
     public void setAsyncSopTestService(@Lazy AsyncSopTestService asyncSopTestService){
         this.asyncSopTestService = asyncSopTestService;
@@ -1605,6 +1609,12 @@ public class QwSopLogsServiceImpl extends ServiceImpl<QwSopLogsMapper, QwSopLogs
         super.updateBatchById(collect);
     }
 
+    @Override
+    public void countQwApiAopLogToken(String dateStr) {
+        List<QwApiSopLogToken> qwApiSopLogTokens = qwSopLogsMapper.countQwApiAopLogToken(dateStr);
+        sopLogTokenService.saveBatch(qwApiSopLogTokens,500);
+    }
+
 
     // 定义一个方法来批量处理插入逻辑,支持每 500 条数据一次的批量插入
     private void processAndInsertQwSopLogs(List<QwSopLogsDoSendListTVO> logsByJsApiNotExtId) {

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

@@ -92,10 +92,10 @@ nuonuo:
 tencent_cloud_config:
   secret_id: AKIDiMq9lDf2EOM9lIfqqfKo7FNgM5meD0sT
   secret_key: u5SuS80342xzx8FRBukza9lVNHKNMSaB
-  bucket: jkj-1323137866
+  bucket: cqsft-1323137866
   app_id: 1323137866
   region: ap-chongqing
-  proxy: jkj
+  proxy: cqsft
 tmp_secret_config:
   secret_id: AKIDCj7NSNAovtqeJpBau8GZ4CGB71thXIxX
   secret_key: lTB5zwqqz7CNhzDOWivFWedgfTBgxgBT
@@ -109,6 +109,7 @@ cloud_host:
 headerImg:
   imgUrl: https://jz-cos-1356808054.cos.ap-chengdu.myqcloud.com/fs/20250515/0877754b59814ea8a428fa3697b20e68.png
 ipad:
+  url:
   ipadUrl: http://ipad.cdwjyyh.com
   aiApi: http://152.136.202.157:3000/api
   voiceApi:

+ 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:
-
-

+ 98 - 0
fs-service/src/main/resources/application-config-druid-gzzdy.yml

@@ -0,0 +1,98 @@
+baidu:
+  token: 12313231232
+  back-domain: https://www.xxxx.com
+#配置
+logging:
+  level:
+    org.springframework.web: INFO
+    com.github.binarywang.demo.wx.cp: DEBUG
+    me.chanjar.weixin: DEBUG
+wx:
+  miniapp:
+    configs:
+      - appid:
+        secret:
+        token:
+        aesKey:
+        msgDataFormat: JSON
+      - appid:
+        secret:
+        token:
+        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
+        msgDataFormat: JSON
+  cp:
+    corpId:
+    appConfigs:
+      - agentId: 100005
+        secret: ec7okROXJqkNafq66aKNasTzQIG0CYrj3vyBbo
+        token: PPKOdAlMO
+        aesKey: PKvaxtpSvNGpfT7VUHIK8Wok2ESyYX24qpXJAdMP
+  pay:
+    appId:  #微信公众号或者小程序等的appid
+    mchId:  #微信支付商户号
+    mchKey:  #微信支付商户密钥
+    subAppId:  #服务商模式下的子商户公众账号ID
+    subMchId:  #服务商模式下的子商户号
+    keyPath: c:\\cert\\apiclient_cert.p12 # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)
+    notifyUrl: https://userapp.dyzkl.cn/app/wxpay/wxPayNotify
+  mp:
+    useRedis: false
+    redisConfig:
+      host: 127.0.0.1
+      port: 6379
+      timeout: 2000
+    configs:
+      - appId:  wxf468f88fbbb845af # 第一个公众号的appid
+        secret: 812d49175dadf579bdd4ad812867793a  # 公众号的appsecret
+        token: PPKOdAlCoMO # 接口配置里的Token值
+        aesKey: Eswa6VjwtVMCcw03qZy6fWllgrv5aytIA1SZPEU0kU2 # 接口配置里的EncodingAESKey值
+aifabu:  #爱链接
+  appKey: 7b471be905ab17ef358c0dd117601d008
+watch:
+  watchUrl: watch.ylrzcloud.com/prod-api
+#  account: tcloud
+#  password: mdf-m2h_6yw2$hq
+  account1: ccif #866655060138751
+  password1: cp-t5or_6xw7$mt
+  account2: tcloud #rt500台
+  password2: mdf-m2h_6yw2$hq
+  account3: whr
+  password3: v9xsKuqn_$d2y
+
+fs :
+  commonApi: http://172.16.16.7:7771
+  h5CommonApi: http://172.16.16.7:7771
+  jwt:
+    # 加密秘钥
+    secret: f4e2e52034348f86b67cde581c0f9eb5
+    # token有效时长,7天,单位秒
+    expire: 31536000
+    header: AppToken
+nuonuo:
+  key: 10924508
+  secret: A2EB20764D304D16
+
+# 存储捅配置
+tencent_cloud_config:
+  secret_id: AKIDiMq9lDf2EOM9lIfqqfKo7FNgM5meD0sT
+  secret_key: u5SuS80342xzx8FRBukza9lVNHKNMSaB
+  bucket: gzzdy-1323137866
+  app_id: 1323137866
+  region: ap-chongqing
+  proxy: gzzdy
+cloud_host:
+  company_name: 广州郑多燕
+  projectCode: GZZDY
+#看课授权时显示的头像
+headerImg:
+  imgUrl:
+ipad:
+  ipadUrl: http://ipad.dyzkl.cn
+  aiApi: http://49.232.181.28:3000/api
+  voiceApi: http://123.207.48.104:8009
+  commonApi: http://123.207.48.104:7771
+wx_miniapp_temp:
+  pay_order_temp_id:
+  inquiry_temp_id:
+
+

+ 1 - 0
fs-service/src/main/resources/application-config-druid-heyantang.yml

@@ -83,6 +83,7 @@ cloud_host:
 headerImg:
   imgUrl: https
 ipad:
+  url:
   ipadUrl: https://qwipad.yytcdtb.cn
   aiApi: http://127.0.0.1:3000/api
   voiceApi:

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

@@ -89,7 +89,7 @@ headerImg:
   imgUrl: https://hzyy.obs.cn-north-4.myhuaweicloud.com/fs/20250616/1750067609692.png
 ipad:
   ipadUrl: http://139.159.133.223:8667
-  aiApi: http://1.95.196.10:3000/api
+  aiApi: http://49.232.181.28:3000/api
   voiceApi:
   commonApi:
 wx_miniapp_temp:

+ 2 - 0
fs-service/src/main/resources/application-config-druid-jnmy.yml

@@ -95,6 +95,8 @@ ipad:
   aiApi: http://49.232.181.28:3000/api
   voiceApi: http://139.186.176.122:8009
   commonApi: http://139.186.176.122:7771
+  watchUrl: https://manwatch.ylrzcloud.com/prod-api
+  fsCompanyId: 13
 wx_miniapp_temp:
   pay_order_temp_id: -SjnK9K6cNKASa6AD9Q_c0YT7J1lPTEpPIpqbMJF8F0
   inquiry_temp_id: hwFXVh0AWqeasBsZpa0-urb3CrPeYEwBiy3P6AMMGFQ

+ 1 - 0
fs-service/src/main/resources/application-config-druid-knt.yml

@@ -91,6 +91,7 @@ cloud_host:
 headerImg:
   imgUrl: https
 ipad:
+  url:
   ipadUrl: http://qwipad.jnmyunl.com
   aiApi: http://49.232.181.28:3000/api
   voiceApi: http://139.186.176.122:8009

+ 1 - 0
fs-service/src/main/resources/application-config-druid-knt2.yml

@@ -91,6 +91,7 @@ cloud_host:
 headerImg:
   imgUrl: https
 ipad:
+  url:
   ipadUrl: http://qwipad.jnmyunl.com
   aiApi: http://49.232.181.28:3000/api
   voiceApi: http://139.186.176.122:8009

+ 6 - 5
fs-service/src/main/resources/application-config-druid-sft.yml

@@ -67,12 +67,12 @@ nuonuo:
   secret: A2EB20764D304D16
 # 存储捅配置
 tencent_cloud_config:
-  secret_id: AKIDpY8d3KcptqdCaoqeVHuKYZMvITULzQta
-  secret_key: cBShmjU4SwNejgS2PYUFnR7dzAC6pW3Q
-  bucket: sft-1361917636
-  app_id: 1361917636
+  secret_id: AKIDiMq9lDf2EOM9lIfqqfKo7FNgM5meD0sT
+  secret_key: u5SuS80342xzx8FRBukza9lVNHKNMSaB
+  bucket: cqsft-1323137866
+  app_id: 1323137866
   region: ap-chongqing
-  proxy: fs
+  proxy: cqsft
 cloud_host:
   company_name: 四福堂
   projectCode: SFT
@@ -80,6 +80,7 @@ cloud_host:
 headerImg:
   imgUrl: https://sft-1361917636.cos.ap-chongqing.myqcloud.com/sft/20250606/b08b1a6212f44f2998423c8c5d7712ee.png
 ipad:
+  url:
   ipadUrl: http://qwipad.cqsft.vip
   aiApi:
   voiceApi:

+ 1 - 1
fs-service/src/main/resources/application-config-druid-sxjz.yml

@@ -92,7 +92,7 @@ headerImg:
   imgUrl: https://jz-cos-1356808054.cos.ap-chengdu.myqcloud.com/fs/20250515/0877754b59814ea8a428fa3697b20e68.png
 ipad:
   ipadUrl: http://ipad.xintaihl.cn
-  aiApi: http://1.95.196.10:3000/api
+  aiApi: http://49.232.181.28:3000/api
   voiceApi:
   commonApi:
 wx_miniapp_temp:

+ 1 - 0
fs-service/src/main/resources/application-config-zkzh.yml

@@ -144,6 +144,7 @@ nuonuo:
   key: 10924508
   secret: A2EB20764D304D16
 ipad:
+  url:
   ipadUrl: http://qwipad.muyi88.com
   aiApi: http://152.136.202.157:3000/api
   voiceApi:

+ 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
 

+ 151 - 0
fs-service/src/main/resources/application-druid-gzzdy.yml

@@ -0,0 +1,151 @@
+# 数据源配置
+spring:
+  profiles:
+    include: common,config-druid-gzzdy
+  # redis 配置
+  redis:
+    # 地址
+    host: 172.16.16.17
+    # 端口,默认为6379
+    port: 6379
+    # 密码
+    password: Ylrz_tM8/oW6$pU9|t#&
+    # 连接超时时间
+    timeout: 30s
+    lettuce:
+      pool:
+        # 连接池中的最小空闲连接
+        min-idle: 0
+        # 连接池中的最大空闲连接
+        max-idle: 8
+        # 连接池的最大数据库连接数
+        max-active: 100
+        # #连接池最大阻塞等待时间(使用负值表示没有限制)
+        max-wait: -1ms
+    database: 0
+  datasource:
+    mysql:
+      type: com.alibaba.druid.pool.DruidDataSource
+      driverClassName: com.mysql.cj.jdbc.Driver
+      druid:
+        # 主库数据源
+        master:
+          url: jdbc:mysql://172.16.16.12:3306/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+          username: root
+          password: ylrz14752131..!@YX
+        # 从库数据源
+        slave:
+          # 从数据源开关/默认关闭
+          enabled: false
+          url:
+          username:
+          password:
+        # 初始连接数
+        initialSize: 5
+        # 最小连接池数量
+        minIdle: 10
+        # 最大连接池数量
+        maxActive: 200
+        # 配置获取连接等待超时的时间
+        maxWait: 60000
+        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+        timeBetweenEvictionRunsMillis: 60000
+        # 配置一个连接在池中最小生存的时间,单位是毫秒
+        minEvictableIdleTimeMillis: 300000
+        # 配置一个连接在池中最大生存的时间,单位是毫秒
+        maxEvictableIdleTimeMillis: 900000
+        # 配置检测连接是否有效
+        validationQuery: SELECT 1 FROM DUAL
+        testWhileIdle: true
+        testOnBorrow: false
+        testOnReturn: false
+        webStatFilter:
+          enabled: true
+        statViewServlet:
+          enabled: false
+          # 设置白名单,不填则允许所有访问
+          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://172.17.0.3:3306/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+          url: jdbc:mysql://172.16.16.12:3306/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+          username: root
+          password: ylrz14752131..!@YX
+        # 初始连接数
+        initialSize: 5
+        # 最小连接池数量
+        minIdle: 10
+        # 最大连接池数量
+        maxActive: 200
+        # 配置获取连接等待超时的时间
+        maxWait: 60000
+        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+        timeBetweenEvictionRunsMillis: 60000
+        # 配置一个连接在池中最小生存的时间,单位是毫秒
+        minEvictableIdleTimeMillis: 300000
+        # 配置一个连接在池中最大生存的时间,单位是毫秒
+        maxEvictableIdleTimeMillis: 900000
+        # 配置检测连接是否有效
+        validationQuery: SELECT 1 FROM DUAL
+        testWhileIdle: true
+        testOnBorrow: false
+        testOnReturn: false
+        webStatFilter:
+          enabled: true
+        statViewServlet:
+          enabled: false
+          # 设置白名单,不填则允许所有访问
+          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-1vjak37re.rocketmq.gz.qcloud.tencenttdmq.com:8080 # RocketMQ NameServer 地址
+  producer:
+    group: course-finish-group
+    access-key: ak1vjak37reb7b19a2b09d1 # 替换为实际的 accessKey
+    secret-key: sk3987beb638e3414f # 替换为实际的 secretKey
+  consumer:
+    group: test-group
+    access-key: ak1vjak37reb7b19a2b09d1 # 替换为实际的 accessKey
+    secret-key: sk3987beb638e3414f # 替换为实际的 secretKey
+openIM:
+  secret: openIM123
+  userID: imAdmin
+  url:
+#是否使用新im
+im:
+  type: NONE
+#是否为新商户,新商户不走mpOpenId
+isNewWxMerchant: true
+
+enableRedPackAccount: 0

+ 73 - 0
fs-service/src/main/resources/application-druid-jnmy-test.yml

@@ -138,6 +138,79 @@ spring:
                     wall:
                         config:
                             multi-statement-allow: true
+    shardingsphere:
+        datasource:
+            names: ds0
+            ds0:
+                # 主库数据源
+                type: com.alibaba.druid.pool.DruidDataSource
+                driverClassName: com.mysql.cj.jdbc.Driver
+                url: jdbc:mysql://120.46.174.121:2345/fs_his_test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                username: root
+                password: Ylrztek250218!3@.
+                # 初始连接数
+                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
+        rules:
+            sharding:
+                tables:
+                    qw_msg:
+                        actual-data-nodes: ds0.qw_msg_$->{0..9}
+                        table-strategy:
+                            standard:
+                                sharding-column: session_id
+                                sharding-algorithm-name: msg-inline
+                    fs_user_operation_log:
+                        actual-data-nodes: ds0.fs_user_operation_log_$->{0..9}
+                        table-strategy:
+                            standard:
+                                sharding-column: user_id
+                                sharding-algorithm-name: oper-inline
+                sharding-algorithms:
+                    msg-inline:
+                        type: INLINE
+                        props:
+                            algorithm-expression: qw_msg_$->{session_id % 10}
+                    oper-inline:
+                        type: INLINE
+                        props:
+                            algorithm-expression: fs_user_operation_log_$->{user_id % 10}
 rocketmq:
     name-server: rmq-1243b25nj.rocketmq.gz.public.tencenttdmq.com:8080 # RocketMQ NameServer 地址
     producer:

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

@@ -160,8 +160,5 @@ im:
     type: OPENIM
 #是否为新商户,新商户不走mpOpenId
 isNewWxMerchant: true
-ipad:
-    url: https://manwatch.ylrzcloud.com/prod-api
-    companyId: 13
 
 

+ 4 - 0
fs-service/src/main/resources/application-druid-kyt.yml

@@ -153,3 +153,7 @@ im:
 isNewWxMerchant: true
 
 enableRedPackAccount: 0
+
+ipad:
+  url: https://manwatch.ylrzcloud.com/prod-api
+  companyId: 99999

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

@@ -134,8 +134,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         b.nick_name fsUserName,
         c.dict_label projectName,
         e.course_name,
-        IF(g.company_user_id = #{userId}, g.qw_user_name, '其他') qwUserName,
---         g.qw_user_name,
+        g.qw_user_name,
         f.title videoName,
         qc.corp_name
         from

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

@@ -239,7 +239,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 AND DATE(create_date) <![CDATA[ <= ]]> #{endTime}
             </if>
         </where>
-
+        group by company_id,DATE(create_date)
         <!-- 排序:合计行放最后 -->
         ORDER BY create_time DESC
     </select>

+ 76 - 0
fs-service/src/main/resources/mapper/his/FsIntegralOrderLogsMapper.xml

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.his.mapper.FsIntegralOrderLogsMapper">
+
+    <resultMap type="FsIntegralOrderLogs" id="FsIntegralOrderLogsResult">
+        <result property="logsId"    column="logs_id"    />
+        <result property="orderId"    column="order_id"    />
+        <result property="changeType"    column="change_type"    />
+        <result property="changeMessage"    column="change_message"    />
+        <result property="changeTime"    column="change_time"    />
+        <result property="operator"    column="operator"    />
+    </resultMap>
+
+    <sql id="selectFsIntegralOrderLogsVo">
+        select logs_id, order_id, change_type, change_message, change_time, operator from fs_integral_order_logs
+    </sql>
+
+    <select id="selectFsIntegralOrderLogsList" parameterType="FsIntegralOrderLogs" resultMap="FsIntegralOrderLogsResult">
+        <include refid="selectFsIntegralOrderLogsVo"/>
+        <where>
+            <if test="orderId != null  and orderId != ''"> and order_id = #{orderId}</if>
+            <if test="changeType != null  and changeType != ''"> and change_type = #{changeType}</if>
+            <if test="changeMessage != null  and changeMessage != ''"> and change_message = #{changeMessage}</if>
+            <if test="changeTime != null "> and change_time = #{changeTime}</if>
+            <if test="operator != null  and operator != ''"> and operator = #{operator}</if>
+        </where>
+    </select>
+
+    <select id="selectFsIntegralOrderLogsByLogsId" parameterType="String" resultMap="FsIntegralOrderLogsResult">
+        <include refid="selectFsIntegralOrderLogsVo"/>
+        where logs_id = #{logsId}
+    </select>
+
+    <insert id="insertFsIntegralOrderLogs" parameterType="FsIntegralOrderLogs" useGeneratedKeys="true" keyProperty="logsId">
+        insert into fs_integral_order_logs
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="orderId != null and orderId != ''">order_id,</if>
+            <if test="changeType != null and changeType != ''">change_type,</if>
+            <if test="changeMessage != null and changeMessage != ''">change_message,</if>
+            <if test="changeTime != null">change_time,</if>
+            <if test="operator != null">operator,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="orderId != null and orderId != ''">#{orderId},</if>
+            <if test="changeType != null and changeType != ''">#{changeType},</if>
+            <if test="changeMessage != null and changeMessage != ''">#{changeMessage},</if>
+            <if test="changeTime != null">#{changeTime},</if>
+            <if test="operator != null">#{operator},</if>
+        </trim>
+    </insert>
+
+    <update id="updateFsIntegralOrderLogs" parameterType="FsIntegralOrderLogs">
+        update fs_integral_order_logs
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="orderId != null and orderId != ''">order_id = #{orderId},</if>
+            <if test="changeType != null and changeType != ''">change_type = #{changeType},</if>
+            <if test="changeMessage != null and changeMessage != ''">change_message = #{changeMessage},</if>
+            <if test="changeTime != null">change_time = #{changeTime},</if>
+            <if test="operator != null">operator = #{operator},</if>
+        </trim>
+        where logs_id = #{logsId}
+    </update>
+
+    <delete id="deleteFsIntegralOrderLogsByLogsId" parameterType="String">
+        delete from fs_integral_order_logs where logs_id = #{logsId}
+    </delete>
+
+    <delete id="deleteFsIntegralOrderLogsByLogsIds" parameterType="String">
+        delete from fs_integral_order_logs where logs_id in
+        <foreach item="logsId" collection="array" open="(" separator="," close=")">
+            #{logsId}
+        </foreach>
+    </delete>
+</mapper>

+ 8 - 6
fs-service/src/main/resources/mapper/his/FsUserInformationCollectionMapper.xml

@@ -108,6 +108,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.packageOrderCode != null  and maps.packageOrderCode != ''"> and fui.package_order_code = #{maps.packageOrderCode}</if>
         </where>
     </select>
+    <select id="selectFsUserInformationCollectionByOrderCode"
+            resultType="com.fs.his.domain.FsUserInformationCollection">
+        <include refid="selectFsUserInformationCollectionVo"/>
+        where package_order_code = #{orderCode}
+    </select>
 
     <insert id="insertFsUserInformationCollection" parameterType="FsUserInformationCollection" useGeneratedKeys="true" keyProperty="id">
         insert into fs_user_information_collection
@@ -171,12 +176,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="allergy != null">#{allergy},</if>
             <if test="remark != null">#{remark},</if>
             <if test="patientId != null">#{patientId},</if>
-            <if test="patientId != null">#{patientId},</if>
-            <if test="patientId != null">#{patientId},</if>
-            <if test="patientId != null">#{patientId},</if>
-            <if test="doctorType2Id != null">doctorType2Id,</if>
-            <if test="doctorType2Confirm != null">doctorType2Confirm,</if>
-            <if test="doctorType2Sign != null">doctorType2Sign,</if>
+            <if test="doctorType2Id != null">#{doctorType2Id},</if>
+            <if test="doctorType2Confirm != null">#{doctorType2Confirm},</if>
+            <if test="doctorType2Sign != null">#{doctorType2Sign},</if>
          </trim>
     </insert>
 

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

@@ -48,11 +48,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="courseMaOpenId"    column="course_ma_open_id"    />
         <result property="qwExtId"    column="qw_ext_id"    />
         <result property="qwUserId"    column="qw_user_id"    />
+        <result property="appId"    column="app_id"    />
         <result property="level" column="level"/>
     </resultMap>
 
     <sql id="selectFsUserVo">
-        select user_id,qw_ext_id,sex,is_buy,`level`,course_ma_open_id,is_push,is_add_qw,source,login_device,is_individuation_push,store_open_id,password,jpush_id, is_vip,vip_start_date,vip_end_date,vip_level,vip_status,nick_name,integral_status, avatar, phone, integral,sign_num, status, tui_user_id, tui_time, tui_user_count, ma_open_id, mp_open_id, union_id, is_del, user_code, remark, create_time, update_time, last_ip, balance,is_weixin_auth,parent_id,qw_user_id,company_id,company_user_id,is_promoter,now_money,brokerage_price,spread_user_id, spread_time,pay_count, spread_count,user_type from fs_user
+        select user_id,qw_ext_id,sex,is_buy,`level`,course_ma_open_id,is_push,is_add_qw,source,login_device,is_individuation_push,store_open_id,password,jpush_id, is_vip,vip_start_date,vip_end_date,vip_level,vip_status,nick_name,integral_status, avatar, phone, integral,sign_num, status, tui_user_id, tui_time, tui_user_count, ma_open_id, mp_open_id, union_id, is_del, user_code, remark, create_time, update_time, last_ip, balance,is_weixin_auth,parent_id,qw_user_id,app_id,company_id,company_user_id,is_promoter,now_money,brokerage_price,spread_user_id, spread_time,pay_count, spread_count,user_type from fs_user
     </sql>
 
     <select id="selectFsUserList" parameterType="FsUser" resultMap="FsUserResult">
@@ -583,6 +584,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isPromoter != null">is_promoter,</if>
             <if test="payCount != null">pay_count,</if>
             <if test="spreadCount != null">spread_count,</if>
+            <if test="appId != null">app_id,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="nickName != null">#{nickName},</if>
@@ -632,6 +634,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isPromoter != null">#{isPromoter},</if>
             <if test="payCount != null">#{payCount},</if>
             <if test="spreadCount != null">#{spreadCount},</if>
+            <if test="appId != null">#{appId},</if>
          </trim>
     </insert>
 
@@ -683,6 +686,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="companyId != null">company_id = #{companyId},</if>
             <if test="orderCount != null">order_count = #{orderCount},</if>
             <if test="companyUserId != null">company_user_id = #{companyUserId},</if>
+            <if test="appId != null">app_id = #{appId},</if>
         </trim>
         where user_id = #{userId}
     </update>

+ 7 - 5
fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml

@@ -1572,9 +1572,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         ${maps.params.dataScope} GROUP BY sp.product_id
         ) AS t
     </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
+        , csc.name miniProgramName,fsp.cost as cost, fspc.cate_name,spavs.bar_code
         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
@@ -1583,10 +1584,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             LEFT JOIN fs_store_order_df df on df.order_id=o.id
 
         </if>
-        <if test = "maps.productName != null and  maps.productName !=  '' ">
-            left join fs_store_order_item_scrm oi on o.id = oi.order_id
-            left join fs_store_product_scrm fsp on fsp.product_id = oi.product_id
-        </if>
+        left join fs_store_order_item_scrm oi on o.id = oi.order_id
+        left join fs_store_product_scrm fsp on fsp.product_id = oi.product_id
+        left join fs_store_product_category_scrm fspc on fspc.cate_id = fsp.cate_id
+        left join fs_store_product_attr_value_scrm spavs on fsp.product_id = spavs.product_id
+
         LEFT JOIN (
         SELECT
         sp.*,

+ 5 - 1
fs-service/src/main/resources/mapper/hisStore/FsUserScrmMapper.xml

@@ -71,10 +71,11 @@
         <result property="react"    column="react"    />
         <result property="orderCount"    column="order_count"    />
         <result property="bindCompanyUserId"    column="bind_company_user_id"    />
+        <result property="appId"    column="app_id"    />
     </resultMap>
 
     <sql id="selectFsUserVo">
-        select user_id, username, nick_name, avatar, phone, integral, status, `level`, spread_user_id, spread_time, user_type, is_promoter, pay_count, spread_count, addres, tui_user_id, tui_time, tui_user_count, ma_open_id, mp_open_id, union_id, is_del, user_code, remark, nickname, create_time, update_time, last_ip, now_money, brokerage_price, balance, sign_num, integral_status, is_buy, password, real_name, birthday, id_card, jpush_id, is_vip, vip_start_date, vip_end_date, vip_level, vip_status, sex, store_open_id, is_official_account_auth, is_push, is_individuation_push, is_weixin_auth, company_id, company_user_id, register_date, register_code, test, login_device, source, is_add_qw, qw_user_id, is_show, parent_id, course_ma_open_id, history_app, qw_ext_id, `rank`, react,order_count,bind_company_user_id from fs_user
+        select user_id, username, nick_name, avatar, phone, integral, status, `level`, spread_user_id, spread_time, user_type, is_promoter, pay_count, spread_count, addres, tui_user_id, tui_time, tui_user_count, ma_open_id, mp_open_id, union_id, is_del, user_code, remark, nickname, create_time, update_time, last_ip, now_money, brokerage_price, balance, sign_num, integral_status, is_buy, password, real_name, birthday, id_card, jpush_id, is_vip, vip_start_date, vip_end_date, vip_level, vip_status, sex, store_open_id, is_official_account_auth, is_push, is_individuation_push, is_weixin_auth, company_id, company_user_id, register_date, register_code, test, login_device, source, is_add_qw, qw_user_id, is_show, parent_id, course_ma_open_id, history_app, qw_ext_id, `rank`, react,order_count,bind_company_user_id,app_id from fs_user
     </sql>
 
     <select id="selectFsUserList" parameterType="FsUserScrm" resultMap="FsUserResult">
@@ -447,6 +448,7 @@
             <if test="rank != null">rank,</if>
             <if test="react != null">react,</if>
             <if test="orderCount != null">order_count,</if>
+            <if test="appId != null">app_id,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="username != null">#{username},</if>
@@ -513,6 +515,7 @@
             <if test="rank != null">#{rank},</if>
             <if test="react != null">#{react},</if>
             <if test="orderCount != null">#{orderCount},</if>
+            <if test="appId != null">#{appId},</if>
         </trim>
     </insert>
 
@@ -564,6 +567,7 @@
             <if test="isPromoter != null">is_promoter = #{isPromoter},</if>
             <if test="spreadUserId != null">spread_user_id = #{spreadUserId},</if>
             <if test="brokeragePrice != null">brokerage_price = #{brokeragePrice},</if>
+            <if test="appId != null">app_id = #{appId},</if>
         </trim>
         where user_id = #{userId}
     </update>

+ 9 - 1
fs-service/src/main/resources/mapper/live/LiveOrderMapper.xml

@@ -950,6 +950,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             o.pay_time,
             o.pay_type,
             o.pay_money,
+            o.pay_delivery,
             o.create_time,
             o.update_time,
             o.status,
@@ -997,7 +998,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
             <!-- 门店信息 -->
             s.store_name AS storeName,
-            s.store_id AS storeId
+            s.store_id AS storeId,
+
+            <!-- 门店信息 -->
+            spavs.bar_code,
+            spcs.cate_name
 
         FROM
             live_order o
@@ -1005,6 +1010,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             LEFT JOIN company_user cu ON o.company_user_id = cu.user_id
             LEFT JOIN fs_store_product_scrm p ON o.product_id = p.product_id
             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
+
         <where>
             o.is_del = 0
             <if test="orderId != null">

+ 78 - 0
fs-service/src/main/resources/mapper/qw/QwApiSopLogTokenMapper.xml

@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.qw.mapper.QwApiSopLogTokenMapper">
+
+    <resultMap type="QwApiSopLogToken" id="QwApiSopLogTokenResult">
+        <result property="id"    column="id"    />
+        <result property="qwUserId"    column="qw_user_id"    />
+        <result property="companyId"    column="company_id"    />
+        <result property="sendTime"    column="send_time"    />
+        <result property="sendCount"    column="send_count"    />
+        <result property="sendCountToken"    column="send_count_token"    />
+    </resultMap>
+
+    <sql id="selectQwApiSopLogTokenVo">
+        select id, qw_user_id, company_id, send_time, send_count, send_count_token from qw_api_sop_log_token
+    </sql>
+
+    <select id="selectQwApiSopLogTokenList" parameterType="QwApiSopLogToken" resultMap="QwApiSopLogTokenResult">
+        <include refid="selectQwApiSopLogTokenVo"/>
+        <where>
+            <if test="qwUserId != null  and qwUserId != ''"> and qw_user_id = #{qwUserId}</if>
+            <if test="companyId != null "> and company_id = #{companyId}</if>
+            <if test="sendTime != null "> and send_time = #{sendTime}</if>
+            <if test="sendCount != null "> and send_count = #{sendCount}</if>
+            <if test="sendCountToken != null "> and send_count_token = #{sendCountToken}</if>
+        </where>
+    </select>
+
+    <select id="selectQwApiSopLogTokenById" parameterType="Long" resultMap="QwApiSopLogTokenResult">
+        <include refid="selectQwApiSopLogTokenVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertQwApiSopLogToken" parameterType="QwApiSopLogToken">
+        insert into qw_api_sop_log_token
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="qwUserId != null">qw_user_id,</if>
+            <if test="companyId != null">company_id,</if>
+            <if test="sendTime != null">send_time,</if>
+            <if test="sendCount != null">send_count,</if>
+            <if test="sendCountToken != null">send_count_token,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="qwUserId != null">#{qwUserId},</if>
+            <if test="companyId != null">#{companyId},</if>
+            <if test="sendTime != null">#{sendTime},</if>
+            <if test="sendCount != null">#{sendCount},</if>
+            <if test="sendCountToken != null">#{sendCountToken},</if>
+         </trim>
+    </insert>
+
+    <update id="updateQwApiSopLogToken" parameterType="QwApiSopLogToken">
+        update qw_api_sop_log_token
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="qwUserId != null">qw_user_id = #{qwUserId},</if>
+            <if test="companyId != null">company_id = #{companyId},</if>
+            <if test="sendTime != null">send_time = #{sendTime},</if>
+            <if test="sendCount != null">send_count = #{sendCount},</if>
+            <if test="sendCountToken != null">send_count_token = #{sendCountToken},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteQwApiSopLogTokenById" parameterType="Long">
+        delete from qw_api_sop_log_token where id = #{id}
+    </delete>
+
+    <delete id="deleteQwApiSopLogTokenByIds" parameterType="String">
+        delete from qw_api_sop_log_token where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>

+ 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>

+ 116 - 0
fs-user-app/src/main/java/com/fs/app/controller/AppLoginController.java

@@ -120,6 +120,81 @@ public class AppLoginController extends AppBaseController{
         }
     }
 
+    @PostMapping("/registerSendCode")
+    public R registerSendCode(@RequestBody Map<String, String> body){
+        String phone = body.get("phone");
+        String encryptPhone = encryptPhone(phone);
+        List<FsUser> user = userService.selectFsUserListByPhone(encryptPhone);
+        if(CollectionUtil.isEmpty(user)){
+            user = userService.selectFsUserListByPhone(encryptPhoneOldKey(phone));
+        }
+        if (!CollectionUtil.isEmpty(user)){
+            return R.error("此电话号码已注册");
+        }
+
+        // 验证码 key(存验证码,3分钟有效)
+        String smsCodeKey = "sms:code:" + phone;
+        // 发送冷却 key(限制60秒内不能再次发送)
+        String smsCooldownKey = "sms:cooldown:" + phone;
+
+        // 判断是否在60秒冷却时间内
+        if (redisCache.getCacheObject(smsCooldownKey) != null) {
+            return R.error("验证码已发送,请稍后再试");
+        }
+
+        // 生成新的验证码
+        String smsCode = VerifyCodeUtil.generateCode();
+
+        // 发送短信
+        smsService.sendCaptcha(phone, smsCode, "验证码");
+
+        // 缓存验证码(3分钟有效)
+        redisCache.setCacheObject(smsCodeKey, smsCode, 180, TimeUnit.SECONDS);
+        // 设置冷却时间(60秒内不能再发)
+        redisCache.setCacheObject(smsCooldownKey, "1", 60, TimeUnit.SECONDS);
+
+        return R.ok("验证码已发送");
+    }
+
+
+    @PostMapping("/registerByPhone")
+    public R registerByPhone(@RequestBody Map<String,String> map){
+        String phone = map.get("phone");
+        String code = map.get("code");
+        String password = map.get("password");
+        String encryptPhone = encryptPhone(phone);
+        List<FsUser> users = userService.selectFsUserListByPhone(encryptPhone);
+        if (users == null || CollectionUtil.isEmpty(users)){
+            String s = encryptPhoneOldKey(phone);
+            users = userService.selectFsUserListByPhone(s);
+        }
+        if (!CollectionUtil.isEmpty(users)){
+            return R.error("此账号已经注册");
+        }
+        String redisCode = redisCache.getCacheObject("sms:code:" + phone);
+        if (StringUtils.isEmpty(redisCode)){
+            return R.error("验证码已过期,请重新发送");
+        }
+        if (!redisCode.equals(code)) {
+            return R.error("验证码错误");
+        }
+        FsUser user = new FsUser();
+        // 创建新用户
+        user.setPhone(phone);
+        user.setJpushId(map.get("jpushId"));
+        user.setSource(map.get("source"));
+        user.setNickName("app用户" + phone.substring(phone.length() - 4));
+        user.setStatus(1);
+        user.setAvatar("https://cos.his.cdwjyyh.com/fs/20240926/420728ee06e54575ba82665dedb4756b.png");
+        user.setPassword(Md5Utils.hash(password));
+        user.setCreateTime(new Date());
+        if (userService.insertFsUser(user) > 0) {
+            return R.ok("注册成功");
+        } else {
+            return R.error("注册失败");
+        }
+    }
+
 
 
 
@@ -181,6 +256,8 @@ public class AppLoginController extends AppBaseController{
                     user.setSex(sex);
                 }
                 user.setUnionId(unionid);
+                // 新用户 - 添加 appId
+                user.setAppId(openProperties.getAppId());
                 user.setCreateTime(new Date());
                 user.setStatus(1);
                 if (StringUtils.isNotEmpty(param.getJpushId())) {
@@ -191,6 +268,15 @@ public class AppLoginController extends AppBaseController{
                 map.put("unionid",unionid);
                 return R.ok(map);
             } else {
+                // 老用户 - 检查并添加appId(不重复添加)
+                String updatedAppId = addAppIdIfNotExists(user.getAppId(), openProperties.getAppId());
+                if (!updatedAppId.equals(user.getAppId())) {
+                    FsUser userMap = new FsUser();
+                    userMap.setUserId(user.getUserId());
+                    userMap.setAppId(updatedAppId);
+                    userService.updateFsUser(userMap);
+                }
+                
                 if (StringUtils.isNotEmpty(param.getJpushId())) {
                     updateExistingUserJpushId(user, param.getJpushId());
                 }
@@ -546,4 +632,34 @@ public class AppLoginController extends AppBaseController{
             return R.error("用户不存在!");
         }
     }
+
+    /**
+     * 添加appId到用户的appId列表中(如果不存在)
+     * @param currentAppIds 当前用户已有的appId列表(逗号分隔)
+     * @param newAppId 新的appId
+     * @return 更新后的appId列表
+     */
+    private String addAppIdIfNotExists(String currentAppIds, String newAppId) {
+        // 如果新appId为空,返回原值
+        if (StringUtils.isEmpty(newAppId)) {
+            return currentAppIds == null ? "" : currentAppIds;
+        }
+        
+        // 如果当前appId为空,直接返回新appId
+        if (StringUtils.isEmpty(currentAppIds)) {
+            return newAppId;
+        }
+        
+        // 检查是否已存在
+        String[] appIdArray = currentAppIds.split(",");
+        for (String appId : appIdArray) {
+            if (appId.trim().equals(newAppId.trim())) {
+                // 已存在,不需要添加
+                return currentAppIds;
+            }
+        }
+        
+        // 不存在,追加到末尾
+        return currentAppIds + "," + newAppId;
+    }
 }

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio