瀏覽代碼

Merge remote-tracking branch 'origin/bly_store' into bly_store

# Conflicts:
#	fs-service/src/main/java/com/fs/hisStore/service/IFsStoreOrderScrmService.java
#	fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java
#	fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml
xgb 10 小時之前
父節點
當前提交
02a28a459b
共有 100 個文件被更改,包括 3230 次插入338 次删除
  1. 1 0
      DirectoryV3.xml
  2. 19 0
      fs-ad-api/src/main/java/com/fs/framework/config/RedisConfig.java
  3. 682 36
      fs-admin/src/main/java/com/fs/api/controller/IndexStatisticsController.java
  4. 41 1
      fs-admin/src/main/java/com/fs/company/controller/CompanyController.java
  5. 103 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyTrafficController.java
  6. 49 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyTrafficLogController.java
  7. 39 3
      fs-admin/src/main/java/com/fs/course/controller/FsCoursePlaySourceConfigController.java
  8. 5 5
      fs-admin/src/main/java/com/fs/course/controller/FsCourseRedPacketLogController.java
  9. 1 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseVideoController.java
  10. 1 2
      fs-admin/src/main/java/com/fs/fastGpt/FastgptExtUserTagController.java
  11. 25 3
      fs-admin/src/main/java/com/fs/his/controller/FsCompanyController.java
  12. 12 12
      fs-admin/src/main/java/com/fs/his/controller/FsHisComplaintController.java
  13. 19 0
      fs-admin/src/main/java/com/fs/his/controller/FsPatientController.java
  14. 24 0
      fs-admin/src/main/java/com/fs/hisStore/FsHisStoreLogController.java
  15. 134 0
      fs-admin/src/main/java/com/fs/hisStore/FsStoreSCRMController.java
  16. 74 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreHealthOrderScrmController.java
  17. 83 0
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java
  18. 12 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductScrmController.java
  19. 108 0
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreRecommendScrmController.java
  20. 20 3
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreScrmController.java
  21. 11 1
      fs-admin/src/main/java/com/fs/hisStore/controller/SysOperlogScrmController.java
  22. 94 0
      fs-admin/src/main/java/com/fs/qw/FsCourseTask.java
  23. 33 1
      fs-admin/src/main/java/com/fs/qw/controller/QwCompanyController.java
  24. 39 0
      fs-admin/src/main/java/com/fs/task/FsStoreTask.java
  25. 106 0
      fs-admin/src/main/java/com/fs/user/controller/FsUserComplaintController.java
  26. 109 0
      fs-admin/src/main/java/com/fs/user/controller/FsUserComplaintMsgController.java
  27. 14 0
      fs-admin/src/main/java/com/fs/web/controller/system/SysLoginController.java
  28. 1 1
      fs-admin/src/main/resources/application.yml
  29. 18 40
      fs-common-api/src/main/java/com/fs/framework/config/MyBatisConfig.java
  30. 19 0
      fs-common-api/src/main/java/com/fs/framework/config/RedisConfig.java
  31. 2 2
      fs-common-api/src/main/resources/application.yml
  32. 6 2
      fs-common/src/main/java/com/fs/common/core/domain/model/LoginUser.java
  33. 9 5
      fs-common/src/main/java/com/fs/common/core/redis/RedisCache.java
  34. 7 2
      fs-common/src/main/java/com/fs/common/enums/BusinessType.java
  35. 21 0
      fs-company-app/src/main/java/com/fs/core/config/RedisConfig.java
  36. 1 1
      fs-company/src/main/java/com/fs/company/controller/company/CompanyController.java
  37. 3 2
      fs-company/src/main/java/com/fs/company/controller/course/FsCourseAnswerLogsController.java
  38. 3 2
      fs-company/src/main/java/com/fs/company/controller/course/FsCourseRedPacketLogController.java
  39. 2 0
      fs-company/src/main/java/com/fs/company/controller/course/FsUserCoursePeriodController.java
  40. 11 0
      fs-company/src/main/java/com/fs/company/controller/qw/QwSopController.java
  41. 3 1
      fs-company/src/main/java/com/fs/company/controller/qw/QwSopLogsController.java
  42. 80 4
      fs-company/src/main/java/com/fs/company/controller/qw/QwUserVoiceLogController.java
  43. 2 2
      fs-company/src/main/java/com/fs/company/controller/qw/SopUserLogsController.java
  44. 18 0
      fs-company/src/main/java/com/fs/framework/config/RedisConfig.java
  45. 2 2
      fs-company/src/main/resources/application.yml
  46. 1 14
      fs-doctor-app/src/main/java/com/fs/app/controller/InquiryOrderController.java
  47. 21 0
      fs-doctor-app/src/main/java/com/fs/framework/config/RedisConfig.java
  48. 25 2
      fs-framework/src/main/java/com/fs/framework/aspectj/LogAspect.java
  49. 21 0
      fs-framework/src/main/java/com/fs/framework/config/RedisConfig.java
  50. 7 1
      fs-framework/src/main/java/com/fs/framework/manager/factory/AsyncFactory.java
  51. 21 0
      fs-hospital/src/main/java/com/fs/framework/config/RedisConfig.java
  52. 26 6
      fs-ipad-task/src/main/java/com/fs/app/service/IpadSendServer.java
  53. 2 2
      fs-ipad-task/src/main/java/com/fs/app/task/SendMsg.java
  54. 22 0
      fs-ipad-task/src/main/java/com/fs/framework/config/RedisConfig.java
  55. 20 0
      fs-live-app/src/main/java/com/fs/framework/config/RedisConfig.java
  56. 38 37
      fs-qw-api-msg/src/main/java/com/fs/app/controller/QwMsgController.java
  57. 21 0
      fs-qw-api-msg/src/main/java/com/fs/framework/config/RedisConfig.java
  58. 21 0
      fs-qw-api/src/main/java/com/fs/framework/config/RedisConfig.java
  59. 20 0
      fs-qw-mq/src/main/java/com/fs/framework/config/RedisConfig.java
  60. 16 9
      fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java
  61. 21 0
      fs-qw-task/src/main/java/com/fs/framework/config/RedisConfig.java
  62. 19 0
      fs-qw-voice/src/main/java/com/fs/framework/config/RedisConfig.java
  63. 21 0
      fs-qwhook-msg/src/main/java/com/fs/framework/config/RedisConfig.java
  64. 36 44
      fs-qwhook-sop/src/main/java/com/fs/framework/config/MyBatisConfig.java
  65. 20 0
      fs-qwhook-sop/src/main/java/com/fs/framework/config/RedisConfig.java
  66. 21 0
      fs-qwhook/src/main/java/com/fs/framework/config/RedisConfig.java
  67. 20 0
      fs-repeat-api/src/main/java/com/fs/framework/config/RedisConfig.java
  68. 5 0
      fs-service/src/main/java/com/fs/company/constant/CompanyTrafficConstants.java
  69. 4 0
      fs-service/src/main/java/com/fs/company/domain/Company.java
  70. 41 0
      fs-service/src/main/java/com/fs/company/domain/CompanyTrafficRecord.java
  71. 45 0
      fs-service/src/main/java/com/fs/company/domain/CompanyTrafficRecordLog.java
  72. 12 6
      fs-service/src/main/java/com/fs/company/mapper/CompanyMapper.java
  73. 10 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyTrafficRecordLogMapper.java
  74. 28 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyTrafficRecordMapper.java
  75. 3 32
      fs-service/src/main/java/com/fs/company/param/CompanyParam.java
  76. 23 0
      fs-service/src/main/java/com/fs/company/param/CompanyTrafficRecordChargeParam.java
  77. 21 0
      fs-service/src/main/java/com/fs/company/param/CompanyTrafficRecordLogQueryParam.java
  78. 17 0
      fs-service/src/main/java/com/fs/company/param/CompanyTrafficRecordQueryParam.java
  79. 2 0
      fs-service/src/main/java/com/fs/company/service/ICompanyConfigService.java
  80. 1 1
      fs-service/src/main/java/com/fs/company/service/ICompanyService.java
  81. 16 0
      fs-service/src/main/java/com/fs/company/service/ICompanyTrafficRecordLogService.java
  82. 25 0
      fs-service/src/main/java/com/fs/company/service/ICompanyTrafficRecordService.java
  83. 38 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyConfigServiceImpl.java
  84. 2 2
      fs-service/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java
  85. 40 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyTrafficRecordLogServiceImpl.java
  86. 272 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyTrafficRecordServiceImpl.java
  87. 4 1
      fs-service/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java
  88. 4 0
      fs-service/src/main/java/com/fs/company/vo/CompanyVO.java
  89. 28 29
      fs-service/src/main/java/com/fs/core/config/WxMaConfiguration.java
  90. 10 9
      fs-service/src/main/java/com/fs/core/utils/OrderCodeUtils.java
  91. 5 0
      fs-service/src/main/java/com/fs/course/config/CourseConfig.java
  92. 4 0
      fs-service/src/main/java/com/fs/course/domain/FsCoursePlaySourceConfig.java
  93. 9 0
      fs-service/src/main/java/com/fs/course/domain/FsCourseRedPacketLog.java
  94. 35 5
      fs-service/src/main/java/com/fs/course/dto/FsOrderDeliveryNoteDTO.java
  95. 6 0
      fs-service/src/main/java/com/fs/course/mapper/FsCourseTrafficLogMapper.java
  96. 5 0
      fs-service/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java
  97. 1 1
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseCategoryMapper.java
  98. 1 1
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseMapper.java
  99. 4 1
      fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigCreateParam.java
  100. 3 0
      fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigEditParam.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/company/controller" title="公司"/>
      <tree path="/fs-admin/src/main/java/com/fs/live/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-admin/src/main/java/com/fs/qw" title="企微"/>
+     <tree path="/fs-ad-api" title="广告回传"/>
  </trees>
  </trees>

+ 19 - 0
fs-ad-api/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.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
 
+import java.math.BigDecimal;
+
 /**
 /**
  * redis配置
  * redis配置
  *
  *
@@ -90,7 +92,24 @@ public class RedisConfig extends CachingConfigurerSupport
         template.afterPropertiesSet();
         template.afterPropertiesSet();
         return template;
         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
     @Bean
     public DefaultRedisScript<Long> limitScript()
     public DefaultRedisScript<Long> limitScript()
     {
     {

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

@@ -1,16 +1,32 @@
 package com.fs.api.controller;
 package com.fs.api.controller;
 
 
 import com.fs.common.core.domain.R;
 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.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.StatisticsRedisConstant;
 import com.fs.statis.dto.*;
 import com.fs.statis.dto.*;
+import com.fs.statis.param.StatisticsDeptCompanyParam;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.service.ISysConfigService;
 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.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.web.bind.annotation.*;
 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.*;
 import static com.fs.statis.StatisticsRedisConstant.*;
 
 
@@ -19,18 +35,31 @@ import static com.fs.statis.StatisticsRedisConstant.*;
  */
  */
 @RestController
 @RestController
 @RequestMapping("/index/statistics")
 @RequestMapping("/index/statistics")
+@Slf4j
 public class IndexStatisticsController {
 public class IndexStatisticsController {
     @Autowired
     @Autowired
     private RedisCache redisCache;
     private RedisCache redisCache;
 
 
     @Autowired
     @Autowired
     private ISysConfigService sysConfigService;
     private ISysConfigService sysConfigService;
+
+    @Autowired
+    private ConfigUtil configUtil;
+
+    @Autowired
+    private ISysDeptService deptService;
+
+    @Autowired
+    private ICompanyService companyService;
+
+    @Autowired
+    private MedicalMallConfig medicalMallConfig;
     /**
     /**
      * 分析概览
      * 分析概览
      */
      */
     @PostMapping("/analysisPreview")
     @PostMapping("/analysisPreview")
     public R analysisPreview(@RequestBody AnalysisPreviewQueryDTO param){
     public R analysisPreview(@RequestBody AnalysisPreviewQueryDTO param){
-        AnalysisPreviewDTO analysisPreviewDTO = null;
+        AnalysisPreviewDTO analysisPreviewDTO = new AnalysisPreviewDTO();
         Integer type = param.getType();
         Integer type = param.getType();
         Integer userType = param.getUserType();
         Integer userType = param.getUserType();
 
 
@@ -41,7 +70,69 @@ public class IndexStatisticsController {
         if(userType == null) {
         if(userType == null) {
             userType = 0;
             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);
         return R.ok().put("data",analysisPreviewDTO);
     }
     }
@@ -51,8 +142,32 @@ public class IndexStatisticsController {
      * 消费余额
      * 消费余额
      */
      */
     @GetMapping("/rechargeComsumption")
     @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);
         return R.ok().put("data", consumptionBalanceDataDTO);
     }
     }
@@ -62,15 +177,58 @@ public class IndexStatisticsController {
      * @return
      * @return
      */
      */
     @GetMapping("/trafficLog")
     @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){
         if(userType == null){
             userType = 0;
             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){
         if(userType == null){
             userType = 0;
             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){
         if(deaMemberTopTenDTOS == null){
             deaMemberTopTenDTOS = new ArrayList<>();
             deaMemberTopTenDTOS = new ArrayList<>();
         }
         }
@@ -123,8 +386,50 @@ public class IndexStatisticsController {
         Integer type = param.getType();
         Integer type = param.getType();
         Integer dataType = param.getDataType();
         Integer dataType = param.getDataType();
         Integer userType = param.getUserType();
         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);
         return R.ok().put("data", rewardMoneyTopTenDTOS);
     }
     }
 
 
@@ -135,7 +440,47 @@ public class IndexStatisticsController {
     public R rewardMoneyTrend(@RequestBody AnalysisPreviewQueryDTO param){
     public R rewardMoneyTrend(@RequestBody AnalysisPreviewQueryDTO param){
         Integer type = param.getType();
         Integer type = param.getType();
         Integer userType = param.getUserType();
         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);
         return R.ok().put("data", rewardMoneyTrendDTOS);
     }
     }
 
 
@@ -148,29 +493,196 @@ public class IndexStatisticsController {
         String sort = param.getSort();
         String sort = param.getSort();
         Integer statisticalType = param.getStatisticalType();
         Integer statisticalType = param.getStatisticalType();
         Integer userType = param.getUserType();
         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);
         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")
     @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")
     @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")
     @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);
         return R.ok().put("data", authorizationInfoDTO);
     }
     }
@@ -190,9 +727,29 @@ public class IndexStatisticsController {
      * @return
      * @return
      */
      */
     @GetMapping("/thisMonthOrderCount")
     @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")
     @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;
 package com.fs.company.controller;
 
 
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.IdUtil;
+import cn.hutool.json.JSONUtil;
 import com.fs.common.annotation.Log;
 import com.fs.common.annotation.Log;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.controller.BaseController;
 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.CompanyVO;
 import com.fs.company.vo.CompanyVoiceCallerListVO;
 import com.fs.company.vo.CompanyVoiceCallerListVO;
 import com.fs.core.utils.OrderCodeUtils;
 import com.fs.core.utils.OrderCodeUtils;
+import com.fs.course.config.CourseConfig;
 import com.fs.framework.web.service.TokenService;
 import com.fs.framework.web.service.TokenService;
 import com.fs.his.vo.OptionsVO;
 import com.fs.his.vo.OptionsVO;
+import com.fs.system.service.ISysConfigService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
@@ -55,6 +58,8 @@ public class CompanyController extends BaseController
     private ICompanyDeductService deductService;
     private ICompanyDeductService deductService;
     @Autowired
     @Autowired
     private ICompanyVoiceCallerService callerService;
     private ICompanyVoiceCallerService callerService;
+    @Autowired
+    private ISysConfigService configService;
     /**
     /**
      * 查询企业列表
      * 查询企业列表
      */
      */
@@ -63,6 +68,12 @@ public class CompanyController extends BaseController
     public TableDataInfo list(CompanyParam param)
     public TableDataInfo list(CompanyParam param)
     {
     {
         startPage();
         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);
         List<CompanyVO> list = companyService.selectCompanyVOList(param);
         return getDataTable(list);
         return getDataTable(list);
     }
     }
@@ -75,6 +86,12 @@ public class CompanyController extends BaseController
     @GetMapping("/export")
     @GetMapping("/export")
     public AjaxResult export(CompanyParam company)
     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);
         List<CompanyVO> list = companyService.selectCompanyVOList(company);
         ExcelUtil<CompanyVO> util = new ExcelUtil<CompanyVO>(CompanyVO.class);
         ExcelUtil<CompanyVO> util = new ExcelUtil<CompanyVO>(CompanyVO.class);
         return util.exportExcel(list, "company");
         return util.exportExcel(list, "company");
@@ -98,6 +115,10 @@ public class CompanyController extends BaseController
     @PostMapping
     @PostMapping
     public R add(@RequestBody Company company)
     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.setPassword(SecurityUtils.encryptPassword(company.getPassword()));
         company.setAppId(Md5Utils.hash(company.getUserName()));
         company.setAppId(Md5Utils.hash(company.getUserName()));
         company.setAppKey(Md5Utils.hash(company.getPassword()));
         company.setAppKey(Md5Utils.hash(company.getPassword()));
@@ -154,6 +175,12 @@ public class CompanyController extends BaseController
     {
     {
         Company map=new Company();
         Company map=new Company();
         map.setIsDel(0);
         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);
         List<Company> list = companyService.selectCompanyList(map);
         return R.ok().put("data",list);
         return R.ok().put("data",list);
     }
     }
@@ -164,6 +191,12 @@ public class CompanyController extends BaseController
     public TableDataInfo companyCrmDayCountList(CompanyParam param)
     public TableDataInfo companyCrmDayCountList(CompanyParam param)
     {
     {
         startPage();
         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);
         List<CompanyCrmVO> list = companyService.selectCompanyCrmDayCountList(param);
         return getDataTable(list);
         return getDataTable(list);
     }
     }
@@ -239,7 +272,14 @@ public class CompanyController extends BaseController
     @GetMapping("/allList")
     @GetMapping("/allList")
     public TableDataInfo getHospital()
     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);
         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, "流量充值记录");
+    }
+
+
+
+}

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

@@ -1,21 +1,29 @@
 package com.fs.course.controller;
 package com.fs.course.controller;
 
 
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 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.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.annotation.Log;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
 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.R;
+import com.fs.common.core.domain.model.LoginUser;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.bean.BeanUtils;
 import com.fs.common.utils.bean.BeanUtils;
+import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.param.FsCoursePlaySourceConfigCreateParam;
 import com.fs.course.param.FsCoursePlaySourceConfigCreateParam;
 import com.fs.course.param.FsCoursePlaySourceConfigEditParam;
 import com.fs.course.param.FsCoursePlaySourceConfigEditParam;
 import com.fs.course.service.IFsCoursePlaySourceConfigService;
 import com.fs.course.service.IFsCoursePlaySourceConfigService;
 import com.fs.course.vo.FsCoursePlaySourceConfigVO;
 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 com.github.pagehelper.PageHelper;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -31,6 +39,8 @@ import java.util.*;
 public class FsCoursePlaySourceConfigController extends BaseController {
 public class FsCoursePlaySourceConfigController extends BaseController {
 
 
     private final IFsCoursePlaySourceConfigService fsCoursePlaySourceConfigService;
     private final IFsCoursePlaySourceConfigService fsCoursePlaySourceConfigService;
+    private final TokenService tokenService;
+    private final ISysConfigService configService;
 
 
     @PreAuthorize("@ss.hasPermi('course:playSourceConfig:list')")
     @PreAuthorize("@ss.hasPermi('course:playSourceConfig:list')")
     @GetMapping("/list")
     @GetMapping("/list")
@@ -41,6 +51,19 @@ public class FsCoursePlaySourceConfigController extends BaseController {
         Map<String, Object> params = new HashMap<>();
         Map<String, Object> params = new HashMap<>();
         params.put("name", name);
         params.put("name", name);
         params.put("appid", appid);
         params.put("appid", appid);
+        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);
         PageHelper.startPage(pageNum, pageSize);
         List<FsCoursePlaySourceConfigVO> list = fsCoursePlaySourceConfigService.selectCoursePlaySourceConfigVOListByMap(params);
         List<FsCoursePlaySourceConfigVO> list = fsCoursePlaySourceConfigService.selectCoursePlaySourceConfigVOListByMap(params);
@@ -70,8 +93,10 @@ public class FsCoursePlaySourceConfigController extends BaseController {
         if (fsCoursePlaySourceConfigService.count(queryWrapper) > 0) {
         if (fsCoursePlaySourceConfigService.count(queryWrapper) > 0) {
             return AjaxResult.error("appid已存在");
             return AjaxResult.error("appid已存在");
         }
         }
-
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         FsCoursePlaySourceConfig config = new FsCoursePlaySourceConfig();
         FsCoursePlaySourceConfig config = new FsCoursePlaySourceConfig();
+        config.setCreateUserId(loginUser.getUserId());
+        config.setCreateDeptId(loginUser.getDeptId());
         BeanUtils.copyProperties(param, config);
         BeanUtils.copyProperties(param, config);
 
 
         config.setIsDel(0);
         config.setIsDel(0);
@@ -114,8 +139,19 @@ public class FsCoursePlaySourceConfigController extends BaseController {
         fsCoursePlaySourceConfigService.update(updateWrapper);
         fsCoursePlaySourceConfigService.update(updateWrapper);
         return AjaxResult.success();
         return AjaxResult.success();
     }
     }
+
     @GetMapping("/listAll")
     @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
     @Autowired
     FsUserCourseMapper fsUserCourseMapper;
     FsUserCourseMapper fsUserCourseMapper;
     @Autowired
     @Autowired
-    FsUserCourseVideoMapper fsUserCourseVideoMapper;
+    TokenService tokenService;
     @Autowired
     @Autowired
-    private TokenService tokenService;
+    ISysConfigService configService;
     @Autowired
     @Autowired
-    private ISysConfigService configService;
+    FsUserCourseVideoMapper fsUserCourseVideoMapper;
     /**
     /**
      * 查询短链课程看课记录列表
      * 查询短链课程看课记录列表
      */
      */
@@ -149,10 +149,10 @@ public class FsCourseRedPacketLogController extends BaseController
         Long userId = loginUser.getUser().getUserId();
         Long userId = loginUser.getUser().getUserId();
         String json = configService.selectConfigByKey("course.config");
         String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        List<OptionsVO> optionsVOS = new ArrayList<>();
+        List<OptionsVO> optionsVOS;
         if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
         if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
             optionsVOS = fsUserCourseMapper.selectFsUserCourseAllListByUserId(userId);
             optionsVOS = fsUserCourseMapper.selectFsUserCourseAllListByUserId(userId);
-        }else {
+        }else{
             optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList();
             optionsVOS = fsUserCourseMapper.selectFsUserCourseAllList();
         }
         }
         return R.ok().put("list", optionsVOS);
         return R.ok().put("list", optionsVOS);

+ 1 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseVideoController.java

@@ -202,6 +202,7 @@ public class FsUserCourseVideoController extends BaseController
         return R.ok();
         return R.ok();
     }
     }
     @PostMapping("/batchUpdateRed")
     @PostMapping("/batchUpdateRed")
+    @Log(title = "按课程批量保存设置红包金额", businessType = BusinessType.UPDATE)
     public R batchUpdateRed(@RequestBody List<BatchRedUpdate> list){
     public R batchUpdateRed(@RequestBody List<BatchRedUpdate> list){
         fsUserCourseVideoService.batchUpdateRed(list);
         fsUserCourseVideoService.batchUpdateRed(list);
         return R.ok();
         return R.ok();

+ 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.common.core.domain.R;
 import com.fs.fastGpt.vo.FastgptExtUserTagVO;
 import com.fs.fastGpt.vo.FastgptExtUserTagVO;
-import com.fs.framework.web.service.TokenService;
 import com.fs.qw.service.IQwCompanyService;
 import com.fs.qw.service.IQwCompanyService;
 import com.fs.qw.vo.QwOptionsVO;
 import com.fs.qw.vo.QwOptionsVO;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -64,7 +63,7 @@ public class FastgptExtUserTagController extends BaseController
     @GetMapping("/getMyQwUserList")
     @GetMapping("/getMyQwUserList")
     public R getMyQwUserList()
     public R getMyQwUserList()
     {
     {
-        List<QwOptionsVO> list = qwCompanyService.selectQwCompanyListOptionsVO();
+        List<QwOptionsVO> list = qwCompanyService.selectQwCompanyListOptionsVO(null, null);
         return  R.ok().put("data",list);
         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 java.util.List;
 
 
-import cn.hutool.core.util.IdUtil;
+import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSON;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.domain.R;
 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.service.ICompanyUserService;
 import com.fs.company.vo.CompanyVO;
 import com.fs.company.vo.CompanyVO;
 import com.fs.core.utils.OrderCodeUtils;
 import com.fs.core.utils.OrderCodeUtils;
+import com.fs.course.config.CourseConfig;
 import com.fs.framework.web.service.TokenService;
 import com.fs.framework.web.service.TokenService;
-import com.fs.his.domain.FsDoctor;
 import com.fs.his.mapper.FsDoctorMapper;
 import com.fs.his.mapper.FsDoctorMapper;
 import com.fs.his.vo.OptionsVO;
 import com.fs.his.vo.OptionsVO;
+import com.fs.system.service.ISysConfigService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
@@ -67,6 +68,8 @@ public class FsCompanyController extends BaseController
     private FsDoctorMapper fsDoctorMapper;
     private FsDoctorMapper fsDoctorMapper;
     @Autowired
     @Autowired
     private ICompanyDeductService deductService;
     private ICompanyDeductService deductService;
+    @Autowired
+    private ISysConfigService configService;
     /**
     /**
      * 查询诊所管理列表
      * 查询诊所管理列表
      */
      */
@@ -75,6 +78,12 @@ public class FsCompanyController extends BaseController
     public TableDataInfo list(Company company)
     public TableDataInfo list(Company company)
     {
     {
         startPage();
         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);
         List<CompanyVO> list = companyService.selectCompanyListVO(company);
         return getDataTable(list);
         return getDataTable(list);
     }
     }
@@ -83,7 +92,14 @@ public class FsCompanyController extends BaseController
     public R companyList()
     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);
         return R.ok().put("data",list);
     }
     }
     /**
     /**
@@ -133,6 +149,12 @@ public class FsCompanyController extends BaseController
     @PostMapping
     @PostMapping
     public R add(@RequestBody Company company)
     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);
         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.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.poi.ExcelUtil;
 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 com.fs.his.vo.FsUserComplaintVo;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -23,20 +23,20 @@ import java.util.List;
  */
  */
 @RestController
 @RestController
 @RequestMapping("/his/complaint")
 @RequestMapping("/his/complaint")
-public class FsUserComplaintController extends BaseController
+public class FsHisComplaintController extends BaseController
 {
 {
     @Autowired
     @Autowired
-    private IFsUserComplaintService fsUserComplaintService;
+    private IFsHisComplaintService fsUserComplaintService;
 
 
     /**
     /**
      * 查询用户投诉列表
      * 查询用户投诉列表
      */
      */
     @PreAuthorize("@ss.hasPermi('his:complaint:list')")
     @PreAuthorize("@ss.hasPermi('his:complaint:list')")
     @GetMapping("/list")
     @GetMapping("/list")
-    public TableDataInfo list(FsUserComplaint fsUserComplaint)
+    public TableDataInfo list(FsHisComplaint fsHisComplaint)
     {
     {
         startPage();
         startPage();
-        List<FsUserComplaintVo> list = fsUserComplaintService.selectFsUserComplaintList(fsUserComplaint);
+        List<FsUserComplaintVo> list = fsUserComplaintService.selectFsUserComplaintList(fsHisComplaint);
         return getDataTable(list);
         return getDataTable(list);
     }
     }
 
 
@@ -46,9 +46,9 @@ public class FsUserComplaintController extends BaseController
     @PreAuthorize("@ss.hasPermi('his:complaint:export')")
     @PreAuthorize("@ss.hasPermi('his:complaint:export')")
     @Log(title = "用户投诉", businessType = BusinessType.EXPORT)
     @Log(title = "用户投诉", businessType = BusinessType.EXPORT)
     @GetMapping("/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);
         ExcelUtil<FsUserComplaintVo> util = new ExcelUtil<FsUserComplaintVo>(FsUserComplaintVo.class);
         return util.exportExcel(list, "用户投诉数据");
         return util.exportExcel(list, "用户投诉数据");
     }
     }
@@ -69,9 +69,9 @@ public class FsUserComplaintController extends BaseController
     @PreAuthorize("@ss.hasPermi('his:complaint:add')")
     @PreAuthorize("@ss.hasPermi('his:complaint:add')")
     @Log(title = "用户投诉", businessType = BusinessType.INSERT)
     @Log(title = "用户投诉", businessType = BusinessType.INSERT)
     @PostMapping
     @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')")
     @PreAuthorize("@ss.hasPermi('his:complaint:edit')")
     @Log(title = "用户投诉", businessType = BusinessType.UPDATE)
     @Log(title = "用户投诉", businessType = BusinessType.UPDATE)
     @PutMapping
     @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);
         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);
+    }
+
     /**
     /**
      * 导出病人列表
      * 导出病人列表
      */
      */

+ 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, "订单数据");
         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')")
     @PreAuthorize("@ss.hasPermi('store:healthStoreOrder:exportItems')")
     @Log(title = "商城订单明细导出", businessType = BusinessType.EXPORT)
     @Log(title = "商城订单明细导出", businessType = BusinessType.EXPORT)
@@ -181,6 +213,47 @@ public class FsStoreHealthOrderScrmController extends BaseController {
         return util.exportExcel(list, "订单明细数据");
         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)
     @Log(title = "发货同步导入", businessType = BusinessType.IMPORT)
     @PostMapping("/importDeliveryNoteExpress")
     @PostMapping("/importDeliveryNoteExpress")
@@ -203,7 +276,7 @@ public class FsStoreHealthOrderScrmController extends BaseController {
         try {
         try {
             List<FsOrderDeliveryNoteDTO> dtoList = util.importExcel(file.getInputStream());
             List<FsOrderDeliveryNoteDTO> dtoList = util.importExcel(file.getInputStream());
             if(!dtoList.isEmpty()){
             if(!dtoList.isEmpty()){
-                fsStoreOrderService.importDeliveryNoteExpress(dtoList);
+               return fsStoreOrderService.importDeliveryNoteExpress(dtoList);
             }else {
             }else {
                 R.error("操作失败,导入数据不能小于1条!");
                 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.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
 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.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.ParseUtils;
+import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.param.CompanyStoreOrderMoneyLogsListParam;
 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.ErpOrderQueryRequert;
 import com.fs.erp.dto.ErpOrderQueryResponse;
 import com.fs.erp.dto.ErpOrderQueryResponse;
 import com.fs.erp.service.IErpOrderService;
 import com.fs.erp.service.IErpOrderService;
+import com.fs.framework.web.service.TokenService;
 import com.fs.his.domain.FsUser;
 import com.fs.his.domain.FsUser;
 import com.fs.his.service.IFsExpressService;
 import com.fs.his.service.IFsExpressService;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.service.IFsUserService;
@@ -101,6 +104,9 @@ public class FsStoreOrderScrmController extends BaseController {
     @Autowired
     @Autowired
     private IFsStoreOrderAuditLogScrmService orderAuditLogService;
     private IFsStoreOrderAuditLogScrmService orderAuditLogService;
 
 
+    @Autowired
+    private TokenService tokenService;
+
     private IErpOrderService getErpService(){
     private IErpOrderService getErpService(){
         //判断是否开启erp
         //判断是否开启erp
         IErpOrderService erpOrderService = null;
         IErpOrderService erpOrderService = null;
@@ -255,6 +261,9 @@ public class FsStoreOrderScrmController extends BaseController {
         List<FsStoreOrderExportVO> list = fsStoreOrderService.selectFsStoreOrderListVOByExport(param);
         List<FsStoreOrderExportVO> list = fsStoreOrderService.selectFsStoreOrderListVOByExport(param);
         //对手机号脱敏
         //对手机号脱敏
         if (list != null) {
         if (list != null) {
+            //获取当前账号角色权限
+            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+
             for (FsStoreOrderExportVO vo : list) {
             for (FsStoreOrderExportVO vo : list) {
                 if (vo.getPhone() != null) {
                 if (vo.getPhone() != null) {
                     vo.setPhone(vo.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
                     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')")
     @PreAuthorize("@ss.hasPermi('store:storeOrder:exportItems')")
     @Log(title = "订单明细导出", businessType = BusinessType.EXPORT)
     @Log(title = "订单明细导出", businessType = BusinessType.EXPORT)
@@ -321,6 +361,49 @@ public class FsStoreOrderScrmController extends BaseController {
         return util.exportExcel(list, "订单明细数据");
         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")
     @GetMapping("/orderItemsNum")
     public R orderItemsNum(FsStoreOrderParam param) {
     public R orderItemsNum(FsStoreOrderParam param) {

+ 12 - 1
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.IFsStoreProductAttrScrmService;
 import com.fs.hisStore.service.IFsStoreProductAttrValueScrmService;
 import com.fs.hisStore.service.IFsStoreProductAttrValueScrmService;
 import com.fs.hisStore.service.IFsStoreProductScrmService;
 import com.fs.hisStore.service.IFsStoreProductScrmService;
+import com.fs.statis.dto.ProductAuditDTO;
 import com.mysql.cj.util.StringUtils;
 import com.mysql.cj.util.StringUtils;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
@@ -69,6 +70,17 @@ public class FsStoreProductScrmController extends BaseController
         return R.ok();
         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();
+    }
+
     /**
     /**
      * 查询商品列表
      * 查询商品列表
      */
      */
@@ -173,7 +185,6 @@ public class FsStoreProductScrmController extends BaseController
         return new ResponseEntity<>(fsStoreProductService.getFormatAttr(productId,jsonStr), HttpStatus.OK);
         return new ResponseEntity<>(fsStoreProductService.getFormatAttr(productId,jsonStr), HttpStatus.OK);
     }
     }
 
 
-
     @GetMapping("/getStoreProductAttrValueList")
     @GetMapping("/getStoreProductAttrValueList")
     public TableDataInfo getStoreProductAttrValueList(FsProductAttrValueParam param)
     public TableDataInfo getStoreProductAttrValueList(FsProductAttrValueParam param)
     {
     {

+ 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.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
 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.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ParseUtils;
 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.hisStore.domain.FsStoreScrm;
 import com.fs.his.param.FsStoreAuditParam;
 import com.fs.his.param.FsStoreAuditParam;
 import com.fs.hisStore.service.IFsStoreScrmService;
 import com.fs.hisStore.service.IFsStoreScrmService;
+import com.fs.hisStore.utils.StoreAuditLogUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
@@ -29,6 +31,9 @@ public class FsStoreScrmController extends BaseController
     @Autowired
     @Autowired
     private IFsStoreScrmService fsStoreService;
     private IFsStoreScrmService fsStoreService;
 
 
+    @Autowired
+    private StoreAuditLogUtil storeAuditLogUtil;
+
     /**
     /**
      * 查询店铺管理列表
      * 查询店铺管理列表
      */
      */
@@ -52,6 +57,7 @@ public class FsStoreScrmController extends BaseController
     @GetMapping("/export")
     @GetMapping("/export")
     public AjaxResult export(FsStoreScrm fsStore)
     public AjaxResult export(FsStoreScrm fsStore)
     {
     {
+        storeAuditLogUtil.generateOperId();
         List<FsStoreScrm> list = fsStoreService.selectFsStoreList(fsStore);
         List<FsStoreScrm> list = fsStoreService.selectFsStoreList(fsStore);
         for (FsStoreScrm store : list) {
         for (FsStoreScrm store : list) {
             store.setPhone(ParseUtils.parsePhone(store.getPhone()));
             store.setPhone(ParseUtils.parsePhone(store.getPhone()));
@@ -80,7 +86,8 @@ public class FsStoreScrmController extends BaseController
     @PostMapping
     @PostMapping
     public AjaxResult add(@RequestBody FsStoreScrm fsStore)
     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')")
     @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")
     @PutMapping("/audit")
     public AjaxResult audit(@RequestBody FsStoreAuditParam fsStore)
     public AjaxResult audit(@RequestBody FsStoreAuditParam fsStore)
     {
     {
@@ -126,9 +134,18 @@ public class FsStoreScrmController extends BaseController
     @PreAuthorize("@ss.hasPermi('his:store:refresh')")
     @PreAuthorize("@ss.hasPermi('his:store:refresh')")
     @Log(title = "店铺管理", businessType = BusinessType.UPDATE,logParam = {"店铺","重置店铺密码"},isStoreLog = true)
     @Log(title = "店铺管理", businessType = BusinessType.UPDATE,logParam = {"店铺","重置店铺密码"},isStoreLog = true)
     @PutMapping("/refresh/{storeId}")
     @PutMapping("/refresh/{storeId}")
-    public AjaxResult refresh(Long storeId)
+    public AjaxResult refresh(@PathVariable Long storeId)
     {
     {
         return toAjax(fsStoreService.refreshFsStore(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.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
 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.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.hisStore.param.StoreOperMainQueryParam;
 import com.fs.hisStore.service.ISysOperLogScrmService;
 import com.fs.hisStore.service.ISysOperLogScrmService;
 import com.fs.hisStore.domain.SysOperLogScrm;
 import com.fs.hisStore.domain.SysOperLogScrm;
+import com.fs.hisStore.vo.StoreOperMainVO;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
@@ -28,7 +31,7 @@ public class SysOperlogScrmController extends BaseController
         this.operLogService = operLogService;
         this.operLogService = operLogService;
     }
     }
 
 
-    @PreAuthorize("@ss.hasPermi('his:storeLog:export')")
+    @PreAuthorize("@ss.hasPermi('his:storeLog:list')")
     @GetMapping("/list")
     @GetMapping("/list")
     public TableDataInfo list(SysOperLogScrm operLog)
     public TableDataInfo list(SysOperLogScrm operLog)
     {
     {
@@ -36,6 +39,13 @@ public class SysOperlogScrmController extends BaseController
         List<SysOperLogScrm> list = operLogService.selectOperLogList(operLog);
         List<SysOperLogScrm> list = operLogService.selectOperLogList(operLog);
         return getDataTable(list);
         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)
     @Log(title = "操作日志", businessType = BusinessType.EXPORT)
     @PreAuthorize("@ss.hasPermi('his:storeLog:export')")
     @PreAuthorize("@ss.hasPermi('his:storeLog:export')")

+ 94 - 0
fs-admin/src/main/java/com/fs/qw/FsCourseTask.java

@@ -1,11 +1,27 @@
 package com.fs.qw;
 package com.fs.qw;
 
 
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.redis.RedisCache;
 import com.fs.course.service.IFsCourseWatchLogService;
 import com.fs.course.service.IFsCourseWatchLogService;
 import com.fs.qw.service.IQwWorkTaskService;
 import com.fs.qw.service.IQwWorkTaskService;
+import com.fs.system.domain.SysConfig;
+import com.fs.system.mapper.SysConfigMapper;
+import io.jsonwebtoken.lang.Assert;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.http.util.Asserts;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
 /**
 /**
  * 后台统计相关 定时任务
  * 后台统计相关 定时任务
  */
  */
@@ -16,7 +32,85 @@ public class FsCourseTask {
     private IFsCourseWatchLogService fsCourseWatchLogService;
     private IFsCourseWatchLogService fsCourseWatchLogService;
     @Autowired
     @Autowired
     private IQwWorkTaskService qwWorkTaskService;
     private IQwWorkTaskService qwWorkTaskService;
+    @Autowired
+    private RedisCache redisCache;
+    private static final String REDPACKET_COMPANY_MONEY_CHANGE = "redpacket_money_CHANGE";
+    @Autowired
+    private SysConfigMapper sysConfigMapper;
+    private static final String REDPACKET_POOL_LOCK = "redpacket_pool_lock";
+    private static final String REDPACKET_COMPANY_MONEY = "redpacket_money";
+
+    @Autowired
+    private RedissonClient redissonClient;
+
+    /**
+     * 润天公司账户充值
+     * @param chargeMoney 充值金额
+     */
+    public void rechargeRedpacketMoney(String chargeMoney){
+        Assert.notNull(chargeMoney,"充值金额不能为空!");
+
+        log.info("润天公司账户充值 充值金额: {}",chargeMoney);
+
+        RLock lock = redissonClient.getLock(REDPACKET_POOL_LOCK);
+        try{
+            boolean locked = lock.tryLock(3, 10, TimeUnit.SECONDS);
+
+            if (!locked) {
+                log.error("获取锁失败...");
+                return;
+            }
+
+            BigDecimal redPacketCompanyMoney = redisCache.getCacheObject(REDPACKET_COMPANY_MONEY);
+            if(ObjectUtils.isNull(redPacketCompanyMoney)){
+                redPacketCompanyMoney = BigDecimal.ZERO;
+            }
+            BigDecimal value = redPacketCompanyMoney.add(new BigDecimal(chargeMoney));
+
+            log.info("润天公司账户充值成功 目前余额: {}",value);
 
 
+            redisCache.setCacheObject(REDPACKET_COMPANY_MONEY,value);
+
+
+            // 保存到数据库
+            SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("company.money");
+
+            sysConfig.setConfigValue(value.setScale(4, RoundingMode.HALF_UP).toPlainString());
+            sysConfig.setConfigKey("company.money");
+            sysConfigMapper.updateConfig(sysConfig);
+
+        }catch (Exception e){
+            log.error("充值失败 原因:{}", ExceptionUtils.getFullStackTrace(e),e);
+            throw new RuntimeException(e);
+        }finally {
+            if (lock.isHeldByCurrentThread()) {
+                lock.unlock();
+            }
+        }
+    }
+    /**
+     * 公司红包金额变更
+     */
+    public void redpacketCompanyMoneyChange(){
+        SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("company.money");
+        Asserts.notNull(sysConfig,"公司账户配置不能为空!");
+
+        String configValue = sysConfig.getConfigValue();
+        Asserts.notNull(configValue,"公司账户余额不能为空");
+
+        BigDecimal oldBigDecimal = new BigDecimal(configValue);
+
+        BigDecimal redPacketCompanyMoney = redisCache.getCacheObject(REDPACKET_COMPANY_MONEY);
+
+        log.info("公司账户红包余额变更 {} -> {}",oldBigDecimal,redPacketCompanyMoney);
+
+        // 如果两者不一致才同步到数据库
+        if(oldBigDecimal.compareTo(redPacketCompanyMoney) != 0){
+            sysConfig.setConfigValue(redPacketCompanyMoney.setScale(4, RoundingMode.HALF_UP).toPlainString());
+            sysConfig.setConfigKey("company.money");
+            sysConfigMapper.updateConfig(sysConfig);
+        }
+    }
     /**
     /**
      * 添加企微观看日志
      * 添加企微观看日志
      * @throws Exception
      * @throws Exception

+ 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 java.util.List;
 
 
+import cn.hutool.json.JSONUtil;
 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.utils.ServletUtils;
+import com.fs.course.config.CourseConfig;
+import com.fs.framework.web.service.TokenService;
 import com.fs.qw.vo.QwOptionsVO;
 import com.fs.qw.vo.QwOptionsVO;
+import com.fs.system.service.ISysConfigService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -35,6 +41,10 @@ public class QwCompanyController extends BaseController
 {
 {
     @Autowired
     @Autowired
     private IQwCompanyService qwCompanyService;
     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)
     public TableDataInfo list(QwCompany qwCompany)
     {
     {
         startPage();
         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);
         List<QwCompany> list = qwCompanyService.selectQwCompanyList(qwCompany);
         return getDataTable(list);
         return getDataTable(list);
     }
     }
@@ -52,7 +69,18 @@ public class QwCompanyController extends BaseController
     @GetMapping("/all")
     @GetMapping("/all")
     public R 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);
         return R.ok().put("data", list);
     }
     }
     /**
     /**
@@ -86,6 +114,10 @@ public class QwCompanyController extends BaseController
     @PostMapping
     @PostMapping
     public AjaxResult add(@RequestBody QwCompany qwCompany)
     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));
         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.List;
 import java.util.Set;
 import java.util.Set;
 
 
+import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.entity.SysRole;
 import com.fs.common.core.domain.entity.SysRole;
 import com.fs.common.utils.PatternUtils;
 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 com.fs.system.service.ISysRoleService;
 import lombok.Synchronized;
 import lombok.Synchronized;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -45,6 +48,12 @@ public class SysLoginController
     @Autowired
     @Autowired
     private ISysRoleService roleService;
     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> roles = permissionService.getRolePermission(user);
         // 权限集合
         // 权限集合
         Set<String> permissions = permissionService.getMenuPermission(user);
         Set<String> permissions = permissionService.getMenuPermission(user);
+        //药品商城参数
         AjaxResult ajax = AjaxResult.success();
         AjaxResult ajax = AjaxResult.success();
+
+        if(medicalMallConfig!=null){
+            ajax.put("medicalMallConfig", medicalMallConfig);
+        }
         ajax.put("user", user);
         ajax.put("user", user);
         Integer isAdmin = 0;
         Integer isAdmin = 0;
         if (permissions.contains("*:*:*")){
         if (permissions.contains("*:*:*")){

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

@@ -10,5 +10,5 @@ spring:
 #    active: druid-sxjz
 #    active: druid-sxjz
 #    active: druid-sft
 #    active: druid-sft
 #    active: druid-fby
 #    active: druid-fby
-    active: dev
+    active: dev-yjb
 
 

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

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

+ 19 - 0
fs-common-api/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.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
 
+import java.math.BigDecimal;
+
 /**
 /**
  * redis配置
  * redis配置
  *
  *
@@ -90,7 +92,24 @@ public class RedisConfig extends CachingConfigurerSupport
         template.afterPropertiesSet();
         template.afterPropertiesSet();
         return template;
         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
     @Bean
     public DefaultRedisScript<Long> limitScript()
     public DefaultRedisScript<Long> limitScript()
     {
     {

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

@@ -4,5 +4,5 @@ server:
 # Spring配置
 # Spring配置
 spring:
 spring:
   profiles:
   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;
 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.GrantedAuthority;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UserDetails;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -14,6 +14,7 @@ import com.fs.common.core.domain.entity.SysUser;
  */
  */
 public class LoginUser implements UserDetails
 public class LoginUser implements UserDetails
 {
 {
+    private static final List<String> ADMIN_USER_NAME = Collections.singletonList("admin");
     private static final long serialVersionUID = 1L;
     private static final long serialVersionUID = 1L;
 
 
     /**
     /**
@@ -254,6 +255,9 @@ public class LoginUser implements UserDetails
     {
     {
         return user;
         return user;
     }
     }
+    public boolean isAdmin(){
+        return ADMIN_USER_NAME.contains(user.getUserName());
+    }
 
 
     public void setUser(SysUser user)
     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;
 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 java.util.concurrent.TimeUnit;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.BoundSetOperations;
 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) {
     public Boolean setIfAbsent(String key, String value, long timeout, TimeUnit unit) {
         return redisTemplate.opsForValue().setIfAbsent(key, value, timeout, 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
 public enum BusinessType
@@ -51,9 +51,14 @@ public enum BusinessType
      * 生成代码
      * 生成代码
      */
      */
     GENCODE,
     GENCODE,
-    
+
     /**
     /**
      * 清空数据
      * 清空数据
      */
      */
     CLEAN,
     CLEAN,
+
+    /**
+     * 审核
+     * */
+    AUDIT,
 }
 }

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

@@ -12,6 +12,8 @@ import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.data.redis.serializer.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
 
+import java.math.BigDecimal;
+
 /**
 /**
  * redis配置
  * redis配置
  *
  *
@@ -62,6 +64,25 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
         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
     @Bean
     @SuppressWarnings(value = { "unchecked", "rawtypes" })
     @SuppressWarnings(value = { "unchecked", "rawtypes" })
     public RedisTemplate<String, Object> redisTemplateForObject(RedisConnectionFactory connectionFactory) {
     public RedisTemplate<String, Object> redisTemplateForObject(RedisConnectionFactory connectionFactory) {

+ 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")
     @GetMapping("/allList")
     public TableDataInfo getHospital()
     public TableDataInfo getHospital()
     {
     {
-        List<OptionsVO> list = companyService.selectAllCompanyList();
+        List<OptionsVO> list = companyService.selectAllCompanyList(null);
         return getDataTable(list);
         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());
             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);
         List<FsCourseAnswerLogsListVO> list = fsCourseAnswerLogsService.selectFsCourseAnswerLogsListVONew(param);
         TableDataInfo rspData = new TableDataInfo();
         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() != "") {
         if (fsCourseRedPacketLog.getPhoneMk() != null && fsCourseRedPacketLog.getPhoneMk() != "") {
             fsCourseRedPacketLog.setPhone(encryptPhone(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);
         List<FsCourseRedPacketLogListPVO> list = fsCourseRedPacketLogService.selectFsCourseRedPacketLogListVO(fsCourseRedPacketLog);
         for (FsCourseRedPacketLogListPVO fsCourseRedPacketLogListPVO : list) {
         for (FsCourseRedPacketLogListPVO fsCourseRedPacketLogListPVO : list) {

+ 2 - 0
fs-company/src/main/java/com/fs/company/controller/course/FsUserCoursePeriodController.java

@@ -191,6 +191,7 @@ public class FsUserCoursePeriodController extends BaseController {
 
 
     @ApiOperation("按课程批量保存设置红包金额")
     @ApiOperation("按课程批量保存设置红包金额")
     @PostMapping("/batchRedPacket")
     @PostMapping("/batchRedPacket")
+    @Log(title = "按课程批量保存设置红包金额", businessType = BusinessType.UPDATE)
     public R batchRedPacketMoney(@RequestBody List<FsUserCourseVideoRedPackage> videoRedPackageList) {
     public R batchRedPacketMoney(@RequestBody List<FsUserCourseVideoRedPackage> videoRedPackageList) {
         try {
         try {
             fsUserCourseVideoRedPackageService.batchSaveCompanyRedPackage(videoRedPackageList);
             fsUserCourseVideoRedPackageService.batchSaveCompanyRedPackage(videoRedPackageList);
@@ -203,6 +204,7 @@ public class FsUserCoursePeriodController extends BaseController {
 
 
     @ApiOperation("按营期批量保存设置红包金额")
     @ApiOperation("按营期批量保存设置红包金额")
     @PostMapping("/batchRedPacket/byPeriod")
     @PostMapping("/batchRedPacket/byPeriod")
+    @Log(title = "按营期批量保存设置红包金额", businessType = BusinessType.UPDATE)
     public R batchRedPacketByPeriod(@RequestBody List<FsBatchPeriodRedPackageParam> periodRedPackageList) {
     public R batchRedPacketByPeriod(@RequestBody List<FsBatchPeriodRedPackageParam> periodRedPackageList) {
         try {
         try {
             fsUserCourseVideoRedPackageService.batchRedPacketByPeriod(periodRedPackageList);
             fsUserCourseVideoRedPackageService.batchRedPacketByPeriod(periodRedPackageList);

+ 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));
         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
      * 批量执行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) {
     private List<Long> getQwUserKeyList(QwSopLogsParam param, LoginUser loginUser) {
-
+        if(param.getFilterSopType() == null){
+            return new ArrayList<>(); // 返回空列表而不是null
+        }
         switch (param.getFilterSopType()) {
         switch (param.getFilterSopType()) {
             case 2:
             case 2:
                 CompanyUser companyUser = iCompanyUserService.selectCompanyUserById(loginUser.getUser().getUserId());
                 CompanyUser companyUser = iCompanyUserService.selectCompanyUserById(loginUser.getUser().getUserId());

+ 80 - 4
fs-company/src/main/java/com/fs/company/controller/qw/QwUserVoiceLogController.java

@@ -1,12 +1,18 @@
 package com.fs.company.controller.qw;
 package com.fs.company.controller.qw;
 
 
 import com.fs.common.annotation.Log;
 import com.fs.common.annotation.Log;
+import com.fs.common.constant.HttpStatus;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.PageDomain;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.core.page.TableSupport;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.service.ICompanyUserService;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
 import com.fs.framework.service.TokenService;
 import com.fs.qw.domain.QwUserVoiceLog;
 import com.fs.qw.domain.QwUserVoiceLog;
@@ -22,8 +28,10 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
 import java.util.Objects;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 
 /**
 /**
  * 企微用户通话记录Controller
  * 企微用户通话记录Controller
@@ -44,6 +52,9 @@ public class QwUserVoiceLogController extends BaseController
     @Autowired
     @Autowired
     private IQwTagService iQwTagService;
     private IQwTagService iQwTagService;
 
 
+    @Autowired
+    private ICompanyUserService userService;
+
     /**
     /**
      * 查询企微用户通话记录列表
      * 查询企微用户通话记录列表
      */
      */
@@ -137,23 +148,88 @@ public class QwUserVoiceLogController extends BaseController
     @GetMapping("/totalList")
     @GetMapping("/totalList")
     public TableDataInfo totalList(QwUserVoiceLogTotalVo qwUserVoiceLog)
     public TableDataInfo totalList(QwUserVoiceLogTotalVo qwUserVoiceLog)
     {
     {
-        startPage();
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         qwUserVoiceLog.setCompanyId(loginUser.getCompany().getCompanyId());
         qwUserVoiceLog.setCompanyId(loginUser.getCompany().getCompanyId());
         qwUserVoiceLog.setQwUserId(1L);
         qwUserVoiceLog.setQwUserId(1L);
         List<QwUserVoiceLogTotalVo> list = qwUserVoiceLogService.selectQwUserVoiceLogTotalList(qwUserVoiceLog);
         List<QwUserVoiceLogTotalVo> list = qwUserVoiceLogService.selectQwUserVoiceLogTotalList(qwUserVoiceLog);
-        return getDataTable(list);
+        list.forEach(item->{
+            if(item.getQwExternalContact() != null){
+                if (item.getQwExternalContact().getTagIds() != null && !Objects.equals(item.getQwExternalContact().getTagIds(), "[]")) {
+                    QwTagSearchParam param = new QwTagSearchParam();
+                    Gson gson = new Gson();
+                    List<String> tagIds = gson.fromJson(
+                            item.getQwExternalContact().getTagIds(),
+                            new TypeToken<List<String>>() {
+                            }.getType()
+                    );
+                    param.setTagIds(tagIds);
+                    item.setTagIdsName(iQwTagService.selectQwTagListByTagIds(param));
+                }
+            }
+        });
+
+        // 获取分页参数
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Integer pageNum = pageDomain.getPageNum();
+        Integer pageSize = pageDomain.getPageSize();
+
+        int total = list.size();
+        // 在内存中进行分页处理
+        if (pageNum != null && pageSize != null) {
+            int fromIndex = (pageNum - 1) * pageSize;
+            int toIndex = Math.min(fromIndex + pageSize, total);
+
+            // 确保索引不越界
+            if (fromIndex < total) {
+                list = list.subList(fromIndex, toIndex);
+            } else {
+                list = new ArrayList<>(); // 返回空列表
+            }
+        }
+
+        // 构造返回结果
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(HttpStatus.SUCCESS);
+        rspData.setMsg("查询成功");
+        rspData.setRows(list);
+        rspData.setTotal(total);
+        return rspData;
     }
     }
 
 
 
 
     @GetMapping("/sellTotalList")
     @GetMapping("/sellTotalList")
     public TableDataInfo sellTotalList(QwUserVoiceLogTotalVo qwUserVoiceLog)
     public TableDataInfo sellTotalList(QwUserVoiceLogTotalVo qwUserVoiceLog)
     {
     {
-        startPage();
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         qwUserVoiceLog.setCompanyId(loginUser.getCompany().getCompanyId());
         qwUserVoiceLog.setCompanyId(loginUser.getCompany().getCompanyId());
         List<QwUserVoiceLogTotalVo> list = qwUserVoiceLogService.selectQwUserVoiceLogTotalList(qwUserVoiceLog);
         List<QwUserVoiceLogTotalVo> list = qwUserVoiceLogService.selectQwUserVoiceLogTotalList(qwUserVoiceLog);
-        return getDataTable(list);
+
+        // 获取分页参数
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Integer pageNum = pageDomain.getPageNum();
+        Integer pageSize = pageDomain.getPageSize();
+
+        int total = list.size();
+        // 在内存中进行分页处理
+        if (pageNum != null && pageSize != null) {
+            int fromIndex = (pageNum - 1) * pageSize;
+            int toIndex = Math.min(fromIndex + pageSize, total);
+
+            // 确保索引不越界
+            if (fromIndex < total) {
+                list = list.subList(fromIndex, toIndex);
+            } else {
+                list = new ArrayList<>(); // 返回空列表
+            }
+        }
+
+        // 构造返回结果
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(HttpStatus.SUCCESS);
+        rspData.setMsg("查询成功");
+        rspData.setRows(list);
+        rspData.setTotal(total);
+        return rspData;
     }
     }
 
 
     @PreAuthorize("@ss.hasPermi('qw:qwUserVoiceLog:sellTotalExport')")
     @PreAuthorize("@ss.hasPermi('qw:qwUserVoiceLog:sellTotalExport')")

+ 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());
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
 
 
         List<String> qwUserIdList=null;
         List<String> qwUserIdList=null;
-        if (sopUserLogs.getType()==2){
+        if (sopUserLogs.getType() != null && sopUserLogs.getType()==2){
             qwUserIdList = iQwUserService.selectQwUserListByCompanyUserId(loginUser.getUser().getUserId(), sopUserLogs.getCorpId());
             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);
             sopUserLogs.setQwIdsList(qwUserIdList);
         }
         }
 
 

+ 18 - 0
fs-company/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -19,6 +19,7 @@ import org.springframework.data.redis.core.script.DefaultRedisScript;
 import org.springframework.data.redis.serializer.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
 
+import java.math.BigDecimal;
 import java.util.Arrays;
 import java.util.Arrays;
 
 
 /**
 /**
@@ -96,7 +97,24 @@ public class RedisConfig extends CachingConfigurerSupport
         template.afterPropertiesSet();
         template.afterPropertiesSet();
         return template;
         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
     @Bean
     public DefaultRedisScript<Long> limitScript()
     public DefaultRedisScript<Long> limitScript()
     {
     {

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

@@ -4,11 +4,11 @@ server:
 spring:
 spring:
   profiles:
   profiles:
 #    active: druid-fcky-test
 #    active: druid-fcky-test
-#    active: dev
+    active: dev
 #    active: druid-jzzx-test
 #    active: druid-jzzx-test
 #    active: druid-hdt
 #    active: druid-hdt
 #    active: druid-sxjz
 #    active: druid-sxjz
 #    active: druid-yzt
 #    active: druid-yzt
 #    active: druid-myhk
 #    active: druid-myhk
 #    active: druid-sft
 #    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;
 package com.fs.app.controller;
 
 
 
 
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSON;
 import com.fs.app.annotation.Login;
 import com.fs.app.annotation.Login;
-import com.fs.app.param.InquiryOrderMsgListParam;
 import com.fs.common.BeanCopyUtils;
 import com.fs.common.BeanCopyUtils;
 import com.fs.common.annotation.Log;
 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.domain.R;
-import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.SecurityUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.StringUtils;
-import com.fs.common.utils.ip.IpUtils;
 import com.fs.company.service.ICompanyService;
 import com.fs.company.service.ICompanyService;
 import com.fs.core.config.WxPayProperties;
 import com.fs.core.config.WxPayProperties;
 import com.fs.core.utils.OrderCodeUtils;
 import com.fs.core.utils.OrderCodeUtils;
 import com.fs.his.domain.*;
 import com.fs.his.domain.*;
 import com.fs.his.dto.FsInquiryOrderPatientDTO;
 import com.fs.his.dto.FsInquiryOrderPatientDTO;
-import com.fs.his.enums.FsInquiryOrderStatusEnum;
 import com.fs.his.param.*;
 import com.fs.his.param.*;
 import com.fs.his.service.*;
 import com.fs.his.service.*;
 import com.fs.his.vo.*;
 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.MsgDataDTO;
 import com.fs.im.dto.MsgDataFormatDTO;
 import com.fs.im.dto.MsgDataFormatDTO;
 import com.fs.im.service.IImService;
 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.binarywang.wxpay.service.WxPayService;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import com.github.pagehelper.PageInfo;
@@ -42,7 +30,6 @@ import io.swagger.annotations.ApiOperation;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
@@ -128,7 +115,7 @@ public class InquiryOrderController extends  AppBaseController {
     @GetMapping("/getCompanyList")
     @GetMapping("/getCompanyList")
     public R getCompanyList()
     public R getCompanyList()
     {
     {
-        List<OptionsVO> list = companyService.selectAllCompanyList();
+        List<OptionsVO> list = companyService.selectAllCompanyList(null);
         return R.ok().put("list",list);
         return R.ok().put("list",list);
     }
     }
     @Login
     @Login

+ 21 - 0
fs-doctor-app/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.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
 
+import java.math.BigDecimal;
+
 /**
 /**
  * redis配置
  * redis配置
  *
  *
@@ -92,6 +94,25 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
         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
     @Bean
     public DefaultRedisScript<Long> limitScript()
     public DefaultRedisScript<Long> limitScript()
     {
     {

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

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

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

@@ -15,6 +15,8 @@ import com.fasterxml.jackson.annotation.PropertyAccessor;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
 import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
 
 
+import java.math.BigDecimal;
+
 /**
 /**
  * redis配置
  * redis配置
  *
  *
@@ -92,6 +94,25 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
         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
     @Bean
     public DefaultRedisScript<Long> limitScript()
     public DefaultRedisScript<Long> limitScript()
     {
     {

+ 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()));
                 operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
-                SpringUtils.getBean(ISysOperLogScrmService.class).insertOperlog(operLog);
+                SpringUtils.getBean(ISysOperLogScrmService.class).updateOperLog(operLog);
             }
             }
         };
         };
     }
     }
+
+    /**
+     * 生成日志记录
+     * */
+
+
 }
 }

+ 21 - 0
fs-hospital/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -16,6 +16,8 @@ import org.springframework.data.redis.core.script.DefaultRedisScript;
 import org.springframework.data.redis.serializer.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
 
+import java.math.BigDecimal;
+
 /**
 /**
  * redis配置
  * redis配置
  *
  *
@@ -93,6 +95,25 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
         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
     @Bean
     public DefaultRedisScript<Long> limitScript()
     public DefaultRedisScript<Long> limitScript()
     {
     {

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

@@ -1,9 +1,12 @@
 package com.fs.app.service;
 package com.fs.app.service;
 
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.fs.common.core.redis.RedisCache;
 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.StringUtils;
 import com.fs.common.utils.date.DateUtil;
 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.FsCoursePlaySourceConfig;
 import com.fs.course.domain.FsCourseWatchLog;
 import com.fs.course.domain.FsCourseWatchLog;
 import com.fs.course.service.IFsCourseWatchLogService;
 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.mapper.QwUserMapper;
 import com.fs.qw.service.IQwUserService;
 import com.fs.qw.service.IQwUserService;
 import com.fs.qw.service.IQwUserVideoService;
 import com.fs.qw.service.IQwUserVideoService;
-import com.fs.qw.service.impl.QwUserServiceImpl;
 import com.fs.qw.vo.QwSopCourseFinishTempSetting;
 import com.fs.qw.vo.QwSopCourseFinishTempSetting;
 import com.fs.qwApi.param.QwExternalContactHParam;
 import com.fs.qwApi.param.QwExternalContactHParam;
 import com.fs.sop.domain.QwSopLogs;
 import com.fs.sop.domain.QwSopLogs;
@@ -27,6 +29,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
+import java.util.List;
 import java.util.Map;
 import java.util.Map;
 
 
 @Slf4j
 @Slf4j
@@ -42,9 +45,26 @@ public class IpadSendServer {
     private final IFsCourseWatchLogService watchLogService;
     private final IFsCourseWatchLogService watchLogService;
     private final IQwUserVideoService qwUserVideoService;
     private final IQwUserVideoService qwUserVideoService;
     private final RedisCache redisCache;
     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()
         MiniProgramVo miniProgramVo = MiniProgramVo.builder()
                 .desc(content.getMiniprogramTitle())
                 .desc(content.getMiniprogramTitle())
@@ -53,7 +73,7 @@ public class IpadSendServer {
                 .imgUrl(content.getMiniprogramPicUrl())
                 .imgUrl(content.getMiniprogramPicUrl())
                 .username(courseMaConfig.getOriginalId() + "@app")
                 .username(courseMaConfig.getOriginalId() + "@app")
                 .pagepath(content.getMiniprogramPage())
                 .pagepath(content.getMiniprogramPage())
-                .appid(content.getMiniprogramAppid())
+                .appid(courseMaConfig.getAppid())
                 .build();
                 .build();
         miniProgramVo.setBase(vo);
         miniProgramVo.setBase(vo);
         WxWorkResponseDTO<WxWorkSendAppMsgRespDTO> resp = ipadSendUtils.sendMiniProgram(miniProgramVo);
         WxWorkResponseDTO<WxWorkSendAppMsgRespDTO> resp = ipadSendUtils.sendMiniProgram(miniProgramVo);
@@ -337,7 +357,7 @@ public class IpadSendServer {
                     break;
                     break;
                 case "4":
                 case "4":
                 case "10":
                 case "10":
-                    sendMiniProgram(vo, content, miniMap);
+                    sendMiniProgram(vo, content, miniMap, qwUser.getCompanyId());
                     break;
                     break;
                 case "5":
                 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() {
     private Map<String, FsCoursePlaySourceConfig> getMiniMap() {
         List<FsCoursePlaySourceConfig> list = fsCoursePlaySourceConfigService.list(new QueryWrapper<FsCoursePlaySourceConfig>().ne("type", 2).eq("is_del", 0));
         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);
         return PubFun.listToMapByGroupObject(list, FsCoursePlaySourceConfig::getAppid);
     }
     }
 
 

+ 22 - 0
fs-ipad-task/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.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
 
+import java.math.BigDecimal;
+
 /**
 /**
  * redis配置
  * redis配置
  *
  *
@@ -91,6 +93,26 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
         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
     @Bean
     public DefaultRedisScript<Long> limitScript()
     public DefaultRedisScript<Long> limitScript()
     {
     {

+ 20 - 0
fs-live-app/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.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
 
+import java.math.BigDecimal;
+
 /**
 /**
  * redis配置
  * redis配置
  *
  *
@@ -91,6 +93,24 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
         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
     @Bean
     public DefaultRedisScript<Long> limitScript()
     public DefaultRedisScript<Long> limitScript()
     {
     {

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

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

+ 21 - 0
fs-qw-api/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.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
 
+import java.math.BigDecimal;
+
 /**
 /**
  * redis配置
  * redis配置
  *
  *
@@ -91,6 +93,25 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
         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
     @Bean
     public DefaultRedisScript<Long> limitScript()
     public DefaultRedisScript<Long> limitScript()
     {
     {

+ 20 - 0
fs-qw-mq/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.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
 
+import java.math.BigDecimal;
+
 /**
 /**
  * redis配置
  * redis配置
  *
  *
@@ -90,6 +92,24 @@ public class RedisConfig extends CachingConfigurerSupport
         template.afterPropertiesSet();
         template.afterPropertiesSet();
         return template;
         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
     @Bean
     public DefaultRedisScript<Long> limitScript()
     public DefaultRedisScript<Long> limitScript()

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

+ 21 - 0
fs-qw-task/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.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
 
+import java.math.BigDecimal;
+
 /**
 /**
  * redis配置
  * redis配置
  *
  *
@@ -91,6 +93,25 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
         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
     @Bean
     public DefaultRedisScript<Long> limitScript()
     public DefaultRedisScript<Long> limitScript()
     {
     {

+ 19 - 0
fs-qw-voice/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.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
 
+import java.math.BigDecimal;
+
 /**
 /**
  * redis配置
  * redis配置
  *
  *
@@ -90,7 +92,24 @@ public class RedisConfig extends CachingConfigurerSupport
         template.afterPropertiesSet();
         template.afterPropertiesSet();
         return template;
         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
     @Bean
     public DefaultRedisScript<Long> limitScript()
     public DefaultRedisScript<Long> limitScript()
     {
     {

+ 21 - 0
fs-qwhook-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.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
 
+import java.math.BigDecimal;
+
 /**
 /**
  * redis配置
  * redis配置
  *
  *
@@ -91,6 +93,25 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
         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
     @Bean
     public DefaultRedisScript<Long> limitScript()
     public DefaultRedisScript<Long> limitScript()
     {
     {

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

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

+ 20 - 0
fs-qwhook-sop/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.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
 
+import java.math.BigDecimal;
+
 /**
 /**
  * redis配置
  * redis配置
  *
  *
@@ -91,6 +93,24 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
         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
     @Bean
     public DefaultRedisScript<Long> limitScript()
     public DefaultRedisScript<Long> limitScript()
     {
     {

+ 21 - 0
fs-qwhook/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.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
 
+import java.math.BigDecimal;
+
 /**
 /**
  * redis配置
  * redis配置
  *
  *
@@ -91,6 +93,25 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
         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
     @Bean
     public DefaultRedisScript<Long> limitScript()
     public DefaultRedisScript<Long> limitScript()
     {
     {

+ 20 - 0
fs-repeat-api/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.GenericToStringSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 import org.springframework.data.redis.serializer.StringRedisSerializer;
 
 
+import java.math.BigDecimal;
+
 /**
 /**
  * redis配置
  * redis配置
  *
  *
@@ -91,6 +93,24 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
         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
     @Bean
     public DefaultRedisScript<Long> limitScript()
     public DefaultRedisScript<Long> limitScript()
     {
     {

+ 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-是*/
     /** 后台制单是否需要付款 默认1 0-否 1-是*/
     private Integer isPay;
     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.CompanyNameVO;
 import com.fs.company.vo.CompanyVO;
 import com.fs.company.vo.CompanyVO;
 import com.fs.his.vo.OptionsVO;
 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.Param;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
 import org.apache.ibatis.annotations.Update;
@@ -81,6 +80,9 @@ public interface CompanyMapper
             "<if test = 'maps.companyName != null and  maps.companyName !=\"\"     '> " +
             "<if test = 'maps.companyName != null and  maps.companyName !=\"\"     '> " +
             "and c.company_name like CONCAT('%',#{maps.companyName},'%') " +
             "and c.company_name like CONCAT('%',#{maps.companyName},'%') " +
             "</if>" +
             "</if>" +
+            "<if test = 'maps.deptId != null'> " +
+            "and c.dept_id = #{maps.deptId} " +
+            "</if>" +
 
 
             "<if test = 'maps.status != null   '> " +
             "<if test = 'maps.status != null   '> " +
             "and c.status = #{maps.status}" +
             "and c.status = #{maps.status}" +
@@ -118,6 +120,9 @@ public interface CompanyMapper
             "<if test = 'maps.companyName != null and  maps.companyName !=\"\"     '> " +
             "<if test = 'maps.companyName != null and  maps.companyName !=\"\"     '> " +
             "and c.company_name like CONCAT('%',#{maps.companyName},'%') " +
             "and c.company_name like CONCAT('%',#{maps.companyName},'%') " +
             "</if>" +
             "</if>" +
+            "<if test = 'maps.deptId != null'> " +
+            "and c.dept_id = #{maps.deptId} " +
+            "</if>" +
 
 
             "<if test = 'maps.phonenumber != null and  maps.phonenumber !=\"\"     '> " +
             "<if test = 'maps.phonenumber != null and  maps.phonenumber !=\"\"     '> " +
             "and c.company_mobile like CONCAT('%',#{maps.phonenumber},'%') " +
             "and c.company_mobile like CONCAT('%',#{maps.phonenumber},'%') " +
@@ -149,8 +154,9 @@ public interface CompanyMapper
 
 
 
 
     @Select({"<script> " +
     @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=\"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=\"companyMobile != null  and companyMobile != ''\"> and c.company_mobile = #{companyMobile}</if>\n" +
             "            <if test=\"companyAddress != null  and companyAddress != ''\"> and c.company_address = #{companyAddress}</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=\"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=\"limitUserCount != null \"> and c.limit_user_count = #{limitUserCount}</if>\n" +
             "            <if test=\"isDel != null \"> and c.is_del = #{isDel}</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>"})
             "</script>"})
     List<CompanyVO> selectCompanyListVO(Company param);
     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")
     @Select("select company_id from company")
     List<Long> selectCompanyIds();
     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;
 package com.fs.company.param;
 
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
 
 
 import java.util.Date;
 import java.util.Date;
 
 
 
 
+@Data
 public class CompanyParam
 public class CompanyParam
 {
 {
 
 
@@ -12,36 +14,5 @@ public class CompanyParam
     private Long companyId;
     private Long companyId;
     private Integer status;
     private Integer status;
     private String phonenumber;
     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;
+}

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

@@ -67,4 +67,6 @@ public interface ICompanyConfigService
     String selectConfigByKey(String configKey);
     String selectConfigByKey(String configKey);
 
 
     CompanyConfig selectCompanyConfigByServerKey(String key);
     CompanyConfig selectCompanyConfigByServerKey(String key);
+
+    String selectRedPacketConfigByKey(Long companyId);
 }
 }

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

+ 38 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanyConfigServiceImpl.java

@@ -8,10 +8,15 @@ import com.fs.company.domain.CompanyConfig;
 import com.fs.company.mapper.CompanyConfigMapper;
 import com.fs.company.mapper.CompanyConfigMapper;
 import com.fs.company.service.ICompanyConfigService;
 import com.fs.company.service.ICompanyConfigService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.domain.SysConfig;
+import org.apache.http.util.Asserts;
+import org.redisson.api.RedissonClient;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
 import java.util.List;
 import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
 
 
 import static com.fs.common.utils.DictUtils.getCacheKey;
 import static com.fs.common.utils.DictUtils.getCacheKey;
 
 
@@ -28,6 +33,10 @@ public class CompanyConfigServiceImpl implements ICompanyConfigService
     private RedisCache redisCache;
     private RedisCache redisCache;
     @Autowired
     @Autowired
     private CompanyConfigMapper companyConfigMapper;
     private CompanyConfigMapper companyConfigMapper;
+    @Autowired
+    private RedisTemplate<String, String> redisTemplate; // 注入RedisTemplate
+    private static final String REDIS_KEY_PREFIX = "red_packet_config:";
+    private static final long CACHE_TIMEOUT = 24 * 60 * 60;
 
 
     /**
     /**
      * 查询参数配置
      * 查询参数配置
@@ -133,4 +142,33 @@ public class CompanyConfigServiceImpl implements ICompanyConfigService
     public CompanyConfig selectCompanyConfigByServerKey(String key) {
     public CompanyConfig selectCompanyConfigByServerKey(String key) {
         return companyConfigMapper.selectCompanyConfigByServerKey(key);
         return companyConfigMapper.selectCompanyConfigByServerKey(key);
     }
     }
+
+    @Override
+    public String selectRedPacketConfigByKey(Long companyId) {
+        Asserts.notNull(companyId,"公司id不能为空!");
+        String redisKey = REDIS_KEY_PREFIX + companyId;
+        String cachedConfig = redisTemplate.opsForValue().get(redisKey);
+        if (cachedConfig != null) {
+            return cachedConfig;
+        }
+        synchronized (getSynchronizationObject(companyId)) {
+            cachedConfig = redisTemplate.opsForValue().get(redisKey);
+
+            if (cachedConfig != null) {
+                return cachedConfig;
+            }
+            String configFromDb = companyConfigMapper.selectRedPacketConfigByKey(companyId);
+            if (configFromDb != null) {
+                redisTemplate.opsForValue().set(redisKey, configFromDb, CACHE_TIMEOUT, TimeUnit.SECONDS);
+            } else {
+                redisTemplate.opsForValue().set(redisKey, "", 5 * 60, TimeUnit.SECONDS);
+            }
+            return configFromDb;
+        }
+    }
+
+    private static final ConcurrentHashMap<Long, Object> LOCKS = new ConcurrentHashMap<>();
+    private static Object getSynchronizationObject(Long companyId) {
+        return LOCKS.computeIfAbsent(companyId, k -> new Object());
+    }
 }
 }

+ 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;
     private CompanyUserMapper companyUserMapper;
 
 
     @Override
     @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");
+    }
+}

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

@@ -12,7 +12,10 @@ import com.fs.common.core.redis.RedisCache;
 import com.fs.common.exception.CustomException;
 import com.fs.common.exception.CustomException;
 import com.fs.common.exception.ServiceException;
 import com.fs.common.exception.ServiceException;
 import com.fs.common.exception.file.OssException;
 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.domain.*;
 import com.fs.company.mapper.*;
 import com.fs.company.mapper.*;
 import com.fs.company.param.CompanyUserAreaParam;
 import com.fs.company.param.CompanyUserAreaParam;

+ 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 String restartTime;
     private List<String> miniAppMaster;
     private List<String> miniAppMaster;
     private List<String> miniAppServer;
     private List<String> miniAppServer;
+    /** 已占用 */
+    private Integer usedNum;
+    /** 所属部门id */
+    private Long deptId;
 }
 }

+ 28 - 29
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 cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.utils.spring.SpringUtils;
 import com.fs.common.utils.spring.SpringUtils;
 import com.fs.course.config.CourseMaConfig;
 import com.fs.course.config.CourseMaConfig;
 import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
 import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
+import com.fs.course.service.IFsCoursePlaySourceConfigService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import com.fs.system.mapper.SysConfigMapper;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Lists;
@@ -33,8 +35,10 @@ import org.yaml.snakeyaml.events.Event;
 import javax.annotation.PostConstruct;
 import javax.annotation.PostConstruct;
 import java.io.File;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
 @Slf4j
 @Slf4j
@@ -45,6 +49,7 @@ public class WxMaConfiguration {
 
 
     private static final Map<String, WxMaMessageRouter> routers = Maps.newHashMap();
     private static final Map<String, WxMaMessageRouter> routers = Maps.newHashMap();
     private static Map<String, WxMaService> maServices;
     private static Map<String, WxMaService> maServices;
+    private static IFsCoursePlaySourceConfigService fsCoursePlaySourceConfigService;
 
 
     @Autowired
     @Autowired
     public WxMaConfiguration(SysConfigMapper sysConfigMapper, FsCoursePlaySourceConfigMapper configMapper) {
     public WxMaConfiguration(SysConfigMapper sysConfigMapper, FsCoursePlaySourceConfigMapper configMapper) {
@@ -65,14 +70,19 @@ public class WxMaConfiguration {
 //            c.add(config2);
 //            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())) {
                 if (appid.equals(courseMaConfig.getAppid())) {
                     continue;
                     continue;
                 }
                 }
-                if (courseMaConfig.getType() != null && courseMaConfig.getType().equals("1")){
+                if (courseMaConfig.getType() != null && courseMaConfig.getType() == 1){
                     WxMaConfig.Config wxMaConfig = new WxMaConfig.Config();
                     WxMaConfig.Config wxMaConfig = new WxMaConfig.Config();
                     BeanUtils.copyProperties(courseMaConfig, wxMaConfig);
                     BeanUtils.copyProperties(courseMaConfig, wxMaConfig);
                     c.add(wxMaConfig);
                     c.add(wxMaConfig);
@@ -97,20 +107,7 @@ public class WxMaConfiguration {
     }
     }
 
 
     public static WxMaService getMaService(String appid) {
     public static WxMaService getMaService(String appid) {
-        // 从缓存获取
-        WxMaService wxService = maServices.get(appid);
-        if (wxService != null) {
-            return wxService;
-        }
-
-        // 缓存未命中,查询数据库
-        synchronized (WxMaConfiguration.class) {
-            // 双重检查
-            wxService = maServices.get(appid);
-            if (wxService != null) {
-                return wxService;
-            }
-
+        return maServices.computeIfAbsent(appid,e->{
             // 查询数据库
             // 查询数据库
             FsCoursePlaySourceConfigMapper configMapper = SpringUtils.getBean(FsCoursePlaySourceConfigMapper.class);
             FsCoursePlaySourceConfigMapper configMapper = SpringUtils.getBean(FsCoursePlaySourceConfigMapper.class);
             Wrapper<FsCoursePlaySourceConfig> queryWrapper = Wrappers.<FsCoursePlaySourceConfig>lambdaQuery()
             Wrapper<FsCoursePlaySourceConfig> queryWrapper = Wrappers.<FsCoursePlaySourceConfig>lambdaQuery()
@@ -121,11 +118,8 @@ public class WxMaConfiguration {
                 throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
                 throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
             }
             }
 
 
-            WxMaService service = getWxMaService(config.getAppid(), config.getSecret(), config.getToken(), config.getAesKey(), config.getMsgDataFormat());
-            maServices.put(appid, service);
-            log.info("Initialized WxMaService for appid: {}", appid);
-            return service;
-        }
+            return getWxMaService(config.getAppid(), config.getSecret(), config.getToken(), config.getAesKey(), config.getMsgDataFormat());
+        });
     }
     }
 
 
     /**
     /**
@@ -156,11 +150,16 @@ public class WxMaConfiguration {
         }
         }
 
 
         maServices = configs.stream()
         maServices = configs.stream()
-            .map(a -> {
-                WxMaService service = getWxMaService(a.getAppid(), a.getSecret(), a.getToken(), a.getAesKey(), a.getMsgDataFormat());
-                routers.put(a.getAppid(), this.newRouter(service));
-                return service;
-            }).collect(Collectors.toMap(s -> s.getWxMaConfig().getAppid(), a -> a));
+                .map(a -> {
+                    WxMaService service = getWxMaService(a.getAppid(), a.getSecret(), a.getToken(), a.getAesKey(), a.getMsgDataFormat());
+                    routers.put(a.getAppid(), this.newRouter(service));
+                    return service;
+                }).collect(Collectors.toMap(
+                        s -> s.getWxMaConfig().getAppid(),
+                        a -> a,
+                        (existing, replacement) -> replacement,
+                        ConcurrentHashMap::new
+                ));
     }
     }
 
 
     private WxMaMessageRouter newRouter(WxMaService service) {
     private WxMaMessageRouter newRouter(WxMaService service) {

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

@@ -44,15 +44,16 @@ public class OrderCodeUtils {
 
 
     }
     }
     public static String getOrderSn(){
     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 isBound;
+    private Boolean dept;
+    /**
+     * 是否单销售观看(只能在第一次绑定的销售头上看课)
+     */
+    private boolean oneCompanyCourse;
 
 
 
 
     @Data
     @Data

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

@@ -86,4 +86,8 @@ public class FsCoursePlaySourceConfig {
      * 销售ID
      * 销售ID
      */
      */
     private Long companyUserId;
     private Long companyUserId;
+    // 创建人
+    private Long createUserId;
+    // 创建部门
+    private Long createDeptId;
 }
 }

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

@@ -64,4 +64,13 @@ public class FsCourseRedPacketLog extends BaseEntity
 
 
     private String appId;//小程序appId
     private String appId;//小程序appId
 
 
+    /**
+     * 账户余额扣减前
+     */
+    private BigDecimal accBalanceBefore;
+    /**
+     * 账户余额扣减后
+     */
+    private BigDecimal accBalanceAfter;
+
 }
 }

+ 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 com.fs.common.annotation.Excel;
 import lombok.Data;
 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;
     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;
     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("offset") int offset,
             @Param("pageSize") int pageSize);
             @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);
 }
 }

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

@@ -519,4 +519,9 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
     Long selectByWatchlxDay(@Param("userId") Long userId,@Param("projectId")  Long projectId);
     Long selectByWatchlxDay(@Param("userId") Long userId,@Param("projectId")  Long projectId);
 
 
     List<FsCourseWatchLogListVO> selectFsCourseWatchLogListVOexport(@Param("maps") FsCourseWatchLogListParam param);
     List<FsCourseWatchLogListVO> selectFsCourseWatchLogListVOexport(@Param("maps") FsCourseWatchLogListParam param);
+
+    /**
+     * 查询训练营看课人数
+     */
+    Integer getUserCountByCampId(@Param("trainingCampId") Long trainingCampId);
 }
 }

+ 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")
     @MapKey("cateName")
     Map<String,FsUserCourseCategory> queryAllCategoryData();
     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 ")
     @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();
     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" +
     @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) ")
             " and find_in_set(#{companyId},company_ids) ")
     List<OptionsVO> selectFsUserCourseByCompany(@Param("companyId") Long companyId);
     List<OptionsVO> selectFsUserCourseByCompany(@Param("companyId") Long companyId);

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

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

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

@@ -39,4 +39,7 @@ public class FsCoursePlaySourceConfigEditParam {
 
 
     @ApiModelProperty("类型 1小程序 2公众号")
     @ApiModelProperty("类型 1小程序 2公众号")
     private Integer type;
     private Integer type;
+
+    @ApiModelProperty("所属公司")
+    private Long companyId;
 }
 }

部分文件因文件數量過多而無法顯示