Bladeren bron

fix:订单导出按照需求用户选则几个属性列表就导出几个属性列表

GHH 13 uur geleden
bovenliggende
commit
83744e5359
100 gewijzigde bestanden met toevoegingen van 3384 en 351 verwijderingen
  1. 1 0
      DirectoryV3.xml
  2. 682 36
      fs-admin/src/main/java/com/fs/api/controller/IndexStatisticsController.java
  3. 41 1
      fs-admin/src/main/java/com/fs/company/controller/CompanyController.java
  4. 103 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyTrafficController.java
  5. 49 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyTrafficLogController.java
  6. 41 3
      fs-admin/src/main/java/com/fs/course/controller/FsCoursePlaySourceConfigController.java
  7. 5 5
      fs-admin/src/main/java/com/fs/course/controller/FsCourseRedPacketLogController.java
  8. 1 2
      fs-admin/src/main/java/com/fs/fastGpt/FastgptExtUserTagController.java
  9. 25 3
      fs-admin/src/main/java/com/fs/his/controller/FsCompanyController.java
  10. 12 12
      fs-admin/src/main/java/com/fs/his/controller/FsHisComplaintController.java
  11. 19 0
      fs-admin/src/main/java/com/fs/his/controller/FsPatientController.java
  12. 11 6
      fs-admin/src/main/java/com/fs/his/controller/FsStoreOrderController.java
  13. 24 0
      fs-admin/src/main/java/com/fs/hisStore/FsHisStoreLogController.java
  14. 134 0
      fs-admin/src/main/java/com/fs/hisStore/FsStoreSCRMController.java
  15. 74 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreHealthOrderScrmController.java
  16. 83 0
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java
  17. 14 2
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductScrmController.java
  18. 108 0
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreRecommendScrmController.java
  19. 20 3
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreScrmController.java
  20. 11 1
      fs-admin/src/main/java/com/fs/hisStore/controller/SysOperlogScrmController.java
  21. 33 1
      fs-admin/src/main/java/com/fs/qw/controller/QwCompanyController.java
  22. 39 0
      fs-admin/src/main/java/com/fs/task/FsStoreTask.java
  23. 106 0
      fs-admin/src/main/java/com/fs/user/controller/FsUserComplaintController.java
  24. 109 0
      fs-admin/src/main/java/com/fs/user/controller/FsUserComplaintMsgController.java
  25. 14 0
      fs-admin/src/main/java/com/fs/web/controller/system/SysLoginController.java
  26. 18 40
      fs-common-api/src/main/java/com/fs/framework/config/MyBatisConfig.java
  27. 2 2
      fs-common-api/src/main/resources/application.yml
  28. 6 2
      fs-common/src/main/java/com/fs/common/core/domain/model/LoginUser.java
  29. 9 5
      fs-common/src/main/java/com/fs/common/core/redis/RedisCache.java
  30. 7 2
      fs-common/src/main/java/com/fs/common/enums/BusinessType.java
  31. 140 0
      fs-common/src/main/java/com/fs/common/utils/poi/ExcelUtil.java
  32. 1 1
      fs-company/src/main/java/com/fs/company/controller/company/CompanyController.java
  33. 3 2
      fs-company/src/main/java/com/fs/company/controller/course/FsCourseAnswerLogsController.java
  34. 3 2
      fs-company/src/main/java/com/fs/company/controller/course/FsCourseRedPacketLogController.java
  35. 1 1
      fs-company/src/main/java/com/fs/company/controller/course/FsUserCourseTrainingCampController.java
  36. 1 1
      fs-company/src/main/java/com/fs/company/controller/course/FsUserOperationLogController.java
  37. 11 0
      fs-company/src/main/java/com/fs/company/controller/qw/QwSopController.java
  38. 3 1
      fs-company/src/main/java/com/fs/company/controller/qw/QwSopLogsController.java
  39. 2 2
      fs-company/src/main/java/com/fs/company/controller/qw/SopUserLogsController.java
  40. 2 2
      fs-company/src/main/java/com/fs/company/controller/store/FsStoreOrderController.java
  41. 2 2
      fs-company/src/main/resources/application.yml
  42. 1 14
      fs-doctor-app/src/main/java/com/fs/app/controller/InquiryOrderController.java
  43. 25 2
      fs-framework/src/main/java/com/fs/framework/aspectj/LogAspect.java
  44. 7 1
      fs-framework/src/main/java/com/fs/framework/manager/factory/AsyncFactory.java
  45. 26 6
      fs-ipad-task/src/main/java/com/fs/app/service/IpadSendServer.java
  46. 2 2
      fs-ipad-task/src/main/java/com/fs/app/task/SendMsg.java
  47. 38 37
      fs-qw-api-msg/src/main/java/com/fs/app/controller/QwMsgController.java
  48. 21 0
      fs-qw-api-msg/src/main/java/com/fs/framework/config/RedisConfig.java
  49. 16 9
      fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java
  50. 36 44
      fs-qwhook-sop/src/main/java/com/fs/framework/config/MyBatisConfig.java
  51. 59 0
      fs-service/src/main/java/com/fs/aiChat/domain/InterestAiChatMsg.java
  52. 73 0
      fs-service/src/main/java/com/fs/aiChat/domain/InterestAiSession.java
  53. 54 0
      fs-service/src/main/java/com/fs/aiChat/domain/SessionRoleInfo.java
  54. 59 0
      fs-service/src/main/java/com/fs/aiChat/mapper/InterestAiChatSessionMapper.java
  55. 15 0
      fs-service/src/main/java/com/fs/aiChat/param/InterestAiMessage.java
  56. 5 0
      fs-service/src/main/java/com/fs/company/constant/CompanyTrafficConstants.java
  57. 4 0
      fs-service/src/main/java/com/fs/company/domain/Company.java
  58. 41 0
      fs-service/src/main/java/com/fs/company/domain/CompanyTrafficRecord.java
  59. 45 0
      fs-service/src/main/java/com/fs/company/domain/CompanyTrafficRecordLog.java
  60. 12 6
      fs-service/src/main/java/com/fs/company/mapper/CompanyMapper.java
  61. 10 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyTrafficRecordLogMapper.java
  62. 28 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyTrafficRecordMapper.java
  63. 3 32
      fs-service/src/main/java/com/fs/company/param/CompanyParam.java
  64. 23 0
      fs-service/src/main/java/com/fs/company/param/CompanyTrafficRecordChargeParam.java
  65. 21 0
      fs-service/src/main/java/com/fs/company/param/CompanyTrafficRecordLogQueryParam.java
  66. 17 0
      fs-service/src/main/java/com/fs/company/param/CompanyTrafficRecordQueryParam.java
  67. 1 1
      fs-service/src/main/java/com/fs/company/service/ICompanyService.java
  68. 16 0
      fs-service/src/main/java/com/fs/company/service/ICompanyTrafficRecordLogService.java
  69. 25 0
      fs-service/src/main/java/com/fs/company/service/ICompanyTrafficRecordService.java
  70. 2 0
      fs-service/src/main/java/com/fs/company/service/ICompanyUserService.java
  71. 2 2
      fs-service/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java
  72. 40 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyTrafficRecordLogServiceImpl.java
  73. 272 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyTrafficRecordServiceImpl.java
  74. 35 1
      fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java
  75. 4 0
      fs-service/src/main/java/com/fs/company/vo/CompanyVO.java
  76. 13 5
      fs-service/src/main/java/com/fs/core/config/WxMaConfiguration.java
  77. 10 9
      fs-service/src/main/java/com/fs/core/utils/OrderCodeUtils.java
  78. 5 0
      fs-service/src/main/java/com/fs/course/config/CourseConfig.java
  79. 9 0
      fs-service/src/main/java/com/fs/course/domain/FsCoursePlaySourceConfig.java
  80. 35 5
      fs-service/src/main/java/com/fs/course/dto/FsOrderDeliveryNoteDTO.java
  81. 6 0
      fs-service/src/main/java/com/fs/course/mapper/FsCourseTrafficLogMapper.java
  82. 1 1
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseCategoryMapper.java
  83. 1 1
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseMapper.java
  84. 7 1
      fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigCreateParam.java
  85. 6 0
      fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigEditParam.java
  86. 9 5
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseLinkServiceImpl.java
  87. 3 3
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseQuestionBankServiceImpl.java
  88. 2 0
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseTrafficLogServiceImpl.java
  89. 2 0
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java
  90. 191 14
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  91. 9 1
      fs-service/src/main/java/com/fs/course/vo/FsCoursePlaySourceConfigVO.java
  92. 6 6
      fs-service/src/main/java/com/fs/erp/http/JstErpHttpServiceImpl.java
  93. 3 0
      fs-service/src/main/java/com/fs/erp/service/IErpOrderService.java
  94. 5 0
      fs-service/src/main/java/com/fs/erp/service/impl/DfOrderServiceImpl.java
  95. 5 0
      fs-service/src/main/java/com/fs/erp/service/impl/ErpOrderServiceImpl.java
  96. 5 0
      fs-service/src/main/java/com/fs/erp/service/impl/HzOMSErpOrderServiceImpl.java
  97. 30 1
      fs-service/src/main/java/com/fs/erp/service/impl/JSTErpOrderServiceImpl.java
  98. 5 0
      fs-service/src/main/java/com/fs/erp/service/impl/K9OrderScrmServiceImpl.java
  99. 5 0
      fs-service/src/main/java/com/fs/erp/service/impl/WdtErpOrderServiceImpl.java
  100. 3 1
      fs-service/src/main/java/com/fs/his/domain/FsHisComplaint.java

+ 1 - 0
DirectoryV3.xml

@@ -5,4 +5,5 @@
      <tree path="/fs-admin/src/main/java/com/fs/company/controller" title="公司"/>
      <tree path="/fs-admin/src/main/java/com/fs/live/controller" title="直播"/>
      <tree path="/fs-admin/src/main/java/com/fs/qw" title="企微"/>
+     <tree path="/fs-ad-api" title="广告回传"/>
  </trees>

+ 682 - 36
fs-admin/src/main/java/com/fs/api/controller/IndexStatisticsController.java

@@ -1,16 +1,32 @@
 package com.fs.api.controller;
 
 import com.fs.common.core.domain.R;
+import com.fs.common.core.domain.entity.SysDept;
 import com.fs.common.core.redis.RedisCache;
+import com.fs.company.constant.CompanyTrafficConstants;
+import com.fs.company.domain.Company;
+import com.fs.company.service.ICompanyService;
+import com.fs.company.service.ICompanyTrafficRecordService;
+import com.fs.company.service.impl.CompanyTrafficRecordServiceImpl;
+import com.fs.his.utils.ConfigUtil;
+import com.fs.hisStore.config.MedicalMallConfig;
 import com.fs.statis.StatisticsRedisConstant;
 import com.fs.statis.dto.*;
+import com.fs.statis.param.StatisticsDeptCompanyParam;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.service.ISysConfigService;
+import com.fs.system.service.ISysDeptService;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.YearMonth;
+import java.util.*;
+import java.util.function.BinaryOperator;
+import java.util.stream.Collectors;
 
 import static com.fs.statis.StatisticsRedisConstant.*;
 
@@ -19,18 +35,31 @@ import static com.fs.statis.StatisticsRedisConstant.*;
  */
 @RestController
 @RequestMapping("/index/statistics")
+@Slf4j
 public class IndexStatisticsController {
     @Autowired
     private RedisCache redisCache;
 
     @Autowired
     private ISysConfigService sysConfigService;
+
+    @Autowired
+    private ConfigUtil configUtil;
+
+    @Autowired
+    private ISysDeptService deptService;
+
+    @Autowired
+    private ICompanyService companyService;
+
+    @Autowired
+    private MedicalMallConfig medicalMallConfig;
     /**
      * 分析概览
      */
     @PostMapping("/analysisPreview")
     public R analysisPreview(@RequestBody AnalysisPreviewQueryDTO param){
-        AnalysisPreviewDTO analysisPreviewDTO = null;
+        AnalysisPreviewDTO analysisPreviewDTO = new AnalysisPreviewDTO();
         Integer type = param.getType();
         Integer userType = param.getUserType();
 
@@ -41,7 +70,69 @@ public class IndexStatisticsController {
         if(userType == null) {
             userType = 0;
         }
-        analysisPreviewDTO = redisCache.getCacheObject(String.format("%s:%d:%d",DATA_OVERVIEW_DEALER_ANALYSISPREVIEW,type,userType));
+        if(medicalMallConfig.isStatics()|| (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
+            analysisPreviewDTO = redisCache.getCacheObject(String.format("%s:%d:%d",DATA_OVERVIEW_DEALER_ANALYSISPREVIEW,type,userType));
+        }else if(param.getCompanyId() != null){
+            analysisPreviewDTO = redisCache.getCacheObject(String.format("%s:%d:%d:%d",DATA_OVERVIEW_DEALER_ANALYSISPREVIEW,type,userType,param.getCompanyId()));
+        }else{
+            Company company = new Company();
+            company.setDeptId(param.getDeptId());
+            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
+            for(Long companyId : companyIds){
+                AnalysisPreviewDTO clildDTO = redisCache.getCacheObject(String.format("%s:%d:%d:%d",DATA_OVERVIEW_DEALER_ANALYSISPREVIEW,type,userType,companyId));
+                if (clildDTO != null) {
+                    //将除了completedRate、correctRate和watchRate之外的数据相加,并计算completedRate、correctRate和watchRate
+                    analysisPreviewDTO.setWatchUserCount(
+                            analysisPreviewDTO.getWatchUserCount() == 0 ? 0 : analysisPreviewDTO.getWatchUserCount()
+                                +(clildDTO.getWatchUserCount() == 0 ? 0 : clildDTO.getWatchUserCount())
+                    );
+                    analysisPreviewDTO.setCompletedUserCount(
+                            analysisPreviewDTO.getCompletedUserCount() == 0 ? 0 : analysisPreviewDTO.getCompletedUserCount()
+                                +(clildDTO.getCompletedUserCount() == 0 ? 0 : clildDTO.getCompletedUserCount())
+                    );
+                    analysisPreviewDTO.setCompletedCount(
+                            analysisPreviewDTO.getCompletedCount() == 0 ? 0 : analysisPreviewDTO.getCompletedCount()
+                                +(clildDTO.getCompletedCount() == 0 ? 0 : clildDTO.getCompletedCount())
+                    );
+                    analysisPreviewDTO.setWatchCount(
+                            analysisPreviewDTO.getWatchCount() == 0 ? 0 : analysisPreviewDTO.getWatchCount()
+                                +(clildDTO.getWatchCount() == 0 ? 0 : clildDTO.getWatchCount())
+                    );
+                    analysisPreviewDTO.setAnswerMemberCount(
+                            analysisPreviewDTO.getAnswerMemberCount() == 0 ? 0 : analysisPreviewDTO.getAnswerMemberCount()
+                                +(clildDTO.getAnswerMemberCount() == 0 ? 0 : clildDTO.getAnswerMemberCount())
+                    );
+                    analysisPreviewDTO.setCorrectUserCount(
+                            analysisPreviewDTO.getCorrectUserCount() == 0 ? 0 : analysisPreviewDTO.getCorrectUserCount()
+                                +(clildDTO.getCorrectUserCount() == 0 ? 0 : clildDTO.getCorrectUserCount())
+                    );
+                    analysisPreviewDTO.setRewardCount(
+                            analysisPreviewDTO.getRewardCount() == 0 ? 0 : analysisPreviewDTO.getRewardCount()
+                                +(clildDTO.getRewardCount() == 0 ? 0 : clildDTO.getRewardCount())
+                    );
+                    analysisPreviewDTO.setRewardMoney(
+                            analysisPreviewDTO.getRewardMoney() == null ? BigDecimal.ZERO : analysisPreviewDTO.getRewardMoney()
+                                .add(clildDTO.getRewardMoney() == null ? BigDecimal.ZERO : clildDTO.getRewardMoney())
+                    );
+                }
+            }
+            if(analysisPreviewDTO.getAnswerMemberCount() != 0){
+                analysisPreviewDTO.setCorrectRate(
+                        analysisPreviewDTO.getCorrectUserCount() == 0 ? "0" : String.format("%.2f", analysisPreviewDTO.getCorrectUserCount() * 100.0 / analysisPreviewDTO.getAnswerMemberCount())
+                );
+            }
+            if(analysisPreviewDTO.getWatchUserCount() != 0){
+                analysisPreviewDTO.setCompletedRate(
+                        analysisPreviewDTO.getCompletedUserCount() == 0 ? "0" : String.format("%.2f", analysisPreviewDTO.getCompletedUserCount() * 100.0 / analysisPreviewDTO.getWatchUserCount())
+                );
+            }
+            if(analysisPreviewDTO.getWatchCount() != 0){
+                analysisPreviewDTO.setWatchRate(
+                        analysisPreviewDTO.getCompletedCount() == 0 ? "0" : String.format("%.2f", analysisPreviewDTO.getCompletedCount() * 100.0 / analysisPreviewDTO.getWatchCount())
+                );
+            }
+
+        }
 
         return R.ok().put("data",analysisPreviewDTO);
     }
@@ -51,8 +142,32 @@ public class IndexStatisticsController {
      * 消费余额
      */
     @GetMapping("/rechargeComsumption")
-    public R rechargeComsumption(){
-        ConsumptionBalanceDataDTO consumptionBalanceDataDTO = redisCache.getCacheObject(StatisticsRedisConstant.DATA_OVERVIEW_DEALER_BALANCE);
+    public R rechargeComsumption(StatisticsDeptCompanyParam param){
+        ConsumptionBalanceDataDTO consumptionBalanceDataDTO = new ConsumptionBalanceDataDTO();
+        if(medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)) {
+            consumptionBalanceDataDTO = redisCache.getCacheObject(StatisticsRedisConstant.DATA_OVERVIEW_DEALER_BALANCE);
+        }else if(param.getCompanyId() != null){
+            consumptionBalanceDataDTO = redisCache.getCacheObject(String.format("%s:%d",DATA_OVERVIEW_DEALER_BALANCE,param.getCompanyId()));
+        }else{
+            Company company = new Company();
+            company.setDeptId(param.getDeptId());
+            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
+            for(Long companyId : companyIds){
+                ConsumptionBalanceDataDTO clildDTO = redisCache.getCacheObject(String.format("%s:%d",DATA_OVERVIEW_DEALER_BALANCE,companyId));
+                consumptionBalanceDataDTO.setBalance(
+                    (consumptionBalanceDataDTO.getBalance() == null ? BigDecimal.ZERO : consumptionBalanceDataDTO.getBalance())
+                    .add(clildDTO.getBalance() == null ? BigDecimal.ZERO : clildDTO.getBalance())
+                );
+                consumptionBalanceDataDTO.setTodayComsumption(
+                    (consumptionBalanceDataDTO.getTodayComsumption() == null ? BigDecimal.ZERO : consumptionBalanceDataDTO.getTodayComsumption())
+                    .add(clildDTO.getTodayComsumption() == null ? BigDecimal.ZERO : clildDTO.getTodayComsumption())
+                );
+                consumptionBalanceDataDTO.setYesterdayComsumption(
+                    (consumptionBalanceDataDTO.getYesterdayComsumption() == null ? BigDecimal.ZERO : consumptionBalanceDataDTO.getYesterdayComsumption())
+                    .add(clildDTO.getYesterdayComsumption() == null ? BigDecimal.ZERO : clildDTO.getYesterdayComsumption())
+                );
+            }
+        }
 
         return R.ok().put("data", consumptionBalanceDataDTO);
     }
@@ -62,15 +177,58 @@ public class IndexStatisticsController {
      * @return
      */
     @GetMapping("/trafficLog")
-    public R getTrafficLog(){
-        TrafficLogDTO trafficLogDTO = redisCache.getCacheObject(DATA_OVERVIEW_TRAFFIC_LOG);
-        SysConfig sysConfig = sysConfigService.selectConfigByConfigKey("redPacket.Traffic.config");
-        if(trafficLogDTO == null || sysConfig == null) {
-            return null;
+    public R getTrafficLog(StatisticsDeptCompanyParam  param){
+        TrafficLogDTO result = new TrafficLogDTO();
+        if(!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)) {
+            result = redisCache.getCacheObject(DATA_OVERVIEW_TRAFFIC_LOG);
+            if (!medicalMallConfig.isStatics()) {
+                SysConfig sysConfig = sysConfigService.selectConfigByConfigKey("redPacket.Traffic.config");
+                if(result == null || sysConfig == null) {
+                    return null;
+                }
+                String configValue = sysConfig.getConfigValue();
+                result.setTraffic(configValue);
+            } else {
+                //所有部门流量之和
+                SysDept dept = new SysDept();
+                dept.setParentId(1L);
+                Long[] deptIds = deptService.selectDeptList(dept).stream().map(SysDept::getDeptId).toArray(Long[]::new);
+                long trafficTemp = 0L;
+                for(Long deptId : deptIds){
+                    Object clildTraffic = redisCache.getCacheObject(CompanyTrafficConstants.CACHE_KEY+":"+deptId);
+                    if(clildTraffic != null){
+                        trafficTemp += Long.parseLong(clildTraffic.toString());
+                    }
+                }
+                result.setTraffic(String.format("%.2f",trafficTemp * 1024.0));
+            }
+        }else if(param.getCompanyId() != null){
+            Company company = companyService.selectCompanyById(param.getCompanyId());
+            getTrafficLogResult(result,CompanyTrafficConstants.CACHE_KEY+":"+company.getDeptId()+":"+param.getCompanyId());
+        }else{
+            getTrafficLogResult(result,CompanyTrafficConstants.CACHE_KEY+":"+param.getDeptId());
         }
-        String configValue = sysConfig.getConfigValue();
-        trafficLogDTO.setTraffic(configValue);
-        return R.ok().put("data",trafficLogDTO);
+        return R.ok().put("data",result);
+    }
+
+    private void getTrafficLogResult(TrafficLogDTO result, String key){
+        //昨天
+        LocalDate yesterday = LocalDate.now().minusDays(1);
+        Object yesterdayCount = redisCache.getCacheObject(key+":"+yesterday);
+        Object todayCount = redisCache.getCacheObject(key+":"+LocalDate.now());
+        Object thisMonthCount = redisCache.getCacheObject(key+":"+YearMonth.now());
+        Object traffic = redisCache.getCacheObject(key);
+        result.setYesterday(parseRedisNumberValueToLong(yesterdayCount));
+        //今天
+        result.setToday(parseRedisNumberValueToLong(todayCount));
+        //本月
+        result.setThisMonth(parseRedisNumberValueToLong(thisMonthCount));
+        //剩余
+        result.setTraffic(traffic == null?"0":traffic.toString());
+    }
+
+    private Long parseRedisNumberValueToLong(Object value){
+        return value == null ? 0 : Long.parseLong(value.toString());
     }
 
     /**
@@ -87,9 +245,73 @@ public class IndexStatisticsController {
         if(userType == null){
             userType = 0;
         }
-        String key = String.format("%s:%d:%d", DATA_OVERVIEW_DEALER_CHARTS, type,userType);
-        List<DeaMemberTopTenDTO> deaMemberTopTenDTOS = redisCache.getCacheObject(key);
-        return R.ok().put("data", deaMemberTopTenDTOS);
+        List<WatchEndPlayTrendDTO> watchEndPlayTrendDTOS;
+        // 参考watchCourseTopTen方法的处理逻辑
+        if (!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
+            String key = String.format("%s:%d:%d", DATA_OVERVIEW_DEALER_CHARTS, type,userType);
+            watchEndPlayTrendDTOS = redisCache.getCacheObject(key);
+        }else if(param.getCompanyId() != null){
+            String key = String.format("%s:%d:%d:%d", DATA_OVERVIEW_DEALER_CHARTS, type,userType,param.getCompanyId());
+            watchEndPlayTrendDTOS = redisCache.getCacheObject(key);
+        }else{
+            Company company = new Company();
+            company.setDeptId(param.getDeptId());
+            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
+            List<WatchEndPlayTrendDTO> tempDTOS = new ArrayList<>();
+            for(Long companyId : companyIds){
+                String key = String.format("%s:%d:%d:%d", DATA_OVERVIEW_DEALER_CHARTS, type,userType,companyId);
+                List<WatchEndPlayTrendDTO> companyData = redisCache.getCacheObject(key);
+                if (companyData != null) {
+                    tempDTOS.addAll(companyData);
+                }
+            }
+            // 根据startDate 和 x 分组,合并watchUserCount和completedUserCount 限制最多返回10条记录
+            watchEndPlayTrendDTOS = tempDTOS.stream()
+                    .collect(Collectors.groupingBy(
+                            dto -> dto.getStartDate() + ":" + dto.getX(),  // 根据startDate和x分组
+                            Collectors.reducing(new WatchEndPlayTrendDTO(), (dto1, dto2) -> {
+                                // 合并watchUserCount和completedUserCount
+                                WatchEndPlayTrendDTO result = new WatchEndPlayTrendDTO();
+                                // 复制分组标识字段
+                                if (dto2 != null && dto2.getStartDate() != null) {
+                                    result.setStartDate(dto2.getStartDate());
+                                } else if (dto1 != null) {
+                                    result.setStartDate(dto1.getStartDate());
+                                }
+
+                                if (dto2 != null && dto2.getX() != null) {
+                                    result.setX(dto2.getX());
+                                } else if (dto1 != null) {
+                                    result.setX(dto1.getX());
+                                }
+
+                                // 合并数值字段
+                                result.setWatchUserCount(
+                                        (dto1 == null || dto1.getWatchUserCount() == null ? 0 : dto1.getWatchUserCount()) +
+                                                (dto2 == null || dto2.getWatchUserCount() == null ? 0 : dto2.getWatchUserCount())
+                                );
+
+                                result.setCompletedUserCount(
+                                        (dto1 == null || dto1.getCompletedUserCount() == null ? 0 : dto1.getCompletedUserCount()) +
+                                                (dto2 == null || dto2.getCompletedUserCount() == null ? 0 : dto2.getCompletedUserCount())
+                                );
+
+                                return result;
+                            })
+                    ))
+                    .values()
+                    .stream()
+                    .filter(Objects::nonNull)  // 过滤掉null值
+                    .limit(10)
+                    .sorted(Comparator.comparing(WatchEndPlayTrendDTO::getX))
+                    .collect(Collectors.toList());
+        }
+
+        if(watchEndPlayTrendDTOS == null){
+            watchEndPlayTrendDTOS = new ArrayList<>();
+        }
+
+        return R.ok().put("data", watchEndPlayTrendDTOS);
     }
 
     /**
@@ -107,8 +329,49 @@ public class IndexStatisticsController {
         if(userType == null){
             userType = 0;
         }
+        List<DeaMemberTopTenDTO> deaMemberTopTenDTOS = new ArrayList<>();
+        // 参考deaMemberTopTen方法处理逻辑
+        if (!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
+            String key = String.format("%s:%d:%d:%d", CHARTS_MEMBER_TOP_TEN_WATCH, type, statisticalType,userType);
+            deaMemberTopTenDTOS =  redisCache.getCacheObject(key);
+        }else if(param.getCompanyId() != null){
+            String key = String.format("%s:%d:%d:%d:%d", CHARTS_MEMBER_TOP_TEN_WATCH, type, statisticalType,userType,param.getCompanyId());
+            deaMemberTopTenDTOS = redisCache.getCacheObject(key);
+        }else{
+            Company company = new Company();
+            company.setDeptId(param.getDeptId());
+            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
+            List<DeaMemberTopTenDTO> tempDTOS = new ArrayList<>();
+            for(Long companyId : companyIds){
+                String key = String.format("%s:%d:%d:%d:%d", CHARTS_MEMBER_TOP_TEN_WATCH, type, statisticalType,userType,companyId);
+                List<DeaMemberTopTenDTO> companyData = redisCache.getCacheObject(key);
+                if (companyData != null) {
+                    tempDTOS.addAll(companyData);
+                }
+            }
+            // companyId 和 companyName 分组,合并watchUserCount 限制最多返回10条记录
+            deaMemberTopTenDTOS = tempDTOS.stream()
+                    .collect(Collectors.groupingBy(
+                            dto -> dto.getCompanyId() + ":" + dto.getCompanyName(),  // 根据companyId和companyName分组
+                            Collectors.reducing(new DeaMemberTopTenDTO(), (dto1, dto2) -> {
+                                DeaMemberTopTenDTO result = new DeaMemberTopTenDTO();
+                                result.setCompanyId(dto1.getCompanyId());
+                                result.setCompanyName(dto1.getCompanyName());
+                                result.setWatchUserCount(
+                                        (dto1.getWatchUserCount() == null ? 0 : dto1.getWatchUserCount()) +
+                                                (dto2 == null || dto2.getWatchUserCount() == null ? 0 : dto2.getWatchUserCount())
+                                );
+                                return result;
+                            })
+                    ))
+                    .values()
+                    .stream()
+                    .filter(Objects::nonNull)  // 过滤掉null值
+                    .limit(10)
+                    .sorted(Comparator.comparing(DeaMemberTopTenDTO::getWatchUserCount, Comparator.nullsLast(Comparator.reverseOrder())))
+                    .collect(Collectors.toList());
+        }
 
-        List<DeaMemberTopTenDTO> deaMemberTopTenDTOS = redisCache.getCacheObject(String.format("%s:%d:%d:%d", CHARTS_MEMBER_TOP_TEN_WATCH, type, statisticalType,userType));
         if(deaMemberTopTenDTOS == null){
             deaMemberTopTenDTOS = new ArrayList<>();
         }
@@ -123,8 +386,50 @@ public class IndexStatisticsController {
         Integer type = param.getType();
         Integer dataType = param.getDataType();
         Integer userType = param.getUserType();
+        List<RewardMoneyTopTenDTO> rewardMoneyTopTenDTOS = new ArrayList<>();
+        // 参考rewardMoneyTopTen方法处理逻辑
+        if(!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
+            String key = String.format("%s:%d:%d:%d", CHARTS_REWARD_MONEY_TOP_TEN, type,dataType,userType);
+            rewardMoneyTopTenDTOS = redisCache.getCacheObject(key);
+        }else if(param.getCompanyId() != null){
+            String key = String.format("%s:%d:%d:%d:%d", CHARTS_REWARD_MONEY_TOP_TEN, type,dataType,userType,param.getCompanyId());
+            rewardMoneyTopTenDTOS = redisCache.getCacheObject(key);
+        }else{
+            Company company = new Company();
+            company.setDeptId(param.getDeptId());
+            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
+            List<RewardMoneyTopTenDTO> tempDTOS = new ArrayList<>();
+            for(Long companyId : companyIds){
+                String key = String.format("%s:%d:%d:%d:%d", CHARTS_REWARD_MONEY_TOP_TEN, type,dataType,userType,companyId);
+                List<RewardMoneyTopTenDTO> companyData = redisCache.getCacheObject(key);
+                if (companyData != null) {
+                    tempDTOS.addAll(companyData);
+                }
+            }
+            rewardMoneyTopTenDTOS = tempDTOS.stream()
+                    .collect(Collectors.groupingBy(
+                            dto -> dto.getCompanyId() + ":" + dto.getCompanyName(),  // 根据companyId和companyName分组
+                            Collectors.reducing(new RewardMoneyTopTenDTO(), (dto1, dto2) -> {
+                                RewardMoneyTopTenDTO result = new RewardMoneyTopTenDTO();
+                                result.setCompanyId(dto1.getCompanyId());
+                                result.setCompanyName(dto1.getCompanyName());
+                                result.setRewardMoney(
+                                        (dto1.getRewardMoney() == null ? BigDecimal.ZERO : dto1.getRewardMoney())
+                                        .add(
+                                                (dto2 == null || dto2.getRewardMoney() == null ? BigDecimal.ZERO : dto2.getRewardMoney())
+                                        )
+                                );
+                                return result;
+                            })
+                    ))
+                    .values()
+                    .stream()
+                    .filter(Objects::nonNull)  // 过滤掉null值
+                    .limit(10)
+                    .sorted(Comparator.comparing(RewardMoneyTopTenDTO::getRewardMoney, Comparator.nullsLast(Comparator.reverseOrder())))
+                    .collect(Collectors.toList());
+        }
 
-        List<RewardMoneyTopTenDTO> rewardMoneyTopTenDTOS = redisCache.getCacheObject( String.format("%s:%d:%d:%d", CHARTS_REWARD_MONEY_TOP_TEN, type,dataType,userType));
         return R.ok().put("data", rewardMoneyTopTenDTOS);
     }
 
@@ -135,7 +440,47 @@ public class IndexStatisticsController {
     public R rewardMoneyTrend(@RequestBody AnalysisPreviewQueryDTO param){
         Integer type = param.getType();
         Integer userType = param.getUserType();
-        List<RewardMoneyTrendDTO> rewardMoneyTrendDTOS = redisCache.getCacheObject( String.format("%s:%d:%d", CHARTS_REWARD_MONEY_TREND, type,userType));
+        List<RewardMoneyTrendDTO> rewardMoneyTrendDTOS = new ArrayList<>();
+        // 参考rewardMoneyTrend方法处理逻辑
+        if(!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
+            String key = String.format("%s:%d:%d", CHARTS_REWARD_MONEY_TREND, type,userType);
+            rewardMoneyTrendDTOS = redisCache.getCacheObject(key);
+        }else if(param.getCompanyId() != null){
+            String key = String.format("%s:%d:%d:%d", CHARTS_REWARD_MONEY_TREND, type,userType,param.getCompanyId());
+            rewardMoneyTrendDTOS = redisCache.getCacheObject(key);
+        }else{
+            Company company = new Company();
+            company.setDeptId(param.getDeptId());
+            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
+            List<RewardMoneyTrendDTO> tempDTOS = new ArrayList<>();
+            for(Long companyId : companyIds){
+                String key = String.format("%s:%d:%d:%d", CHARTS_REWARD_MONEY_TREND, type,userType,companyId);
+                List<RewardMoneyTrendDTO> companyData = redisCache.getCacheObject(key);
+                if (companyData != null) {
+                    tempDTOS.addAll(companyData);
+                }
+            }
+            //根据startDate和x分组,合并rewardMoney,根据x排序,限制10
+            rewardMoneyTrendDTOS = tempDTOS.stream()
+                    .collect(Collectors.groupingBy(dto -> dto.getStartDate() + ":" + dto.getX(),
+                            Collectors.reducing(new RewardMoneyTrendDTO(), (dto1, dto2) -> {
+                        RewardMoneyTrendDTO result = new RewardMoneyTrendDTO();
+                        result.setStartDate(dto1.getStartDate());
+                        result.setX(dto1.getX());
+                        result.setRewardMoney(
+                                (dto1.getRewardMoney() == null ? BigDecimal.ZERO : dto1.getRewardMoney())
+                                .add(
+                                        (dto2 == null || dto2.getRewardMoney() == null ? BigDecimal.ZERO : dto2.getRewardMoney())
+                                )
+                        );
+                        return result;
+                    })))
+                    .values()
+                    .stream()
+                    .sorted(Comparator.comparing(RewardMoneyTrendDTO::getX))
+                    .limit(10)
+                    .collect(Collectors.toList());
+        }
         return R.ok().put("data", rewardMoneyTrendDTOS);
     }
 
@@ -148,29 +493,196 @@ public class IndexStatisticsController {
         String sort = param.getSort();
         Integer statisticalType = param.getStatisticalType();
         Integer userType = param.getUserType();
+        List<CourseStatsDTO> courseStatsDTOS;
+        if (!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
+            courseStatsDTOS = redisCache.getCacheObject(String.format("%s:%d:%d:%d:%s", CHARTS_WATCH_TOP_TEN, type,statisticalType,userType,sort));
+        }else if(param.getCompanyId() != null){
+            courseStatsDTOS = redisCache.getCacheObject(String.format("%s:%d:%d:%d:%s:%d", CHARTS_WATCH_TOP_TEN, type,statisticalType,userType,sort,param.getCompanyId()));
+        }else{
+            Company company = new Company();
+            company.setDeptId(param.getDeptId());
+            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
+            List<CourseStatsDTO> tempDTOS = new ArrayList<>();
+            for(Long companyId : companyIds){
+                List<CourseStatsDTO> companyDTO = redisCache.getCacheObject(String.format("%s:%d:%d:%d:%s:%d", CHARTS_WATCH_TOP_TEN, type,statisticalType,userType,sort,companyId));
+                if (companyDTO != null) {
+                    tempDTOS.addAll(companyDTO);
+                }
+            }
+            // courseId和courseName分组,合并watchUserCount、completedUserCount、answerUserCount、correctUserCount 限制最多返回10条记录
+            courseStatsDTOS = tempDTOS.stream()
+                    .collect(Collectors.groupingBy(dto -> dto.getCourseId() + ":" + dto.getCourseName()))
+                    .values()
+                    .stream()
+                    .map(group -> {
+                        if (group.isEmpty()) {
+                            return null;
+                        }
+
+                        // 取第一个作为基础对象
+                        CourseStatsDTO result = new CourseStatsDTO();
+                        CourseStatsDTO first = group.get(0);
+                        result.setCourseId(first.getCourseId());
+                        result.setCourseName(first.getCourseName());
+
+                        // 合并所有数值字段
+                        int watchUserCount = 0;
+                        int completedUserCount = 0;
+                        int answerUserCount = 0;
+                        int correctUserCount = 0;
+
+                        for (CourseStatsDTO dto : group) {
+                            watchUserCount += (dto.getWatchUserCount() == null ? 0 : dto.getWatchUserCount());
+                            completedUserCount += (dto.getCompletedUserCount() == null ? 0 : dto.getCompletedUserCount());
+                            answerUserCount += (dto.getAnswerUserCount() == null ? 0 : dto.getAnswerUserCount());
+                            correctUserCount += (dto.getCorrectUserCount() == null ? 0 : dto.getCorrectUserCount());
+                        }
+
+                        result.setWatchUserCount(watchUserCount);
+                        result.setCompletedUserCount(completedUserCount);
+                        result.setAnswerUserCount(answerUserCount);
+                        result.setCorrectUserCount(correctUserCount);
+
+                        return result;
+                    })
+                    .filter(Objects::nonNull)
+                    .sorted(Comparator.comparing(CourseStatsDTO::getWatchUserCount, Comparator.nullsLast(Comparator.reverseOrder())))
+                    .limit(10)
+                    .collect(Collectors.toList());
+
+        }
 
-        List<CourseStatsDTO> courseStatsDTOS = redisCache.getCacheObject(String.format("%s:%d:%d:%d:%s", CHARTS_WATCH_TOP_TEN, type,statisticalType,userType,sort));
         return R.ok().put("data", courseStatsDTOS);
     }
 
+    private List<CourseStatsDTO> groupAndSumCourseStatsWithStream(List<CourseStatsDTO> courseStatsList) {
+        // 定义合并逻辑
+        BinaryOperator<CourseStatsDTO> mergeFunction = (s1, s2) -> {
+            s1.setWatchUserCount(
+                    (s1.getWatchUserCount() == null ? 0 : s1.getWatchUserCount()) +
+                            (s2.getWatchUserCount() == null ? 0 : s2.getWatchUserCount())
+            );
+
+            s1.setCompletedUserCount(
+                    (s1.getCompletedUserCount() == null ? 0 : s1.getCompletedUserCount()) +
+                            (s2.getCompletedUserCount() == null ? 0 : s2.getCompletedUserCount())
+            );
+
+            s1.setAnswerUserCount(
+                    (s1.getAnswerUserCount() == null ? 0 : s1.getAnswerUserCount()) +
+                            (s2.getAnswerUserCount() == null ? 0 : s2.getAnswerUserCount())
+            );
+
+            s1.setCorrectUserCount(
+                    (s1.getCorrectUserCount() == null ? 0 : s1.getCorrectUserCount()) +
+                            (s2.getCorrectUserCount() == null ? 0 : s2.getCorrectUserCount())
+            );
+
+            return s1;
+        };
+
+        // 分组、合并并排序、限制10条
+        return courseStatsList.stream()
+                .collect(Collectors.toMap(
+                        CourseStatsDTO::getCourseId,
+                        dto -> {
+                            CourseStatsDTO copy = new CourseStatsDTO();
+                            copy.setCourseId(dto.getCourseId());
+                            copy.setCourseName(dto.getCourseName());
+                            copy.setWatchUserCount(dto.getWatchUserCount() == null ? 0 : dto.getWatchUserCount());
+                            copy.setCompletedUserCount(dto.getCompletedUserCount() == null ? 0 : dto.getCompletedUserCount());
+                            copy.setAnswerUserCount(dto.getAnswerUserCount() == null ? 0 : dto.getAnswerUserCount());
+                            copy.setCorrectUserCount(dto.getCorrectUserCount() == null ? 0 : dto.getCorrectUserCount());
+                            return copy;
+                        },
+                        mergeFunction,
+                        LinkedHashMap::new
+                ))
+                .values()
+                .stream()
+                .sorted(Comparator.comparing(CourseStatsDTO::getWatchUserCount, Comparator.nullsLast(Comparator.reverseOrder())))
+                .limit(10)
+                .collect(Collectors.toList());
+    }
+
     /**
      * 数据概览
      */
     @GetMapping("/dealerAggregated")
-    public R dealerAggregated(){
-        DealerAggregatedDTO dealerAggregatedDTO = redisCache.getCacheObject(StatisticsRedisConstant.DATA_OVERVIEW_DEALER_AGGREGATED);
+    public R dealerAggregated(StatisticsDeptCompanyParam param){
+        DealerAggregatedDTO result = new DealerAggregatedDTO();
+        if (!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)) {
+            result = redisCache.getCacheObject(StatisticsRedisConstant.DATA_OVERVIEW_DEALER_AGGREGATED);
+        }else if (param.getCompanyId() != null) {
+            result = redisCache.getCacheObject(String.format("%s:%d", DATA_OVERVIEW_DEALER_AGGREGATED, param.getCompanyId()));
+        //没选中销售公司,部门不为总公司
+        }else{
+            //Long padMaxNum = deptLimiteService.selectById(param.getDeptId()).getMaxPadNum();
+            Company company = new Company();
+            company.setDeptId(param.getDeptId());
+            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
+            for(Long companyId : companyIds) {
+                DealerAggregatedDTO dealerAggregatedDTO = redisCache.getCacheObject(String.format("%s:%d", DATA_OVERVIEW_DEALER_AGGREGATED, companyId));
+                // 添加空值检查
+                if (dealerAggregatedDTO != null) {
+                    result.setDealderCount((result.getDealderCount() == null ? 0 : result.getDealderCount())
+                            + (dealerAggregatedDTO.getDealderCount() == null ? 0 : dealerAggregatedDTO.getDealderCount()));
+                    result.setGroupMgrCount((result.getGroupMgrCount() == null ? 0 : result.getGroupMgrCount())
+                            + (dealerAggregatedDTO.getGroupMgrCount() == null ? 0 : dealerAggregatedDTO.getGroupMgrCount()));
+                    result.setMemberCount((result.getMemberCount() == null ? 0 : result.getMemberCount())
+                            + (dealerAggregatedDTO.getMemberCount() == null ? 0 : dealerAggregatedDTO.getMemberCount()));
+                    result.setNormalNum((result.getNormalNum() == null ? 0 : result.getNormalNum())
+                            + (dealerAggregatedDTO.getNormalNum() == null ? 0 : dealerAggregatedDTO.getNormalNum()));
+                    result.setBlackNum((result.getBlackNum() == null ? 0 : result.getBlackNum())
+                            + (dealerAggregatedDTO.getBlackNum() == null ? 0 : dealerAggregatedDTO.getBlackNum()));
+                    result.setQwMemberNum((result.getQwMemberNum() == null ? 0 : result.getQwMemberNum())
+                            + (dealerAggregatedDTO.getQwMemberNum() == null ? 0 : dealerAggregatedDTO.getQwMemberNum()));
+                    result.setTodayIncreaseUserNum((result.getTodayIncreaseUserNum() == null ? 0 : result.getTodayIncreaseUserNum())
+                            + (dealerAggregatedDTO.getTodayIncreaseUserNum() == null ? 0 : dealerAggregatedDTO.getTodayIncreaseUserNum()));
+                    result.setOrderTotalNum((result.getOrderTotalNum() == null ? 0 : result.getOrderTotalNum())
+                            + (dealerAggregatedDTO.getOrderTotalNum() == null ? 0 : dealerAggregatedDTO.getOrderTotalNum()));
+                    result.setTodayOrderNum((result.getTodayOrderNum() == null ? 0 : result.getTodayOrderNum())
+                            + (dealerAggregatedDTO.getTodayOrderNum() == null ? 0 : dealerAggregatedDTO.getTodayOrderNum()));
+                    result.setRecvTodayNum((result.getRecvTodayNum() == null ? 0 : result.getRecvTodayNum())
+                            + (dealerAggregatedDTO.getRecvTodayNum() == null ? 0 : dealerAggregatedDTO.getRecvTodayNum()));
+                    result.setRecvTotalNum((result.getRecvTotalNum() == null ? 0 : result.getRecvTotalNum())
+                            + (dealerAggregatedDTO.getRecvTotalNum() == null ? 0 : dealerAggregatedDTO.getRecvTotalNum()));
+                    result.setGoodsTotalNum((result.getGoodsTotalNum() == null ? 0 : result.getGoodsTotalNum())
+                            + (dealerAggregatedDTO.getGoodsTotalNum() == null ? 0 : dealerAggregatedDTO.getGoodsTotalNum()));
+                    result.setTodayGoodsNum((result.getTodayGoodsNum() == null ? 0 : result.getTodayGoodsNum())
+                            + (dealerAggregatedDTO.getTodayGoodsNum() == null ? 0 : dealerAggregatedDTO.getTodayGoodsNum()));
+                    result.setPadUsedNum((result.getPadUsedNum() == null ? 0 : result.getPadUsedNum())
+                            + (dealerAggregatedDTO.getPadUsedNum() == null ? 0 : dealerAggregatedDTO.getPadUsedNum()));
+                }
+            }
+        }
 
-        return R.ok().put("data",dealerAggregatedDTO);
+        return R.ok().put("data",result);
     }
 
+
     /**
      * 短信余额
      */
     @GetMapping("/smsBalance")
-    public R smsBalance(){
-        Long smsBalance = redisCache.getCacheObject(StatisticsRedisConstant.DATA_OVERVIEW_DEALER_SMS_BALANCE);
-
-        return R.ok().put("data", smsBalance);
+    public R smsBalance(StatisticsDeptCompanyParam param){
+        if (!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
+            return R.ok().put("data", redisCache.getCacheObject(StatisticsRedisConstant.DATA_OVERVIEW_DEALER_SMS_BALANCE));
+        }else if(param.getCompanyId() != null){
+            return R.ok().put("data", redisCache.getCacheObject(String.format("%s:%d", DATA_OVERVIEW_DEALER_SMS_BALANCE, param.getCompanyId())));
+        }else{
+            Company company = new Company();
+            company.setDeptId(param.getDeptId());
+            long smsBalance = 0L;
+            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
+            for(Long companyId : companyIds) {
+                Long smsBalanceCompany = redisCache.getCacheObject(String.format("%s:%d", DATA_OVERVIEW_DEALER_SMS_BALANCE, companyId));
+                if (smsBalanceCompany != null) {
+                    smsBalance += smsBalanceCompany;
+                }
+            }
+            return R.ok().put("data", smsBalance);
+        }
     }
 
 
@@ -178,8 +690,33 @@ public class IndexStatisticsController {
      * 授权信息
      */
     @GetMapping("/authorizationInfo")
-    public R authorizationInfo(){
-        AuthorizationInfoDTO authorizationInfoDTO = redisCache.getCacheObject(StatisticsRedisConstant.DATA_OVERVIEW_DEALER_AUTHORIZATION_INFO);
+    public R authorizationInfo(StatisticsDeptCompanyParam  param){
+        AuthorizationInfoDTO authorizationInfoDTO = new AuthorizationInfoDTO();
+        if (!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
+            return R.ok().put("data", redisCache.getCacheObject(StatisticsRedisConstant.DATA_OVERVIEW_DEALER_AUTHORIZATION_INFO));
+        }else if(param.getCompanyId() != null){
+            return R.ok().put("data", redisCache.getCacheObject(String.format("%s:%d", DATA_OVERVIEW_DEALER_AUTHORIZATION_INFO, param.getCompanyId())));
+        }else{
+            Company company = new Company();
+            company.setDeptId(param.getDeptId());
+            AuthorizationInfoDTO authorizationInfoDTO1 = new AuthorizationInfoDTO();
+            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
+            for(Long companyId : companyIds) {
+                AuthorizationInfoDTO companyDTO = redisCache.getCacheObject(String.format("%s:%d", DATA_OVERVIEW_DEALER_AUTHORIZATION_INFO, companyId));
+                log.info("授权信息:{}", authorizationInfoDTO);
+                if (companyDTO != null) {
+                    authorizationInfoDTO1.setTodayWatchUserCount(
+                            (authorizationInfoDTO1.getTodayWatchUserCount() == null ? 0 : authorizationInfoDTO1.getTodayWatchUserCount()) +
+                                    (companyDTO.getTodayWatchUserCount() == null ? 0 : companyDTO.getTodayWatchUserCount())
+                    );
+
+                    authorizationInfoDTO1.setVersionLimit(
+                            (authorizationInfoDTO1.getVersionLimit() == null ? 0 : authorizationInfoDTO1.getVersionLimit()) +
+                                    (companyDTO.getVersionLimit() == null ? 0 : companyDTO.getVersionLimit())
+                    );
+                }
+            }
+        }
 
         return R.ok().put("data", authorizationInfoDTO);
     }
@@ -190,9 +727,29 @@ public class IndexStatisticsController {
      * @return
      */
     @GetMapping("/thisMonthOrderCount")
-    public R thisMonthOrderCount(){
-        R result = redisCache.getCacheObject(StatisticsRedisConstant.THIS_MONTH_ORDER_COUNT);
-        return result;
+    public R thisMonthOrderCount(StatisticsDeptCompanyParam  param){
+        if (!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
+            return redisCache.getCacheObject(StatisticsRedisConstant.THIS_MONTH_ORDER_COUNT);
+        }else if(param.getCompanyId() != null){
+            return redisCache.getCacheObject(String.format("%s:%d", THIS_MONTH_ORDER_COUNT, param.getCompanyId()));
+        }else{
+            Company company = new Company();
+            company.setDeptId(param.getDeptId());
+            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
+            List<String> datesList = new ArrayList<>();
+            List<Integer> orderCountList = new ArrayList<>();
+            List<Integer> payPriceList = new ArrayList<>();
+            for(Long companyId : companyIds) {
+                R result = redisCache.getCacheObject(String.format("%s:%d", THIS_MONTH_ORDER_COUNT, companyId));
+                Object datas = result.get("datas");
+                Object orderCount = result.get("orderCount");
+                Object payPrice = result.get("payPrice");
+                if(datas != null){
+                    mergeDataListsForInteger(datesList, orderCountList, payPriceList, (List<String>)datas, (List<Integer>)orderCount, (List<Integer>)payPrice);
+                }
+            }
+            return R.ok().put("dates", datesList).put("orderCount", orderCountList).put("payPrice", payPriceList);
+        }
     }
 
     /**
@@ -201,8 +758,97 @@ public class IndexStatisticsController {
      */
 
     @GetMapping("/thisMonthRecvCount")
-    public R thisMonthRecvCount(){
-        R result = redisCache.getCacheObject(StatisticsRedisConstant.THIS_MONTH_RECV_COUNT);
-        return result;
+    public R thisMonthRecvCount(StatisticsDeptCompanyParam  param){
+        if (!medicalMallConfig.isStatics() || (param.getCompanyId() == null && param.getDeptId() == null) || (param.getCompanyId() == null && param.getDeptId() == 1)){
+            return redisCache.getCacheObject(StatisticsRedisConstant.THIS_MONTH_RECV_COUNT);
+        }else if(param.getCompanyId() != null){
+            return redisCache.getCacheObject(String.format("%s:%d", THIS_MONTH_RECV_COUNT, param.getCompanyId()));
+        }else{
+            Company company = new Company();
+            company.setDeptId(param.getDeptId());
+            Long[] companyIds = companyService.selectCompanyList(company).stream().map(Company::getCompanyId).toArray(Long[]::new);
+            List<String> datesList = new ArrayList<>();
+            List<Integer> orderCountList = new ArrayList<>();
+            List<Float> payMoneyList = new ArrayList<>();
+            for(Long companyId : companyIds) {
+               R result = redisCache.getCacheObject(String.format("%s:%d", THIS_MONTH_RECV_COUNT, companyId));
+               Object datas = result.get("datas");
+               Object orderCount = result.get("orderCount");
+               Object payMoney = result.get("payMoney");
+               if(datas != null){
+                   mergeDataLists(datesList, orderCountList, payMoneyList, (List<String>)datas, (List<Integer>)orderCount, (List<Float>)payMoney);
+               }
+            }
+            return R.ok().put("dates", datesList).put("orderCount", orderCountList).put("payMoney", payMoneyList);
+        }
+    }
+
+    private void mergeDataLists(List<String> datasList, List<Integer> orderCountList, List<Float> payMoneyList,
+                               List<String> datas, List<Integer> orderCount, List<Float> payMoney) {
+
+        // 遍历新数据
+        for (int i = 0; i < datas.size(); i++) {
+            String newData = datas.get(i);
+            Integer newOrderCount = orderCount.get(i);
+            Float newPayMoney = payMoney.get(i);
+
+            // 查找在现有列表中的位置
+            int existingIndex = datasList.indexOf(newData);
+
+            if (existingIndex != -1) {
+                // 如果存在,将orderCount和payMoney相加
+                Integer existingOrderCount = orderCountList.get(existingIndex);
+                Float existingPayMoney = payMoneyList.get(existingIndex);
+
+                // 累加orderCount
+                orderCountList.set(existingIndex,
+                        (existingOrderCount == null ? 0 : existingOrderCount) +
+                                (newOrderCount == null ? 0 : newOrderCount));
+
+                // 累加payMoney
+                payMoneyList.set(existingIndex,
+                        (existingPayMoney == null ? 0.0f : existingPayMoney) +
+                                (newPayMoney == null ? 0.0f : newPayMoney));
+            } else {
+                // 如果不存在,直接添加新项
+                datasList.add(newData);
+                orderCountList.add(newOrderCount);
+                payMoneyList.add(newPayMoney);
+            }
+        }
+    }
+
+    private void mergeDataListsForInteger(List<String> datasList, List<Integer> orderCountList, List<Integer> payMoneyList,
+                                          List<String> datas, List<Integer> orderCount, List<Integer> payMoney) {
+        // 遍历新数据
+        for (int i = 0; i < datas.size(); i++) {
+            String newData = datas.get(i);
+            Integer newOrderCount = orderCount.get(i);
+            Integer newPayMoney = payMoney.get(i);
+
+            // 查找在现有列表中的位置
+            int existingIndex = datasList.indexOf(newData);
+
+            if (existingIndex != -1) {
+                // 如果存在,将orderCount和payMoney相加
+                Integer existingOrderCount = orderCountList.get(existingIndex);
+                Integer existingPayMoney = payMoneyList.get(existingIndex);
+
+                // 累加orderCount
+                orderCountList.set(existingIndex,
+                        (existingOrderCount == null ? 0 : existingOrderCount) +
+                                (newOrderCount == null ? 0 : newOrderCount));
+
+                // 累加payMoney
+                payMoneyList.set(existingIndex,
+                        (existingPayMoney == null ? 0 : existingPayMoney) +
+                                (newPayMoney == null ? 0 : newPayMoney));
+            } else {
+                // 如果不存在,直接添加新项
+                datasList.add(newData);
+                orderCountList.add(newOrderCount);
+                payMoneyList.add(newPayMoney);
+            }
+        }
     }
 }

+ 41 - 1
fs-admin/src/main/java/com/fs/company/controller/CompanyController.java

@@ -1,6 +1,7 @@
 package com.fs.company.controller;
 
 import cn.hutool.core.util.IdUtil;
+import cn.hutool.json.JSONUtil;
 import com.fs.common.annotation.Log;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.controller.BaseController;
@@ -24,8 +25,10 @@ import com.fs.company.vo.CompanyCrmVO;
 import com.fs.company.vo.CompanyVO;
 import com.fs.company.vo.CompanyVoiceCallerListVO;
 import com.fs.core.utils.OrderCodeUtils;
+import com.fs.course.config.CourseConfig;
 import com.fs.framework.web.service.TokenService;
 import com.fs.his.vo.OptionsVO;
+import com.fs.system.service.ISysConfigService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.transaction.annotation.Transactional;
@@ -55,6 +58,8 @@ public class CompanyController extends BaseController
     private ICompanyDeductService deductService;
     @Autowired
     private ICompanyVoiceCallerService callerService;
+    @Autowired
+    private ISysConfigService configService;
     /**
      * 查询企业列表
      */
@@ -63,6 +68,12 @@ public class CompanyController extends BaseController
     public TableDataInfo list(CompanyParam param)
     {
         startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+            param.setDeptId(loginUser.getDeptId());
+        }
         List<CompanyVO> list = companyService.selectCompanyVOList(param);
         return getDataTable(list);
     }
@@ -75,6 +86,12 @@ public class CompanyController extends BaseController
     @GetMapping("/export")
     public AjaxResult export(CompanyParam company)
     {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+            company.setDeptId(loginUser.getDeptId());
+        }
         List<CompanyVO> list = companyService.selectCompanyVOList(company);
         ExcelUtil<CompanyVO> util = new ExcelUtil<CompanyVO>(CompanyVO.class);
         return util.exportExcel(list, "company");
@@ -98,6 +115,10 @@ public class CompanyController extends BaseController
     @PostMapping
     public R add(@RequestBody Company company)
     {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        if(company.getDeptId() != null){
+            company.setDeptId(loginUser.getDeptId());
+        }
         company.setPassword(SecurityUtils.encryptPassword(company.getPassword()));
         company.setAppId(Md5Utils.hash(company.getUserName()));
         company.setAppKey(Md5Utils.hash(company.getPassword()));
@@ -154,6 +175,12 @@ public class CompanyController extends BaseController
     {
         Company map=new Company();
         map.setIsDel(0);
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+            map.setDeptId(loginUser.getDeptId());
+        }
         List<Company> list = companyService.selectCompanyList(map);
         return R.ok().put("data",list);
     }
@@ -164,6 +191,12 @@ public class CompanyController extends BaseController
     public TableDataInfo companyCrmDayCountList(CompanyParam param)
     {
         startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+            param.setDeptId(loginUser.getDeptId());
+        }
         List<CompanyCrmVO> list = companyService.selectCompanyCrmDayCountList(param);
         return getDataTable(list);
     }
@@ -239,7 +272,14 @@ public class CompanyController extends BaseController
     @GetMapping("/allList")
     public TableDataInfo getHospital()
     {
-        List<OptionsVO> list = companyService.selectAllCompanyList();
+        Long deptId = null;
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+            deptId = loginUser.getDeptId();
+        }
+        List<OptionsVO> list = companyService.selectAllCompanyList(deptId);
         return getDataTable(list);
     }
 }

+ 103 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyTrafficController.java

@@ -0,0 +1,103 @@
+package com.fs.company.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+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.ServletUtils;
+import com.fs.company.domain.CompanyTrafficRecord;
+import com.fs.company.param.CompanyTrafficRecordChargeParam;
+import com.fs.company.param.CompanyTrafficRecordQueryParam;
+import com.fs.company.service.ICompanyTrafficRecordService;
+import com.fs.framework.web.service.TokenService;
+import com.fs.hisStore.config.MedicalMallConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.PostConstruct;
+import java.util.List;
+
+@RestController
+@RequestMapping("/company/traffic")
+public class CompanyTrafficController extends BaseController {
+
+    @Autowired
+    private ICompanyTrafficRecordService companyTrafficRecordService;
+
+    @Autowired
+    private TokenService tokenService;
+
+    @Autowired
+    private MedicalMallConfig medicalMallConfig;
+
+    /**
+     * 每天扣除流量余额
+     * */
+    @Scheduled(cron = "0 1 0 * * ?")
+    public void refreshTraffic(){
+        if(medicalMallConfig.isStatics())
+            companyTrafficRecordService.refreshTraffic();
+    }
+
+    /**
+     * 重启时重新计算并更新公司缓存
+     * */
+    @PostConstruct
+    public void init() {
+        if(medicalMallConfig.isStatics())
+            companyTrafficRecordService.init();
+    }
+
+    /** 充值流量 */
+    @PreAuthorize("@ss.hasPermi('company:traffic:charge')")
+    @Log(title = "公司流量充值", businessType = BusinessType.INSERT)
+    @PostMapping(value = "/rechargeTraffic")
+    public R rechargeTraffic(@RequestBody CompanyTrafficRecordChargeParam companyTrafficRecord) {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        companyTrafficRecord.setUserId(loginUser.getUser().getUserId());
+        companyTrafficRecord.setUserName(loginUser.getUser().getUserName());
+        companyTrafficRecordService.recharge(companyTrafficRecord);
+        return R.ok();
+    }
+
+    /** 流量充值记录查询 */
+    @PreAuthorize("@ss.hasPermi('company:traffic:list')")
+    @GetMapping(value = "/list")
+    public TableDataInfo list(CompanyTrafficRecordQueryParam param) {
+        startPage();
+        List<CompanyTrafficRecord> list = companyTrafficRecordService.selectList(param);
+        return getDataTable(list);
+    }
+
+    /** 流量充值详情 */
+    @PreAuthorize("@ss.hasPermi('company:traffic:detail')")
+    @GetMapping(value = "/detail/{logId}")
+    public R detail(@PathVariable("logId") Long logId) {
+        CompanyTrafficRecord record = companyTrafficRecordService.selectById(logId);
+        return R.ok().put("data", record);
+    }
+
+    /** 流量换算*/
+    @GetMapping(value = "/trafficConversion")
+    public R trafficConversion(@RequestParam("traffic") Long amount) {
+        Long trafficKB = companyTrafficRecordService.trafficConversion(amount);
+        return R.ok().put("data", trafficKB);
+    }
+
+    /** 刷新单价*/
+    @GetMapping(value = "/refreshPrice")
+    public R refreshPrice() {
+        companyTrafficRecordService.refreshPrice();
+        return R.ok();
+    }
+
+    /** 流量统计*/
+    @GetMapping(value = "/trafficStatistics")
+    public R trafficStatistics(CompanyTrafficRecord record) {
+        return R.ok().put("tatol","").put("dept","").put("company","");
+    }
+}

+ 49 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyTrafficLogController.java

@@ -0,0 +1,49 @@
+package com.fs.company.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.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.company.domain.CompanyTrafficRecordLog;
+import com.fs.company.param.CompanyTrafficRecordLogQueryParam;
+import com.fs.company.service.ICompanyTrafficRecordLogService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/company/trafficLog")
+public class CompanyTrafficLogController extends BaseController {
+
+    @Autowired
+    private ICompanyTrafficRecordLogService companyTrafficRecordLogService;
+
+
+    /** 流量充值记录查询 */
+    @PreAuthorize("@ss.hasPermi('company:trafficLog:list')")
+    @GetMapping(value = "/list")
+    public TableDataInfo list(CompanyTrafficRecordLogQueryParam param) {
+        startPage();
+        List<CompanyTrafficRecordLog> list = companyTrafficRecordLogService.selectList(param);
+        return getDataTable(list);
+    }
+
+
+    /** 导出 */
+    @PreAuthorize("@ss.hasPermi('company:trafficLog:export')")
+    @Log(title = "流量充值记录导出", businessType = BusinessType.EXPORT)
+    @GetMapping(value = "/export")
+    public AjaxResult export(CompanyTrafficRecordLogQueryParam param) {
+        List<CompanyTrafficRecordLog> list = companyTrafficRecordLogService.selectList(param);
+        ExcelUtil<CompanyTrafficRecordLog> util = new ExcelUtil<>(CompanyTrafficRecordLog.class);
+        return util.exportExcel(list, "流量充值记录");
+    }
+
+
+
+}

+ 41 - 3
fs-admin/src/main/java/com/fs/course/controller/FsCoursePlaySourceConfigController.java

@@ -1,21 +1,29 @@
 package com.fs.course.controller;
 
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 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.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.ServletUtils;
 import com.fs.common.utils.bean.BeanUtils;
+import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.param.FsCoursePlaySourceConfigCreateParam;
 import com.fs.course.param.FsCoursePlaySourceConfigEditParam;
 import com.fs.course.service.IFsCoursePlaySourceConfigService;
 import com.fs.course.vo.FsCoursePlaySourceConfigVO;
+import com.fs.framework.web.service.TokenService;
+import com.fs.system.service.ISysConfigService;
 import com.github.pagehelper.PageHelper;
 import lombok.AllArgsConstructor;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -31,16 +39,33 @@ import java.util.*;
 public class FsCoursePlaySourceConfigController extends BaseController {
 
     private final IFsCoursePlaySourceConfigService fsCoursePlaySourceConfigService;
+    private final TokenService tokenService;
+    private final ISysConfigService configService;
 
     @PreAuthorize("@ss.hasPermi('course:playSourceConfig:list')")
     @GetMapping("/list")
     public TableDataInfo list(@RequestParam(required = false) String name,
                               @RequestParam(required = false) String appid,
+                              @RequestParam(required = false) Integer isMall,
                               @RequestParam(required = false, defaultValue = "1") Integer pageNum,
                               @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
         Map<String, Object> params = new HashMap<>();
         params.put("name", name);
         params.put("appid", appid);
+        params.put("isMall", isMall);
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        Long userId = null;
+        Long deptId = null;
+        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+            deptId = loginUser.getDeptId();
+            if(config.getDept() == null || !config.getDept()){
+                userId = loginUser.getUserId();
+            }
+        }
+        params.put("userId", userId);
+        params.put("deptId", deptId);
 
         PageHelper.startPage(pageNum, pageSize);
         List<FsCoursePlaySourceConfigVO> list = fsCoursePlaySourceConfigService.selectCoursePlaySourceConfigVOListByMap(params);
@@ -70,8 +95,10 @@ public class FsCoursePlaySourceConfigController extends BaseController {
         if (fsCoursePlaySourceConfigService.count(queryWrapper) > 0) {
             return AjaxResult.error("appid已存在");
         }
-
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         FsCoursePlaySourceConfig config = new FsCoursePlaySourceConfig();
+        config.setCreateUserId(loginUser.getUserId());
+        config.setCreateDeptId(loginUser.getDeptId());
         BeanUtils.copyProperties(param, config);
 
         config.setIsDel(0);
@@ -114,8 +141,19 @@ public class FsCoursePlaySourceConfigController extends BaseController {
         fsCoursePlaySourceConfigService.update(updateWrapper);
         return AjaxResult.success();
     }
+
     @GetMapping("/listAll")
-    public R listAll() {
-        return R.ok().put("data", fsCoursePlaySourceConfigService.list(new QueryWrapper<FsCoursePlaySourceConfig>().eq("is_del", 0)));
+    public R listAll(Long companyId) {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        QueryWrapper<FsCoursePlaySourceConfig> queryWrapper = new QueryWrapper<FsCoursePlaySourceConfig>().eq("is_del", 0);
+        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+            queryWrapper.eq("create_user_id", loginUser.getUserId()).eq(config.getDept() == null || !config.getDept(), "create_dept_id", loginUser.getDeptId());
+        }
+        if(companyId != null){
+            queryWrapper.and(e -> e.eq("company_id", companyId).or().isNull("company_id"));
+        }
+        return R.ok().put("data", fsCoursePlaySourceConfigService.list(queryWrapper));
     }
 }

+ 5 - 5
fs-admin/src/main/java/com/fs/course/controller/FsCourseRedPacketLogController.java

@@ -53,11 +53,11 @@ public class FsCourseRedPacketLogController extends BaseController
     @Autowired
     FsUserCourseMapper fsUserCourseMapper;
     @Autowired
-    FsUserCourseVideoMapper fsUserCourseVideoMapper;
+    TokenService tokenService;
     @Autowired
-    private TokenService tokenService;
+    ISysConfigService configService;
     @Autowired
-    private ISysConfigService configService;
+    FsUserCourseVideoMapper fsUserCourseVideoMapper;
     /**
      * 查询短链课程看课记录列表
      */
@@ -149,10 +149,10 @@ public class FsCourseRedPacketLogController extends BaseController
         Long userId = loginUser.getUser().getUserId();
         String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        List<OptionsVO> optionsVOS = new ArrayList<>();
+        List<OptionsVO> optionsVOS;
         if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
             optionsVOS = fsUserCourseMapper.selectFsUserCourseAllListByUserId(userId);
-        }else {
+        }else{
             optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList();
         }
         return R.ok().put("list", optionsVOS);

+ 1 - 2
fs-admin/src/main/java/com/fs/fastGpt/FastgptExtUserTagController.java

@@ -4,7 +4,6 @@ import java.util.List;
 
 import com.fs.common.core.domain.R;
 import com.fs.fastGpt.vo.FastgptExtUserTagVO;
-import com.fs.framework.web.service.TokenService;
 import com.fs.qw.service.IQwCompanyService;
 import com.fs.qw.vo.QwOptionsVO;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -64,7 +63,7 @@ public class FastgptExtUserTagController extends BaseController
     @GetMapping("/getMyQwUserList")
     public R getMyQwUserList()
     {
-        List<QwOptionsVO> list = qwCompanyService.selectQwCompanyListOptionsVO();
+        List<QwOptionsVO> list = qwCompanyService.selectQwCompanyListOptionsVO(null, null);
         return  R.ok().put("data",list);
     }
 

+ 25 - 3
fs-admin/src/main/java/com/fs/his/controller/FsCompanyController.java

@@ -2,7 +2,7 @@ package com.fs.his.controller;
 
 import java.util.List;
 
-import cn.hutool.core.util.IdUtil;
+import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.domain.R;
@@ -22,10 +22,11 @@ import com.fs.company.service.ICompanyService;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.company.vo.CompanyVO;
 import com.fs.core.utils.OrderCodeUtils;
+import com.fs.course.config.CourseConfig;
 import com.fs.framework.web.service.TokenService;
-import com.fs.his.domain.FsDoctor;
 import com.fs.his.mapper.FsDoctorMapper;
 import com.fs.his.vo.OptionsVO;
+import com.fs.system.service.ISysConfigService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
@@ -67,6 +68,8 @@ public class FsCompanyController extends BaseController
     private FsDoctorMapper fsDoctorMapper;
     @Autowired
     private ICompanyDeductService deductService;
+    @Autowired
+    private ISysConfigService configService;
     /**
      * 查询诊所管理列表
      */
@@ -75,6 +78,12 @@ public class FsCompanyController extends BaseController
     public TableDataInfo list(Company company)
     {
         startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+            company.setDeptId(loginUser.getDeptId());
+        }
         List<CompanyVO> list = companyService.selectCompanyListVO(company);
         return getDataTable(list);
     }
@@ -83,7 +92,14 @@ public class FsCompanyController extends BaseController
     public R companyList()
     {
 
-        List<OptionsVO> list = companyService.selectAllCompanyList();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long depId = null;
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+            depId = loginUser.getDeptId();
+        }
+        List<OptionsVO> list = companyService.selectAllCompanyList(depId);
         return R.ok().put("data",list);
     }
     /**
@@ -133,6 +149,12 @@ public class FsCompanyController extends BaseController
     @PostMapping
     public R add(@RequestBody Company company)
     {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+            company.setDeptId(loginUser.getDeptId());
+        }
         return companyService.insertCompany(company);
     }
 

+ 12 - 12
fs-admin/src/main/java/com/fs/his/controller/FsUserComplaintController.java → fs-admin/src/main/java/com/fs/his/controller/FsHisComplaintController.java

@@ -6,8 +6,8 @@ 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.FsUserComplaint;
-import com.fs.his.service.IFsUserComplaintService;
+import com.fs.his.domain.FsHisComplaint;
+import com.fs.his.service.IFsHisComplaintService;
 import com.fs.his.vo.FsUserComplaintVo;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -23,20 +23,20 @@ import java.util.List;
  */
 @RestController
 @RequestMapping("/his/complaint")
-public class FsUserComplaintController extends BaseController
+public class FsHisComplaintController extends BaseController
 {
     @Autowired
-    private IFsUserComplaintService fsUserComplaintService;
+    private IFsHisComplaintService fsUserComplaintService;
 
     /**
      * 查询用户投诉列表
      */
     @PreAuthorize("@ss.hasPermi('his:complaint:list')")
     @GetMapping("/list")
-    public TableDataInfo list(FsUserComplaint fsUserComplaint)
+    public TableDataInfo list(FsHisComplaint fsHisComplaint)
     {
         startPage();
-        List<FsUserComplaintVo> list = fsUserComplaintService.selectFsUserComplaintList(fsUserComplaint);
+        List<FsUserComplaintVo> list = fsUserComplaintService.selectFsUserComplaintList(fsHisComplaint);
         return getDataTable(list);
     }
 
@@ -46,9 +46,9 @@ public class FsUserComplaintController extends BaseController
     @PreAuthorize("@ss.hasPermi('his:complaint:export')")
     @Log(title = "用户投诉", businessType = BusinessType.EXPORT)
     @GetMapping("/export")
-    public AjaxResult export(FsUserComplaint fsUserComplaint)
+    public AjaxResult export(FsHisComplaint fsHisComplaint)
     {
-        List<FsUserComplaintVo> list = fsUserComplaintService.selectFsUserComplaintList(fsUserComplaint);
+        List<FsUserComplaintVo> list = fsUserComplaintService.selectFsUserComplaintList(fsHisComplaint);
         ExcelUtil<FsUserComplaintVo> util = new ExcelUtil<FsUserComplaintVo>(FsUserComplaintVo.class);
         return util.exportExcel(list, "用户投诉数据");
     }
@@ -69,9 +69,9 @@ public class FsUserComplaintController extends BaseController
     @PreAuthorize("@ss.hasPermi('his:complaint:add')")
     @Log(title = "用户投诉", businessType = BusinessType.INSERT)
     @PostMapping
-    public AjaxResult add(@RequestBody FsUserComplaint fsUserComplaint)
+    public AjaxResult add(@RequestBody FsHisComplaint fsHisComplaint)
     {
-        return toAjax(fsUserComplaintService.insertFsUserComplaint(fsUserComplaint));
+        return toAjax(fsUserComplaintService.insertFsUserComplaint(fsHisComplaint));
     }
 
     /**
@@ -80,9 +80,9 @@ public class FsUserComplaintController extends BaseController
     @PreAuthorize("@ss.hasPermi('his:complaint:edit')")
     @Log(title = "用户投诉", businessType = BusinessType.UPDATE)
     @PutMapping
-    public AjaxResult edit(@RequestBody FsUserComplaint fsUserComplaint)
+    public AjaxResult edit(@RequestBody FsHisComplaint fsHisComplaint)
     {
-        return toAjax(fsUserComplaintService.updateFsUserComplaint(fsUserComplaint));
+        return toAjax(fsUserComplaintService.updateFsUserComplaint(fsHisComplaint));
     }
 
     /**

+ 19 - 0
fs-admin/src/main/java/com/fs/his/controller/FsPatientController.java

@@ -67,6 +67,25 @@ public class FsPatientController extends BaseController
         return getDataTable(list);
     }
 
+    @GetMapping("/userList")
+    public TableDataInfo userList(FsPatientVO fsPatient)
+    {
+        startPage();
+        List<FsPatientVO> list = fsPatientService.selectFsPatientListVO(fsPatient);
+        for (FsPatientVO fsPatientVO : list){
+            if (fsPatientVO.getPhone()!=null){
+                fsPatientVO.setPhone(fsPatientVO.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+            }
+            if (fsPatientVO.getIdCard()!=null){
+                fsPatientVO.setIdCard(fsPatientVO.getIdCard().replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1**********$2"));
+            }
+            if (fsPatientVO.getMobile()!=null){
+                fsPatientVO.setMobile(fsPatientVO.getMobile().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+            }
+        }
+        return getDataTable(list);
+    }
+
     /**
      * 导出病人列表
      */

+ 11 - 6
fs-admin/src/main/java/com/fs/his/controller/FsStoreOrderController.java

@@ -2,10 +2,7 @@ package com.fs.his.controller;
 
 import java.math.BigDecimal;
 import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 import cn.hutool.core.util.StrUtil;
@@ -224,11 +221,19 @@ public class FsStoreOrderController extends BaseController
     @PreAuthorize("@ss.hasPermi('store:storeOrder:export')")
     @Log(title = "导出订单", businessType = BusinessType.EXPORT)
     @GetMapping("/orderExport")
-    public AjaxResult orderExport(FsStoreOrderParam param) {
+    public AjaxResult orderExport(FsStoreOrderParam param,String filter) {
         Integer exportType1 = exportTaskService.isExportType1(SecurityUtils.getUserId());
 //        if (exportType1>0){
 //            return AjaxResult.error("你已经有正在导出的任务");
 //        }
+        // 1. 处理filter参数:将逗号分隔的字符串拆分为ArrayList<String>
+        ArrayList<String> filterList = new ArrayList<>();
+        if (StringUtils.isNotBlank(filter)) {
+            // 按逗号拆分,同时去除可能的空格(如filter传"orderId, orderCode"时兼容)
+            String[] filterArr = filter.split("\\s*,\\s*");
+            filterList.addAll(Arrays.asList(filterArr));
+        }
+
         if (fsStoreOrderService.isEntityNull(param)){
             return AjaxResult.error("请筛选数据导出");
         }
@@ -255,7 +260,7 @@ public class FsStoreOrderController extends BaseController
         exportTaskService.insertFsExportTask(task);
         param.setTaskId(task.getTaskId());
         boolean checkPhone = isCheckPhone();
-        exportTaskService.exportStore1Data(param,checkPhone);
+        exportTaskService.exportStore1Data(param,checkPhone, filterList);
 
         return new AjaxResult(200,"后台正在导出,请等待...任务ID:"+task.getTaskId(),task.getTaskId());
 

+ 24 - 0
fs-admin/src/main/java/com/fs/hisStore/FsHisStoreLogController.java

@@ -0,0 +1,24 @@
+package com.fs.hisStore;
+
+import com.fs.common.core.domain.R;
+import com.fs.hisStore.domain.SysOperLogScrm;
+import com.fs.hisStore.service.IFsHisStoreAuditLogScrmService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/store/hisStoreLog")
+public class FsHisStoreLogController {
+
+    @Autowired
+    private IFsHisStoreAuditLogScrmService fsHisStoreLogScrmService;
+    @RequestMapping("/{mainId}")
+    public R getInfo(@PathVariable("mainId") Long mainId) {
+        List<SysOperLogScrm> sysOperLogScrms = fsHisStoreLogScrmService.selectOperLogByMainId(mainId);
+        return R.ok().put("data",sysOperLogScrms);
+    }
+}

+ 134 - 0
fs-admin/src/main/java/com/fs/hisStore/FsStoreSCRMController.java

@@ -0,0 +1,134 @@
+package com.fs.hisStore;
+
+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.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ParseUtils;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.his.domain.FsStore;
+import com.fs.his.param.FsStoreAuditParam;
+import com.fs.his.service.IFsStoreService;
+import com.fs.hisStore.domain.FsStoreScrm;
+import com.fs.hisStore.service.IFsStoreScrmService;
+import com.fs.hisStore.vo.FsStoreScrmVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 店铺管理Controller
+ *
+ * @author fs
+ * @date 2023-06-15
+ */
+@RestController
+@RequestMapping("/store/store")
+public class FsStoreSCRMController extends BaseController
+{
+    @Autowired
+    private IFsStoreScrmService fsStoreService;
+
+    /**
+     * 查询店铺管理列表
+     */
+    @PreAuthorize("@ss.hasPermi('store:store:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsStoreScrm fsStore)
+    {
+        startPage();
+        List<FsStoreScrm> list = fsStoreService.selectFsStoreList(fsStore);
+        for (FsStoreScrm store : list) {
+            store.setPhone(ParseUtils.parsePhone(store.getPhone()));
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出店铺管理列表
+     */
+    @PreAuthorize("@ss.hasPermi('store:store:export')")
+    @Log(title = "店铺管理", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsStoreScrm fsStore)
+    {
+        List<FsStoreScrm> list = fsStoreService.selectFsStoreList(fsStore);
+        for (FsStoreScrm store : list) {
+            store.setPhone(ParseUtils.parsePhone(store.getPhone()));
+        }
+        ExcelUtil<FsStoreScrm> util = new ExcelUtil<FsStoreScrm>(FsStoreScrm.class);
+        return util.exportExcel(list, "店铺管理数据");
+    }
+
+    /**
+     * 获取店铺管理详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('store:store:query')")
+    @GetMapping(value = "/{storeId}")
+    public AjaxResult getInfo(@PathVariable("storeId") Long storeId)
+    {
+        FsStoreScrm fsStore = fsStoreService.selectFsStoreByStoreId(storeId);
+        fsStore.setPhone(ParseUtils.parsePhone(fsStore.getPhone()));
+        return AjaxResult.success(fsStore);
+    }
+
+    /**
+     * 新增店铺管理
+     */
+    @PreAuthorize("@ss.hasPermi('store:store:add')")
+    @Log(title = "店铺管理", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsStoreScrm fsStore)
+    {
+        return AjaxResult.success(fsStoreService.insertFsStore(fsStore));
+    }
+
+    /**
+     * 修改店铺管理
+     */
+    @PreAuthorize("@ss.hasPermi('store:store:edit')")
+    @Log(title = "店铺管理", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsStoreScrm fsStore)
+    {
+
+        if (fsStore.getPhone()!=null&&fsStore.getPhone().contains("*")){
+            fsStore.setPhone(null);
+        }
+        return toAjax(fsStoreService.updateFsStore(fsStore));
+    }
+
+    /**
+     * 删除店铺管理
+     */
+    @PreAuthorize("@ss.hasPermi('store:store:remove')")
+    @Log(title = "店铺管理", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{storeIds}")
+    public AjaxResult remove(@PathVariable Long[] storeIds)
+    {
+        return toAjax(fsStoreService.deleteFsStoreByStoreIds(storeIds));
+    }
+
+    /**
+     * 店铺审核
+     */
+    @PreAuthorize("@ss.hasPermi('store:store:audit')")
+    @Log(title = "店铺管理", businessType = BusinessType.UPDATE)
+    @PutMapping("/audit")
+    public AjaxResult audit(@RequestBody FsStoreAuditParam fsStore)
+    {
+        return toAjax(fsStoreService.updateFsStoreAudit(fsStore));
+    }
+
+    @GetMapping("/storeList")
+    public R storeList(){
+        List<FsStoreScrmVO> list = fsStoreService.selectAllStore();
+        return R.ok().put("data",list);
+    }
+
+
+}

+ 74 - 1
fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreHealthOrderScrmController.java

@@ -135,6 +135,38 @@ public class FsStoreHealthOrderScrmController extends BaseController {
         return util.exportExcel(list, "订单数据");
     }
 
+    /**
+     * 导出健康商城列表(明文)
+     */
+    @PreAuthorize("@ss.hasPermi('store:healthStoreOrder:export:details')")
+    @Log(title = "健康商城订单", businessType = BusinessType.EXPORT)
+    @GetMapping("/healthExportDetails")
+    public AjaxResult healthExportDetails(FsStoreOrderParam param) {
+        if ("".equals(param.getBeginTime()) && "".equals(param.getEndTime())){
+            param.setBeginTime(null);
+            param.setEndTime(null);
+        }
+        if (fsStoreOrderService.isEntityNull(param)){
+            return AjaxResult.error("请筛选数据导出");
+        }
+        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
+            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getPayTimeRange())){
+            param.setPayTimeList(param.getPayTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getDeliverySendTimeRange())){
+            param.setDeliverySendTimeList(param.getDeliverySendTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getDeliveryImportTimeRange())){
+            param.setDeliveryImportTimeList(param.getDeliveryImportTimeRange().split("--"));
+        }
+        param.setIsHealth("1");
+        List<FsStoreOrderExportVO> list = fsStoreOrderService.selectFsStoreOrderListVOByExport(param);
+        ExcelUtil<FsStoreOrderExportVO> util = new ExcelUtil<FsStoreOrderExportVO>(FsStoreOrderExportVO.class);
+        return util.exportExcel(list, "订单数据");
+    }
+
 
     @PreAuthorize("@ss.hasPermi('store:healthStoreOrder:exportItems')")
     @Log(title = "商城订单明细导出", businessType = BusinessType.EXPORT)
@@ -181,6 +213,47 @@ public class FsStoreHealthOrderScrmController extends BaseController {
         return util.exportExcel(list, "订单明细数据");
     }
 
+    @PreAuthorize("@ss.hasPermi('store:healthStoreOrder:exportItems:details')")
+    @Log(title = "商城订单明细导出", businessType = BusinessType.EXPORT)
+    @GetMapping("/healthExportItemsDetails")
+    public AjaxResult healthExportItemsDetails(FsStoreOrderParam param) {
+        if ("".equals(param.getBeginTime()) && "".equals(param.getEndTime())){
+            param.setBeginTime(null);
+            param.setEndTime(null);
+        }
+        if (fsStoreOrderService.isEntityNull(param)){
+            return AjaxResult.error("请筛选数据导出");
+        }
+        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
+            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getPayTimeRange())){
+            param.setPayTimeList(param.getPayTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getDeliverySendTimeRange())){
+            param.setDeliverySendTimeList(param.getDeliverySendTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getDeliveryImportTimeRange())){
+            param.setDeliveryImportTimeList(param.getDeliveryImportTimeRange().split("--"));
+        }
+        param.setIsHealth("1");
+        List<FsStoreOrderItemExportVO> list = orderItemService.selectFsStoreOrderItemListExportVO(param);
+        //对手机号脱敏
+        if (list != null) {
+            for (FsStoreOrderItemExportVO vo : list) {
+                if (!StringUtils.isEmpty(vo.getJsonInfo())) {
+                    try {
+                        StoreOrderProductDTO orderProductDTO = JSONObject.parseObject(vo.getJsonInfo(), StoreOrderProductDTO.class);
+                        BeanUtil.copyProperties(orderProductDTO, vo);
+                    } catch (Exception e) {
+                    }
+                }
+            }
+        }
+        ExcelUtil<FsStoreOrderItemExportVO> util = new ExcelUtil<FsStoreOrderItemExportVO>(FsStoreOrderItemExportVO.class);
+        return util.exportExcel(list, "订单明细数据");
+    }
+
     //订单发货批量导入
     @Log(title = "发货同步导入", businessType = BusinessType.IMPORT)
     @PostMapping("/importDeliveryNoteExpress")
@@ -203,7 +276,7 @@ public class FsStoreHealthOrderScrmController extends BaseController {
         try {
             List<FsOrderDeliveryNoteDTO> dtoList = util.importExcel(file.getInputStream());
             if(!dtoList.isEmpty()){
-                fsStoreOrderService.importDeliveryNoteExpress(dtoList);
+               return fsStoreOrderService.importDeliveryNoteExpress(dtoList);
             }else {
                 R.error("操作失败,导入数据不能小于1条!");
             }

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

@@ -7,9 +7,11 @@ 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.ParseUtils;
+import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.param.CompanyStoreOrderMoneyLogsListParam;
@@ -20,6 +22,7 @@ import com.fs.erp.domain.ErpOrderQuery;
 import com.fs.erp.dto.ErpOrderQueryRequert;
 import com.fs.erp.dto.ErpOrderQueryResponse;
 import com.fs.erp.service.IErpOrderService;
+import com.fs.framework.web.service.TokenService;
 import com.fs.his.domain.FsUser;
 import com.fs.his.service.IFsExpressService;
 import com.fs.his.service.IFsUserService;
@@ -101,6 +104,9 @@ public class FsStoreOrderScrmController extends BaseController {
     @Autowired
     private IFsStoreOrderAuditLogScrmService orderAuditLogService;
 
+    @Autowired
+    private TokenService tokenService;
+
     private IErpOrderService getErpService(){
         //判断是否开启erp
         IErpOrderService erpOrderService = null;
@@ -255,6 +261,9 @@ public class FsStoreOrderScrmController extends BaseController {
         List<FsStoreOrderExportVO> list = fsStoreOrderService.selectFsStoreOrderListVOByExport(param);
         //对手机号脱敏
         if (list != null) {
+            //获取当前账号角色权限
+            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+
             for (FsStoreOrderExportVO vo : list) {
                 if (vo.getPhone() != null) {
                     vo.setPhone(vo.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
@@ -272,6 +281,37 @@ public class FsStoreOrderScrmController extends BaseController {
     }
 
 
+    /**
+     * 导出订单列表(明文)
+     */
+    @PreAuthorize("@ss.hasPermi('store:storeOrder:export:details')")
+    @Log(title = "订单", businessType = BusinessType.EXPORT)
+    @GetMapping("/exportDetails")
+    public AjaxResult exportDetails(FsStoreOrderParam param) {
+        if ("".equals(param.getBeginTime()) && "".equals(param.getEndTime())){
+            param.setBeginTime(null);
+            param.setEndTime(null);
+        }
+        if (fsStoreOrderService.isEntityNull(param)){
+            return AjaxResult.error("请筛选数据导出");
+        }
+        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
+            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getPayTimeRange())){
+            param.setPayTimeList(param.getPayTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getDeliverySendTimeRange())){
+            param.setDeliverySendTimeList(param.getDeliverySendTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getDeliveryImportTimeRange())){
+            param.setDeliveryImportTimeList(param.getDeliveryImportTimeRange().split("--"));
+        }
+        param.setNotHealth(1);
+        List<FsStoreOrderExportVO> list = fsStoreOrderService.selectFsStoreOrderListVOByExport(param);
+        ExcelUtil<FsStoreOrderExportVO> util = new ExcelUtil<FsStoreOrderExportVO>(FsStoreOrderExportVO.class);
+        return util.exportExcel(list, "订单数据");
+    }
 
     @PreAuthorize("@ss.hasPermi('store:storeOrder:exportItems')")
     @Log(title = "订单明细导出", businessType = BusinessType.EXPORT)
@@ -321,6 +361,49 @@ public class FsStoreOrderScrmController extends BaseController {
         return util.exportExcel(list, "订单明细数据");
     }
 
+    /**
+     * 订单明细导出(明文)
+     * **/
+    @PreAuthorize("@ss.hasPermi('store:storeOrder:exportItems:details')")
+    @Log(title = "订单明细导出", businessType = BusinessType.EXPORT)
+    @GetMapping("/exportItemsDetails")
+    public AjaxResult exportItemsDetails(FsStoreOrderParam param) {
+        if ("".equals(param.getBeginTime()) && "".equals(param.getEndTime())){
+            param.setBeginTime(null);
+            param.setEndTime(null);
+        }
+        if (fsStoreOrderService.isEntityNull(param)){
+            return AjaxResult.error("请筛选数据导出");
+        }
+        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
+            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getPayTimeRange())){
+            param.setPayTimeList(param.getPayTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getDeliveryImportTimeRange())){
+            param.setDeliveryImportTimeList(param.getDeliveryImportTimeRange().split("--"));
+        }
+        if(!StringUtils.isEmpty(param.getDeliverySendTimeRange())){
+            param.setDeliverySendTimeList(param.getDeliverySendTimeRange().split("--"));
+        }
+        param.setNotHealth(1);
+        List<FsStoreOrderItemExportVO> list = orderItemService.selectFsStoreOrderItemListExportVO(param);
+        //对手机号脱敏
+        if (list != null) {
+            for (FsStoreOrderItemExportVO vo : list) {
+                if (!StringUtils.isEmpty(vo.getJsonInfo())) {
+                    try {
+                        StoreOrderProductDTO orderProductDTO = JSONObject.parseObject(vo.getJsonInfo(), StoreOrderProductDTO.class);
+                        BeanUtil.copyProperties(orderProductDTO, vo);
+                    } catch (Exception e) {
+                    }
+                }
+            }
+        }
+        ExcelUtil<FsStoreOrderItemExportVO> util = new ExcelUtil<FsStoreOrderItemExportVO>(FsStoreOrderItemExportVO.class);
+        return util.exportExcel(list, "订单明细数据");
+    }
 
     @GetMapping("/orderItemsNum")
     public R orderItemsNum(FsStoreOrderParam param) {

+ 14 - 2
fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductScrmController.java

@@ -21,6 +21,7 @@ import com.fs.hisStore.param.FsStoreTuiProductAttrValueParam;
 import com.fs.hisStore.service.IFsStoreProductAttrScrmService;
 import com.fs.hisStore.service.IFsStoreProductAttrValueScrmService;
 import com.fs.hisStore.service.IFsStoreProductScrmService;
+import com.fs.statis.dto.ProductAuditDTO;
 import com.mysql.cj.util.StringUtils;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
@@ -69,6 +70,17 @@ public class FsStoreProductScrmController extends BaseController
         return R.ok();
     }
 
+    @PreAuthorize("@ss.hasPermi('store:storeProduct:list')")
+    @PostMapping("/batchAudit")
+    @Log(title = "商品审核", businessType = BusinessType.AUDIT,isStoreLog = true,logParam = {"商品","批量审核商品信息"},
+    logParamExpression = "#p0.getProductIds().size()>1?"
+            +"(#p0.isAudit==1?new String[]{'商品','商品批量审核通过'}: new String[]{'商品','商品批量审核退回'}):" +
+            "(#p0.isAudit==1?new String[]{'商品','商品审核通过'}: new String[]{'商品','商品审核退回'})")
+    public R batchAudit(@RequestBody ProductAuditDTO auditDTO){
+        fsStoreProductService.batchAudit(auditDTO);
+        return R.ok();
+    }
+
     /**
      * 查询商品列表
      */
@@ -169,8 +181,8 @@ public class FsStoreProductScrmController extends BaseController
 
     @ApiOperation(value = "生成属性")
     @PostMapping(value = "/genFormatAttr/{productId}")
-    public ResponseEntity genFormatAttr(@PathVariable Long productId, @RequestBody String jsonStr){
-        return new ResponseEntity<>(fsStoreProductService.getFormatAttr(productId,jsonStr), HttpStatus.OK);
+    public ResponseEntity genFormatAttr(@PathVariable Long productId, @RequestBody String jsonStr,Long[] stores){
+        return new ResponseEntity<>(fsStoreProductService.getFormatAttr(productId,jsonStr, stores), HttpStatus.OK);
     }
 
 

+ 108 - 0
fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreRecommendScrmController.java

@@ -0,0 +1,108 @@
+package com.fs.hisStore.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.hisStore.domain.FsStoreRecommendScrm;
+import com.fs.hisStore.service.IFsStoreRecommendScrmService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 店铺推荐Controller
+ *
+ * @author fs
+ * @date 2023-06-15
+ */
+@RestController
+@RequestMapping("/store/recommend")
+public class FsStoreRecommendScrmController extends BaseController
+{
+    @Autowired
+    private IFsStoreRecommendScrmService fsStoreRecommendService;
+
+    /**
+     * 查询店铺推荐列表
+     */
+    @PreAuthorize("@ss.hasPermi('store:recommend:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsStoreRecommendScrm fsStoreRecommendScrm)
+    {
+        startPage();
+        List<FsStoreRecommendScrm> list = fsStoreRecommendService.selectFsStoreRecommendScrmList(fsStoreRecommendScrm);
+        return getDataTable(list);
+    }
+
+    /**
+     * 获取店铺推荐详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('store:recommend:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsStoreRecommendService.selectFsStoreRecommendScrmById(id));
+    }
+
+    /**
+     * 新增店铺推荐
+     */
+    @PreAuthorize("@ss.hasPermi('store:recommend:add')")
+    @Log(title = "店铺推荐", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsStoreRecommendScrm fsStoreRecommendScrm)
+    {
+        return toAjax(fsStoreRecommendService.insertFsStoreRecommendScrm(fsStoreRecommendScrm));
+    }
+
+    /**
+     * 修改店铺推荐
+     */
+    @PreAuthorize("@ss.hasPermi('store:recommend:edit')")
+    @Log(title = "店铺推荐", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsStoreRecommendScrm fsStoreRecommendScrm)
+    {
+        return toAjax(fsStoreRecommendService.updateFsStoreRecommendScrm(fsStoreRecommendScrm));
+    }
+
+    /**
+     * 删除店铺推荐
+     */
+    @PreAuthorize("@ss.hasPermi('store:recommend:delete')")
+    @Log(title = "店铺推荐", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsStoreRecommendService.deleteFsStoreRecommendScrmByIds(ids));
+    }
+
+    /**
+     * 查询有效的推荐店铺列表(用于前端展示)
+     */
+    @GetMapping("/validList")
+    public TableDataInfo validList(FsStoreRecommendScrm fsStoreRecommendScrm)
+    {
+        startPage();
+        List<FsStoreRecommendScrm> list = fsStoreRecommendService.selectValidRecommendList(fsStoreRecommendScrm);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出
+     * */
+    @PreAuthorize("@ss.hasPermi('store:recommend:export')")
+    @Log(title = "店铺推荐", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsStoreRecommendScrm fsStoreRecommendScrm)
+        {
+        List<FsStoreRecommendScrm> list = fsStoreRecommendService.selectFsStoreRecommendScrmList(fsStoreRecommendScrm);
+        ExcelUtil<FsStoreRecommendScrm> util = new ExcelUtil<>(FsStoreRecommendScrm.class);
+        return util.exportExcel(list, "店铺推荐数据");
+    }
+}

+ 20 - 3
fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreScrmController.java

@@ -3,6 +3,7 @@ package com.fs.hisStore.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.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ParseUtils;
@@ -10,6 +11,7 @@ import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.hisStore.domain.FsStoreScrm;
 import com.fs.his.param.FsStoreAuditParam;
 import com.fs.hisStore.service.IFsStoreScrmService;
+import com.fs.hisStore.utils.StoreAuditLogUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
@@ -29,6 +31,9 @@ public class FsStoreScrmController extends BaseController
     @Autowired
     private IFsStoreScrmService fsStoreService;
 
+    @Autowired
+    private StoreAuditLogUtil storeAuditLogUtil;
+
     /**
      * 查询店铺管理列表
      */
@@ -52,6 +57,7 @@ public class FsStoreScrmController extends BaseController
     @GetMapping("/export")
     public AjaxResult export(FsStoreScrm fsStore)
     {
+        storeAuditLogUtil.generateOperId();
         List<FsStoreScrm> list = fsStoreService.selectFsStoreList(fsStore);
         for (FsStoreScrm store : list) {
             store.setPhone(ParseUtils.parsePhone(store.getPhone()));
@@ -80,7 +86,8 @@ public class FsStoreScrmController extends BaseController
     @PostMapping
     public AjaxResult add(@RequestBody FsStoreScrm fsStore)
     {
-        return toAjax(fsStoreService.insertFsStore(fsStore));
+        storeAuditLogUtil.addOperLog(fsStoreService.insertFsStore(fsStore));
+        return AjaxResult.success();
     }
 
     /**
@@ -113,7 +120,8 @@ public class FsStoreScrmController extends BaseController
      * 店铺审核
      */
     @PreAuthorize("@ss.hasPermi('his:store:audit')")
-    @Log(title = "店铺审核", businessType = BusinessType.UPDATE,logParam = {"店铺","店铺审核"},isStoreLog = true)
+    @Log(title = "店铺审核", businessType = BusinessType.AUDIT,logParam = {"店铺","店铺审核"},isStoreLog = true
+    ,logParamExpression = "#p0.getIsAudit()==1?new String[]{'店铺','店铺审核通过'}: new String[]{'店铺','店铺审核退回'}")
     @PutMapping("/audit")
     public AjaxResult audit(@RequestBody FsStoreAuditParam fsStore)
     {
@@ -126,9 +134,18 @@ public class FsStoreScrmController extends BaseController
     @PreAuthorize("@ss.hasPermi('his:store:refresh')")
     @Log(title = "店铺管理", businessType = BusinessType.UPDATE,logParam = {"店铺","重置店铺密码"},isStoreLog = true)
     @PutMapping("/refresh/{storeId}")
-    public AjaxResult refresh(Long storeId)
+    public AjaxResult refresh(@PathVariable Long storeId)
     {
         return toAjax(fsStoreService.refreshFsStore(storeId));
     }
 
+
+    /**
+     * 店铺审核日志
+     * */
+    @PreAuthorize("@ss.hasPermi('his:store:auditLog')")
+    @GetMapping("/auditLog/{storeId}")
+    public R auditLog(@PathVariable Long storeId){
+        return R.ok().put("auditLog",storeAuditLogUtil.selectOperLogByMainId(storeId));
+    }
 }

+ 11 - 1
fs-admin/src/main/java/com/fs/hisStore/controller/SysOperlogScrmController.java

@@ -3,11 +3,14 @@ package com.fs.hisStore.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.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.hisStore.param.StoreOperMainQueryParam;
 import com.fs.hisStore.service.ISysOperLogScrmService;
 import com.fs.hisStore.domain.SysOperLogScrm;
+import com.fs.hisStore.vo.StoreOperMainVO;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
@@ -28,7 +31,7 @@ public class SysOperlogScrmController extends BaseController
         this.operLogService = operLogService;
     }
 
-    @PreAuthorize("@ss.hasPermi('his:storeLog:export')")
+    @PreAuthorize("@ss.hasPermi('his:storeLog:list')")
     @GetMapping("/list")
     public TableDataInfo list(SysOperLogScrm operLog)
     {
@@ -36,6 +39,13 @@ public class SysOperlogScrmController extends BaseController
         List<SysOperLogScrm> list = operLogService.selectOperLogList(operLog);
         return getDataTable(list);
     }
+    @PreAuthorize("@ss.hasPermi('his:storeLog:list')")
+    @GetMapping("/getMains")
+    public R getMains(StoreOperMainQueryParam operLog)
+    {
+        List<StoreOperMainVO> list = operLogService.getMains(operLog);
+        return R.ok().put("data", list);
+    }
 
     @Log(title = "操作日志", businessType = BusinessType.EXPORT)
     @PreAuthorize("@ss.hasPermi('his:storeLog:export')")

+ 33 - 1
fs-admin/src/main/java/com/fs/qw/controller/QwCompanyController.java

@@ -2,8 +2,14 @@ package com.fs.qw.controller;
 
 import java.util.List;
 
+import cn.hutool.json.JSONUtil;
 import com.fs.common.core.domain.R;
+import com.fs.common.core.domain.model.LoginUser;
+import com.fs.common.utils.ServletUtils;
+import com.fs.course.config.CourseConfig;
+import com.fs.framework.web.service.TokenService;
 import com.fs.qw.vo.QwOptionsVO;
+import com.fs.system.service.ISysConfigService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -35,6 +41,10 @@ public class QwCompanyController extends BaseController
 {
     @Autowired
     private IQwCompanyService qwCompanyService;
+    @Autowired
+    private TokenService tokenService;
+    @Autowired
+    private ISysConfigService configService;
 
     /**
      * 查询企微主体列表
@@ -44,6 +54,13 @@ public class QwCompanyController extends BaseController
     public TableDataInfo list(QwCompany qwCompany)
     {
         startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+            qwCompany.setCreateDeptId(loginUser.getDeptId());
+            qwCompany.setCreateUserId(loginUser.getUserId());
+        }
         List<QwCompany> list = qwCompanyService.selectQwCompanyList(qwCompany);
         return getDataTable(list);
     }
@@ -52,7 +69,18 @@ public class QwCompanyController extends BaseController
     @GetMapping("/all")
     public R all()
     {
-        List<QwOptionsVO> list = qwCompanyService.selectQwCompanyListOptionsVO();
+        Long userId = null;
+        Long deptId = null;
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+            deptId = loginUser.getDeptId();
+            if(config.getDept() == null || !config.getDept()){
+                userId = loginUser.getUserId();
+            }
+        }
+        List<QwOptionsVO> list = qwCompanyService.selectQwCompanyListOptionsVO(userId, deptId);
         return R.ok().put("data", list);
     }
     /**
@@ -86,6 +114,10 @@ public class QwCompanyController extends BaseController
     @PostMapping
     public AjaxResult add(@RequestBody QwCompany qwCompany)
     {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+
+        qwCompany.setCreateUserId(loginUser.getUserId());
+        qwCompany.setCreateDeptId(loginUser.getDeptId());
         return toAjax(qwCompanyService.insertQwCompany(qwCompany));
     }
 

+ 39 - 0
fs-admin/src/main/java/com/fs/task/FsStoreTask.java

@@ -0,0 +1,39 @@
+package com.fs.task;
+
+import com.fs.hisStore.domain.FsStoreScrm;
+import com.fs.hisStore.service.IFsStoreScrmService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Component;
+import com.fs.common.utils.PubFun;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@AllArgsConstructor
+@Component("storeTaskScrm")
+public class FsStoreTask {
+
+    private final IFsStoreScrmService fsStoreScrmService;
+
+
+    public void store(){
+        LocalDate now = LocalDate.now();
+        List<FsStoreScrm> storeList = fsStoreScrmService.selectOverList();
+        List<FsStoreScrm> collect = storeList.stream().filter(e -> {
+            // 过期判定:任一证件到期日为 null 或 早于今天
+            return e.getBusinessLicenseExpireEnd() == null
+                    || e.getDrugLicenseExpiryEnd() == null
+                    || e.getMedicalLicenseExpiryEnd() == null
+                    || e.getBusinessLicenseExpireEnd().isBefore(now)
+                    || e.getDrugLicenseExpiryEnd().isBefore(now)
+                    || e.getMedicalLicenseExpiryEnd().isBefore(now);
+        }).collect(Collectors.toList());
+
+        if (!collect.isEmpty()) {
+            List<Long> ids = PubFun.listToNewList(collect, FsStoreScrm::getStoreId);
+            fsStoreScrmService.batchUpdateStatusByIds(ids, 0);
+        }
+    }
+
+}

+ 106 - 0
fs-admin/src/main/java/com/fs/user/controller/FsUserComplaintController.java

@@ -0,0 +1,106 @@
+package com.fs.user.controller;
+
+import java.util.List;
+
+import com.fs.user.domain.param.FsUserComplaintParam;
+import com.fs.user.domain.vo.FsUserComplaintVo;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.user.domain.FsUserComplaint;
+import com.fs.user.service.IFsUserComplaintService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 用户投诉Controller
+ *
+ * @author fs
+ * @date 2025-08-27
+ */
+@RestController
+@RequestMapping("/user/complaint")
+public class FsUserComplaintController extends BaseController
+{
+    @Autowired
+    private IFsUserComplaintService fsUserComplaintService;
+
+    /**
+     * 查询用户投诉列表
+     */
+    @PreAuthorize("@ss.hasPermi('user:complaint:list')")
+    @PostMapping("/list")
+    public TableDataInfo list(@RequestBody FsUserComplaintParam param)
+    {
+        startPage();
+        List<FsUserComplaintVo> list = fsUserComplaintService.selectFsUserComplaintVoList(param);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出用户投诉列表
+     */
+    @PreAuthorize("@ss.hasPermi('user:complaint:export')")
+    @Log(title = "用户投诉", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserComplaint fsUserComplaint)
+    {
+        List<FsUserComplaint> list = fsUserComplaintService.selectFsUserComplaintList(fsUserComplaint);
+        ExcelUtil<FsUserComplaint> util = new ExcelUtil<FsUserComplaint>(FsUserComplaint.class);
+        return util.exportExcel(list, "用户投诉数据");
+    }
+
+    /**
+     * 获取用户投诉详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('user:complaint:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsUserComplaintService.selectFsUserComplaintVoById(id));
+    }
+
+    /**
+     * 新增用户投诉
+     */
+    @PreAuthorize("@ss.hasPermi('user:complaint:add')")
+    @Log(title = "用户投诉", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserComplaint fsUserComplaint)
+    {
+        return toAjax(fsUserComplaintService.insertFsUserComplaint(fsUserComplaint));
+    }
+
+    /**
+     * 修改用户投诉
+     */
+    @PreAuthorize("@ss.hasPermi('user:complaint:edit')")
+    @Log(title = "用户投诉", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserComplaint fsUserComplaint)
+    {
+        return toAjax(fsUserComplaintService.updateFsUserComplaint(fsUserComplaint));
+    }
+
+    /**
+     * 删除用户投诉
+     */
+    @PreAuthorize("@ss.hasPermi('user:complaint:remove')")
+    @Log(title = "用户投诉", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsUserComplaintService.deleteFsUserComplaintByIds(ids));
+    }
+}

+ 109 - 0
fs-admin/src/main/java/com/fs/user/controller/FsUserComplaintMsgController.java

@@ -0,0 +1,109 @@
+package com.fs.user.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.user.domain.FsUserComplaintMsg;
+import com.fs.user.service.IFsUserComplaintMsgService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 投诉消息记录Controller
+ *
+ * @author fs
+ * @date 2025-09-08
+ */
+@RestController
+@RequestMapping("/user/msg")
+public class FsUserComplaintMsgController extends BaseController
+{
+    @Autowired
+    private IFsUserComplaintMsgService fsUserComplaintMsgService;
+
+    /**
+     * 查询投诉消息记录列表
+     */
+//    @PreAuthorize("@ss.hasPermi('user:msg:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserComplaintMsg fsUserComplaintMsg)
+    {
+        startPage();
+        List<FsUserComplaintMsg> list = fsUserComplaintMsgService.selectFsUserComplaintMsgList(fsUserComplaintMsg);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出投诉消息记录列表
+     */
+//    @PreAuthorize("@ss.hasPermi('user:msg:export')")
+    @Log(title = "投诉消息记录", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserComplaintMsg fsUserComplaintMsg)
+    {
+        List<FsUserComplaintMsg> list = fsUserComplaintMsgService.selectFsUserComplaintMsgList(fsUserComplaintMsg);
+        ExcelUtil<FsUserComplaintMsg> util = new ExcelUtil<FsUserComplaintMsg>(FsUserComplaintMsg.class);
+        return util.exportExcel(list, "投诉消息记录数据");
+    }
+
+    /**
+     * 获取投诉消息记录详细信息
+     */
+//    @PreAuthorize("@ss.hasPermi('user:msg:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsUserComplaintMsgService.selectFsUserComplaintMsgById(id));
+    }
+
+    /**
+     * 新增投诉消息记录
+     */
+    @PreAuthorize("@ss.hasPermi('user:msg:add')")
+    @Log(title = "投诉消息记录", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserComplaintMsg fsUserComplaintMsg)
+    {
+        if (fsUserComplaintMsg.getComplaintId() == null){
+            return AjaxResult.error("未查询到相关投诉!");
+        }
+        Long userId = getUserId();
+        fsUserComplaintMsg.setUserId(userId);
+        fsUserComplaintMsg.setSendType(2); //平台
+        return toAjax(fsUserComplaintMsgService.insertFsUserComplaintMsg(fsUserComplaintMsg));
+    }
+
+    /**
+     * 修改投诉消息记录
+     */
+    @PreAuthorize("@ss.hasPermi('user:msg:edit')")
+    @Log(title = "投诉消息记录", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserComplaintMsg fsUserComplaintMsg)
+    {
+        return toAjax(fsUserComplaintMsgService.updateFsUserComplaintMsg(fsUserComplaintMsg));
+    }
+
+    /**
+     * 删除投诉消息记录
+     */
+    @PreAuthorize("@ss.hasPermi('user:msg:remove')")
+    @Log(title = "投诉消息记录", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsUserComplaintMsgService.deleteFsUserComplaintMsgByIds(ids));
+    }
+}

+ 14 - 0
fs-admin/src/main/java/com/fs/web/controller/system/SysLoginController.java

@@ -3,9 +3,12 @@ package com.fs.web.controller.system;
 import java.util.List;
 import java.util.Set;
 
+import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.entity.SysRole;
 import com.fs.common.utils.PatternUtils;
+import com.fs.his.utils.ConfigUtil;
+import com.fs.hisStore.config.MedicalMallConfig;
 import com.fs.system.service.ISysRoleService;
 import lombok.Synchronized;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -45,6 +48,12 @@ public class SysLoginController
     @Autowired
     private ISysRoleService roleService;
 
+    @Autowired
+    private ConfigUtil configUtil;
+
+    @Autowired
+    private MedicalMallConfig medicalMallConfig;
+
     /**
      * 登录方法
      *
@@ -78,7 +87,12 @@ public class SysLoginController
         Set<String> roles = permissionService.getRolePermission(user);
         // 权限集合
         Set<String> permissions = permissionService.getMenuPermission(user);
+        //药品商城参数
         AjaxResult ajax = AjaxResult.success();
+
+        if(medicalMallConfig!=null){
+            ajax.put("medicalMallConfig", medicalMallConfig);
+        }
         ajax.put("user", user);
         Integer isAdmin = 0;
         if (permissions.contains("*:*:*")){

+ 18 - 40
fs-common-api/src/main/java/com/fs/framework/config/MyBatisConfig.java

@@ -32,82 +32,60 @@ import java.util.List;
 
  */
 @Configuration
-public class MyBatisConfig
-{
+public class MyBatisConfig {
     @Autowired
     private Environment env;
 
     static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
 
-    public static String setTypeAliasesPackage(String typeAliasesPackage)
-    {
+    public static String setTypeAliasesPackage(String typeAliasesPackage) {
         ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();
         MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
         List<String> allResult = new ArrayList<String>();
-        try
-        {
-            for (String aliasesPackage : typeAliasesPackage.split(","))
-            {
+        try {
+            for (String aliasesPackage : typeAliasesPackage.split(",")) {
                 List<String> result = new ArrayList<String>();
                 aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                         + ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN;
                 Resource[] resources = resolver.getResources(aliasesPackage);
-                if (resources != null && resources.length > 0)
-                {
+                if (resources != null && resources.length > 0) {
                     MetadataReader metadataReader = null;
-                    for (Resource resource : resources)
-                    {
-                        if (resource.isReadable())
-                        {
+                    for (Resource resource : resources) {
+                        if (resource.isReadable()) {
                             metadataReader = metadataReaderFactory.getMetadataReader(resource);
-                            try
-                            {
+                            try {
                                 result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
-                            }
-                            catch (ClassNotFoundException e)
-                            {
+                            } catch (ClassNotFoundException e) {
                                 e.printStackTrace();
                             }
                         }
                     }
                 }
-                if (result.size() > 0)
-                {
+                if (result.size() > 0) {
                     HashSet<String> hashResult = new HashSet<String>(result);
                     allResult.addAll(hashResult);
                 }
             }
-            if (allResult.size() > 0)
-            {
+            if (allResult.size() > 0) {
                 typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0]));
-            }
-            else
-            {
+            } else {
                 throw new RuntimeException("mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包");
             }
-        }
-        catch (IOException e)
-        {
+        } catch (IOException e) {
             e.printStackTrace();
         }
         return typeAliasesPackage;
     }
 
-    public Resource[] resolveMapperLocations(String[] mapperLocations)
-    {
+    public Resource[] resolveMapperLocations(String[] mapperLocations) {
         ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
         List<Resource> resources = new ArrayList<Resource>();
-        if (mapperLocations != null)
-        {
-            for (String mapperLocation : mapperLocations)
-            {
-                try
-                {
+        if (mapperLocations != null) {
+            for (String mapperLocation : mapperLocations) {
+                try {
                     Resource[] mappers = resourceResolver.getResources(mapperLocation);
                     resources.addAll(Arrays.asList(mappers));
-                }
-                catch (IOException e)
-                {
+                } catch (IOException e) {
                     // ignore
                 }
             }

+ 2 - 2
fs-common-api/src/main/resources/application.yml

@@ -4,5 +4,5 @@ server:
 # Spring配置
 spring:
   profiles:
-#    active: dev
-    active: druid-jnmy
+    active: dev-yjb
+#    active: druid-jnmy

+ 6 - 2
fs-common/src/main/java/com/fs/common/core/domain/model/LoginUser.java

@@ -1,7 +1,7 @@
 package com.fs.common.core.domain.model;
 
-import java.util.Collection;
-import java.util.Set;
+import java.util.*;
+
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.userdetails.UserDetails;
 import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -14,6 +14,7 @@ import com.fs.common.core.domain.entity.SysUser;
  */
 public class LoginUser implements UserDetails
 {
+    private static final List<String> ADMIN_USER_NAME = Collections.singletonList("admin");
     private static final long serialVersionUID = 1L;
 
     /**
@@ -254,6 +255,9 @@ public class LoginUser implements UserDetails
     {
         return user;
     }
+    public boolean isAdmin(){
+        return ADMIN_USER_NAME.contains(user.getUserName());
+    }
 
     public void setUser(SysUser user)
     {

+ 9 - 5
fs-common/src/main/java/com/fs/common/core/redis/RedisCache.java

@@ -1,10 +1,6 @@
 package com.fs.common.core.redis;
 
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 import java.util.concurrent.TimeUnit;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.BoundSetOperations;
@@ -236,4 +232,12 @@ public class RedisCache
     public Boolean setIfAbsent(String key, String value, long timeout, TimeUnit unit) {
         return redisTemplate.opsForValue().setIfAbsent(key, value, timeout, unit);
     }
+
+    public Long decr(final String key,final Long delta) {
+        return redisTemplate.opsForValue().decrement(key, delta);
+    }
+
+    public Long incr(final String key,final Long delta) {
+        return redisTemplate.opsForValue().increment(key, delta);
+    }
 }

+ 7 - 2
fs-common/src/main/java/com/fs/common/enums/BusinessType.java

@@ -2,7 +2,7 @@ package com.fs.common.enums;
 
 /**
  * 业务操作类型
- * 
+ *
 
  */
 public enum BusinessType
@@ -51,9 +51,14 @@ public enum BusinessType
      * 生成代码
      */
     GENCODE,
-    
+
     /**
      * 清空数据
      */
     CLEAN,
+
+    /**
+     * 审核
+     * */
+    AUDIT,
 }

+ 140 - 0
fs-common/src/main/java/com/fs/common/utils/poi/ExcelUtil.java

@@ -1274,4 +1274,144 @@ public class ExcelUtil<T>
         }
         return sheetIndexPicMap;
     }
+    /**
+     * 对list数据源将其里面的数据导入到excel表单(只导出选中的列)
+     *
+     * @param list 导出数据集合
+     * @param sheetName 工作表的名称
+     * @param selectedFields 选中的字段列表
+     * @return 结果
+     */
+    public AjaxResult exportExcelSelectedColumns(List<T> list, String sheetName, List<String> selectedFields) {
+        this.init(list, sheetName, Type.EXPORT);
+        return exportExcelSelectedColumns(selectedFields);
+    }
+
+    /**
+     * 对list数据源将其里面的数据导入到excel表单(只导出选中的列)
+     *
+     * @param response 返回数据
+     * @param list 导出数据集合
+     * @param sheetName 工作表的名称
+     * @param selectedFields 选中的字段列表
+     * @return 结果
+     * @throws IOException
+     */
+    public void exportExcelSelectedColumns(HttpServletResponse response, List<T> list, String sheetName, List<String> selectedFields) throws IOException {
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+        this.init(list, sheetName, Type.EXPORT);
+        exportExcelSelectedColumns(response.getOutputStream(), selectedFields);
+    }
+
+    /**
+     * 对list数据源将其里面的数据导入到excel表单(只导出选中的列)
+     *
+     * @param selectedFields 选中的字段列表
+     * @return 结果
+     */
+    public void exportExcelSelectedColumns(OutputStream out, List<String> selectedFields) {
+        try {
+            writeSelectedSheet(selectedFields);
+            wb.write(out);
+        } catch (Exception e) {
+            log.error("导出Excel异常{}", e.getMessage());
+        } finally {
+            IOUtils.closeQuietly(wb);
+            IOUtils.closeQuietly(out);
+        }
+    }
+
+    /**
+     * 对list数据源将其里面的数据导入到excel表单(只导出选中的列)
+     *
+     * @param selectedFields 选中的字段列表
+     * @return 结果
+     */
+    public AjaxResult exportExcelSelectedColumns(List<String> selectedFields) {
+        OutputStream out = null;
+        try {
+            writeSelectedSheet(selectedFields);
+            String filename = encodingFilename(sheetName);
+            out = new FileOutputStream(getAbsoluteFile(filename));
+            wb.write(out);
+            return AjaxResult.success(filename);
+        } catch (Exception e) {
+            log.error("导出Excel异常{}", e.getMessage());
+            throw new UtilException("导出Excel失败,请联系网站管理员!");
+        } finally {
+            IOUtils.closeQuietly(wb);
+            IOUtils.closeQuietly(out);
+        }
+    }
+
+    /**
+     * 创建写入数据到Sheet(只写入选中的列)
+     */
+    public void writeSelectedSheet(List<String> selectedFields) {
+        // 筛选出选中的字段
+        List<Object[]> selectedFieldList = filterSelectedFields(selectedFields);
+
+        // 取出一共有多少个sheet.
+        double sheetNo = Math.ceil(list.size() / sheetSize);
+        for (int index = 0; index <= sheetNo; index++) {
+            createSheet(sheetNo, index);
+
+            // 产生一行
+            Row row = sheet.createRow(0);
+            int column = 0;
+            // 写入各个字段的列头名称(只写入选中的字段)
+            for (Object[] os : selectedFieldList) {
+                Excel excel = (Excel) os[1];
+                this.createCell(excel, row, column++);
+            }
+            if (Type.EXPORT.equals(type)) {
+                fillSelectedExcelData(index, row, selectedFieldList);
+                addStatisticsRow();
+            }
+        }
+    }
+
+    /**
+     * 筛选出选中的字段
+     */
+    private List<Object[]> filterSelectedFields(List<String> selectedFields) {
+        if (selectedFields == null || selectedFields.isEmpty()) {
+            return this.fields; // 如果没有选择字段,返回所有字段
+        }
+
+        List<Object[]> selectedFieldList = new ArrayList<>();
+        for (Object[] fieldInfo : this.fields) {
+            Field field = (Field) fieldInfo[0];
+            if (selectedFields.contains(field.getName())) {
+                selectedFieldList.add(fieldInfo);
+            }
+        }
+        return selectedFieldList;
+    }
+
+    /**
+     * 填充excel数据(只填充选中的列)
+     *
+     * @param index 序号
+     * @param row 单元格行
+     * @param selectedFieldList 选中的字段列表
+     */
+    public void fillSelectedExcelData(int index, Row row, List<Object[]> selectedFieldList) {
+        int startNo = index * sheetSize;
+        int endNo = Math.min(startNo + sheetSize, list.size());
+        for (int i = startNo; i < endNo; i++) {
+            row = sheet.createRow(i + 1 - startNo);
+            // 得到导出对象.
+            T vo = (T) list.get(i);
+            int column = 0;
+            for (Object[] os : selectedFieldList) {
+                Field field = (Field) os[0];
+                Excel excel = (Excel) os[1];
+                // 设置实体类私有属性可访问
+                field.setAccessible(true);
+                this.addCell(excel, row, vo, field, column++);
+            }
+        }
+    }
 }

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

@@ -107,7 +107,7 @@ public class CompanyController extends BaseController
     @GetMapping("/allList")
     public TableDataInfo getHospital()
     {
-        List<OptionsVO> list = companyService.selectAllCompanyList();
+        List<OptionsVO> list = companyService.selectAllCompanyList(null);
         return getDataTable(list);
     }
 

+ 3 - 2
fs-company/src/main/java/com/fs/company/controller/course/FsCourseAnswerLogsController.java

@@ -49,8 +49,9 @@ public class FsCourseAnswerLogsController extends BaseController
             param.setPhone(param.getPhoneMk());
         }
 
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        param.setCompanyId( loginUser.getCompany().getCompanyId());
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        // 如果他可以看两个销售公司就会查不出来
+//        param.setCompanyId( loginUser.getCompany().getCompanyId());
 
         List<FsCourseAnswerLogsListVO> list = fsCourseAnswerLogsService.selectFsCourseAnswerLogsListVONew(param);
         TableDataInfo rspData = new TableDataInfo();

+ 3 - 2
fs-company/src/main/java/com/fs/company/controller/course/FsCourseRedPacketLogController.java

@@ -57,8 +57,9 @@ public class FsCourseRedPacketLogController extends BaseController
         if (fsCourseRedPacketLog.getPhoneMk() != null && fsCourseRedPacketLog.getPhoneMk() != "") {
             fsCourseRedPacketLog.setPhone(encryptPhone(fsCourseRedPacketLog.getPhoneMk()));
         }
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        fsCourseRedPacketLog.setCompanyId( loginUser.getCompany().getCompanyId());
+//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        // 如果他可以看两个销售公司就会查不出来
+//        fsCourseRedPacketLog.setCompanyId( loginUser.getCompany().getCompanyId());
 
         List<FsCourseRedPacketLogListPVO> list = fsCourseRedPacketLogService.selectFsCourseRedPacketLogListVO(fsCourseRedPacketLog);
         for (FsCourseRedPacketLogListPVO fsCourseRedPacketLogListPVO : list) {

+ 1 - 1
fs-company/src/main/java/com/fs/company/controller/course/FsUserCourseTrainingCampController.java

@@ -36,7 +36,7 @@ public class FsUserCourseTrainingCampController {
     /**
      * 查询训练营列表
      */
-    @PreAuthorize("@ss.hasPermi('course:trainingCamp:list')")
+    //@PreAuthorize("@ss.hasPermi('course:trainingCamp:list')")
     @GetMapping("/list")
     public AjaxResult list(@RequestParam(required = false) String trainingCampName,
                            @RequestParam(required = false) String userId,

+ 1 - 1
fs-company/src/main/java/com/fs/company/controller/course/FsUserOperationLogController.java

@@ -25,7 +25,7 @@ public class FsUserOperationLogController extends BaseController {
     @Autowired
     private IFsUserOperationLogService fsUserOperationLogService;
 
-    @PreAuthorize("@ss.hasPermi('his:userOperationLog:list')")
+    //@PreAuthorize("@ss.hasPermi('his:userOperationLog:list')")
     @GetMapping("/list")
     public TableDataInfo list(FsUserOperationLog fsUserOperationLog)
     {

+ 11 - 0
fs-company/src/main/java/com/fs/company/controller/qw/QwSopController.java

@@ -278,6 +278,17 @@ public class QwSopController extends BaseController
         return toAjax(qwSopService.deleteQwSopByIds(ids));
     }
 
+    /**
+     * 批量删除SOP 任务下面的执行记录
+     */
+    @PreAuthorize("@ss.hasPermi('qw:sopLogs:removeAll')")
+    @Log(title = "企微sop", businessType = BusinessType.DELETE)
+	@DeleteMapping("/delSopLogs/{ids}")
+    public AjaxResult removeAll(@PathVariable String[] ids)
+    {
+        return toAjax(qwSopService.deleteQwSopLogsBySopIds(ids));
+    }
+
 
     /**
      * 批量执行SOP

+ 3 - 1
fs-company/src/main/java/com/fs/company/controller/qw/QwSopLogsController.java

@@ -149,7 +149,9 @@ public class QwSopLogsController extends BaseController
      * 我的自动化任务 和部门自动化任务 就只显示自己的或者部门的
      */
     private List<Long> getQwUserKeyList(QwSopLogsParam param, LoginUser loginUser) {
-
+        if(param.getFilterSopType() == null){
+            return new ArrayList<>(); // 返回空列表而不是null
+        }
         switch (param.getFilterSopType()) {
             case 2:
                 CompanyUser companyUser = iCompanyUserService.selectCompanyUserById(loginUser.getUser().getUserId());

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

@@ -83,10 +83,10 @@ public class SopUserLogsController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
 
         List<String> qwUserIdList=null;
-        if (sopUserLogs.getType()==2){
+        if (sopUserLogs.getType() != null && sopUserLogs.getType()==2){
             qwUserIdList = iQwUserService.selectQwUserListByCompanyUserId(loginUser.getUser().getUserId(), sopUserLogs.getCorpId());
         }
-        if (qwUserIdList!=null&& !qwUserIdList.isEmpty() && sopUserLogs.getType()==2 ){
+        if (qwUserIdList!=null&& !qwUserIdList.isEmpty() && sopUserLogs.getType() != null &&  sopUserLogs.getType()==2 ){
             sopUserLogs.setQwIdsList(qwUserIdList);
         }
 

+ 2 - 2
fs-company/src/main/java/com/fs/company/controller/store/FsStoreOrderController.java

@@ -130,7 +130,7 @@ public class FsStoreOrderController extends BaseController
         task.setCompanyUserId(userId);
         exportTaskService.insertFsExportTask(task);
         param.setTaskId(task.getTaskId());
-        exportTaskService.exportStore1Data(param,false);
+        exportTaskService.exportStore1Data(param,false, null);
         return new AjaxResult(200,"后台正在导出,请等待...任务ID:"+task.getTaskId(),task.getTaskId());
 
 
@@ -172,7 +172,7 @@ public class FsStoreOrderController extends BaseController
         task.setCompanyUserId(userId);
         exportTaskService.insertFsExportTask(task);
         param.setTaskId(task.getTaskId());
-        exportTaskService.exportStore1Data(param,false);
+        exportTaskService.exportStore1Data(param,false, null);
         return new AjaxResult(200,"后台正在导出,请等待...任务ID:"+task.getTaskId(),task.getTaskId());
     }
     /**

+ 2 - 2
fs-company/src/main/resources/application.yml

@@ -4,11 +4,11 @@ server:
 spring:
   profiles:
 #    active: druid-fcky-test
-#    active: dev
+    active: dev
 #    active: druid-jzzx-test
 #    active: druid-hdt
 #    active: druid-sxjz
 #    active: druid-yzt
 #    active: druid-myhk
 #    active: druid-sft
-    active: dev
+#    active: dev-yjb

+ 1 - 14
fs-doctor-app/src/main/java/com/fs/app/controller/InquiryOrderController.java

@@ -1,27 +1,19 @@
 package com.fs.app.controller;
 
 
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.fs.app.annotation.Login;
-import com.fs.app.param.InquiryOrderMsgListParam;
 import com.fs.common.BeanCopyUtils;
 import com.fs.common.annotation.Log;
-import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
-import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.SecurityUtils;
 import com.fs.common.utils.StringUtils;
-import com.fs.common.utils.ip.IpUtils;
 import com.fs.company.service.ICompanyService;
 import com.fs.core.config.WxPayProperties;
 import com.fs.core.utils.OrderCodeUtils;
 import com.fs.his.domain.*;
 import com.fs.his.dto.FsInquiryOrderPatientDTO;
-import com.fs.his.enums.FsInquiryOrderStatusEnum;
 import com.fs.his.param.*;
 import com.fs.his.service.*;
 import com.fs.his.vo.*;
@@ -30,10 +22,6 @@ import com.fs.im.dto.MsgDTO;
 import com.fs.im.dto.MsgDataDTO;
 import com.fs.im.dto.MsgDataFormatDTO;
 import com.fs.im.service.IImService;
-import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
-import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
-import com.github.binarywang.wxpay.config.WxPayConfig;
-import com.github.binarywang.wxpay.exception.WxPayException;
 import com.github.binarywang.wxpay.service.WxPayService;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
@@ -42,7 +30,6 @@ import io.swagger.annotations.ApiOperation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
@@ -128,7 +115,7 @@ public class InquiryOrderController extends  AppBaseController {
     @GetMapping("/getCompanyList")
     public R getCompanyList()
     {
-        List<OptionsVO> list = companyService.selectAllCompanyList();
+        List<OptionsVO> list = companyService.selectAllCompanyList(null);
         return R.ok().put("list",list);
     }
     @Login

+ 25 - 2
fs-framework/src/main/java/com/fs/framework/aspectj/LogAspect.java

@@ -1,6 +1,8 @@
 package com.fs.framework.aspectj;
 
 import java.lang.reflect.Method;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Map;
@@ -11,6 +13,8 @@ import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.bean.BeanUtils;
 import com.fs.framework.web.domain.server.Sys;
 import com.fs.hisStore.domain.SysOperLogScrm;
+import com.fs.statis.dto.ProductAuditDTO;
+import com.fs.statis.dto.StoreAuditDTO;
 import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.Signature;
@@ -18,6 +22,7 @@ import org.aspectj.lang.annotation.*;
 import org.aspectj.lang.reflect.MethodSignature;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
 import org.springframework.expression.EvaluationContext;
 import org.springframework.expression.ExpressionParser;
 import org.springframework.expression.spel.standard.SpelExpressionParser;
@@ -39,6 +44,8 @@ import com.fs.framework.manager.AsyncManager;
 import com.fs.framework.manager.factory.AsyncFactory;
 import com.fs.system.domain.SysOperLog;
 
+import static com.fs.common.utils.SecurityUtils.getUserId;
+
 /**
  * 操作日志记录处理
  *
@@ -123,9 +130,17 @@ public class LogAspect
             getControllerMethodDescription(joinPoint, controllerLog, operLog);
             // 保存数据库
             AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
-            if(controllerLog.isStoreLog()){
+            if(controllerLog.isStoreLog() ){
                 SysOperLogScrm operLogScrm = new SysOperLogScrm();
+                //插入operId
+                String operId = MDC.get("operIds");
                 BeanUtils.copyProperties(operLog, operLogScrm);
+                Long[] operIds = new Long[operId.split(",").length];
+                String[] operIdStrs = operId.split(",");
+                for (int i = 0; i < operIdStrs.length; i++) {
+                    operIds[i] = Long.parseLong(operIdStrs[i]);
+                }
+                operLogScrm.setOperIds(operIds);
                 resolveParam((ProceedingJoinPoint)joinPoint,operLogScrm);
                 AsyncManager.me().execute(AsyncFactory.recordOperScrm(operLogScrm));
             }
@@ -258,7 +273,7 @@ public class LogAspect
 
     private final ExpressionParser parser = new SpelExpressionParser();
 
-    public void resolveParam(ProceedingJoinPoint joinPoint, SysOperLogScrm operLog) throws Throwable {
+    public void resolveParam(ProceedingJoinPoint joinPoint, SysOperLogScrm operLog) {
         // 1. 获取注解实例
         Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
         Log annotation = method.getAnnotation(Log.class);
@@ -300,4 +315,12 @@ public class LogAspect
         operLog.setMainType(logParam[0]);
         operLog.setDes(logParam[1]);
     }
+
+
+    @After("logPointCut()")
+    public void after(JoinPoint joinPoint) throws Throwable {
+        // 移除 MDC 中的 logId
+        MDC.remove("operIds");
+    }
+
 }

+ 7 - 1
fs-framework/src/main/java/com/fs/framework/manager/factory/AsyncFactory.java

@@ -118,8 +118,14 @@ public class AsyncFactory
             {
                 // 远程查询操作地点
                 operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
-                SpringUtils.getBean(ISysOperLogScrmService.class).insertOperlog(operLog);
+                SpringUtils.getBean(ISysOperLogScrmService.class).updateOperLog(operLog);
             }
         };
     }
+
+    /**
+     * 生成日志记录
+     * */
+
+
 }

+ 26 - 6
fs-ipad-task/src/main/java/com/fs/app/service/IpadSendServer.java

@@ -1,9 +1,12 @@
 package com.fs.app.service;
 
+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.course.config.CourseMaConfig;
+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;
@@ -15,7 +18,6 @@ import com.fs.qw.mapper.QwExternalContactMapper;
 import com.fs.qw.mapper.QwUserMapper;
 import com.fs.qw.service.IQwUserService;
 import com.fs.qw.service.IQwUserVideoService;
-import com.fs.qw.service.impl.QwUserServiceImpl;
 import com.fs.qw.vo.QwSopCourseFinishTempSetting;
 import com.fs.qwApi.param.QwExternalContactHParam;
 import com.fs.sop.domain.QwSopLogs;
@@ -27,6 +29,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
+import java.util.List;
 import java.util.Map;
 
 @Slf4j
@@ -42,9 +45,26 @@ public class IpadSendServer {
     private final IFsCourseWatchLogService watchLogService;
     private final IQwUserVideoService qwUserVideoService;
     private final RedisCache redisCache;
+    private final ICompanyMiniappService companyMiniappService;
 
-    private void sendMiniProgram(BaseVo vo, QwSopCourseFinishTempSetting.Setting content, Map<String, FsCoursePlaySourceConfig> miniMap) {
-        FsCoursePlaySourceConfig courseMaConfig = miniMap.get(content.getMiniprogramAppid());
+    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();
+            }
+        }
+        FsCoursePlaySourceConfig courseMaConfig = miniMap.get(appid);
+        if(courseMaConfig == null){
+            List<CompanyMiniapp> list = companyMiniappService.list(new QueryWrapper<CompanyMiniapp>().eq("company_id", companyId).eq("type", 1));
+            if(!list.isEmpty() && list.get(0) != null && StringUtils.isNotEmpty(list.get(0).getAppId())){
+                courseMaConfig = miniMap.get(list.get(0).getAppId());
+            }
+        }
+        if(courseMaConfig == null){
+            throw new BaseException("未找到小程序配置:{}", appid);
+        }
         // 小程序
         MiniProgramVo miniProgramVo = MiniProgramVo.builder()
                 .desc(content.getMiniprogramTitle())
@@ -53,7 +73,7 @@ public class IpadSendServer {
                 .imgUrl(content.getMiniprogramPicUrl())
                 .username(courseMaConfig.getOriginalId() + "@app")
                 .pagepath(content.getMiniprogramPage())
-                .appid(content.getMiniprogramAppid())
+                .appid(courseMaConfig.getAppid())
                 .build();
         miniProgramVo.setBase(vo);
         WxWorkResponseDTO<WxWorkSendAppMsgRespDTO> resp = ipadSendUtils.sendMiniProgram(miniProgramVo);
@@ -337,7 +357,7 @@ public class IpadSendServer {
                     break;
                 case "4":
                 case "10":
-                    sendMiniProgram(vo, content, miniMap);
+                    sendMiniProgram(vo, content, miniMap, qwUser.getCompanyId());
                     break;
                 case "5":
                     // 文件

+ 2 - 2
fs-ipad-task/src/main/java/com/fs/app/task/SendMsg.java

@@ -92,8 +92,8 @@ public class SendMsg {
 
     private Map<String, FsCoursePlaySourceConfig> getMiniMap() {
         List<FsCoursePlaySourceConfig> list = fsCoursePlaySourceConfigService.list(new QueryWrapper<FsCoursePlaySourceConfig>().ne("type", 2).eq("is_del", 0));
-//        SysConfig maConfig = sysConfigMapper.selectConfigByConfigKey("courseMa.config");
-//        List<CourseMaConfig> courseMaConfigs = JSON.parseArray(maConfig.getConfigValue(), CourseMaConfig.class);
+        log.info("获取到的小程序配置:{}", JSON.toJSONString(list));
+        log.info("获取到的小程序配置:{}", JSON.toJSONString(list));
         return PubFun.listToMapByGroupObject(list, FsCoursePlaySourceConfig::getAppid);
     }
 

+ 38 - 37
fs-qw-api-msg/src/main/java/com/fs/app/controller/QwMsgController.java

@@ -206,43 +206,43 @@ public class QwMsgController {
         }
         switch (type){
             case 100001:
-                System.out.println("扫码返回");
+                log.info("id:{}, 扫码返回", id);
                 break;
             case 100002:
-                System.out.println("取消扫码");
+                log.info("id:{}, 取消扫码", id);
               //  redisCache.setCacheObject("qrCodeUid:"+wxWorkMsgResp.getUuid(),100002,10, TimeUnit.MINUTES);
                 break;
             case 100003:
-                System.out.println("确认扫码返回");
+                log.info("id:{}, 确认扫码返回", id);
 
                 break;
             case 104001:
-                System.out.println("登录成功");
+                log.info("id:{}, 登录成功", id);
 
                 JSONObject jsonObject = new JSONObject(wxWorkMsgResp.getJson());
                 QwUser qu = qwUserMapper.selectQwUserById(id);
                 Long corpId = jsonObject.getLong("Corpid");
-                System.out.println("回调中的"+corpId);
+                log.info("id:{}, 回调中的"+corpId, id);
                 String sCorpId = wxWorkService.getCorpId(wxWorkMsgResp.getUuid(), corpId,serverId);
                 if (sCorpId==null&& sCorpId.isEmpty()){
                     break;
                 }
                 if (!qu.getCorpId().equals(sCorpId)){
                     redisCache.setCacheObject("qrCodeUid:"+wxWorkMsgResp.getUuid(),22,10, TimeUnit.MINUTES);
-                    System.out.println("公司不匹配不给登录");
+                    log.info("id:{}, 公司不匹配不给登录", id);
                     WxWorkGetQrCodeDTO wxWorkGetQrCodeDTO = new WxWorkGetQrCodeDTO();
                     wxWorkGetQrCodeDTO.setUuid(wxWorkMsgResp.getUuid());
                     wxWorkService.LoginOut(wxWorkGetQrCodeDTO,serverId);
-                    log.info("调用退出登录");
+                    log.info("id:{}, 调用退出登录", id);
                     break;
                 }
                 if (!qu.getQwUserId().equals(jsonObject.get("acctid"))){
                     redisCache.setCacheObject("qrCodeUid:"+wxWorkMsgResp.getUuid(),23,10, TimeUnit.MINUTES);
-                    System.out.println("账号不匹配不给登录");
+                    log.info("id:{}, 账号不匹配不给登录", id);
                     WxWorkGetQrCodeDTO wxWorkGetQrCodeDTO = new WxWorkGetQrCodeDTO();
                     wxWorkGetQrCodeDTO.setUuid(wxWorkMsgResp.getUuid());
                     wxWorkService.LoginOut(wxWorkGetQrCodeDTO,serverId);
-                    log.info("调用退出登录");
+                    log.info("id:{}, 调用退出登录", id);
                     break;
                 }
                 QwUser qwUser = new QwUser();
@@ -250,44 +250,44 @@ public class QwMsgController {
                 qwUser.setVid(jsonObject.get("Vid").toString());
                 qwUser.setIpadStatus(1);
                 qwUserMapper.updateQwUser(qwUser);
-                System.out.println("存Vid");
+                log.info("id:{}, 存Vid", id);
                 redisCache.setCacheObject("qrCodeUid:"+wxWorkMsgResp.getUuid(),104001,10, TimeUnit.MINUTES);
                 break;
             case 100006:
 
                 break;
             case 100004:
-                System.out.println("需要验证二维码消息");
+                log.info("id:{}, 需要验证二维码消息", id);
                 redisCache.setCacheObject("qrCodeUid:"+wxWorkMsgResp.getUuid(),100004,10, TimeUnit.MINUTES);
                 break;
             case 100012:
-                log.info("需要二次验证:"+wxWorkMsgResp.getJson());
+                log.info("id:{}, 需要二次验证:"+wxWorkMsgResp.getJson(), id);
 
                 redisCache.setCacheObject("qrCodeUid:"+wxWorkMsgResp.getUuid(),100012,10, TimeUnit.MINUTES);
 
                 break;
             case 100005:
 
-                log.info("手机端结束登录:"+wxWorkMsgResp.getJson());
+                log.info("id:{}, 手机端结束登录:"+wxWorkMsgResp.getJson(), id);
                 JSONObject jsonObject1 = new JSONObject(wxWorkMsgResp.getJson());
                 qwUserStatus(wxWorkMsgResp.getUuid(),0, jsonObject1.getString("msg"));
                 break;
             case 100008:
                 QwUser vidUser = qwUserMapper.selectQwUserById(id);
                 if (vidUser.getUid().equals(wxWorkMsgResp.getUuid())){
-                    log.info("当前账号在其他设备登录:"+wxWorkMsgResp.getJson());
+                    log.info("id:{}, 当前账号在其他设备登录:"+wxWorkMsgResp.getJson(), id);
                     JSONObject jsonObject2 = new JSONObject(wxWorkMsgResp.getJson());
                     qwUserStatus(wxWorkMsgResp.getUuid(),0, jsonObject2.getString("msg"));
                 }
-                log.info("当前账号重新登录:"+wxWorkMsgResp.getJson());
+                log.info("id:{}, 当前账号重新登录:"+wxWorkMsgResp.getJson(), id);
                 break;
             case 100007:
-                log.info("异常断开:"+wxWorkMsgResp.getJson());
+                log.info("id:{}, 异常断开:"+wxWorkMsgResp.getJson(), id);
                 JSONObject jsonObject3 = new JSONObject(wxWorkMsgResp.getJson());
                 qwUserStatus(wxWorkMsgResp.getUuid(),0, "异常断开 - " + jsonObject3.getString("msg"));
                 break;
             case 100009:
-                log.info("二次验证:"+wxWorkMsgResp.getJson());
+                log.info("id:{}, 二次验证:"+wxWorkMsgResp.getJson(), id);
                 JSONObject jsonObject4 = new JSONObject(wxWorkMsgResp.getJson());
                 qwUserStatus(wxWorkMsgResp.getUuid(),0, "二次验证 - " + jsonObject4.getString("msg"));
                 break;
@@ -307,9 +307,9 @@ public class QwMsgController {
                 if (wxWorkMessageDTO.getMsgtype()==2||wxWorkMessageDTO.getMsgtype()==0||wxWorkMessageDTO.getMsgtype()==16||wxWorkMessageDTO.getMsgtype() == 101||wxWorkMessageDTO.getMsgtype() == 104){
 
                     String content = wxWorkMessageDTO.getContent();
-                    System.out.println("接收人:"+wxWorkMessageDTO.getReceiver());
-                    System.out.println("发送人:"+wxWorkMessageDTO.getSender());
-                    System.out.println("内容:"+content);
+                    log.info("id:{}, 接收人:"+wxWorkMessageDTO.getReceiver(), id);
+                    log.info("id:{}, 发送人:"+wxWorkMessageDTO.getSender(), id);
+                    log.info("id:{}, 内容:"+content, id);
                     Long receiver = wxWorkMessageDTO.getReceiver();
                     Long sender = wxWorkMessageDTO.getSender();
                     if(wxWorkMessageDTO.getMsgtype()==16){
@@ -323,32 +323,32 @@ public class QwMsgController {
                                 TimeUnit.SECONDS.sleep(1); // 阻塞1秒
                             } catch (InterruptedException e) {
                                 Thread.currentThread().interrupt(); // 处理中断异常
-                                System.out.println("第一次语音转换失败");
+                                log.info("id:{}, 第一次语音转换失败", id);
                             }
                             dto = wxWorkService.SpeechToTextEntity(ste, serverId);
                         }
                         WxwSpeechToTextEntityRespDTO data = dto.getData();
                         content = data.getText();
-                        System.out.println("语音消息"+content);
                         if(content == null || content.isEmpty()){
                             content = "==语音转换失败==";
                         }
+                        log.info("id:{}, 语音消息"+content, id);
                     }
                     else if (wxWorkMessageDTO.getMsgtype() == 101){
                         content = processImageMessage(serverId, wxWorkMessageDTO, wxWorkMsgResp);
-                        System.out.println("用户发送图片"+content);
+                        log.info("id:{}, 用户发送图片"+content, id);
                     }
                     // gif 表情消息
                     else if (wxWorkMessageDTO.getMsgtype() == 104){
                         content = wxWorkMessageDTO.getUrl();
-                        System.out.println("用户发送表情"+content);
+                        log.info("id:{}, 用户发送表情"+content, id);
                     }
 
                     if (2000000000000000L-receiver>0){
-                        System.out.println("客户发送");
+                        log.info("id:{}, 客户发送", id);
                         aiHookService.qwHookNotifyAiReply(id,sender,content,wxWorkMsgResp.getUuid(),wxWorkMessageDTO.getMsgtype());
                     }else {
-                        System.out.println("销售发送");
+                        log.info("id:{}, 销售发送", id);
                         aiHookService.qwHookNotifyAddMsg(id,receiver,content,wxWorkMsgResp.getUuid());
                     }
 
@@ -360,12 +360,12 @@ public class QwMsgController {
                     }
                     Long receiver = wxWorkMessageDTO.getReceiver();
                     Long extId=null;
-                    Long totalSeconds=null;
+                    long totalSeconds=0L;
                     if (2000000000000000L-receiver>0){
                          extId = wxWorkMessageDTO.getSender();
-                        System.out.println("客户发起");
+                        log.info("id:{}, 客户发起", id);
                     }else {
-                        System.out.println("销售发起");
+                        log.info("id:{}, 销售发起", id);
                         extId = wxWorkMessageDTO.getReceiver();
                     }
                     Integer recordType = wxWorkMessageDTO.getRecordtype();
@@ -392,11 +392,11 @@ public class QwMsgController {
                                     seconds = Integer.parseInt(matcher.group(2));
                                 }
                                 totalSeconds = hours * 3600L + minutes * 60L + seconds;
-                                System.out.println("总通话秒数: " + totalSeconds);
+                                log.info("id:{}, 总通话秒数: " + totalSeconds, id);
                             }
                         }
                     } else if (recordType==2){
-                        System.out.println("通话挂断");
+                        log.info("id:{}, 通话挂断", id);
                     }else {
                         break;
                     }
@@ -425,15 +425,15 @@ public class QwMsgController {
         QwUser user = qwUserMapper.selectQwUserById(qwUserId);
         //查询接收人
         if(user==null){
-            System.out.println("查询接收人为空");
+            log.info("查询接收人为空");
         }
         if(user.getFastGptRoleId()==null){
-            System.out.println("未绑定角色");
+            log.info("未绑定角色");
         }
         Long serverId = user.getServerId();
-        System.out.println("服务器id"+serverId);
+        log.info("服务器id"+serverId);
         if (serverId == null) {
-            System.out.println("服务id为空");
+            log.info("服务id为空");
         }
 
         WxWorkVid2UserIdDTO wxWorkVid2UserIdDTO = new WxWorkVid2UserIdDTO();
@@ -444,13 +444,13 @@ public class QwMsgController {
         List<WxWorkVid2UserIdRespDTO> data = WxWorkVid2UserIdRespDTO.getData();
         if (data==null|| data.isEmpty()){
 
-            System.out.println("未获取到extId"+wxWorkVid2UserIdDTO);
+            log.info("未获取到extId"+wxWorkVid2UserIdDTO);
         }
         com.fs.wxwork.dto.WxWorkVid2UserIdRespDTO dto = data.get(0);
 
         QwExternalContact qwExternalContacts = qwExternalContactMapper.selectQwExternalContactByExternalUserIdAndQwUserId(dto.getOpenid(), user.getCorpId(),user.getQwUserId());
         if (qwExternalContacts==null){
-            System.out.println("没有外部联系人");
+            log.info("没有外部联系人");
         }
 
         //处理拉黑的
@@ -519,6 +519,7 @@ public class QwMsgController {
         Long id = redisCache.getCacheObject("qrCode:uuid:"+uid);
         QwUser qwUser = new QwUser();
         qwUser.setId(id);
+        qwUser.setRemark(msg);
         qwUser.setIpadStatus(status);
         qwUserMapper.updateQwUser(qwUser);
         QwUser qwUser1 = qwUserMapper.selectQwUserById(id);

+ 21 - 0
fs-qw-api-msg/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -15,6 +15,8 @@ import org.springframework.data.redis.core.script.DefaultRedisScript;
 import org.springframework.data.redis.serializer.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
+import java.math.BigDecimal;
+
 /**
  * redis配置
  *
@@ -66,6 +68,25 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
     }
 
+    @Bean
+    public RedisTemplate<String, BigDecimal> redisTemplateForBigDecimal(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, BigDecimal> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(BigDecimal.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(BigDecimal.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
+
     @Bean
     @SuppressWarnings(value = { "unchecked", "rawtypes" })
     public RedisTemplate<String, Object> redisTemplateForObject(RedisConnectionFactory connectionFactory) {

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

@@ -367,7 +367,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 
 
     private void processSopGroup(String sopId, List<SopUserLogsVo> userLogsVos,LocalDateTime currentTime, Map<String,
-            QwGroupChat> groupChatMap,CourseConfig config,Map<Long, Map<Integer, List<CompanyMiniapp>>> miniMap,
+                                         QwGroupChat> groupChatMap,CourseConfig config,Map<Long, Map<Integer, List<CompanyMiniapp>>> miniMap,
                                  List<Company> companies) throws Exception {
         QwSopRuleTimeVO ruleTimeVO = sopMapper.selectQwSopByClickHouseId(sopId);
 
@@ -861,7 +861,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                                      SopUserLogsVo logVo, Date sendTime, Long courseId, Long videoId, String qwUserId, String companyUserId,
                                      String companyId, String externalId, String welcomeText, String qwUserName,
                                      Long fsUserId, boolean isGroupChat, String miniAppId, QwGroupChat groupChat,CourseConfig config,Map<Long,
-                                     Map<Integer, List<CompanyMiniapp>>> miniMap,Integer grade, Integer sendMsgType,
+                    Map<Integer, List<CompanyMiniapp>>> miniMap,Integer grade, Integer sendMsgType,
                                      List<Company> companies) {
         // 深拷贝 Content 对象,避免使用 JSON
         QwSopTempSetting.Content clonedContent = deepCopyContent(content);
@@ -957,6 +957,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                     if(sopLogs.getSendType()==1){
                         setting.setMiniprogramAppid(miniAppId);
                     }else {
+                        int miniType = getLevel(grade);
                         //算主备小程序
                         String finalAppId = getAppIdFromMiniMap(miniMap, companyId, sendMsgType, grade);
 
@@ -964,6 +965,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                             finalAppId = miniAppId;
                         }
 
+                        setting.setMiniType(miniType);
                         if (!StringUtil.strIsNullOrEmpty(finalAppId)) {
                             setting.setMiniprogramAppid(finalAppId);
                         } else {
@@ -1036,8 +1038,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
             return null;
         }
 
-        int effectiveGrade = (grade == null) ? 5 : grade;
-        int listIndex = (effectiveGrade == 1 || effectiveGrade == 2) ? 0 : 1;
+        int listIndex = getLevel(grade);
         List<CompanyMiniapp> miniapps = gradeMap.get(listIndex);
 
         if (miniapps == null || miniapps.isEmpty()) {
@@ -1050,6 +1051,12 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                 : null;
     }
 
+    private static int getLevel(Integer grade) {
+        int effectiveGrade = (grade == null) ? 5 : grade;
+        int listIndex = (effectiveGrade == 1 || effectiveGrade == 2) ? 0 : 1;
+        return listIndex;
+    }
+
     /**
      * 深拷贝 Content 对象,避免使用 JSON 进行序列化和反序列化
      */
@@ -1213,9 +1220,9 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 
 
     public FsCourseSopAppLink createFsCourseSopAppLink(String link, Date sendTime, Date updateTime, String companyId,
-                                         String companyUserId,String qwUserId,String qwUserName,String corpId,
-                                         Long courseId,String linkTile,String linkImageUrl,Long videoId,
-                                         String linkDescribe,String appMsgLink,String externalId){
+                                                       String companyUserId,String qwUserId,String qwUserName,String corpId,
+                                                       Long courseId,String linkTile,String linkImageUrl,Long videoId,
+                                                       String linkDescribe,String appMsgLink,String externalId){
 
         FsCourseSopAppLink sopAppLink=new FsCourseSopAppLink();
         sopAppLink.setLink(link);
@@ -1279,8 +1286,8 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
     }
 
     private String createLinkByMiniApp(QwSopTempSetting.Content.Setting setting, SopUserLogsVo logVo, Date sendTime,
-                                     Long courseId, Long videoId, String qwUserId,
-                                     String companyUserId, String companyId, String externalId,String isOfficial,Long fsUserId) {
+                                       Long courseId, Long videoId, String qwUserId,
+                                       String companyUserId, String companyId, String externalId,String isOfficial,Long fsUserId) {
         // 获取缓存的配置
         CourseConfig config;
         synchronized(configLock) {

+ 36 - 44
fs-qwhook-sop/src/main/java/com/fs/framework/config/MyBatisConfig.java

@@ -29,85 +29,62 @@ import java.util.List;
 /**
  * Mybatis支持*匹配扫描包
  *
-
  */
 @Configuration
-public class MyBatisConfig
-{
+public class MyBatisConfig {
     @Autowired
     private Environment env;
 
     static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
 
-    public static String setTypeAliasesPackage(String typeAliasesPackage)
-    {
+    public static String setTypeAliasesPackage(String typeAliasesPackage) {
         ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();
         MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
         List<String> allResult = new ArrayList<String>();
-        try
-        {
-            for (String aliasesPackage : typeAliasesPackage.split(","))
-            {
+        try {
+            for (String aliasesPackage : typeAliasesPackage.split(",")) {
                 List<String> result = new ArrayList<String>();
                 aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                         + ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN;
                 Resource[] resources = resolver.getResources(aliasesPackage);
-                if (resources != null && resources.length > 0)
-                {
+                if (resources != null && resources.length > 0) {
                     MetadataReader metadataReader = null;
-                    for (Resource resource : resources)
-                    {
-                        if (resource.isReadable())
-                        {
+                    for (Resource resource : resources) {
+                        if (resource.isReadable()) {
                             metadataReader = metadataReaderFactory.getMetadataReader(resource);
-                            try
-                            {
+                            try {
                                 result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
-                            }
-                            catch (ClassNotFoundException e)
-                            {
+                            } catch (ClassNotFoundException e) {
                                 e.printStackTrace();
                             }
                         }
                     }
                 }
-                if (result.size() > 0)
-                {
+                if (result.size() > 0) {
                     HashSet<String> hashResult = new HashSet<String>(result);
                     allResult.addAll(hashResult);
                 }
             }
-            if (allResult.size() > 0)
-            {
+            if (allResult.size() > 0) {
                 typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0]));
-            }
-            else
-            {
+            } else {
                 throw new RuntimeException("mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包");
             }
-        }
-        catch (IOException e)
-        {
+        } catch (IOException e) {
             e.printStackTrace();
         }
         return typeAliasesPackage;
     }
 
-    public Resource[] resolveMapperLocations(String[] mapperLocations)
-    {
+    public Resource[] resolveMapperLocations(String[] mapperLocations) {
         ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
         List<Resource> resources = new ArrayList<Resource>();
-        if (mapperLocations != null)
-        {
-            for (String mapperLocation : mapperLocations)
-            {
-                try
-                {
+        if (mapperLocations != null) {
+            for (String mapperLocation : mapperLocations) {
+                try {
                     Resource[] mappers = resourceResolver.getResources(mapperLocation);
                     resources.addAll(Arrays.asList(mappers));
-                }
-                catch (IOException e)
-                {
+                } catch (IOException e) {
                     // ignore
                 }
             }
@@ -115,9 +92,24 @@ public class MyBatisConfig
         return resources.toArray(new Resource[resources.size()]);
     }
 
+    //    @Bean
+//    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
+//    {
+//        String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage");
+//        String mapperLocations = env.getProperty("mybatis.mapperLocations");
+//        String configLocation = env.getProperty("mybatis.configLocation");
+//        typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
+//        VFS.addImplClass(SpringBootVFS.class);
+//
+//        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
+//        sessionFactory.setDataSource(dataSource);
+//        sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
+//        sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
+//        sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
+//        return sessionFactory.getObject();
+//    }
     @Bean
-    public SqlSessionFactory sqlSessionFactorys(DataSource dataSource) throws Exception
-    {
+    public SqlSessionFactory sqlSessionFactorys(DataSource dataSource) throws Exception {
         String typeAliasesPackage = env.getProperty("mybatis-plus.typeAliasesPackage");
         String mapperLocations = env.getProperty("mybatis-plus.mapperLocations");
         String configLocation = env.getProperty("mybatis-plus.configLocation");
@@ -131,4 +123,4 @@ public class MyBatisConfig
         sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
         return sessionFactory.getObject();
     }
-}
+}

+ 59 - 0
fs-service/src/main/java/com/fs/aiChat/domain/InterestAiChatMsg.java

@@ -0,0 +1,59 @@
+package com.fs.aiChat.domain;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+@Data
+public class InterestAiChatMsg extends BaseEntity {
+    /** $column.columnComment */
+    private Long msgId;
+
+    /** 消息id */
+    @Excel(name = "消息id")
+    private Long sessionId;
+
+    /** 用户id */
+    @Excel(name = "用户id")
+    private String userId;
+
+    /** 消息内容 */
+    @Excel(name = "消息内容")
+    private String content;
+
+    /** 发送类型 1用户发送 2ai发送 */
+    @Excel(name = "发送类型 1用户发送 2ai发送")
+    private Integer sendType;
+
+    /** 角色ID */
+    @Excel(name = "角色ID")
+    private Long roleId;
+
+    /** 角色名称 */
+    @Excel(name = "角色名称")
+    private String roleName;
+
+    /** 昵称 */
+    @Excel(name = "昵称")
+    private String nickName;
+
+    /** 头像 */
+    @Excel(name = "头像")
+    private String avatar;
+
+    /** 用户输入的令牌数量 */
+    @Excel(name = "用户输入的令牌数量")
+    private Long promptTokens;
+
+    /** 生成的回复中使用的令牌 */
+    @Excel(name = "生成的回复中使用的令牌")
+    private Long completionTokens;
+
+    /** 总令牌数量 */
+    @Excel(name = "总令牌数量")
+    private Long totalTokens;
+
+    /** 角色头像 */
+    @Excel(name = "角色头像")
+    private String roleAvatar;
+}

+ 73 - 0
fs-service/src/main/java/com/fs/aiChat/domain/InterestAiSession.java

@@ -0,0 +1,73 @@
+package com.fs.aiChat.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class InterestAiSession extends BaseEntity {
+
+
+    /** 会话ID */
+    private Long sessionId;
+
+    /** 会话标识 */
+    @Excel(name = "会话标识")
+    private String chatId;
+
+    /** 用户id */
+    @Excel(name = "用户id")
+    private Long userId;
+
+    /** 客服ID */
+    @Excel(name = "客服ID")
+    private Long roleId;
+
+    /** 客服名称 */
+    @Excel(name = "客服名称")
+    private String roleName;
+
+    /** 状态 1会话中 2已结束 */
+    @Excel(name = "状态 1会话中 2已结束")
+    private Integer status;
+
+    /** 客户昵称 */
+    @Excel(name = "客户昵称")
+    private String nickName;
+
+    /** 头像 */
+    @Excel(name = "头像")
+    private String avatar;
+
+    /**
+     * 当前会话最后一条消息记录
+     */
+    @Excel(name = "最后一条消息记录")
+    private String lastContent;
+
+    /**
+     * 角色头像
+     */
+    @Excel(name = "角色头像")
+    private String roleAvatar;
+
+    /**
+     * 标签
+     */
+    @Excel(name = "标签")
+    private String roleTag;
+
+    @Excel(name = "欢迎语")
+    private String welcomeMessage;
+
+    @Excel(name = "文本说明")
+    private String textDescription;
+
+    @Excel(name = "最后回复时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date lastCreateTime;
+
+}

+ 54 - 0
fs-service/src/main/java/com/fs/aiChat/domain/SessionRoleInfo.java

@@ -0,0 +1,54 @@
+package com.fs.aiChat.domain;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+@Data
+public class SessionRoleInfo extends BaseEntity {
+
+    /** ID */
+    private Long roleId;
+
+    /** 角色名称 */
+    @Excel(name = "角色名称")
+    private String roleName;
+
+    /** 标签 */
+    @Excel(name = "标签")
+    private String roleTag;
+
+    /** 模型key */
+    @Excel(name = "模型key")
+    private String appKey;
+
+    /** 客服头像 */
+    @Excel(name = "客服头像")
+    private String avatar;
+
+    /** 欢迎语 */
+    @Excel(name = "欢迎语")
+    private String welcomeMessage;
+
+    @Excel(name = "封面图片")
+    private String imageUrl;
+
+    @Excel(name = "文本描述")
+    private String textDescription;
+
+    /** 提示词列表 */
+    @Excel(name = "提示词列表")
+    private String wordList;
+
+    @Excel(name = "标题")
+    private String title;
+
+    @Excel(name = "是否推荐")
+    private int isRecommend;
+
+    @Excel(name = "推荐图")
+    private String recommendImgUrl;
+
+    @Excel(name = "会话ID")
+    private Long sessionId;
+}

+ 59 - 0
fs-service/src/main/java/com/fs/aiChat/mapper/InterestAiChatSessionMapper.java

@@ -0,0 +1,59 @@
+package com.fs.aiChat.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.aiChat.domain.DoctorAiChatLog;
+import com.fs.aiChat.domain.InterestAiChatMsg;
+import com.fs.aiChat.domain.InterestAiSession;
+import com.fs.aiChat.domain.SessionRoleInfo;
+import com.fs.his.domain.FsInterestAiMsg;
+import com.fs.his.domain.FsInterestAiRole;
+import com.fs.his.domain.FsInterestAiSession;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+
+public interface InterestAiChatSessionMapper extends BaseMapper<DoctorAiChatLog> {
+
+    /**
+     * 查询用户对话列表
+     * @param userId
+     * @return
+     */
+    List<InterestAiSession> getSessionListByUserId(Long userId);
+
+    /**
+     * 根据roleid获取会话角色信息
+     * @param roleId
+     * @return
+     */
+    SessionRoleInfo getSessionRoleInfoByRoleId(Long roleId);
+
+    /**
+     * 获取聊天记录
+     * @param sessionId
+     * @return
+     */
+    List<InterestAiChatMsg> getSessionChatList(String sessionId);
+
+    /**
+     * 获取会话
+     * @param roleId
+     * @param userId
+     * @return
+     */
+    @Select("  select session_id,chat_id,user_id,role_id,role_name, status, nick_name,avatar,create_time,update_time\n" +
+            "            from fs_interest_ai_session where role_id = #{roleId} and user_id = #{userId} limit 1")
+    FsInterestAiSession getInterestAiSessionByRoleIdAndUserId(@Param(value =  "roleId")Long roleId,@Param(value = "userId") Long userId);
+
+
+    int insertFsInterestAiSession(FsInterestAiSession fsInterestAiSession);
+
+    int insertFsInterestAiMsg(FsInterestAiMsg fsInterestAiMsg);
+
+    List<SessionRoleInfo> getRecommendRoleList(String userId);
+
+
+    FsInterestAiRole selectFsInterestAiRoleByRoleId(Long roleId);
+}

+ 15 - 0
fs-service/src/main/java/com/fs/aiChat/param/InterestAiMessage.java

@@ -0,0 +1,15 @@
+package com.fs.aiChat.param;
+
+import lombok.Data;
+
+@Data
+public class InterestAiMessage {
+    Long userId;
+    String nickName;
+    String avatar;
+    Long roleId;
+    String roleName;
+    String message;
+    Long sessionId;
+//    Integer isWelcome;
+}

+ 5 - 0
fs-service/src/main/java/com/fs/company/constant/CompanyTrafficConstants.java

@@ -0,0 +1,5 @@
+package com.fs.company.constant;
+
+public class CompanyTrafficConstants {
+    public static final String CACHE_KEY = "company:traffic:record";
+}

+ 4 - 0
fs-service/src/main/java/com/fs/company/domain/Company.java

@@ -131,5 +131,9 @@ public class Company extends BaseEntity
 
     /** 后台制单是否需要付款 默认1 0-否 1-是*/
     private Integer isPay;
+    /** 限制销售公司Pad数量 -1表示不做限制*/
+    private Integer maxPadNum;
+    /** 所属部门id */
+    private Long deptId;
 
 }

+ 41 - 0
fs-service/src/main/java/com/fs/company/domain/CompanyTrafficRecord.java

@@ -0,0 +1,41 @@
+package com.fs.company.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fs.common.annotation.Excel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * 销售公司流量记录对象 company_traffic_record
+ *
+ * */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class CompanyTrafficRecord {
+
+    @Excel(name = "id")
+    @TableId
+    private Long id;
+    @Excel(name = "公司id")
+    private Long companyId;
+    @Excel(name = "部门id")
+    private Long deptId;
+    @Excel(name="公司名称")
+    private String companyName;
+    @Excel(name = "流量余额")
+    private Long balance;     // 单位: KB
+    @Excel(name = "创建时间")
+    private Date createTime;
+    @Excel(name = "更新时间")
+    private Date updateTime;
+    @Excel(name = "创建人")
+    private Long createBy;
+    @Excel(name = "更新人")
+    private Long updateBy;
+}

+ 45 - 0
fs-service/src/main/java/com/fs/company/domain/CompanyTrafficRecordLog.java

@@ -0,0 +1,45 @@
+package com.fs.company.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * 销售公司流量记录对象 company_traffic_record_log
+ *
+ * */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class CompanyTrafficRecordLog {
+
+    @Excel(name = "id")
+    @TableId
+    private Long id;
+    @Excel(name = "公司id")
+    private Long companyId;
+    @Excel(name = "用户id")
+    private Long userId;
+    @Excel(name = "用户名称")
+    private String userName;
+    @Excel(name = "操作类型")
+    private Integer operationType; // 1-充值 2-扣费
+    @Excel(name = "流量变动数")
+    private Long trafficAmount;    // 单位: KB
+    @Excel(name = "充值金额")
+    private Long chargeAmount;    // 单位: 元
+    @Excel(name = "流量余额")
+    private Long balance;     // 单位: KB
+    @Excel(name = "备注")
+    private String remark;
+    @Excel(name = "创建时间" , width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Excel.Type.EXPORT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+}

+ 12 - 6
fs-service/src/main/java/com/fs/company/mapper/CompanyMapper.java

@@ -11,7 +11,6 @@ import com.fs.company.vo.CompanyCrmVO;
 import com.fs.company.vo.CompanyNameVO;
 import com.fs.company.vo.CompanyVO;
 import com.fs.his.vo.OptionsVO;
-import com.fs.huifuPay.sdk.opps.core.utils.StringUtil;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
@@ -81,6 +80,9 @@ public interface CompanyMapper
             "<if test = 'maps.companyName != null and  maps.companyName !=\"\"     '> " +
             "and c.company_name like CONCAT('%',#{maps.companyName},'%') " +
             "</if>" +
+            "<if test = 'maps.deptId != null'> " +
+            "and c.dept_id = #{maps.deptId} " +
+            "</if>" +
 
             "<if test = 'maps.status != null   '> " +
             "and c.status = #{maps.status}" +
@@ -118,6 +120,9 @@ public interface CompanyMapper
             "<if test = 'maps.companyName != null and  maps.companyName !=\"\"     '> " +
             "and c.company_name like CONCAT('%',#{maps.companyName},'%') " +
             "</if>" +
+            "<if test = 'maps.deptId != null'> " +
+            "and c.dept_id = #{maps.deptId} " +
+            "</if>" +
 
             "<if test = 'maps.phonenumber != null and  maps.phonenumber !=\"\"     '> " +
             "and c.company_mobile like CONCAT('%',#{maps.phonenumber},'%') " +
@@ -149,8 +154,9 @@ public interface CompanyMapper
 
 
     @Select({"<script> " +
-            "select c.*,cu.user_name FROM company c LEFT JOIN company_user cu ON c.user_id =cu.user_id  " +
-            "where is_del=0 " +
+            "select c.*,cu.user_name,qu.used_num FROM company c LEFT JOIN company_user cu ON c.user_id =cu.user_id  " +
+            "LEFT JOIN (select company_id, count(id) as used_num from qw_user where server_id is not null group by company_id) qu ON qu.company_id = c.company_id " +
+            "where c.is_del=0 " +
             "            <if test=\"companyName != null  and companyName != ''\"> and c.company_name like concat('%', #{companyName}, '%')</if>\n" +
             "            <if test=\"companyMobile != null  and companyMobile != ''\"> and c.company_mobile = #{companyMobile}</if>\n" +
             "            <if test=\"companyAddress != null  and companyAddress != ''\"> and c.company_address = #{companyAddress}</if>\n" +
@@ -163,13 +169,13 @@ public interface CompanyMapper
             "            <if test=\"linkName != null  and linkName != ''\"> and c.link_name like concat('%', #{linkName}, '%')</if>\n" +
             "            <if test=\"limitUserCount != null \"> and c.limit_user_count = #{limitUserCount}</if>\n" +
             "            <if test=\"isDel != null \"> and c.is_del = #{isDel}</if>\n" +
+            "            <if test=\"deptId != null \"> and c.dept_id = #{deptId}</if> " +
             "        " +
-            "order by company_id desc" +
+            " order by company_id desc" +
             "</script>"})
     List<CompanyVO> selectCompanyListVO(Company param);
 
-    @Select("select company_id dictValue,company_name dictLabel from company where is_del= 0")
-    List<OptionsVO> selectAllCompanyList();
+    List<OptionsVO> selectAllCompanyList(@Param("deptId") Long deptId);
 
     @Select("select company_id from company")
     List<Long> selectCompanyIds();

+ 10 - 0
fs-service/src/main/java/com/fs/company/mapper/CompanyTrafficRecordLogMapper.java

@@ -0,0 +1,10 @@
+package com.fs.company.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.company.domain.CompanyTrafficRecordLog;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface CompanyTrafficRecordLogMapper extends BaseMapper<CompanyTrafficRecordLog> {
+
+}

+ 28 - 0
fs-service/src/main/java/com/fs/company/mapper/CompanyTrafficRecordMapper.java

@@ -0,0 +1,28 @@
+package com.fs.company.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.company.domain.CompanyTrafficRecord;
+import com.fs.company.param.CompanyTrafficRecordQueryParam;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+@Mapper
+public interface CompanyTrafficRecordMapper extends BaseMapper<CompanyTrafficRecord> {
+
+    @Select("SELECT SUM(ctr.balance) FROM company_traffic_record ctr inner join company c on ctr.company_id = c.company_id and c.dept_id = #{deptId}")
+    Long calculateTotalTrafficByDeptId(@Param("deptId") Long deptId);
+
+    @Select({"<script>"+
+                "SELECT ctr.id,c.company_id,c.company_name,ctr.balance from company c " +
+                "LEFT JOIN company_traffic_record ctr on ctr.company_id = c.company_id " +
+                "WHERE c.is_del = 0 "+
+                "<if test = 'maps.companyIds != null'> " +
+                "and c.company_id IN " +
+                "<foreach collection='maps.companyIds'  item='item' index='index'  open='(' separator=',' close=')'> #{item} </foreach> "+
+                "</if> " +
+            "</script>"})
+    List<CompanyTrafficRecord> selectListWithUncharged(@Param("maps") CompanyTrafficRecordQueryParam record);
+}

+ 3 - 32
fs-service/src/main/java/com/fs/company/param/CompanyParam.java

@@ -1,10 +1,12 @@
 package com.fs.company.param;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
 
 import java.util.Date;
 
 
+@Data
 public class CompanyParam
 {
 
@@ -12,36 +14,5 @@ public class CompanyParam
     private Long companyId;
     private Integer status;
     private String phonenumber;
-
-    public String getCompanyName() {
-        return companyName;
-    }
-
-    public void setCompanyName(String companyName) {
-        this.companyName = companyName;
-    }
-
-    public Long getCompanyId() {
-        return companyId;
-    }
-
-    public void setCompanyId(Long companyId) {
-        this.companyId = companyId;
-    }
-
-    public Integer getStatus() {
-        return status;
-    }
-
-    public void setStatus(Integer status) {
-        this.status = status;
-    }
-
-    public String getPhonenumber() {
-        return phonenumber;
-    }
-
-    public void setPhonenumber(String phonenumber) {
-        this.phonenumber = phonenumber;
-    }
+    private Long deptId;
 }

+ 23 - 0
fs-service/src/main/java/com/fs/company/param/CompanyTrafficRecordChargeParam.java

@@ -0,0 +1,23 @@
+package com.fs.company.param;
+
+import com.fs.company.domain.Company;
+import lombok.Data;
+
+@Data
+public class CompanyTrafficRecordChargeParam {
+
+    private Long companyId;
+    private Integer operationType; // 1-充值 2-扣费
+    //充值金额
+    private Long chargeAmount;
+    //扣除流量
+    private Long changeTraffic;
+    private String remark;
+    private Long userId;
+    private String userName;
+
+    /**
+     *公司实例
+     * */
+    private Company company;
+}

+ 21 - 0
fs-service/src/main/java/com/fs/company/param/CompanyTrafficRecordLogQueryParam.java

@@ -0,0 +1,21 @@
+package com.fs.company.param;
+
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class CompanyTrafficRecordLogQueryParam {
+
+
+    private Long id;
+    private Long companyId;
+    private List<Long> companyIds;
+    private Long userId;
+    private String userName;
+    private Integer operationType; // 1-充值 2-扣费
+    private Date createTime;
+    private Date createTimeStart;
+    private Date createTimeEnd;
+}

+ 17 - 0
fs-service/src/main/java/com/fs/company/param/CompanyTrafficRecordQueryParam.java

@@ -0,0 +1,17 @@
+package com.fs.company.param;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class CompanyTrafficRecordQueryParam {
+
+
+    private Long id;
+    private Long companyId;
+    private List<Long> companyIds;
+    private Long createBy;
+}

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

@@ -28,7 +28,7 @@ import org.springframework.transaction.annotation.Transactional;
  */
 public interface ICompanyService
 {
-     List<OptionsVO> selectAllCompanyList() ;
+     List<OptionsVO> selectAllCompanyList(Long deptId) ;
 
     /**
      * 查询企业

+ 16 - 0
fs-service/src/main/java/com/fs/company/service/ICompanyTrafficRecordLogService.java

@@ -0,0 +1,16 @@
+package com.fs.company.service;
+
+import com.fs.company.domain.CompanyTrafficRecordLog;
+import com.fs.company.param.CompanyTrafficRecordLogQueryParam;
+
+import java.util.List;
+
+public interface ICompanyTrafficRecordLogService {
+    //查询流量记录列表
+    List<CompanyTrafficRecordLog> selectList(CompanyTrafficRecordLogQueryParam record);
+    //查询流量记录
+    CompanyTrafficRecordLog selectById(Long id);
+    //保存流量记录
+    boolean save(CompanyTrafficRecordLog entity);
+
+}

+ 25 - 0
fs-service/src/main/java/com/fs/company/service/ICompanyTrafficRecordService.java

@@ -0,0 +1,25 @@
+package com.fs.company.service;
+
+import com.fs.company.domain.CompanyTrafficRecord;
+import com.fs.company.param.CompanyTrafficRecordChargeParam;
+import com.fs.company.param.CompanyTrafficRecordQueryParam;
+
+import java.util.List;
+
+public interface ICompanyTrafficRecordService {
+    //启动时初始化流量
+    void init();
+
+    void refreshTraffic();
+
+    //添加流量记录
+    boolean recharge(CompanyTrafficRecordChargeParam record);
+    //查询流量记录列表
+    List<CompanyTrafficRecord> selectList(CompanyTrafficRecordQueryParam record);
+    //查询流量记录
+    CompanyTrafficRecord selectById(Long id);
+
+    Long trafficConversion(Long amount);
+
+    void refreshPrice();
+}

+ 2 - 0
fs-service/src/main/java/com/fs/company/service/ICompanyUserService.java

@@ -236,4 +236,6 @@ public interface ICompanyUserService {
     R bindDoctor(CompanyUser param);
 
     R unBindDoctor(Long userId);
+
+    R getBindInfo(Long companyUserId);
 }

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

@@ -97,8 +97,8 @@ public class CompanyServiceImpl implements ICompanyService
     private CompanyUserMapper companyUserMapper;
 
     @Override
-    public List<OptionsVO> selectAllCompanyList() {
-        return companyMapper.selectAllCompanyList();
+    public List<OptionsVO> selectAllCompanyList(Long deptId) {
+        return companyMapper.selectAllCompanyList(deptId);
     }
 
     /**

+ 40 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanyTrafficRecordLogServiceImpl.java

@@ -0,0 +1,40 @@
+package com.fs.company.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.company.domain.CompanyTrafficRecordLog;
+import com.fs.company.mapper.CompanyTrafficRecordLogMapper;
+import com.fs.company.param.CompanyTrafficRecordLogQueryParam;
+import com.fs.company.service.ICompanyTrafficRecordLogService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+@Slf4j
+public class CompanyTrafficRecordLogServiceImpl extends ServiceImpl<CompanyTrafficRecordLogMapper, CompanyTrafficRecordLog> implements ICompanyTrafficRecordLogService {
+
+
+    @Override
+    public List<CompanyTrafficRecordLog> selectList(CompanyTrafficRecordLogQueryParam record) {
+        return baseMapper.selectList(new LambdaQueryWrapper<CompanyTrafficRecordLog>()
+                .eq(record.getCompanyId() != null ,CompanyTrafficRecordLog::getCompanyId, record.getCompanyId())
+                .in(record.getCompanyIds() != null,CompanyTrafficRecordLog::getCompanyId, record.getCompanyIds())
+                .eq(record.getUserId() != null ,CompanyTrafficRecordLog::getUserId, record.getUserId())
+                .eq(record.getOperationType() != null ,CompanyTrafficRecordLog::getOperationType, record.getOperationType())
+                .eq(record.getCreateTime() != null ,CompanyTrafficRecordLog::getCreateTime, record.getCreateTime())
+                .between(record.getCreateTimeStart() != null && record.getCreateTimeEnd() != null,CompanyTrafficRecordLog::getCreateTime, record.getCreateTimeStart(), record.getCreateTimeEnd())
+                .orderByDesc(CompanyTrafficRecordLog::getCreateTime));
+    }
+
+    @Override
+    public CompanyTrafficRecordLog selectById(Long id) {
+        return baseMapper.selectById(id);
+    }
+
+    @Override
+    public boolean save(CompanyTrafficRecordLog entity) {
+        return baseMapper.insert(entity)==1;
+    }
+}

+ 272 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanyTrafficRecordServiceImpl.java

@@ -0,0 +1,272 @@
+package com.fs.company.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.core.redis.RedisCache;
+import com.fs.company.constant.CompanyTrafficConstants;
+import com.fs.company.domain.Company;
+import com.fs.company.domain.CompanyTrafficRecord;
+import com.fs.company.domain.CompanyTrafficRecordLog;
+import com.fs.company.mapper.CompanyTrafficRecordMapper;
+import com.fs.company.param.CompanyTrafficRecordChargeParam;
+import com.fs.company.param.CompanyTrafficRecordQueryParam;
+import com.fs.company.service.ICompanyService;
+import com.fs.company.service.ICompanyTrafficRecordLogService;
+import com.fs.company.service.ICompanyTrafficRecordService;
+import com.fs.course.mapper.FsCourseTrafficLogMapper;
+import com.fs.system.domain.SysConfig;
+import com.fs.system.service.ISysConfigService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+import java.time.YearMonth;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+@Slf4j
+public class CompanyTrafficRecordServiceImpl extends ServiceImpl<CompanyTrafficRecordMapper, CompanyTrafficRecord> implements ICompanyTrafficRecordService {
+
+    @Autowired
+    RedisCache redisCache;
+
+    @Autowired
+    private ISysConfigService iSysConfigService;
+
+    @Autowired
+    private ICompanyService companyService;
+
+    private SysConfig config;
+
+    @Autowired
+    private ICompanyTrafficRecordLogService companyTrafficRecordLogService;
+
+    @Autowired
+    private FsCourseTrafficLogMapper fsCourseTrafficLogMapper;
+
+    //启动时初始化部门流量缓存
+    @Override
+    public void init() {
+        List<CompanyTrafficRecord> companyTrafficRecords = baseMapper.selectList(new LambdaQueryWrapper<>());
+        Map<Long,Long> deptTrafficMap = new HashMap<>();
+        for (CompanyTrafficRecord companyTrafficRecord : companyTrafficRecords) {
+            // 获取公司ID
+            Long companyId = companyTrafficRecord.getCompanyId();
+            // 部门ID
+            Long deptId = companyService.selectCompanyById(companyId).getDeptId();
+            companyTrafficRecord.setDeptId(deptId);
+
+            // 公司流量 - 消耗流量
+            Long balance = companyTrafficRecord.getBalance();
+            //消耗的流量
+            Long totalInternetTraffic = fsCourseTrafficLogMapper.sumTrafficByCompany(companyId) == null?0L:fsCourseTrafficLogMapper.sumTrafficByCompany(companyId);
+            balance -= totalInternetTraffic;
+            //部门流量记录
+            Long deptTrafficAdd = (deptTrafficMap.get(deptId) == null ? 0L : deptTrafficMap.get(deptId)) + totalInternetTraffic;
+            deptTrafficMap.put(deptId, deptTrafficAdd);
+            //更新缓存
+            redisCache.deleteObject(CompanyTrafficConstants.CACHE_KEY + ":" + deptId + ":" + companyId);
+            redisCache.incr(CompanyTrafficConstants.CACHE_KEY + ":" + deptId + ":" + companyId, balance);
+            //删除前天流量缓存(如果存在;保留两天)
+            redisCache.deleteObject(CompanyTrafficConstants.CACHE_KEY + ":" + deptId + ":" + companyId + ":" + LocalDate.now().minusDays(2));
+            //删除上上个月流量缓存
+            redisCache.deleteObject(CompanyTrafficConstants.CACHE_KEY + ":" + deptId + ":" + companyId + ":" + YearMonth.now().minusMonths(2));
+        }
+
+        // 缓存 key=CACHE_KEY:deptId  value=部门ID
+        calculateTotalTrafficByDeptId(deptTrafficMap);
+    }
+
+    @Override
+    public void refreshTraffic() {
+        log.info("【定时更新流量】:{}", "开始");
+        List<CompanyTrafficRecord> companyTrafficRecords = baseMapper.selectList(new LambdaQueryWrapper<>());
+        for (CompanyTrafficRecord companyTrafficRecord : companyTrafficRecords) {
+            doReduce(companyTrafficRecord,"1");
+        }
+    }
+
+    //通过redis更新表流量并添加扣除日志
+    private void doReduce(CompanyTrafficRecord companyTrafficRecord, String doType) {
+
+        //根据fs_course_traffic_log表获取公司昨天流量
+        Long trafficAmountYesterday = fsCourseTrafficLogMapper.sumTrafficByCompanyYesterday(companyTrafficRecord.getCompanyId());
+        if(trafficAmountYesterday!=null) {
+            long balance = companyTrafficRecord.getBalance() - trafficAmountYesterday;
+            companyTrafficRecord.setBalance(balance);
+            log.info("【更新流量】:{}", "部门ID:" + companyTrafficRecord.getDeptId() +"公司ID:" + companyTrafficRecord.getCompanyId() +  "消耗流量:" + trafficAmountYesterday+"剩余流量:"+balance);
+            if (trafficAmountYesterday > 0) {
+                baseMapper.updateById(CompanyTrafficRecord.builder()
+                        .id(companyTrafficRecord.getId())
+                        .balance(balance)
+                        .updateTime(new Date())
+                        .updateBy(1L).build());
+                companyTrafficRecordLogService.save(CompanyTrafficRecordLog.builder()
+                        .balance(balance)
+                        .trafficAmount(trafficAmountYesterday)
+                        .companyId(companyTrafficRecord.getCompanyId())
+                        .createTime(new Date())
+                        .operationType(2)
+                        .userId(1L)//表示amdin
+                        .remark("0".equals(doType)?"重启同步流量":"定时更新扣除流量")
+                        .userName("admin")
+                        .build());
+            }
+        }
+        init();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean recharge(CompanyTrafficRecordChargeParam record) {
+        CompanyTrafficRecord companyTrafficRecord = new CompanyTrafficRecord();
+        //校验参数companyId
+        if (record.getCompanyId() == null || !validCompany(record))
+            throw new IllegalArgumentException("销售公司异常");
+
+        //查询公司流量记录
+        CompanyTrafficRecord companyRecord = baseMapper.selectOne(new LambdaQueryWrapper<CompanyTrafficRecord>()
+                .eq(CompanyTrafficRecord::getCompanyId, record.getCompanyId()));
+
+        //充值
+        if (record.getOperationType() == 1) {//获取转换后的流量
+            Long trafficAmount = trafficConversion(record.getChargeAmount());
+            record.setChangeTraffic(trafficAmount);//用于处理日志
+            if (companyRecord != null) {
+                //不是第一次充值  增加流量
+                companyTrafficRecord.setBalance(companyRecord.getBalance() + trafficAmount);
+                companyTrafficRecord.setId(companyRecord.getId());
+                companyTrafficRecord.setUpdateTime(new Date());
+                companyTrafficRecord.setUpdateBy(record.getUserId());
+                baseMapper.updateById(companyTrafficRecord);
+            } else {
+                companyTrafficRecord.setBalance(trafficAmount);
+                companyTrafficRecord.setCompanyId(record.getCompanyId());
+                companyTrafficRecord.setDeptId(record.getCompany().getDeptId());
+                companyTrafficRecord.setCompanyName(record.getCompany().getCompanyName());
+                companyTrafficRecord.setCreateTime(new Date());
+                companyTrafficRecord.setCreateBy(record.getUserId());
+                baseMapper.insert(companyTrafficRecord);
+            }
+                /*//扣除
+            case 2:
+                //扣除流量
+                *//*if (companyRecord.getBalance() < record.getChangeTraffic())
+                    throw new IllegalArgumentException("公司流量余额不足");*//*
+                companyTrafficRecord.setBalance(companyTrafficRecord.getBalance() - record.getChangeTraffic());
+                companyTrafficRecord.setId(companyRecord.getId());
+                companyTrafficRecord.setUpdateTime(new Date());
+                companyTrafficRecord.setUpdateBy(record.getUserId());
+                baseMapper.updateById(companyTrafficRecord);
+                break;*/
+        } else {
+            throw new IllegalArgumentException("非法的操作类型");
+        }
+        // 更新Redis缓存
+        doRefresh(record, companyTrafficRecord);
+
+        return doLog(companyTrafficRecord, record);
+    }
+
+    private boolean validCompany(CompanyTrafficRecordChargeParam record) {
+        Company company = new Company();
+        company.setCompanyId(record.getCompanyId());
+        company.setIsDel(0);
+        List<Company> companies = companyService.selectCompanyList(company);
+        if (companies != null && companies.size() == 1) {
+            record.setCompany(companies.get(0));
+            return true;
+        } else {
+            return false;
+        }
+    }
+    /**
+     * 更新Redis缓存
+     * @param record               充值参数
+     * @param companyTrafficRecord 公司流量记录
+     */
+    private void doRefresh(CompanyTrafficRecordChargeParam record, CompanyTrafficRecord companyTrafficRecord) {
+        if (record.getCompany() != null && record.getCompany().getDeptId() != null) {
+            // 更新缓存 key=CACHE_KEY:deptId:companyId  value=剩余流量
+            redisCache.incr(CompanyTrafficConstants.CACHE_KEY + ":" + record.getCompany().getDeptId() + ":" + record.getCompanyId(),
+                    companyTrafficRecord.getBalance());
+
+            // 部门新增流量
+            calculateTrafficByDeptId(record.getCompany().getDeptId(),companyTrafficRecord.getBalance());
+        } else {
+            // 抛出异常
+            throw new IllegalArgumentException("缓存ID异常");
+        }
+    }
+    /**
+     * 部门下所有公司流量总和减去使用的流量
+     */
+    private void calculateTrafficByDeptId(Long deptId,Long traffic) {
+        redisCache.incr(CompanyTrafficConstants.CACHE_KEY + ":" + deptId, traffic);
+    }
+
+    /**
+     * 部门下所有公司流量总和减去使用的流量
+     */
+    private void calculateTotalTrafficByDeptId(Map<Long,Long> deptTrafficMap) {
+        deptTrafficMap.forEach((deptId,totalTraffic) -> {
+            Long total = baseMapper.calculateTotalTrafficByDeptId(deptId);
+            redisCache.deleteObject(CompanyTrafficConstants.CACHE_KEY + ":" + deptId);
+            redisCache.incr(CompanyTrafficConstants.CACHE_KEY + ":" + deptId, total-totalTraffic);
+            //删除前天缓存
+            redisCache.deleteObject(CompanyTrafficConstants.CACHE_KEY + ":" + deptId + ":" + LocalDate.now().minusDays(2));
+            //删除上上月缓存
+            redisCache.deleteObject(CompanyTrafficConstants.CACHE_KEY + ":" + deptId + ":" + YearMonth.now().minusMonths(2));
+        });
+    }
+
+    private boolean doLog(CompanyTrafficRecord companyTrafficRecord, CompanyTrafficRecordChargeParam record) {
+        return companyTrafficRecordLogService.save(CompanyTrafficRecordLog.builder()
+                .balance(companyTrafficRecord.getBalance())
+                .trafficAmount(record.getChangeTraffic())
+                .chargeAmount(record.getChargeAmount())
+                .companyId(record.getCompanyId())
+                .createTime(new Date())
+                .operationType(record.getOperationType())
+                .userId(record.getUserId())
+                .remark(record.getRemark())
+                .userName(record.getUserName())
+                .build());
+    }
+
+    @Override
+    public List<CompanyTrafficRecord> selectList(CompanyTrafficRecordQueryParam record) {
+        return baseMapper.selectListWithUncharged(record);
+    }
+
+    @Override
+    public CompanyTrafficRecord selectById(Long id) {
+        return baseMapper.selectById(id);
+    }
+
+
+    /**
+     * 充值金额转换流量KB
+     */
+    @Override
+    public Long trafficConversion(Long amount) {
+        if (this.config == null) {
+            this.config = iSysConfigService.selectConfigByConfigKey("statis.config");
+        }
+        JSONObject jsonObject = JSONObject.parseObject(this.config.getConfigValue());
+        float trafficPrice = jsonObject.getFloatValue("trafficPrice");
+        double trafficGB = amount / trafficPrice;
+        return (long) (trafficGB * 1024 * 1024);
+    }
+
+    @Override
+    public void refreshPrice() {
+        this.config = iSysConfigService.selectConfigByConfigKey("statis.config");
+    }
+}

+ 35 - 1
fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
 import com.fs.common.BeanCopyUtils;
+import com.fs.common.QRutils;
 import com.fs.common.annotation.DataScope;
 import com.fs.common.constant.UserConstants;
 import com.fs.common.core.domain.AjaxResult;
@@ -12,7 +13,10 @@ import com.fs.common.core.redis.RedisCache;
 import com.fs.common.exception.CustomException;
 import com.fs.common.exception.ServiceException;
 import com.fs.common.exception.file.OssException;
-import com.fs.common.utils.*;
+import com.fs.common.utils.DateUtils;
+import com.fs.common.utils.PatternUtils;
+import com.fs.common.utils.SecurityUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.*;
 import com.fs.company.mapper.*;
 import com.fs.company.param.CompanyUserAreaParam;
@@ -51,6 +55,7 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.math.BigDecimal;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
@@ -974,4 +979,33 @@ public class CompanyUserServiceImpl implements ICompanyUserService
             return R.error();
         }
     }
+
+
+    private final static String bindBaseUrl = "https://userapp.jnmyunl.com/bindcompanyuser?companyUserId=";
+    /**
+     * @param companyUserId
+     * @return
+     */
+    @Override
+    public R getBindInfo(Long companyUserId) {
+        //链接
+        String url = bindBaseUrl + companyUserId;
+        //查询码是否存在
+        CompanyUser companyUser = selectCompanyUserById(companyUserId);
+        if (companyUser != null) {
+            if (StringUtils.isBlank(companyUser.getBindCode())) {
+                //生成二维码
+                InputStream qrCodeStream = QRutils.getQRCodeImageInputStream(url, 250, 250);
+                CloudStorageService storage = OSSFactory.build();
+                if (storage != null) {
+                    String link = storage.uploadSuffix(qrCodeStream, ".jpg");
+                    companyUser.setBindCode(link);
+                    updateCompanyUser(companyUser);
+
+                }
+            }
+            return R.ok().put("url", url).put("imageUrl", companyUser.getBindCode());
+        }
+        return R.error();
+    }
 }

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

@@ -91,4 +91,8 @@ public class CompanyVO implements Serializable
     private String restartTime;
     private List<String> miniAppMaster;
     private List<String> miniAppServer;
+    /** 已占用 */
+    private Integer usedNum;
+    /** 所属部门id */
+    private Long deptId;
 }

+ 13 - 5
fs-service/src/main/java/com/fs/core/config/WxMaConfiguration.java

@@ -9,11 +9,13 @@ import cn.binarywang.wx.miniapp.message.WxMaMessageHandler;
 import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
 import com.alibaba.fastjson.JSON;
 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.utils.spring.SpringUtils;
 import com.fs.course.config.CourseMaConfig;
 import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
+import com.fs.course.service.IFsCoursePlaySourceConfigService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import com.google.common.collect.Lists;
@@ -47,6 +49,7 @@ public class WxMaConfiguration {
 
     private static final Map<String, WxMaMessageRouter> routers = Maps.newHashMap();
     private static Map<String, WxMaService> maServices;
+    private static IFsCoursePlaySourceConfigService fsCoursePlaySourceConfigService;
 
     @Autowired
     public WxMaConfiguration(SysConfigMapper sysConfigMapper, FsCoursePlaySourceConfigMapper configMapper) {
@@ -67,14 +70,19 @@ public class WxMaConfiguration {
 //            c.add(config2);
 //        }
         //看课小程序加载
-        SysConfig sysConfig3 = sysConfigMapper.selectConfigByConfigKey("courseMa.config");
-        List<CourseMaConfig> courseMaConfigs = JSON.parseArray(sysConfig3.getConfigValue(), CourseMaConfig.class);
-        if (courseMaConfigs!=null&& !courseMaConfigs.isEmpty()){
-            for (CourseMaConfig courseMaConfig : courseMaConfigs) {
+//        SysConfig sysConfig3 = sysConfigMapper.selectConfigByConfigKey("courseMa.config");
+//        List<CourseMaConfig> courseMaConfigs = JSON.parseArray(sysConfig3.getConfigValue(), CourseMaConfig.class);
+        // 使用 SpringUtils 获取服务实例,而不是依赖注入
+        IFsCoursePlaySourceConfigService coursePlaySourceConfigService = SpringUtils.getBean(IFsCoursePlaySourceConfigService.class);
+
+        // 看课小程序加载
+        List<FsCoursePlaySourceConfig> list = coursePlaySourceConfigService.list(new QueryWrapper<FsCoursePlaySourceConfig>().ne("type", 2).eq("is_del", 0));
+        if (list!=null&& !list.isEmpty()){
+            for (FsCoursePlaySourceConfig courseMaConfig : list) {
                 if (appid.equals(courseMaConfig.getAppid())) {
                     continue;
                 }
-                if (courseMaConfig.getType() != null && courseMaConfig.getType().equals("1")){
+                if (courseMaConfig.getType() != null && courseMaConfig.getType() == 1){
                     WxMaConfig.Config wxMaConfig = new WxMaConfig.Config();
                     BeanUtils.copyProperties(courseMaConfig, wxMaConfig);
                     c.add(wxMaConfig);

+ 10 - 9
fs-service/src/main/java/com/fs/core/utils/OrderCodeUtils.java

@@ -44,15 +44,16 @@ public class OrderCodeUtils {
 
     }
     public static String getOrderSn(){
-        String url= FSConfig.getCommonApi()+ "/app/common/genOrderCode";
-//        String url= "42.194.245.189:8010/app/common/genOrderCode";
-        String json = HttpRequest.get(url)
-                .execute().body();
-        OrderCodeVO vo= JSONUtil.toBean(json, OrderCodeVO.class);
-        if(vo.getCode()==200){
-            return vo.getOrderCode();
-        }
-        else return null;
+//        String url= FSConfig.getCommonApi()+ "/app/common/genOrderCode";
+////        String url= "42.194.245.189:8010/app/common/genOrderCode";
+//        String json = HttpRequest.get(url)
+//                .execute().body();
+//        OrderCodeVO vo= JSONUtil.toBean(json, OrderCodeVO.class);
+//        if(vo.getCode()==200){
+//            return vo.getOrderCode();
+//        }
+//        else return null;
+        return OrderCodeUtils.genOrderSn();
 
     }
 

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

@@ -62,6 +62,11 @@ public class CourseConfig implements Serializable {
      * 是否绑定
      */
     private Boolean isBound;
+    private Boolean dept;
+    /**
+     * 是否单销售观看(只能在第一次绑定的销售头上看课)
+     */
+    private boolean oneCompanyCourse;
 
 
     @Data

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

@@ -86,4 +86,13 @@ public class FsCoursePlaySourceConfig {
      * 销售ID
      */
     private Long companyUserId;
+    // 创建人
+    private Long createUserId;
+    // 创建部门
+    private Long createDeptId;
+
+    /**
+     * 是否是互医/商城小程序
+     */
+    private Integer isMall;
 }

+ 35 - 5
fs-service/src/main/java/com/fs/course/dto/FsOrderDeliveryNoteDTO.java

@@ -3,6 +3,8 @@ package com.fs.course.dto;
 import com.fs.common.annotation.Excel;
 import lombok.Data;
 
+import java.math.BigDecimal;
+
 /**
  * 订单发货下载模板
  * **/
@@ -11,12 +13,40 @@ public class FsOrderDeliveryNoteDTO {
     /**
      * 系统订单号
      * **/
-    @Excel(name = "系统订单号(必填)",width = 40,sort = 1)
+    @Excel(name = "系统订单号(必填)",width = 20,sort = 1)
     private String orderNumber;
 
-    /**
-     * 发货状态
-     * **/
-    @Excel(name = "系统订单号(1:待发货、2:待收货、3:交易完成,-3:已取消)填写对应数字",width = 90,sort = 2)
+    @Excel(name = "物流公司编号(必填)(SF:顺丰、EMS:邮政、ZTO:中通、JD:京东、DBL:德邦)",width = 30,sort = 2)
+    private String deliverySn;
+
+    private String deliveryName;
+
+    @Excel(name = "快递单号(必填)",width = 20,sort = 3)
+    private String deliveryId;
+
+    @Excel(name = "物流状态(0:暂无信息、1:已揽收、2:在途中、3:签收、4:问题件)",width = 40,sort = 4)
+    private Integer deliveryStatus;
+
+    @Excel(name = "物流结算费用",width = 20,sort = 5)
+    private BigDecimal deliveryPayMoney;
+
+    @Excel(name = "物流跟踪状态(311:快递柜或驿站签收、304:派件异常后最终签收、301:正常签收、211:已放入快递柜或驿站、202:派件中、201:到达派件城市、401:发货无信息、412:快递柜或驿站超时未取、407:退货未签收)",width = 40,sort = 6)
+    private Integer deliveryType;
+
+    @Excel(name = "物流结算状态(1:已结算、2:冻结、3:解冻、4:退回运费、5.调账)",width = 20,sort = 7)
+    private Integer deliveryPayStatus;
+
+    @Excel(name = "快递账单日期",width = 20,sort = 8)
+    private String deliveryTime;
+
+    @Excel(name = "快递结算日期",width = 20,sort = 9)
+    private String deliveryPayTime;
+
+//    /**
+//     * 发货状态
+//     * **/
+//    @Excel(name = "系统订单号(1:待发货、2:待收货、3:交易完成,-3:已取消)填写对应数字",width = 40,sort = 7)
+//    private Integer deliveryNoteStatus;
+
     private Integer deliveryNoteStatus;
 }

+ 6 - 0
fs-service/src/main/java/com/fs/course/mapper/FsCourseTrafficLogMapper.java

@@ -188,5 +188,11 @@ public interface FsCourseTrafficLogMapper
             @Param("offset") int offset,
             @Param("pageSize") int pageSize);
 
+    @Select("SELECT SUM(T.internet_traffic)/1024 AS totalInternetTraffic FROM fs_course_traffic_log T " +
+            "WHERE DATE(T.create_time) = DATE(CURDATE()) AND T.company_id = #{companyId} GROUP BY T.company_id ")
+    Long sumTrafficByCompany(Long companyId);
 
+    @Select("SELECT SUM(T.internet_traffic)/1024 AS totalInternetTraffic FROM fs_course_traffic_log T " +
+            "WHERE DATE(T.create_time) = DATE(CURDATE() - INTERVAL 1 DAY) AND T.company_id = #{companyId} GROUP BY T.company_id ")
+    Long sumTrafficByCompanyYesterday(Long companyId);
 }

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

@@ -85,7 +85,7 @@ public interface FsUserCourseCategoryMapper
     /**
      * 查询所有分类
      */
-    @Select("select cate_id as cateId, cate_name as cateName, pid from fs_user_course_category where is_del=0")
+    @Select("select cate_id as cateId, concat(cate_name,'-',pid) as cateName, pid from fs_user_course_category where is_del=0")
     @MapKey("cateName")
     Map<String,FsUserCourseCategory> queryAllCategoryData();
 

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

@@ -233,7 +233,7 @@ public interface FsUserCourseMapper
 
     @Select("select course_id dict_value, course_name dict_label,img_url dict_imgUrl  from fs_user_course where is_del = 0 and is_private = 1 ")
     List<OptionsVO> selectFsUserCourseAllList();
-
+    
     @Select("select course_id dict_value, course_name dict_label,img_url dict_imgUrl  from fs_user_course where is_del = 0 and is_private = 1" +
             " and find_in_set(#{companyId},company_ids) ")
     List<OptionsVO> selectFsUserCourseByCompany(@Param("companyId") Long companyId);

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

@@ -40,6 +40,12 @@ public class FsCoursePlaySourceConfigCreateParam {
     private String msgDataFormat;
 
     @NotNull(message = "类型不能为空")
-    @ApiModelProperty("类型 1小程序 2公众号")
+    @ApiModelProperty("类型 1主要小程序 2公众号 3炮灰小程序")
     private Integer type;
+
+    @ApiModelProperty("所属公司")
+    private Long companyId;
+
+    @ApiModelProperty("是否是互医/商城小程序")
+    private Integer isMall;
 }

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

@@ -39,4 +39,10 @@ public class FsCoursePlaySourceConfigEditParam {
 
     @ApiModelProperty("类型 1小程序 2公众号")
     private Integer type;
+
+    @ApiModelProperty("所属公司")
+    private Long companyId;
+
+    @ApiModelProperty("是否是互医/商城小程序")
+    private Integer isMall;
 }

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

@@ -4,6 +4,7 @@ import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
@@ -24,6 +25,7 @@ import com.fs.course.mapper.FsUserCourseVideoMapper;
 import com.fs.course.param.FsCourseLinkCreateParam;
 import com.fs.course.param.FsCourseLinkRoomParam;
 import com.fs.course.service.IFsCourseLinkService;
+import com.fs.course.service.IFsCoursePlaySourceConfigService;
 import com.fs.course.service.IFsUserCourseService;
 import com.fs.his.config.FsSysConfig;
 import com.fs.his.utils.ConfigUtil;
@@ -87,6 +89,8 @@ public class FsCourseLinkServiceImpl implements IFsCourseLinkService
     private FsCourseLinkMapper fsCourseLinkMapper;
     @Autowired
     private ISysConfigService configService;
+    @Autowired
+    private IFsCoursePlaySourceConfigService fsCoursePlaySourceConfigService;
 
     @Autowired
     private FsCourseDomainNameMapper fsCourseDomainNameMapper;
@@ -851,11 +855,11 @@ public class FsCourseLinkServiceImpl implements IFsCourseLinkService
                 query = URLEncoder.encode(query, StandardCharsets.UTF_8.toString());
 
 
-
-                SysConfig sysConfig3 = sysConfigMapper.selectConfigByConfigKey("courseMa.config");
-                List<CourseMaConfig> courseMaConfigs = JSON.parseArray(sysConfig3.getConfigValue(), CourseMaConfig.class);
-                if (courseMaConfigs!=null&& !courseMaConfigs.isEmpty()){
-                    for (CourseMaConfig courseMaConfig : courseMaConfigs) {
+                List<FsCoursePlaySourceConfig> list = fsCoursePlaySourceConfigService.list(new QueryWrapper<FsCoursePlaySourceConfig>().ne("type", 2).eq("is_del", 0));
+//                SysConfig sysConfig3 = sysConfigMapper.selectConfigByConfigKey("courseMa.config");
+//                List<CourseMaConfig> courseMaConfigs = JSON.parseArray(sysConfig3.getConfigValue(), CourseMaConfig.class);
+                if (list!=null&& !list.isEmpty()){
+                    for (FsCoursePlaySourceConfig courseMaConfig : list) {
                         if (appId.equals(courseMaConfig.getAppid())) {
 
                             //获取微信token

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

@@ -648,14 +648,14 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
             return;
         }
 
-        FsUserCourseCategory category = categoryData.get(importDTO.getQuestionType().trim());
+        FsUserCourseCategory category = categoryData.get(importDTO.getQuestionType().trim()+"-0");
         if (category != null) {
             questionBank.setQuestionType(category.getCateId());
 
             // 子分类
             if (StringUtils.isNotBlank(importDTO.getQuestionSubTyp())) {
-                FsUserCourseCategory subCategory = categoryData.get(importDTO.getQuestionSubTyp().trim());
-                if (subCategory != null && Objects.equals(subCategory.getPid(), category.getCateId())) {
+                FsUserCourseCategory subCategory = categoryData.get(importDTO.getQuestionSubTyp().trim()+"-" + category.getCateId());
+                if (subCategory != null) {
                     questionBank.setQuestionSubType(subCategory.getCateId());
                 }
             }

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

@@ -185,6 +185,8 @@ public class FsCourseTrafficLogServiceImpl implements IFsCourseTrafficLogService
         }
         if (ObjectUtils.isNotEmpty(param.getTabType())&&param.getTabType().equals("common")){
             param.setCommon(param.getTabType());
+        }else if(ObjectUtils.isNotNull(param.getCompanyId())){
+            param.setCommon("company");
         }
         List<FsCourseTrafficLogListVO> fsCourseTrafficLogListVOS = fsCourseTrafficLogMapper.selectTrafficNew(param);
         for (FsCourseTrafficLogListVO log : fsCourseTrafficLogListVOS) {

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

@@ -57,6 +57,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.checkerframework.checker.units.qual.A;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import com.fs.course.service.IFsUserCourseService;
 import org.springframework.transaction.annotation.Transactional;
@@ -116,6 +117,7 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
     private IFsUserCourseService fsUserCourseService;
 
     @Autowired
+    @Lazy
     private IFsUserCourseVideoService fsUserCourseVideoService;
 
     @Autowired

+ 191 - 14
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -17,6 +17,7 @@ import com.fs.common.utils.CloudHostUtils;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.date.DateUtil;
+import com.fs.company.constant.CompanyTrafficConstants;
 import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.mapper.CompanyMapper;
@@ -47,6 +48,7 @@ import com.fs.his.param.WxSendRedPacketParam;
 import com.fs.his.service.IFsStorePaymentService;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.service.IFsUserWxService;
+import com.fs.his.utils.ConfigUtil;
 import com.fs.his.vo.OptionsVO;
 import com.fs.qw.domain.QwCompany;
 import com.fs.qw.domain.QwExternalContact;
@@ -87,9 +89,8 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
-import java.time.Instant;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
+import java.time.*;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
@@ -248,6 +249,9 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     @Autowired
     private CloudHostProper cloudHostProper;
 
+    @Autowired
+    ConfigUtil configUtil;
+
     @Autowired
     private RedisTemplate<String,BigDecimal> redisTemplate;
 
@@ -487,12 +491,21 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 //            logger.error("看课重粉提交mq失败", e);
 //        }
 
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        boolean oneCompanyCourse = config.isOneCompanyCourse();
+        if(oneCompanyCourse && fsUser.getQwExtId() != null){
+            QwExternalContact qwExternalContact = qwExternalContactMapper.selectById(fsUser.getQwExtId());
+            if(qwExternalContact.getCompanyUserId() != null && !qwExternalContact.getCompanyUserId().equals(param.getCompanyUserId())){
+                return R.error(500, "该用户("+fsUser.getUserId() + ")已成为其他销售会员");
+            }
+        }
         Integer isRoom = param.getIsRoom();
 
         // 处理逻辑
         if (isRoom == null || isRoom == 0) {
             // 当 isRoom 为 null 或 0 时走 handleExt
-            return handleExt(param,msg);
+            return handleExt(param,msg, oneCompanyCourse);
         } else if (isRoom == 1) {
             // 当 isRoom 为 1 时走 handleRoom
             return handleRoom(param,fsUser);
@@ -622,7 +635,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         courseWatchLogMapper.insertFsCourseWatchLog(log);
     }
 
-    private R handleExt(FsUserCourseVideoAddKfUParam param,String msg){
+    private R handleExt(FsUserCourseVideoAddKfUParam param, String msg, boolean oneCompanyCourse){
         if (param.getLinkType()!=null&&param.getLinkType()==1){
             if (param.getLinkId()!=null){
                 // 从数据库中查找短链对应的真实链接
@@ -825,6 +838,10 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             if (video == null) {
                 return R.error("视频不存在");
             }
+            Company company = companyMapper.selectCompanyById(param.getCompanyId());
+            if (company==null){
+                return R.error("公司不存在");
+            }
 
             // 计算流量
             BigDecimal result = param.getBufferRate().divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP);
@@ -839,9 +856,9 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
             // 处理 UUID 为空的情况
             if (StringUtils.isNotEmpty(trafficLog.getUuId())) {
-                // 直接插入或更新
-//                logger.error("【插入或更新流量】:{}",trafficLog);
+                // 插入或更新
                 fsCourseTrafficLogMapper.insertOrUpdateTrafficLog(trafficLog);
+                asyncDeductTraffic(company, trafficLog);
             }
         } catch (Exception e) {
             e.printStackTrace();
@@ -852,6 +869,79 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         return R.ok();
     }
 
+    public void asyncDeductTraffic(Company company, FsCourseTrafficLog trafficLog) {
+        try {
+            //根据uuid查询
+            FsCourseTrafficLog existingLog = fsCourseTrafficLogMapper.selectFsCourseTrafficLogByuuId(trafficLog.getUuId());
+            long recordedTraffic;
+            if (existingLog != null) {
+                recordedTraffic = trafficLog.getInternetTraffic() - existingLog.getInternetTraffic();
+            }else{
+                recordedTraffic = trafficLog.getInternetTraffic();
+            }
+            if (recordedTraffic <= 0) {
+                return;
+            }
+            // 扣除流量
+            Long remainingTraffic = updateRedisCache(company, recordedTraffic/1024);
+
+            if ("1".equals(configUtil.generateConfigByKey("watch.course.config").getString("doNotPlay")) && remainingTraffic <= 0) {
+                logger.warn("公司ID: {} 流量不足,当前剩余: {}", company.getCompanyId(), remainingTraffic);
+                throw new Exception("流量不足");
+            }
+
+            /*logger.info("异步扣除流量成功 - 公司ID: {}, 扣除流量: {}, 剩余流量: {}",
+                    company.getCompanyId(), traffic, remainingTraffic);*/
+        } catch (Exception e) {
+            logger.error("异步扣除流量失败 - 公司ID: {}, 错误信息: {}",
+                    company.getCompanyId(), e.getMessage(), e);
+        }
+    }
+
+    //
+    private Long updateRedisCache(Company company, Long traffic) throws Exception {
+        // 分布式扣除流量
+        String companyKey = CompanyTrafficConstants.CACHE_KEY + ":" + company.getDeptId() + ":" + company.getCompanyId();
+        String companyDayKey = companyKey + ":"+ LocalDate.now();
+        String companyMonthKey = companyKey + ":"+ YearMonth.now();
+
+        String deptKey = CompanyTrafficConstants.CACHE_KEY + ":" + company.getDeptId();
+        String deptDayKey = deptKey + ":"+ LocalDate.now();
+        String deptMonthKey = deptKey + ":"+ YearMonth.now();
+
+        String lockKey = companyKey + ":lock";
+        //销售公司剩余流量
+        Object companyTraffic = redisCache.getCacheObject(companyKey);
+        Long balance;
+        if(companyTraffic instanceof Long) {
+            balance = (Long) companyTraffic;
+        }else if(companyTraffic instanceof Integer){
+            balance = ((Integer) companyTraffic).longValue();
+        }else if(companyTraffic instanceof String){
+            balance = Long.parseLong(companyTraffic.toString());
+        }else{
+            throw new IllegalArgumentException("流量转换异常");
+        }
+        try {
+            if (redisCache.setIfAbsent(lockKey, "1", 2, TimeUnit.SECONDS)) {
+                try {
+                    balance = redisCache.decr(companyKey, traffic);
+                   redisCache.decr(deptKey, traffic);
+                   redisCache.incr(companyDayKey, traffic);
+                   redisCache.incr(deptDayKey, traffic);
+                   redisCache.incr(companyMonthKey, traffic);
+                   redisCache.incr(deptMonthKey, traffic);
+                } finally {
+                    redisCache.deleteObject(lockKey); // 释放锁
+                }
+            }
+        } catch (Exception e) {
+            logger.error("【更新Redis缓存失败】企业ID: {}, 流量: {}, 错误信息:{}", company.getCompanyId(), traffic, e.getMessage(), e);
+            throw e;
+        }
+        return balance;
+    }
+
 
     @Override
     public R getIntegralByH5Video(FsUserCourseVideoFinishUParam param) {
@@ -1067,13 +1157,9 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             amount = video.getRedPacketMoney();
         }
 
-
-
         // 准备发送红包参数
         WxSendRedPacketParam packetParam = new WxSendRedPacketParam();
         packetParam.setOpenId(user.getMpOpenId());
-
-
         // 来源是小程序切换openId
         if (param.getSource() == 2) {
             //处理多小程序问题
@@ -1437,6 +1523,93 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
     }
 
+    /**
+     * 直接发送奖励
+     *
+     * @param config
+     * @param packetParam
+     * @param param
+     * @param amount
+     * @param log
+     * @return
+     */
+    private R processRedPacket(CourseConfig config, WxSendRedPacketParam packetParam, FsCourseSendRewardUParam param, BigDecimal amount, FsCourseWatchLog log) {
+        R sendRedPacket = paymentService.sendRedPacket(packetParam);
+
+        if (!sendRedPacket.get("code").equals(200)) {
+            return R.error("奖励发送失败,请联系客服");
+        }
+
+        createRedPacketLog(sendRedPacket, param, amount, log);
+        updateWatchLogRewardType(log, config);
+
+        return sendRedPacket;
+    }
+
+    private void createRedPacketLog(R sendRedPacket, FsCourseSendRewardUParam param, BigDecimal amount, FsCourseWatchLog log) {
+        FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
+
+        // Set common fields
+        redPacketLog.setCourseId(param.getCourseId());
+        redPacketLog.setCompanyId(param.getCompanyId());
+        redPacketLog.setUserId(param.getUserId());
+        redPacketLog.setVideoId(param.getVideoId());
+        redPacketLog.setStatus(0);
+        redPacketLog.setQwUserId(param.getQwUserId());
+        redPacketLog.setCompanyUserId(param.getCompanyUserId());
+        redPacketLog.setCreateTime(new Date());
+        redPacketLog.setAmount(amount);
+        redPacketLog.setWatchLogId(log != null ? log.getLogId() : null);
+        redPacketLog.setPeriodId(param.getPeriodId());
+        redPacketLog.setAppId(param.getAppId());
+
+        // Set batch number based on isNew flag
+        if (sendRedPacket.get("isNew").equals(1)) {
+            TransferBillsResult transferBillsResult = (TransferBillsResult) sendRedPacket.get("data");
+            redPacketLog.setResult(JSON.toJSONString(sendRedPacket));
+            redPacketLog.setOutBatchNo(transferBillsResult.getOutBillNo());
+        } else {
+            redPacketLog.setOutBatchNo(sendRedPacket.get("orderCode").toString());
+        }
+
+        redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
+    }
+
+    private void updateWatchLogRewardType(FsCourseWatchLog log, CourseConfig config) {
+        if (log != null) {
+            log.setRewardType(config.getRewardType());
+            courseWatchLogMapper.updateFsCourseWatchLog(log);
+        }
+    }
+    /**
+     * 获取用户openId
+     *
+     * @param userId    用户ID
+     * @param companyId 公司ID
+     * @param source    来源 1公众号 2小程序
+     * @return openId
+     */
+    private String getOpenId(Long userId, Long companyId, Integer source) {
+        Company company = companyMapper.selectCompanyById(companyId);
+        String appId = source == 1 ? company.getCourseMaAppId() : company.getCourseMiniAppId();
+
+        // 公司配置为空时获取默认配置
+        if (StringUtils.isBlank(appId)) {
+            String json = configService.selectConfigByKey("course.config");
+            CourseConfig config = JSON.parseObject(json, CourseConfig.class);
+            appId = source == 1 ? config.getMpAppId() : config.getMiniprogramAppid();
+        }
+
+        // 查询openId
+        Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery().eq(FsUserWx::getFsUserId, userId).eq(FsUserWx::getAppId, appId);
+        FsUserWx fsUserWx = fsUserWxService.getOne(queryWrapper);
+        if (Objects.isNull(fsUserWx)) {
+            throw new CustomException("获取openId失败");
+        }
+
+        return fsUserWx.getOpenId();
+    }
+
     /**
      * 发放积分奖励
      *
@@ -1578,7 +1751,9 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     @Transactional
     public ResponseResult<FsUser> isAddCompanyUser(FsUserCourseAddCompanyUserParam param) {
         logger.info("\n 【进入个微-判断是否添加客服】,入参:{}",param);
-
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        boolean oneCompanyCourse = config.isOneCompanyCourse();
         //查询用户
        FsUser fsUser = fsUserMapper.selectFsUserById(param.getUserId());
          if (fsUser == null){
@@ -2645,11 +2820,13 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             long roundedResult = result.multiply(longAsBigDecimal).setScale(0, RoundingMode.HALF_UP).longValue();
             trafficLog.setInternetTraffic(roundedResult);
 
+            //扣除流量
+            Company company = companyMapper.selectCompanyById(param.getCompanyId());
             // 处理 UUID 为空的情况
             if (StringUtils.isNotEmpty(trafficLog.getUuId())) {
-                // 直接插入或更新
-//                logger.error("【插入或更新流量】:{}",trafficLog);
+                // 插入或更新
                 fsCourseTrafficLogMapper.insertOrUpdateTrafficLog(trafficLog);
+                asyncDeductTraffic(company, trafficLog);
             }
         } catch (Exception e) {
             e.printStackTrace();

+ 9 - 1
fs-service/src/main/java/com/fs/course/vo/FsCoursePlaySourceConfigVO.java

@@ -36,9 +36,12 @@ public class FsCoursePlaySourceConfigVO {
     @ApiModelProperty("msgDataFormat")
     private String msgDataFormat;
 
-    @ApiModelProperty("类型 1小程序 2公众号")
+    @ApiModelProperty("类型 1主要小程序 2公众号 3炮灰小程序")
     private Integer type;
 
+    @ApiModelProperty("所属公司")
+    private Long companyId;
+
     @ApiModelProperty("创建时间")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime createTime;
@@ -46,4 +49,9 @@ public class FsCoursePlaySourceConfigVO {
     @ApiModelProperty("修改时间")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime updateTime;
+
+    /**
+     * 是否是互医/商城小程序
+     */
+    private Integer isMall;
 }

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

@@ -30,7 +30,7 @@ import java.util.Map;
 public class JstErpHttpServiceImpl implements JstErpHttpService {
 
     //正式
-    private static final String BASE_URL = "https://openapi.jushuitan.com";
+    private static final String BASE_URL = "https://openapi.jushuitan.com/";
     /**
      * 获取access_token、refresh_token url
      */
@@ -83,7 +83,7 @@ public class JstErpHttpServiceImpl implements JstErpHttpService {
 
     @Override
     public ProductUploadResultDTO uploadGoods(JSONObject dto) {
-        String url = BASE_URL + "/open/jushuitan/itemsku/upload";
+        String url = BASE_URL + "open/jushuitan/itemsku/upload";
         log.info("上传商品信息 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));
 
         HttpResponse response = executeJsonPost(url, dto);
@@ -92,7 +92,7 @@ public class JstErpHttpServiceImpl implements JstErpHttpService {
 
     @Override
     public ProductResponseDTO queryGoods(ProductQueryRequestDTO dto) {
-        String url = BASE_URL + "/open/sku/query";
+        String url = BASE_URL + "open/sku/query";
         log.info("查询商品信息 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));
 
         HttpResponse response = executeJsonPost(url, dto);
@@ -119,7 +119,7 @@ public class JstErpHttpServiceImpl implements JstErpHttpService {
 
     @Override
     public CommonResponse cancel(OrderCancelRequestDTO dto) {
-        String url = BASE_URL + "/open/jushuitan/orderbyoid/cancel";
+        String url = BASE_URL + "open/jushuitan/orderbyoid/cancel";
         log.info("取消订单 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));
 
         HttpResponse response = executeJsonPost(url, dto);
@@ -129,7 +129,7 @@ public class JstErpHttpServiceImpl implements JstErpHttpService {
 
     @Override
     public CommonResponse<AfterSaleResponseDTO> aftersaleUpload(RefundOrderDTO dto) {
-        String url = BASE_URL + "/open/aftersale/upload";
+        String url = BASE_URL + "open/aftersale/upload";
         log.info("售后上传 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));
 
         HttpResponse response = executeJsonPost(url, Collections.singletonList(dto));
@@ -139,7 +139,7 @@ public class JstErpHttpServiceImpl implements JstErpHttpService {
 
     @Override
     public CommonResponse<AssetProcessResultDTO> aftersaleConfirm(AfterSaleConfirmRequestDTO dto) {
-        String url = BASE_URL + "/open/webapi/aftersaleapi/open/confirm";
+        String url = BASE_URL + "open/webapi/aftersaleapi/open/confirm";
         log.info("售后单确认 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));
 
         HttpResponse response = executeJsonPost(url, dto);

+ 3 - 0
fs-service/src/main/java/com/fs/erp/service/IErpOrderService.java

@@ -16,7 +16,10 @@ public interface IErpOrderService
     ErpOrderResponse refundOrder(ErpRefundOrder order);
     ErpDeliverysResponse getDeliver(ErpDeliverysRequest param);
     ErpOrderQueryResponse getOrder(ErpOrderQueryRequert param);
+
     BaseResponse refundUpdate(ErpRefundUpdateRequest param);
+    BaseResponse refundUpdateScrm(ErpRefundUpdateRequest param);
+
     ErpOrderResponse finishOrder(ErpOrder order);
     //代服管家查物流状态
     void getOrderDeliveryStatus(FsStoreOrder order);

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

@@ -247,6 +247,11 @@ public class DfOrderServiceImpl implements IErpOrderService
         return refundOrder(erpRefundOrder);
     }
 
+    @Override
+    public BaseResponse refundUpdateScrm(ErpRefundUpdateRequest param) {
+        return null;
+    }
+
     @Override
     public ErpOrderResponse finishOrder(ErpOrder order) {
         return null;

+ 5 - 0
fs-service/src/main/java/com/fs/erp/service/impl/ErpOrderServiceImpl.java

@@ -134,6 +134,11 @@ public class ErpOrderServiceImpl implements IErpOrderService
         return response;
     }
 
+    @Override
+    public BaseResponse refundUpdateScrm(ErpRefundUpdateRequest param) {
+        return null;
+    }
+
     @Override
     public ErpOrderResponse finishOrder(ErpOrder order) {
         return null;

+ 5 - 0
fs-service/src/main/java/com/fs/erp/service/impl/HzOMSErpOrderServiceImpl.java

@@ -151,6 +151,11 @@ public class HzOMSErpOrderServiceImpl implements IErpOrderService {
         return res;
     }
 
+    @Override
+    public BaseResponse refundUpdateScrm(ErpRefundUpdateRequest param) {
+        return null;
+    }
+
     @Override
     public ErpOrderResponse finishOrder(ErpOrder order) {
         return null;

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

@@ -267,7 +267,8 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
             shopOrderDTO.setFreight(fsStoreOrder.getPayDelivery().doubleValue());
         }
         // 备注
-        shopOrderDTO.setRemark(order.getBuyer_memo());
+        //shopOrderDTO.setRemark(order.getBuyer_memo());
+        shopOrderDTO.setRemark(DateUtil.format(new Date(), "dd"));
         // 买家留言
         shopOrderDTO.setBuyerMessage(order.getBuyer_memo());
 
@@ -526,6 +527,34 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
         return baseResponse;
     }
 
+    @Override
+    public BaseResponse refundUpdateScrm(ErpRefundUpdateRequest param) {
+
+        FsStoreOrderScrm fsStoreOrder = fsStoreOrderScrmService.selectFsStoreOrderByOrderCode(param.getTid());
+        //todo 待合并
+//        FsStoreDelivers byOrderCode = fsStoreDeliversMapper.findByOrderCode(fsStoreOrder.getOrderCode());
+        //todo
+        // 发货后退款
+//        if(ObjectUtil.isNotNull(byOrderCode)){
+
+//        } else {
+        // 如果是发货前退款,直接走取消订单流程
+        // 如果是发货后退款,走售后流程
+        OrderCancelRequestDTO requestDTO = new OrderCancelRequestDTO();
+        requestDTO.setOIds(Collections.singletonList(Integer.valueOf(fsStoreOrder.getExtendOrderId())));
+        requestDTO.setCancelType("用户退款");
+        requestDTO.setRemark("用户退款");
+
+        jstErpHttpService.cancel(requestDTO);
+//        }
+
+
+        BaseResponse baseResponse = new BaseResponse();
+        baseResponse.setSuccess(true);
+
+        return baseResponse;
+    }
+
     @Override
     public ErpOrderResponse finishOrder(ErpOrder order) {
         return null;

+ 5 - 0
fs-service/src/main/java/com/fs/erp/service/impl/K9OrderScrmServiceImpl.java

@@ -133,6 +133,11 @@ public class K9OrderScrmServiceImpl implements IErpOrderService {
         return null;
     }
 
+    @Override
+    public BaseResponse refundUpdateScrm(ErpRefundUpdateRequest param) {
+        return null;
+    }
+
 
     /**
      * 退款 运单号已获取到

+ 5 - 0
fs-service/src/main/java/com/fs/erp/service/impl/WdtErpOrderServiceImpl.java

@@ -906,6 +906,11 @@ public class WdtErpOrderServiceImpl implements IErpOrderService {
         }
     }
 
+    @Override
+    public BaseResponse refundUpdateScrm(ErpRefundUpdateRequest param) {
+        return null;
+    }
+
     @Override
     public ErpOrderResponse finishOrder(ErpOrder order) {
         FsSysConfig sysConfig = configUtil.getSysConfig();

+ 3 - 1
fs-service/src/main/java/com/fs/his/domain/FsUserComplaint.java → fs-service/src/main/java/com/fs/his/domain/FsHisComplaint.java

@@ -1,6 +1,7 @@
 package com.fs.his.domain;
 
 import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
 import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
 import lombok.Data;
@@ -16,7 +17,8 @@ import java.util.Date;
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-public class FsUserComplaint extends BaseEntity{
+@TableName("fs_user_complaint")
+public class FsHisComplaint extends BaseEntity{
 
     @TableId
     private Long id;

Some files were not shown because too many files changed in this diff