Browse Source

Merge branch 'master' into 企微聊天

# Conflicts:
#	fs-qw-api-msg/src/main/java/com/fs/app/controller/QwMsgController.java
#	fs-service/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java
#	fs-service/src/main/java/com/fs/course/param/FsCourseListBySidebarParam.java
#	fs-service/src/main/java/com/fs/course/service/IFsCourseWatchLogService.java
#	fs-service/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java
#	fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
#	fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactMapper.java
#	fs-service/src/main/java/com/fs/qw/service/IQwExternalContactService.java
#	fs-service/src/main/java/com/fs/wxwork/dto/WxWorkMessageDTO.java
#	fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml
#	fs-service/src/main/resources/mapper/qw/QwExternalContactMapper.xml
Long 1 week ago
parent
commit
ee9c19327b
100 changed files with 3762 additions and 984 deletions
  1. 28 13
      README.md
  2. 4 0
      fs-admin/pom.xml
  3. 25 3
      fs-admin/src/main/java/com/fs/api/controller/IndexStatisticsController.java
  4. 27 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyStatisticsController.java
  5. 41 0
      fs-admin/src/main/java/com/fs/course/controller/CourseRedPacketStatisticsController.java
  6. 3 6
      fs-admin/src/main/java/com/fs/course/controller/FsCourseWatchLogController.java
  7. 172 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseCompanyStatisticsController.java
  8. 13 0
      fs-admin/src/main/java/com/fs/course/controller/qw/QwFsCourseWatchLogController.java
  9. 64 0
      fs-admin/src/main/java/com/fs/course/task/CompanyBalanceTask.java
  10. 17 0
      fs-admin/src/main/java/com/fs/course/task/CourseStatisticsTask.java
  11. 37 0
      fs-admin/src/main/java/com/fs/course/task/RedPacketLogsTask.java
  12. 31 0
      fs-admin/src/main/java/com/fs/course/task/WatchCourseStatistics.java
  13. 15 13
      fs-admin/src/main/java/com/fs/crm/controller/CrmCustomerController.java
  14. 6 6
      fs-admin/src/main/java/com/fs/his/controller/FsArticleController.java
  15. 26 4
      fs-admin/src/main/java/com/fs/his/controller/FsCompanyController.java
  16. 103 0
      fs-admin/src/main/java/com/fs/his/controller/FsCompanyDivItemController.java
  17. 103 0
      fs-admin/src/main/java/com/fs/his/controller/FsDfAccountController.java
  18. 2 2
      fs-admin/src/main/java/com/fs/his/controller/FsInquiryOrderController.java
  19. 31 25
      fs-admin/src/main/java/com/fs/his/controller/FsStoreOrderController.java
  20. 4 0
      fs-admin/src/main/java/com/fs/his/controller/FsUserAddressController.java
  21. 26 41
      fs-admin/src/main/java/com/fs/his/controller/FsUserController.java
  22. 48 0
      fs-admin/src/main/java/com/fs/his/controller/HzOMSErpApiController.java
  23. 345 148
      fs-admin/src/main/java/com/fs/his/task/Task.java
  24. 93 14
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreHealthOrderScrmController.java
  25. 305 19
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java
  26. 29 1
      fs-admin/src/main/java/com/fs/hisStore/controller/FsStorePaymentScrmController.java
  27. 1 1
      fs-admin/src/main/java/com/fs/hisStore/task/ErpTask.java
  28. 71 17
      fs-admin/src/main/java/com/fs/hisStore/task/MallStoreTask.java
  29. 0 109
      fs-admin/src/main/java/com/fs/hospital/controller/HospitalController.java
  30. 2 2
      fs-admin/src/main/java/com/fs/qw/FsCourseTask.java
  31. 1 4
      fs-admin/src/main/java/com/fs/qw/controller/QwExternalContactController.java
  32. 5 2
      fs-admin/src/main/java/com/fs/qw/controller/QwExternalContactTransferCompanyAuditController.java
  33. 48 0
      fs-admin/src/main/java/com/fs/qw/controller/QwPushCountController.java
  34. 103 0
      fs-admin/src/main/java/com/fs/qw/controller/QwUserComplainRecordController.java
  35. 17 1
      fs-admin/src/main/java/com/fs/qw/controller/QwUserController.java
  36. 27 0
      fs-admin/src/main/java/com/fs/task/SgTestController.java
  37. 25 0
      fs-admin/src/main/java/com/fs/task/SyncTuLinStudentInfoTask.java
  38. 79 4
      fs-admin/src/main/java/com/fs/web/controller/common/CommonController.java
  39. 26 7
      fs-admin/src/main/java/com/fs/web/controller/system/SysLoginController.java
  40. 2 2
      fs-admin/src/main/resources/application.yml
  41. 1 1
      fs-admin/src/main/resources/logback.xml
  42. 2 2
      fs-common-api/src/main/resources/application.yml
  43. 7 0
      fs-common/src/main/java/com/fs/common/constant/FsConstants.java
  44. 7 0
      fs-common/src/main/java/com/fs/common/enums/ImTypeEnum.java
  45. 59 0
      fs-common/src/main/java/com/fs/common/utils/DateUtils.java
  46. 26 0
      fs-common/src/main/java/com/fs/common/utils/model/DateTimeEntity.java
  47. 37 0
      fs-company-app/src/main/java/com/fs/app/controller/AppBaseController.java
  48. 222 6
      fs-company-app/src/main/java/com/fs/app/controller/CompanyUserController.java
  49. 1 0
      fs-company-app/src/main/java/com/fs/app/controller/FsUserController.java
  50. 107 12
      fs-company-app/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java
  51. 28 32
      fs-company-app/src/main/java/com/fs/core/aspectj/DataScopeAspect.java
  52. 3 3
      fs-company-app/src/main/java/com/fs/core/aspectj/DataSourceAspect.java
  53. 44 19
      fs-company-app/src/main/java/com/fs/core/aspectj/LogAspect.java
  54. 19 48
      fs-company-app/src/main/java/com/fs/core/config/DataSourceConfig.java
  55. 123 123
      fs-company-app/src/main/java/com/fs/core/config/DruidConfig.java
  56. 4 0
      fs-company-app/src/main/java/com/fs/core/config/RedisConfig.java
  57. 3 3
      fs-company-app/src/main/java/com/fs/core/datasource/DynamicDataSource.java
  58. 4 5
      fs-company-app/src/main/java/com/fs/core/datasource/DynamicDataSourceContextHolder.java
  59. 3 3
      fs-company-app/src/main/java/com/fs/core/manager/AsyncManager.java
  60. 1 1
      fs-company-app/src/main/java/com/fs/core/manager/ShutdownManager.java
  61. 15 24
      fs-company-app/src/main/java/com/fs/core/manager/factory/AsyncFactory.java
  62. 1 1
      fs-company-app/src/main/resources/application.yml
  63. 39 0
      fs-company/src/main/java/com/fs/company/controller/common/CommonController.java
  64. 222 9
      fs-company/src/main/java/com/fs/company/controller/common/Test.java
  65. 7 12
      fs-company/src/main/java/com/fs/company/controller/company/CompanyDeptController.java
  66. 9 0
      fs-company/src/main/java/com/fs/company/controller/company/CompanyProfileController.java
  67. 72 21
      fs-company/src/main/java/com/fs/company/controller/company/CompanyUserController.java
  68. 26 2
      fs-company/src/main/java/com/fs/company/controller/company/IndexStatisticsController.java
  69. 1 1
      fs-company/src/main/java/com/fs/company/controller/course/FsCourseAnswerLogsController.java
  70. 13 0
      fs-company/src/main/java/com/fs/company/controller/course/FsCourseFinishTempController.java
  71. 1 1
      fs-company/src/main/java/com/fs/company/controller/course/FsCourseRedPacketLogController.java
  72. 65 6
      fs-company/src/main/java/com/fs/company/controller/course/FsCourseWatchLogController.java
  73. 8 0
      fs-company/src/main/java/com/fs/company/controller/course/FsUserCoursePeriodController.java
  74. 20 2
      fs-company/src/main/java/com/fs/company/controller/course/qw/FsQwCourseWatchLogController.java
  75. 59 0
      fs-company/src/main/java/com/fs/company/controller/qw/QwExternalContactController.java
  76. 5 2
      fs-company/src/main/java/com/fs/company/controller/qw/QwExternalContactTransferCompanyAuditController.java
  77. 4 2
      fs-company/src/main/java/com/fs/company/controller/qw/QwExternalContactTransferLogController.java
  78. 10 1
      fs-company/src/main/java/com/fs/company/controller/qw/QwSopLogsController.java
  79. 15 14
      fs-company/src/main/java/com/fs/company/controller/qw/QwSopTempController.java
  80. 54 12
      fs-company/src/main/java/com/fs/company/controller/qw/QwUserController.java
  81. 16 1
      fs-company/src/main/java/com/fs/company/controller/qw/SopUserLogsController.java
  82. 71 0
      fs-company/src/main/java/com/fs/company/controller/store/FsPrescribeController.java
  83. 2 2
      fs-company/src/main/java/com/fs/company/controller/store/FsStoreOrderController.java
  84. 29 0
      fs-company/src/main/java/com/fs/company/utils/QwStatusEnum.java
  85. 1 1
      fs-company/src/main/java/com/fs/framework/config/SecurityConfig.java
  86. 3 1
      fs-company/src/main/java/com/fs/framework/service/UserDetailsServiceImpl.java
  87. 23 7
      fs-company/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java
  88. 26 0
      fs-company/src/main/java/com/fs/user/FsUserAdminController.java
  89. 3 2
      fs-company/src/main/resources/application.yml
  90. 1 1
      fs-company/src/main/resources/logback.xml
  91. 19 6
      fs-doctor-app/src/main/java/com/fs/app/controller/CommonController.java
  92. 5 0
      fs-doctor-app/src/main/java/com/fs/app/controller/DiagnosisController.java
  93. 8 3
      fs-doctor-app/src/main/java/com/fs/app/controller/DoctorController.java
  94. 24 6
      fs-doctor-app/src/main/java/com/fs/app/controller/DrugReportController.java
  95. 50 11
      fs-doctor-app/src/main/java/com/fs/app/controller/InquiryOrderController.java
  96. 108 6
      fs-doctor-app/src/main/java/com/fs/app/controller/PrescribeController.java
  97. 18 2
      fs-doctor-app/src/main/java/com/fs/framework/config/MyBatisConfig.java
  98. 1 1
      fs-doctor-app/src/main/resources/application.yml
  99. 2 2
      fs-doctor-app/src/main/resources/mybatis/mybatis-config.xml
  100. 0 120
      fs-hospital/pom.xml

+ 28 - 13
README.md

@@ -3,21 +3,26 @@
 #### 介绍
 问诊平台
 
-#### 软件架构
-软件架构说明
+#### 软件模块说明
+
+| 模块名称         | 模块描述         | 对应前端项目                  |
+|--------------|--------------|-------------------------|
+| fs-admin     | 总后台服务        | ylrz_his_scrm_adminUI   |
+| fs-company   | 销售端          | ylrz_his_scrm_companyUI |
+| fs-user-app  | 微信小程序端       | 对应某个微信小程序(前端蒲瑶清楚)       |
+| fs-framework | 主要依赖包,核心包    | /                       |
+| fs-service   | 所有的链接配置文件都在里面 | /                       |
 
 
 #### 安装教程
 
 1.  xxxx
 2.  xxxx
-3.  xxxx
 
 #### 使用说明
 
-1.  xxxx
-2.  xxxx
-3.  xxxx
+1.  注意调整Memory的大小,以及堆内存大小
+2.  对于maven仓库缺少的jar包引用,需要拷贝现有的文件(拷贝后依然出现错误,直接删除错误包下的_remote.repositories文件)。
 
 #### 参与贡献
 
@@ -27,11 +32,21 @@
 4.  新建 Pull Request
 
 
-#### 特技
+#### sql更新
+
+-- 添加字段(修改企微的备注手机号码搜索时用到)
+
+ALTER TABLE qw_external_contact
+ADD COLUMN search_mobile char(44)
+GENERATED ALWAYS AS (
+CAST(
+REGEXP_REPLACE(
+COALESCE(JSON_UNQUOTE(JSON_EXTRACT(remark_mobiles, '$[0]')), ''),
+'[^0-9]', ''
+) AS CHAR(44)
+)
+) VIRTUAL;
+
+-- 创建索引
 
-1.  使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
-2.  Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
-3.  你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
-4.  [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
-5.  Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
-6.  Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
+CREATE INDEX idx_search_mobile ON qw_external_contact(search_mobile);

+ 4 - 0
fs-admin/pom.xml

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

+ 25 - 3
fs-admin/src/main/java/com/fs/api/controller/IndexStatisticsController.java

@@ -1,24 +1,23 @@
 package com.fs.api.controller;
 
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.entity.SysDept;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.company.constant.CompanyTrafficConstants;
 import com.fs.company.domain.Company;
 import com.fs.company.service.ICompanyService;
-import com.fs.company.service.ICompanyTrafficRecordService;
-import com.fs.company.service.impl.CompanyTrafficRecordServiceImpl;
 import com.fs.his.utils.ConfigUtil;
 import com.fs.hisStore.config.MedicalMallConfig;
 import com.fs.statis.StatisticsRedisConstant;
 import com.fs.statis.dto.*;
 import com.fs.statis.param.StatisticsDeptCompanyParam;
+import com.fs.statis.service.IStatisticsService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.service.ISysConfigService;
 import com.fs.system.service.ISysDeptService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.web.bind.annotation.*;
 
 import java.math.BigDecimal;
@@ -54,6 +53,9 @@ public class IndexStatisticsController {
 
     @Autowired
     private MedicalMallConfig medicalMallConfig;
+
+    @Autowired
+    private IStatisticsService statisticsService;
     /**
      * 分析概览
      */
@@ -168,6 +170,11 @@ public class IndexStatisticsController {
                 );
             }
         }
+        BigDecimal redPacketCompanyMoney = redisCache.getCacheObject("redpacket_money");
+        if(ObjectUtils.isNull(redPacketCompanyMoney)){
+            redPacketCompanyMoney = BigDecimal.ZERO;
+        }
+        consumptionBalanceDataDTO.setRunTianBalance(redPacketCompanyMoney);
 
         return R.ok().put("data", consumptionBalanceDataDTO);
     }
@@ -851,4 +858,19 @@ public class IndexStatisticsController {
             }
         }
     }
+
+    /**
+     * @Description: 看课统计按公司
+     * @Param:
+     * @Return:
+     * @Author xgb
+     * @Date 2025/10/27 16:29
+     */
+    @PostMapping("/getWatchCourseStatisticsData")
+    public R getWatchCourseStatisticsData(@RequestBody AnalysisPreviewQueryDTO param){
+        // 从缓存获取看客统计数据
+        List<WatchCourseStatisticsResultDTO> data=statisticsService.getWatchCourseStatisticsData( param);
+
+        return R.ok().put("data", data);
+    }
 }

+ 27 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyStatisticsController.java

@@ -19,9 +19,14 @@ import com.fs.crm.service.ICrmCustomerService;
 import com.fs.crm.service.ICrmCustomerVisitService;
 import com.fs.crm.vo.CrmCustomerStatisticsVO;
 import com.fs.crm.vo.CrmCustomerVisitStatisticsVO;
+import com.fs.his.dto.FsStoreOrderAmountScrmStatsQueryDto;
+import com.fs.his.dto.FsStoreOrderAmountStatsQueryDto;
 import com.fs.his.service.IFsStoreAfterSalesService;
 import com.fs.his.service.IFsStoreOrderService;
 import com.fs.his.service.IFsStorePaymentService;
+import com.fs.his.vo.FsStoreOrderAmountScrmStatsVo;
+import com.fs.his.vo.FsStoreOrderAmountStatsVo;
+import com.fs.hisStore.service.IFsStoreOrderScrmService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -67,6 +72,10 @@ public class CompanyStatisticsController extends BaseController
     private ICrmCustomerService crmCustomerService;
     @Autowired
     private ICrmCustomerVisitService crmCustomerVisitService;
+
+    //app商城订单接口Service
+    @Autowired
+    private IFsStoreOrderScrmService fsStoreOrderScrmService;
     @GetMapping("/storeOrder")
     public R storeOrder(FsStoreStatisticsParam param)
     {
@@ -724,4 +733,22 @@ public class CompanyStatisticsController extends BaseController
         return util.exportExcel(qwIpadTotalVos, "visit");
     }
 
+    /**
+     * 获取互联网医院订单统计数据
+     * */
+    @GetMapping("/hisOrderCountStats")
+    public AjaxResult getHisOrderCount(FsStoreOrderAmountStatsQueryDto statsQueryDto){
+        FsStoreOrderAmountStatsVo fsStoreOrderAmountStatsVo = storeOrderService.selectFsStoreOrderAmountStats(statsQueryDto);
+        return AjaxResult.success(fsStoreOrderAmountStatsVo);
+    }
+
+    /**
+     * 获取App商城订单统计数据
+     * */
+    @GetMapping("/appOrderCountStats")
+    public AjaxResult getAppOrderCount(FsStoreOrderAmountScrmStatsQueryDto statsQueryDto){
+        FsStoreOrderAmountScrmStatsVo scrmStatsVo = fsStoreOrderScrmService.selectFsStoreOrderAmountScrmStats(statsQueryDto);
+        return AjaxResult.success(scrmStatsVo);
+    }
+
 }

+ 41 - 0
fs-admin/src/main/java/com/fs/course/controller/CourseRedPacketStatisticsController.java

@@ -0,0 +1,41 @@
+package com.fs.course.controller;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.course.dto.CourseRedPacketStatisticsDTO;
+import com.fs.course.param.CourseRedPacketStatisticsParam;
+import com.fs.course.service.CourseRedPacketStatisticsService;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.ApiModelProperty;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * @description: 看客红包发送统计
+ * @author: Xgb
+ * @createDate: 2025/10/14
+ * @version: 1.0
+ */
+@RestController
+@RequestMapping("/course/courseRedPacketStatistics")
+public class CourseRedPacketStatisticsController extends BaseController {
+
+    @Autowired
+    private CourseRedPacketStatisticsService courseRedPacketStatisticsService;
+
+    @ApiModelProperty("看客红包发送统计")
+    @GetMapping("/list")
+    public R list(CourseRedPacketStatisticsParam param) {
+
+        startPage();
+        // 看客红包发送统计
+        List<CourseRedPacketStatisticsDTO> list = courseRedPacketStatisticsService.statistics(param);
+
+        return R.ok().put("data", new PageInfo<>(list));
+    }
+
+}

+ 3 - 6
fs-admin/src/main/java/com/fs/course/controller/FsCourseWatchLogController.java

@@ -103,13 +103,10 @@ public class FsCourseWatchLogController extends BaseController
         if (param.getSTime()==null||param.getETime()==null){
             throw new CustomException("必须选择开始时间和结束时间!");
         }
+        startPage();
         List<FsCourseWatchLogStatisticsListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogStatisticsListVONew(param);
-        TableDataInfo rspData = new TableDataInfo();
-        rspData.setCode(HttpStatus.SUCCESS);
-        rspData.setMsg("查询成功");
-        rspData.setRows(list);
-        rspData.setTotal(fsCourseWatchLogService.selectFsCourseWatchLogStatisticsListVONewCount(param));
-        return rspData;
+
+        return getDataTable(list);
     }
 
     /**

+ 172 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseCompanyStatisticsController.java

@@ -0,0 +1,172 @@
+package com.fs.course.controller;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+import com.fs.common.exception.ServiceException;
+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.course.domain.FsUserCourseCompanyStatistics;
+import com.fs.course.service.IFsUserCourseCompanyStatisticsService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 会员每日看课统计Controller
+ *
+ * @author fs
+ * @date 2025-10-27
+ */
+@RestController
+@RequestMapping("/course/statistics")
+public class FsUserCourseCompanyStatisticsController extends BaseController
+{
+    @Autowired
+    private IFsUserCourseCompanyStatisticsService fsUserCourseCompanyStatisticsService;
+
+    /**
+     * 查询会员每日看课统计列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:statistics:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserCourseCompanyStatistics fsUserCourseCompanyStatistics)
+    {
+        if (fsUserCourseCompanyStatistics.getBeginTime() == null || fsUserCourseCompanyStatistics.getEndTime() == null) {
+            throw new ServiceException("请选择开始时间和结束时间!");
+        }
+
+        startPage();
+        List<FsUserCourseCompanyStatistics> list =
+                fsUserCourseCompanyStatisticsService.selectFsUserCourseCompanyStatisticsTotal(fsUserCourseCompanyStatistics);
+        Optional.ofNullable(list).orElse(Collections.emptyList())
+                .forEach(item -> {
+                    // 完播率
+                    Long watchCount = item.getWatchCount() != null ? item.getWatchCount() : 0L;
+                    Long completeWatchCount = item.getCompleteWatchCount() != null ? item.getCompleteWatchCount() : 0L;
+                    if (watchCount > 0) {
+                        BigDecimal rate = BigDecimal.valueOf(completeWatchCount)
+                                .multiply(BigDecimal.valueOf(100))
+                                .divide(BigDecimal.valueOf(watchCount), 2, RoundingMode.HALF_UP);
+                        item.setCompleteRate(rate.longValue());
+                    } else {
+                        item.setCompleteRate(0L);
+                    }
+
+                    // 正确率
+                    Long answerCount = item.getAnswerCount() != null ? item.getAnswerCount() : 0L;
+                    Long correctCount = item.getCorrectCount() != null ? item.getCorrectCount() : 0L;
+                    if (answerCount > 0) {
+                        BigDecimal rate = BigDecimal.valueOf(correctCount)
+                                .multiply(BigDecimal.valueOf(100))
+                                .divide(BigDecimal.valueOf(answerCount), 2, RoundingMode.HALF_UP);
+                        item.setCorrectRate(rate.longValue());
+                    } else {
+                        item.setCorrectRate(0L);
+                    }
+                });
+
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出会员每日看课统计列表
+     */
+    @PreAuthorize("@ss.hasPermi('course:statistics:export')")
+    @Log(title = "会员每日看课统计", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsUserCourseCompanyStatistics fsUserCourseCompanyStatistics)
+    {
+        List<FsUserCourseCompanyStatistics> list =
+                fsUserCourseCompanyStatisticsService.selectFsUserCourseCompanyStatisticsTotal(fsUserCourseCompanyStatistics);
+
+        Optional.ofNullable(list).orElse(Collections.emptyList())
+                .forEach(item -> {
+                    // 计算完播率 (完播次数 / 观看次数 * 100)
+                    item.setCompleteRate(
+                            Optional.ofNullable(item.getWatchCount())
+                                    .filter(watchCount -> watchCount > 0)
+                                    .map(watchCount -> BigDecimal.valueOf(
+                                                    Optional.ofNullable(item.getCompleteWatchCount()).orElse(0L))
+                                            .multiply(BigDecimal.valueOf(100))
+                                            .divide(BigDecimal.valueOf(watchCount), 2, RoundingMode.HALF_UP)
+                                            .longValue()
+                                    )
+                                    .orElse(0L)
+                    );
+
+                    // 计算正确率 (正确人次 / 答题人次 * 100)
+                    item.setCorrectRate(
+                            Optional.ofNullable(item.getAnswerCount())
+                                    .filter(answerCount -> answerCount > 0)
+                                    .map(answerCount -> BigDecimal.valueOf(
+                                                    Optional.ofNullable(item.getCorrectCount()).orElse(0L))
+                                            .multiply(BigDecimal.valueOf(100))
+                                            .divide(BigDecimal.valueOf(answerCount), 2, RoundingMode.HALF_UP)
+                                            .longValue()
+                                    )
+                                    .orElse(0L)
+                    );
+                });
+
+        ExcelUtil<FsUserCourseCompanyStatistics> util = new ExcelUtil<FsUserCourseCompanyStatistics>(FsUserCourseCompanyStatistics.class);
+        return util.exportExcel(list, "会员每日看课统计数据");
+    }
+
+    /**
+     * 获取会员每日看课统计详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('course:statistics:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsUserCourseCompanyStatisticsService.selectFsUserCourseCompanyStatisticsById(id));
+    }
+
+    /**
+     * 新增会员每日看课统计
+     */
+    @PreAuthorize("@ss.hasPermi('course:statistics:add')")
+    @Log(title = "会员每日看课统计", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsUserCourseCompanyStatistics fsUserCourseCompanyStatistics)
+    {
+        return toAjax(fsUserCourseCompanyStatisticsService.insertFsUserCourseCompanyStatistics(fsUserCourseCompanyStatistics));
+    }
+
+    /**
+     * 修改会员每日看课统计
+     */
+    @PreAuthorize("@ss.hasPermi('course:statistics:edit')")
+    @Log(title = "会员每日看课统计", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsUserCourseCompanyStatistics fsUserCourseCompanyStatistics)
+    {
+        return toAjax(fsUserCourseCompanyStatisticsService.updateFsUserCourseCompanyStatistics(fsUserCourseCompanyStatistics));
+    }
+
+    /**
+     * 删除会员每日看课统计
+     */
+    @PreAuthorize("@ss.hasPermi('course:statistics:remove')")
+    @Log(title = "会员每日看课统计", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsUserCourseCompanyStatisticsService.deleteFsUserCourseCompanyStatisticsByIds(ids));
+    }
+}

+ 13 - 0
fs-admin/src/main/java/com/fs/course/controller/qw/QwFsCourseWatchLogController.java

@@ -3,6 +3,7 @@ package com.fs.course.controller.qw;
 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.exception.CustomException;
@@ -16,6 +17,7 @@ import com.fs.course.param.PeriodStatisticCountParam;
 import com.fs.course.service.IFsCourseWatchLogService;
 import com.fs.course.vo.FsCourseOverVO;
 import com.fs.course.vo.FsCourseWatchLogListVO;
+import com.fs.course.vo.FsCourseWatchLogStatisticsListByCompanyVO;
 import com.fs.course.vo.FsCourseWatchLogStatisticsListVO;
 import com.fs.qw.param.QwWatchLogStatisticsListParam;
 import com.fs.qw.service.IQwWatchLogService;
@@ -78,6 +80,17 @@ public class QwFsCourseWatchLogController extends BaseController
         List<FsCourseWatchLogStatisticsListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogStatisticsListVO(param);
         return getDataTable(list);
     }
+
+    @GetMapping("/statisticsListByCompany")
+    public R statisticsListByCompany(FsCourseWatchLogStatisticsListParam param)
+    {
+        if (param.getSTime()==null||param.getETime()==null){
+            return R.ok().put("rows", new ArrayList<>());
+        }
+        param.setSendType(2); //企微
+        List<FsCourseWatchLogStatisticsListByCompanyVO> list = fsCourseWatchLogService.selectFsCourseWatchLogStatisticsListByCompanyVO(param);
+        return R.ok().put("rows", list);
+    }
     @GetMapping("/qwWatchLogStatisticsList")
     public TableDataInfo qwWatchLogStatisticsList(QwWatchLogStatisticsListParam param)
     {

+ 64 - 0
fs-admin/src/main/java/com/fs/course/task/CompanyBalanceTask.java

@@ -0,0 +1,64 @@
+package com.fs.course.task;
+
+import com.fs.company.service.ICompanyService;
+import com.fs.course.service.BalanceRollbackErrorService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+/**
+ * @description: 公司余额同步定时任务
+ * @author: Xgb
+ * @createDate: 2025/10/22
+ * @version: 1.0
+ */
+@Component("companyBalanceTask")
+public class CompanyBalanceTask {
+
+
+    @Autowired
+    private BalanceRollbackErrorService balanceRollbackErrorService;
+
+    @Autowired
+    private ICompanyService companyService;
+
+
+    /**
+     * @Description: 每10分钟从缓存获取余额同步到公司账户中
+     * @Param:
+     * @Return:
+     * @Author xgb
+     * @Date 2025/10/22 10:56
+     */
+    public void syncCompanyBalance() {
+        companyService.syncCompanyBalance();
+    }
+
+    /**
+     * @Description: 定时回滚公司余额数据
+     * @Param:
+     * @Return:
+     * @Author xgb
+     * @Date 2025/10/22 11:48
+     */
+    public void processBatchRollbackByCompanyId() {
+        balanceRollbackErrorService.processBatchRollbackByCompanyId();
+    }
+
+    /**
+     * @Description: spring启动执行 initCompanyBalance 查询余额报存到缓存中
+     * 如果新增公司可以重启admin或者定时配置一下这个方法手动执行一次
+     * @Param:
+     * @Return:
+     * @Author xgb
+     * @Date 2025/10/22 11:52
+     */
+    public void initCompanyBalance() {
+        balanceRollbackErrorService.initCompanyBalance();
+
+    }
+
+
+
+}

+ 17 - 0
fs-admin/src/main/java/com/fs/course/task/CourseStatisticsTask.java

@@ -0,0 +1,17 @@
+package com.fs.course.task;
+
+import com.fs.course.service.IFsUserCourseCompanyStatisticsService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component("courseStatisticsTask")
+public class CourseStatisticsTask {
+    @Autowired
+    private IFsUserCourseCompanyStatisticsService fsUserCourseCompanyStatisticsService;
+
+    public void saveCourseStatisticsTask(Integer status,Integer day) {
+        fsUserCourseCompanyStatisticsService.courseDailyStatisticsTask(status,day);
+
+    }
+
+}

+ 37 - 0
fs-admin/src/main/java/com/fs/course/task/RedPacketLogsTask.java

@@ -0,0 +1,37 @@
+package com.fs.course.task;
+
+import com.fs.course.mapper.FsCourseRedPacketLogMapper;
+import com.fs.course.service.IFsCourseRedPacketLogService;
+import com.fs.course.service.impl.FsCourseRedPacketLogServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+
+/**
+ * @description: 微信红包转账回调部分没有接收到,主动自己去查询
+ * @author: Xgb
+ * @createDate: 2025/10/15
+ * @version: 1.0
+ */
+@Component("redPacketLogsTask")
+public class RedPacketLogsTask {
+
+    @Autowired
+    private IFsCourseRedPacketLogService fsCourseRedPacketLogService;
+
+    /**
+     * @Description: 查询微信红包转账结果 每10分钟查询上一个10分钟区间的红包转账结果
+     * (定时调取失败 可以启动fs-qw-task 中的 CommonController queryRedPacketResult 手动调取) 仅给内部人员使用
+     * @Param:
+     * @Return:
+     * @Author xgb
+     * @Date 2025/10/15 16:32
+     */
+    public void queryRedPacketResult() {
+
+        // 查询RedPacketLog表,
+        fsCourseRedPacketLogService.queryRedPacketResult(null, null);
+    }
+
+}

+ 31 - 0
fs-admin/src/main/java/com/fs/course/task/WatchCourseStatistics.java

@@ -0,0 +1,31 @@
+package com.fs.course.task;
+
+import com.fs.statis.service.IStatisticsService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * @description: 看客相关统计定时任务
+ * @author: Xgb
+ * @createDate: 2025/10/27
+ * @version: 1.0
+ */
+@Component("watchCourseStatistics")
+public class WatchCourseStatistics {
+
+    @Autowired
+    private IStatisticsService statisticsService;
+
+    /**
+     * @Description: 统计统计按TimeType 0-今天,1-昨天,2-本周,3-本月,4-上月;各公司的观看人数和完播人数,
+     * 各公司的观看人数和完播人数, 存到redis中,定时任务每15分钟执行一次
+     *
+     * @Param:
+     * @Return:
+     * @Author xgb
+     * @Date 2025/10/27 11:47
+     */
+    public void watchCourseStatisticsGroupByCompany() {
+        statisticsService.watchCourseStatisticsGroupByCompany();
+    }
+}

+ 15 - 13
fs-admin/src/main/java/com/fs/crm/controller/CrmCustomerController.java

@@ -151,14 +151,14 @@ public class CrmCustomerController extends BaseController
         crmCustomer.setIsLine(0);
         List<CrmCustomerListVO> list = crmCustomerService.selectCrmCustomerListVO(crmCustomer);
         List<CrmCustomerExportVO> exportList=new ArrayList<>();
-        boolean checkPhone = isCheckPhone();
+        SysRole sysRole = isCheckPermission();
         for(CrmCustomerListVO customer:list){
             CrmCustomerExportVO vo=new CrmCustomerExportVO();
             if(customer.getSource()!=null){
                 vo.setSource(customer.getSource().toString());
             }
             BeanUtils.copyProperties(customer,vo);
-            if(customer.getMobile()!=null && !checkPhone){
+            if(customer.getMobile()!=null && !(sysRole.getIsCheckPhone()==1)){
                 vo.setMobile(customer.getMobile().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
             }
             exportList.add(vo);
@@ -197,9 +197,9 @@ public class CrmCustomerController extends BaseController
         }
         List<CrmCustomerListVO> list = crmCustomerService.selectCrmCustomerListQueryParam(crmCustomer);
         if (list != null) {
-            boolean checkPhone = isCheckPhone();
+            SysRole sysRole = isCheckPermission();
             for (CrmCustomerListVO vo : list) {
-                if(vo.getMobile()!=null && !checkPhone){
+                if(vo.getMobile()!=null && !(sysRole.getIsCheckPhone()==1)){
                     vo.setMobile(vo.getMobile().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
                 }
 
@@ -211,19 +211,21 @@ public class CrmCustomerController extends BaseController
 
     @Autowired
     private ISysRoleService sysRoleService;
-    private boolean isCheckPhone() {
+    private SysRole isCheckPermission() {
+        SysRole sysRole = new SysRole();
         SysUser user = getLoginUser().getUser();
         boolean flag = user.isAdmin();
         if (flag) {
-            return true;
-        }
-        List<SysRole> roles = user.getRoles();
-        if (roles != null && !roles.isEmpty()) {
-            Long[] roleIds = roles.stream().map(SysRole::getRoleId).toArray(Long[]::new);
-            return sysRoleService.getIsCheckPhone(roleIds);
+            sysRole.setIsCheckPhone(1);
+            sysRole.setIsCheckAddress(1);
+        } else {
+            List<SysRole> roles = user.getRoles();
+            if (roles != null && !roles.isEmpty()) {
+                Long[] roleIds = roles.stream().map(SysRole::getRoleId).toArray(Long[]::new);
+                return sysRoleService.getIsCheckPermission(roleIds);
+            }
         }
-
-        return false;
+        return sysRole;
     }
 
 

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

@@ -42,7 +42,7 @@ public class FsArticleController extends BaseController
     /**
      * 查询文章列表
      */
-    @PreAuthorize("@ss.hasPermi('his:article:list')")
+    @PreAuthorize("@ss.hasPermi('his:healthArticle:list')")
     @GetMapping("/list")
     public TableDataInfo list(FsArticle fsArticle)
     {
@@ -54,7 +54,7 @@ public class FsArticleController extends BaseController
     /**
      * 导出文章列表
      */
-    @PreAuthorize("@ss.hasPermi('his:article:export')")
+    @PreAuthorize("@ss.hasPermi('his:healthArticle:export')")
     @Log(title = "文章", businessType = BusinessType.EXPORT)
     @GetMapping("/export")
     public AjaxResult export(FsArticle fsArticle)
@@ -67,7 +67,7 @@ public class FsArticleController extends BaseController
     /**
      * 获取文章详细信息
      */
-    @PreAuthorize("@ss.hasPermi('his:article:query')")
+    @PreAuthorize("@ss.hasPermi('his:healthArticle:query')")
     @GetMapping(value = "/{articleId}")
     public AjaxResult getInfo(@PathVariable("articleId") Long articleId)
     {
@@ -77,7 +77,7 @@ public class FsArticleController extends BaseController
     /**
      * 新增文章
      */
-    @PreAuthorize("@ss.hasPermi('his:article:add')")
+    @PreAuthorize("@ss.hasPermi('his:healthArticle:add')")
     @Log(title = "文章", businessType = BusinessType.INSERT)
     @PostMapping
     public AjaxResult add(@RequestBody FsArticle fsArticle)
@@ -94,7 +94,7 @@ public class FsArticleController extends BaseController
     /**
      * 修改文章
      */
-    @PreAuthorize("@ss.hasPermi('his:article:edit')")
+    @PreAuthorize("@ss.hasPermi('his:healthArticle:edit')")
     @Log(title = "文章", businessType = BusinessType.UPDATE)
     @PutMapping
     public AjaxResult edit(@RequestBody FsArticle fsArticle)
@@ -110,7 +110,7 @@ public class FsArticleController extends BaseController
     /**
      * 删除文章
      */
-    @PreAuthorize("@ss.hasPermi('his:article:remove')")
+    @PreAuthorize("@ss.hasPermi('his:healthArticle:remove')")
     @Log(title = "文章", businessType = BusinessType.DELETE)
 	@DeleteMapping("/{articleIds}")
     public AjaxResult remove(@PathVariable Long[] articleIds)

+ 26 - 4
fs-admin/src/main/java/com/fs/his/controller/FsCompanyController.java

@@ -15,11 +15,9 @@ import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyDeduct;
 import com.fs.company.domain.CompanyRecharge;
 import com.fs.company.param.CompanyDeductParam;
+import com.fs.company.param.CompanyDivConfigUpdateParam;
 import com.fs.company.param.CompanyRechargeParam;
-import com.fs.company.service.ICompanyDeductService;
-import com.fs.company.service.ICompanyRechargeService;
-import com.fs.company.service.ICompanyService;
-import com.fs.company.service.ICompanyUserService;
+import com.fs.company.service.*;
 import com.fs.company.vo.CompanyVO;
 import com.fs.core.utils.OrderCodeUtils;
 import com.fs.course.config.CourseConfig;
@@ -70,6 +68,8 @@ public class FsCompanyController extends BaseController
     private ICompanyDeductService deductService;
     @Autowired
     private ISysConfigService configService;
+    @Autowired
+    private ICompanyDivConfigService companyDivConfigService;
     /**
      * 查询诊所管理列表
      */
@@ -241,4 +241,26 @@ public class FsCompanyController extends BaseController
         deductService.insertCompanyDeduct(deduct);
         return R.ok("提交成功,等待审核");
     }
+
+    /**
+     * 获取公司分账配置详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('his:companyDivConfig:query')")
+    @GetMapping(value = "/getDivConfig/{companyId}")
+    public AjaxResult getDivConfig(@PathVariable("companyId") Long companyId)
+    {
+        return AjaxResult.success(companyDivConfigService.selectCompanyDivConfigByCompanyId(companyId));
+    }
+
+    /**
+     * 公司分账配置
+     */
+    @PreAuthorize("@ss.hasPermi('his:companyDivConfig:set')")
+    @Log(title = "公司分账配置", businessType = BusinessType.UPDATE)
+    @PostMapping("/setDiv")
+    public R setDiv(@RequestBody CompanyDivConfigUpdateParam param)
+    {
+        return companyDivConfigService.setDiv(param);
+    }
+
 }

+ 103 - 0
fs-admin/src/main/java/com/fs/his/controller/FsCompanyDivItemController.java

@@ -0,0 +1,103 @@
+package com.fs.his.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.company.domain.CompanyDivItem;
+import com.fs.company.service.ICompanyDivItemService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 分账明细Controller
+ *
+ * @author fs
+ * @date 2025-10-21
+ */
+@RestController
+@RequestMapping("/his/divItem")
+public class FsCompanyDivItemController extends BaseController
+{
+    @Autowired
+    private ICompanyDivItemService companyDivItemService;
+
+    /**
+     * 查询分账明细列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:divItem:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyDivItem companyDivItem)
+    {
+        startPage();
+        List<CompanyDivItem> list = companyDivItemService.selectCompanyDivItemList(companyDivItem);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出分账明细列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:divItem:export')")
+    @Log(title = "分账明细", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyDivItem companyDivItem)
+    {
+        List<CompanyDivItem> list = companyDivItemService.selectCompanyDivItemList(companyDivItem);
+        ExcelUtil<CompanyDivItem> util = new ExcelUtil<CompanyDivItem>(CompanyDivItem.class);
+        return util.exportExcel(list, "分账明细数据");
+    }
+
+    /**
+     * 获取分账明细详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('his:divItem:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(companyDivItemService.selectCompanyDivItemById(id));
+    }
+
+//    /**
+//     * 新增分账明细
+//     */
+//    @PreAuthorize("@ss.hasPermi('his:divItem:add')")
+//    @Log(title = "分账明细", businessType = BusinessType.INSERT)
+//    @PostMapping
+//    public AjaxResult add(@RequestBody CompanyDivItem companyDivItem)
+//    {
+//        return toAjax(companyDivItemService.insertCompanyDivItem(companyDivItem));
+//    }
+//
+//    /**
+//     * 修改分账明细
+//     */
+//    @PreAuthorize("@ss.hasPermi('his:divItem:edit')")
+//    @Log(title = "分账明细", businessType = BusinessType.UPDATE)
+//    @PutMapping
+//    public AjaxResult edit(@RequestBody CompanyDivItem companyDivItem)
+//    {
+//        return toAjax(companyDivItemService.updateCompanyDivItem(companyDivItem));
+//    }
+//
+//    /**
+//     * 删除分账明细
+//     */
+//    @PreAuthorize("@ss.hasPermi('his:divItem:remove')")
+//    @Log(title = "分账明细", businessType = BusinessType.DELETE)
+//	@DeleteMapping("/{ids}")
+//    public AjaxResult remove(@PathVariable Long[] ids)
+//    {
+//        return toAjax(companyDivItemService.deleteCompanyDivItemByIds(ids));
+//    }
+}

+ 103 - 0
fs-admin/src/main/java/com/fs/his/controller/FsDfAccountController.java

@@ -0,0 +1,103 @@
+package com.fs.his.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.his.domain.FsDfAccount;
+import com.fs.his.service.IFsDfAccountService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 代服账户Controller
+ *
+ * @author fs
+ * @date 2025-10-13
+ */
+@RestController
+@RequestMapping("/his/dfAccount")
+public class FsDfAccountController extends BaseController
+{
+    @Autowired
+    private IFsDfAccountService fsDfAccountService;
+
+    /**
+     * 查询代服账户列表
+     */
+
+    @GetMapping("/list")
+    public TableDataInfo list(FsDfAccount fsDfAccount)
+    {
+        startPage();
+        List<FsDfAccount> list = fsDfAccountService.selectFsDfAccountList(fsDfAccount);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出代服账户列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:dfAccount:export')")
+    @Log(title = "代服账户", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsDfAccount fsDfAccount)
+    {
+        List<FsDfAccount> list = fsDfAccountService.selectFsDfAccountList(fsDfAccount);
+        ExcelUtil<FsDfAccount> util = new ExcelUtil<FsDfAccount>(FsDfAccount.class);
+        return util.exportExcel(list, "代服账户数据");
+    }
+
+    /**
+     * 获取代服账户详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('his:dfAccount:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsDfAccountService.selectFsDfAccountById(id));
+    }
+
+    /**
+     * 新增代服账户
+     */
+    @PreAuthorize("@ss.hasPermi('his:dfAccount:add')")
+    @Log(title = "代服账户", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsDfAccount fsDfAccount)
+    {
+        return toAjax(fsDfAccountService.insertFsDfAccount(fsDfAccount));
+    }
+
+    /**
+     * 修改代服账户
+     */
+    @PreAuthorize("@ss.hasPermi('his:dfAccount:edit')")
+    @Log(title = "代服账户", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsDfAccount fsDfAccount)
+    {
+        return toAjax(fsDfAccountService.updateFsDfAccount(fsDfAccount));
+    }
+
+    /**
+     * 删除代服账户
+     */
+    @PreAuthorize("@ss.hasPermi('his:dfAccount:remove')")
+    @Log(title = "代服账户", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsDfAccountService.deleteFsDfAccountByIds(ids));
+    }
+}

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

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

+ 31 - 25
fs-admin/src/main/java/com/fs/his/controller/FsStoreOrderController.java

@@ -122,6 +122,9 @@ public class FsStoreOrderController extends BaseController
 
     @Autowired
     private IFsStoreOrderLogsService fsStoreOrderLogsService;
+
+    @Autowired
+    private IFsDfAccountService fsDfAccountService;
     /**
      * 查询订单列表
      */
@@ -257,8 +260,9 @@ public class FsStoreOrderController extends BaseController
         task.setUserId(SecurityUtils.getUserId());
         exportTaskService.insertFsExportTask(task);
         param.setTaskId(task.getTaskId());
-        boolean checkPhone = isCheckPhone();
-        exportTaskService.exportStore1Data(param,checkPhone, filterList);
+
+        SysRole sysRole = isCheckPermission();
+        exportTaskService.exportStore1Data(param,sysRole.getIsCheckPhone() == 1,sysRole.getIsCheckAddress() == 1, filterList);
 
         return new AjaxResult(200,"后台正在导出,请等待...任务ID:"+task.getTaskId(),task.getTaskId());
 
@@ -267,19 +271,21 @@ public class FsStoreOrderController extends BaseController
 
     @Autowired
     private ISysRoleService sysRoleService;
-    private boolean isCheckPhone() {
+    private SysRole isCheckPermission() {
+        SysRole sysRole = new SysRole();
         SysUser user = getLoginUser().getUser();
         boolean flag = user.isAdmin();
         if (flag) {
-            return true;
-        }
-        List<SysRole> roles = user.getRoles();
-        if (roles != null && !roles.isEmpty()) {
-            Long[] roleIds = roles.stream().map(SysRole::getRoleId).toArray(Long[]::new);
-            return sysRoleService.getIsCheckPhone(roleIds);
+            sysRole.setIsCheckPhone(1);
+            sysRole.setIsCheckAddress(1);
+        } else {
+            List<SysRole> roles = user.getRoles();
+            if (roles != null && !roles.isEmpty()) {
+                Long[] roleIds = roles.stream().map(SysRole::getRoleId).toArray(Long[]::new);
+                return sysRoleService.getIsCheckPermission(roleIds);
+            }
         }
-
-        return false;
+        return sysRole;
     }
 
     @GetMapping("/importTemplate")
@@ -764,19 +770,16 @@ public class FsStoreOrderController extends BaseController
 
     private FsStoreOrderDf getDFInfo(String loginAccount) {
         //查询订单账户 判断是否存在该订单账户
-        List<DFConfigVo> erpAccounts = fsStoreOrderService.getErpAccount();
+        FsDfAccount erpAccount = fsDfAccountService.selectFsDfAccountByAccount(loginAccount);
         FsStoreOrderDf df = new FsStoreOrderDf();
-        for (DFConfigVo erpAccount : erpAccounts) {
-            if (loginAccount.equals(erpAccount.getLoginAccount())){
-                //添加df记录
-                df.setAppKey(erpAccount.getDfAppKey());
-                df.setAppSecret(erpAccount.getDfAppsecret());
-                df.setLoginAccount(loginAccount);
-                df.setMonthlyCard(erpAccount.getMonthlyCard());
-                df.setExpressProductCode(erpAccount.getExpressProductCode());
-                df.setStatus(0);
-                break;
-            }
+        if (erpAccount != null){
+            //添加df记录
+            df.setAppKey(erpAccount.getDfAppKey());
+            df.setAppSecret(erpAccount.getDfAppsecret());
+            df.setLoginAccount(loginAccount);
+            df.setMonthlyCard(erpAccount.getMonthlyCard());
+            df.setExpressProductCode(erpAccount.getExpressProductCode());
+            df.setStatus(0);
         }
         return df;
     }
@@ -954,8 +957,11 @@ public class FsStoreOrderController extends BaseController
     @GetMapping("/getErpAccount")
     public R getErpAccount()
     {
-        List<DFConfigVo> erpAccounts = fsStoreOrderService.getErpAccount();
-        List<String> list = erpAccounts.stream().map(DFConfigVo::getLoginAccount).collect(Collectors.toList());
+        List<String> list = new ArrayList<>();
+        if (CloudHostUtils.hasCloudHostName("金牛明医","康年堂")){
+                List<FsDfAccount> erpAccounts = fsDfAccountService.selectFsDfAccountList(null);
+                list = erpAccounts.stream().map(FsDfAccount::getLoginAccount).collect(Collectors.toList());
+        }
         return R.ok().put("data", list);
     }
 }

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

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

+ 26 - 41
fs-admin/src/main/java/com/fs/his/controller/FsUserController.java

@@ -4,7 +4,7 @@ import java.util.*;
 import java.util.stream.Collectors;
 
 import com.alibaba.fastjson.JSON;
-import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.core.domain.entity.SysRole;
@@ -13,9 +13,10 @@ import com.fs.common.exception.CustomException;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.SecurityUtils;
 import com.fs.common.utils.StringUtils;
-import com.fs.course.domain.FsUserWatchStatistics;
-import com.fs.course.mapper.FsUserWatchStatisticsMapper;
+import com.fs.course.dto.BatchSendCourseDTO;
+import com.fs.course.param.FsCourseLinkCreateParam;
 import com.fs.course.service.IFsUserCompanyUserService;
+import com.fs.course.service.IFsUserCourseService;
 import com.fs.his.domain.FsUserAddress;
 import com.fs.his.enums.FsUserIntegralLogTypeEnum;
 import com.fs.his.mapper.FsUserMapper;
@@ -27,6 +28,8 @@ import com.fs.his.utils.PhoneUtil;
 import com.fs.his.vo.FsUserExportListVO;
 import com.fs.his.vo.FsUserVO;
 import com.fs.his.vo.UserVo;
+import com.fs.im.dto.OpenImResponseDTO;
+import com.fs.im.service.OpenIMService;
 import com.fs.qw.dto.UserProjectDTO;
 import com.fs.store.param.h5.FsUserPageListParam;
 import com.fs.store.vo.h5.FsUserPageListVO;
@@ -39,6 +42,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.ibatis.session.ExecutorType;
 import org.apache.ibatis.session.SqlSession;
 import org.apache.ibatis.session.SqlSessionFactory;
+import org.springframework.beans.BeanUtils;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -97,10 +101,10 @@ public class FsUserController extends BaseController
             fsUser.setPhone(encryptPhone(fsUser.getPhone()));
         }
         List<FsUserVO> list = fsUserService.selectFsUserListVO(fsUser);
-        boolean checkPhone = isCheckPhone();
+        SysRole sysRole = isCheckPermission();
         for (FsUserVO fsUserVO : list) {
             if(fsUserVO.getPhone() != null&&fsUserVO.getPhone()!=""){
-                if (!checkPhone){
+                if (!(sysRole.getIsCheckPhone()==1)){
                     if (fsUserVO.getPhone().length()>11){
                         fsUserVO.setPhone(decryptPhoneMk(fsUserVO.getPhone()));
                     }else {
@@ -119,19 +123,21 @@ public class FsUserController extends BaseController
 
     @Autowired
     private ISysRoleService sysRoleService;
-    private boolean isCheckPhone() {
+    private SysRole isCheckPermission() {
+        SysRole sysRole = new SysRole();
         SysUser user = getLoginUser().getUser();
         boolean flag = user.isAdmin();
         if (flag) {
-            return true;
-        }
-        List<SysRole> roles = user.getRoles();
-        if (roles != null && !roles.isEmpty()) {
-            Long[] roleIds = roles.stream().map(SysRole::getRoleId).toArray(Long[]::new);
-            return sysRoleService.getIsCheckPhone(roleIds);
+            sysRole.setIsCheckPhone(1);
+            sysRole.setIsCheckAddress(1);
+        } else {
+            List<SysRole> roles = user.getRoles();
+            if (roles != null && !roles.isEmpty()) {
+                Long[] roleIds = roles.stream().map(SysRole::getRoleId).toArray(Long[]::new);
+                return sysRoleService.getIsCheckPermission(roleIds);
+            }
         }
-
-        return false;
+        return sysRole;
     }
 
     @PreAuthorize("@ss.hasPermi('his:user:list')")
@@ -143,10 +149,10 @@ public class FsUserController extends BaseController
             fsUser.setPhone(encryptPhone(fsUser.getPhone()));
         }
         List<FsUserVO> list = fsUserService.selectFsUserVOListByProject(fsUser);
-        boolean checkPhone = isCheckPhone();
+        SysRole sysRole = isCheckPermission();
         for (FsUserVO fsUserVO : list) {
             if(fsUserVO.getPhone() != null&&fsUserVO.getPhone()!=""){
-                if (!checkPhone){
+                if (!(sysRole.getIsCheckPhone()==1)){
                     if (fsUserVO.getPhone().length()>11){
                         fsUserVO.setPhone(decryptPhoneMk(fsUserVO.getPhone()));
                     }else {
@@ -170,10 +176,10 @@ public class FsUserController extends BaseController
             fsUser.setPhone(encryptPhone(fsUser.getPhone()));
         }
         List<FsUserVO> list = fsUserService.selectFsUserVOListByProject(fsUser);
-        boolean checkPhone = isCheckPhone();
+        SysRole sysRole = isCheckPermission();
         for (FsUserVO fsUserVO : list) {
             if(fsUserVO.getPhone() != null&&fsUserVO.getPhone()!=""){
-                if (!checkPhone){
+                if (!(sysRole.getIsCheckPhone()==1)){
                     if (fsUserVO.getPhone().length()>11){
                         fsUserVO.setPhone(decryptPhoneMk(fsUserVO.getPhone()));
                     }else {
@@ -207,9 +213,9 @@ public class FsUserController extends BaseController
             return AjaxResult.error("导出数据不可超过1w条");
         }
         List<FsUserExportListVO> list = fsUserService.selectFsUserExportListVO(fsUser);
-        boolean checkPhone = isCheckPhone();
+        SysRole sysRole = isCheckPermission();
         for (FsUserExportListVO vo : list) {
-            if (vo.getMobile()!=null && !checkPhone){
+            if (vo.getMobile()!=null && !(sysRole.getIsCheckPhone()==1)){
                 vo.setMobile(vo.getMobile().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
             } else {
                 if (vo.getMobile().length()>11){
@@ -384,26 +390,5 @@ public class FsUserController extends BaseController
         return userIntegralLogsService.addIntegralTemplate(integralTemplateParam);
     }
 
-//    @PutMapping("/encryptPhoneTemp")
-//    @ApiOperation("临时接口")
-//    public void encryptPhoneTemp(){
-//        FsUser fsUser = new FsUser();
-//        List<FsUser> list = fsUserService.selectFsUserList(fsUser);
-//        List<FsUser> fsUserList = list.stream().peek(v -> v.setPhone(encryptPhone(v.getPhone()))).collect(Collectors.toList());
-//
-//        // 分批次处理,一次提交500条
-//        List<List<FsUser>> batches = Lists.partition(fsUserList, 500);
-//        batches.forEach(batch -> {
-//            SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
-//            try {
-//                FsUserMapper mapper = sqlSession.getMapper(FsUserMapper.class);
-//                batch.forEach(mapper::updateFsUser);
-//                sqlSession.commit();
-//            } finally {
-//                sqlSession.close();
-//            }
-//        });
-//
-//    }
 
 }

+ 48 - 0
fs-admin/src/main/java/com/fs/his/controller/HzOMSErpApiController.java

@@ -8,6 +8,7 @@ import com.fs.his.param.HzOMSErpApiParam;
 import com.fs.his.service.ErpApiService;
 import com.fs.his.service.IFsStoreOrderService;
 import com.fs.his.vo.HzOMSErpResponseVO;
+import com.fs.hisStore.service.IFsStoreOrderScrmService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.IOUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -40,6 +41,9 @@ public class HzOMSErpApiController {
     @Autowired
     private IFsStoreOrderService fsStoreOrderService;
 
+    @Autowired
+    private IFsStoreOrderScrmService fsStoreOrderScrmService;
+
     /**
      * 用于将瀚智商品库存同步到第三方
      *
@@ -169,4 +173,48 @@ public class HzOMSErpApiController {
                 ? fsStoreOrderService.receiveWaybillPush(body)
                 : R.ok();
     }
+
+    /**
+     * 代服管家订单回调
+     */
+    @PostMapping("/dfNotifyUrlScrm")
+    public R dfOrderScrmResult(HttpServletRequest request){
+        String body = null;
+        try {
+            // 1. 先设置编码
+            request.setCharacterEncoding("UTF-8");
+            // 3. 按 UTF-8 解码
+            body = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);
+        } catch (IOException e) {
+            log.error("读取 body 失败", e);
+            return null;
+        }
+        log.info("Body UTF-8: {}", body);
+
+        return StringUtils.isNotBlank(body)
+                ? fsStoreOrderScrmService.dfOrderResult(body)
+                : R.ok();
+    }
+
+    /**
+     * 代服管家订单状态回调
+     */
+    @PostMapping("/receiveWaybillPushScrm")
+    public R receiveWaybillPushScrm(HttpServletRequest request) {
+        String body = null;
+        try {
+            // 1. 先设置编码
+            request.setCharacterEncoding("UTF-8");
+            // 3. 按 UTF-8 解码
+            body = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);
+        } catch (IOException e) {
+            log.error("读取 body 失败", e);
+            return null;
+        }
+        log.info("Body UTF-8: {}", body);
+
+        return StringUtils.isNotBlank(body)
+                ? fsStoreOrderScrmService.receiveWaybillPush(body)
+                : R.ok();
+    }
 }

+ 345 - 148
fs-admin/src/main/java/com/fs/his/task/Task.java

@@ -15,6 +15,7 @@ import com.fs.company.service.ICompanyService;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.company.vo.QwIpadTotalVo;
 import com.fs.company.vo.RedPacketMoneyVO;
+import com.fs.course.dto.BatchSendCourseAllDTO;
 import com.fs.course.mapper.FsCourseRedPacketLogMapper;
 import com.fs.course.service.IFsCourseWatchLogService;
 import com.fs.course.service.ITencentCloudCosService;
@@ -28,9 +29,15 @@ import com.fs.erp.dto.ErpOrderResponse;
 import com.fs.erp.mapper.FsErpFinishPushMapper;
 import com.fs.erp.service.IErpOrderService;
 import com.fs.fastGpt.domain.FastGptEventTokenLog;
+import com.fs.fastGpt.domain.FastGptPushTokenTotal;
+import com.fs.fastGpt.domain.FastgptChatVoiceHomo;
 import com.fs.fastGpt.domain.FastgptEventLogTotal;
 import com.fs.fastGpt.mapper.FastGptChatSessionMapper;
+import com.fs.fastGpt.mapper.FastgptChatVoiceHomoMapper;
 import com.fs.fastGpt.service.IFastgptEventLogTotalService;
+import com.fs.fastgptApi.util.AudioUtils;
+import com.fs.fastgptApi.vo.AudioVO;
+import com.fs.gtPush.mapper.PushLogMapper;
 import com.fs.his.config.FsSysConfig;
 import com.fs.his.config.StoreConfig;
 import com.fs.his.domain.FsInquiryOrder;
@@ -46,11 +53,16 @@ import com.fs.his.service.*;
 import com.fs.his.service.impl.FsPackageOrderServiceImpl;
 import com.fs.his.utils.ConfigUtil;
 import com.fs.his.vo.FsSubOrderResultVO;
+import com.fs.hisStore.domain.FsStoreOrderScrm;
 import com.fs.im.dto.*;
 import com.fs.im.service.IImService;
+import com.fs.im.service.OpenIMService;
 import com.fs.qw.domain.QwCompany;
+import com.fs.qw.mapper.QwRestrictionPushRecordMapper;
 import com.fs.qw.service.*;
 import com.fs.qwApi.service.QwApiService;
+import com.fs.sop.domain.QwSopTempVoice;
+import com.fs.sop.service.IQwSopTempVoiceService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import com.google.gson.Gson;
@@ -59,10 +71,14 @@ import org.apache.commons.lang3.StringUtils;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Component;
 
+import java.time.LocalDate;
+import java.time.LocalDateTime;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
 
 @Slf4j
 @Component("task")
@@ -85,7 +101,7 @@ public class Task {
     private IFsFollowService fsFollowService;
     @Autowired
     private IFsStoreAfterSalesService fsStoreAfterSalesService;
-//    @Autowired
+    //    @Autowired
 //    IErpOrderService erpOrderService;
     @Autowired
     FsIntegralOrderMapper integralOrderMapper;
@@ -126,7 +142,7 @@ public class Task {
     FsPackageOrderServiceImpl packageOrderService;
     @Autowired
     private IFsStoreOrderLogsService fsStoreOrderLogsService;
-    org.slf4j.Logger logger= LoggerFactory.getLogger(getClass());
+    org.slf4j.Logger logger = LoggerFactory.getLogger(getClass());
     @Autowired
     IFsDoctorService doctorService;
     @Autowired
@@ -158,6 +174,10 @@ public class Task {
     private IQwCompanyService qwCompanyService;
     @Autowired
     private IQwUserService qwUserService;
+    @Autowired
+    private OpenIMService openIMService;
+    @Autowired
+    public RedisTemplate redisTemplate;
 
     @Autowired
     private ICompanyUserService userService;
@@ -165,6 +185,97 @@ public class Task {
     @Autowired
     private IFastgptEventLogTotalService fastgptEventLogTotalService;
 
+    @Autowired
+    private FastgptChatVoiceHomoMapper fastgptChatVoiceHomoMapper;
+    @Autowired
+    private IQwSopTempVoiceService qwSopTempVoiceService;
+
+    @Autowired
+    private QwRestrictionPushRecordMapper qwRestrictionPushRecordMapper;
+
+    public static final String SOP_TEMP_VOICE_KEY = "sop:tempVoice";
+
+    /**
+     * sop任务token消耗统计
+     */
+    public void sopPushTokenTotal() {
+        // 判断是否是凌晨 00:00 - 00:59
+        boolean isEarlyMorning = isEarlyMorning();
+
+        // 获取日期字符串(今天或昨天)
+        String dateTime;
+        if (isEarlyMorning) {
+            dateTime = DateUtils.addDateDays(-1); // 昨天
+        } else {
+            dateTime = DateUtils.getDate(); // 今天
+        }
+        log.info("开始执行sop任务token消耗统计");
+        try {
+            List<FastGptPushTokenTotal> fastGptPushTotalList = qwRestrictionPushRecordMapper.selectFastgptPushTokenTotal(dateTime);
+            if (fastGptPushTotalList != null && !fastGptPushTotalList.isEmpty()) {
+                for (FastGptPushTokenTotal fastGptPushTotal : fastGptPushTotalList) {
+                    // 获取统计数据
+                    Integer type = fastGptPushTotal.getType();
+                    Long count = 0L;
+                    if(type == 7){
+                        count = fastGptPushTotal.getCount() * 450;
+                    }else{
+                        count = fastGptPushTotal.getCount() * 150;
+                    }
+                    fastGptPushTotal.setCount(count);
+                    FastGptPushTokenTotal pushTotal = qwRestrictionPushRecordMapper.selectFastGptPushTokenTotalByInfo(fastGptPushTotal);
+                    if(pushTotal == null){
+                        qwRestrictionPushRecordMapper.insertPushTokenTotal(fastGptPushTotal);
+                    }else{
+                        fastGptPushTotal.setId(pushTotal.getId());
+                        qwRestrictionPushRecordMapper.updatePushTokenTotal(fastGptPushTotal);
+                    }
+                }
+            }
+            log.info("结束执行sop任务token消耗统计");
+        } catch (Exception e) {
+            log.error("执行sop任务token消耗统计异常", e);
+        }
+    }
+
+    /**
+     * 一键生成语音定时任务
+     */
+    public void ConsumerSopTempVoice() {
+        try {
+            Long newCompanyUserId = redisCache.popVoiceKey(SOP_TEMP_VOICE_KEY);
+            if (newCompanyUserId != null) {
+                List<QwSopTempVoice> sopTempVoices = redisCache.getVoiceAllList(SOP_TEMP_VOICE_KEY + ":" + newCompanyUserId);
+                if (sopTempVoices != null && !sopTempVoices.isEmpty()) {
+                    try {
+                        for (QwSopTempVoice qwSopTempVoice : sopTempVoices) {
+                            try {
+                                AudioVO audioVO = new AudioVO();
+                                List<FastgptChatVoiceHomo> homos = fastgptChatVoiceHomoMapper.selectFastgptChatVoiceHomoList(new FastgptChatVoiceHomo());
+                                audioVO = AudioUtils.createUserUrlAndUrl(homos, qwSopTempVoice.getCompanyUserId(), qwSopTempVoice.getVoiceTxt());
+                                if (audioVO != null && audioVO.getWavUrl() != null && audioVO.getUrl() != null) {
+                                    qwSopTempVoice.setVoiceUrl(audioVO.getUrl());
+                                    qwSopTempVoice.setUserVoiceUrl(audioVO.getWavUrl());
+                                    qwSopTempVoice.setDuration(audioVO.getDuration());
+                                    qwSopTempVoice.setRecordType(1);
+                                    qwSopTempVoiceService.updateQwSopTempVoice(qwSopTempVoice);
+                                }
+                            } catch (Exception e) {
+
+                            }
+                        }
+                    } finally {
+                        redisCache.deleteObject(SOP_TEMP_VOICE_KEY + ":" + newCompanyUserId);
+                    }
+                }
+            } else {
+                log.info("没有需要生成的语音");
+            }
+        } catch (Exception e) {
+            log.error("生成语音定时任务执行异常", e);
+        }
+    }
+
     //统计ai事件埋点
     public void eventLogTotals() {
         // 判断是否是凌晨 00:00 - 00:59
@@ -229,7 +340,7 @@ public class Task {
                         FastgptEventLogTotal eventLogTotal = new FastgptEventLogTotal();
                         eventLogTotal.setId(info.getId());
                         eventLogTotal.setCount(newCount);
-                        if(!processedKeys.contains(uniqueKey)) {
+                        if (!processedKeys.contains(uniqueKey)) {
                             toUpdateList.add(eventLogTotal);
                             // 标记为已处理
                             processedKeys.add(uniqueKey);
@@ -237,7 +348,7 @@ public class Task {
                     }
                 } else {
                     total.setStatTime(dateTime);
-                    if(!processedKeys.contains(uniqueKey)) {
+                    if (!processedKeys.contains(uniqueKey)) {
                         toInsertList.add(total);
                         // 标记为已处理
                         processedKeys.add(uniqueKey);
@@ -340,7 +451,7 @@ public class Task {
                         FastgptEventLogTotal eventLogTotalNew = new FastgptEventLogTotal();
                         eventLogTotalNew.setId(info.getId());
                         eventLogTotalNew.setCount(totalCount);
-                        if(!processedKeys.contains(uniqueKey)){
+                        if (!processedKeys.contains(uniqueKey)) {
                             toUpdateList.add(eventLogTotalNew);
                             // 标记为已处理
                             processedKeys.add(uniqueKey);
@@ -357,7 +468,7 @@ public class Task {
                     eventLogTotal.setQwUserId(tokenLog.getQwUserId());
                     eventLogTotal.setStatTime(dateTime);
 
-                    if(!processedKeys.contains(uniqueKey)) {
+                    if (!processedKeys.contains(uniqueKey)) {
                         toInsertList.add(eventLogTotal);
                         // 标记为已处理
                         processedKeys.add(uniqueKey);
@@ -383,23 +494,23 @@ public class Task {
 
 
     //定时查询ipad主机使用情况,建议每天凌晨1点执行一次
-    public void totalIpadTask(){
+    public void totalIpadTask() {
         String dateTime = DateUtils.addDateDays(-1); // 昨天
         List<QwIpadTotalVo> qwIpadTotalVos = userService.selectCompanyByIpadStatusCount();
-        if(qwIpadTotalVos != null && !qwIpadTotalVos.isEmpty()){
+        if (qwIpadTotalVos != null && !qwIpadTotalVos.isEmpty()) {
             qwIpadTotalVos.forEach(qwIpadTotalVo ->
                     qwIpadTotalVo.setStatTime(dateTime)
             );
             int a = userService.insertQwIpadTotal(qwIpadTotalVos);
-            if(a == 0){
+            if (a == 0) {
                 log.error("插入ipad主机失败");
             }
-        }else{
+        } else {
             log.error("查询没有数据");
         }
     }
 
-    public void addQwUserName(){
+    public void addQwUserName() {
         QwCompany qwCompany = new QwCompany();
         List<QwCompany> companyList = qwCompanyService.selectQwCompanyList(qwCompany);
         for (QwCompany company : companyList) {
@@ -407,50 +518,56 @@ public class Task {
         }
     }
 
-    public void videoTranscode() throws Exception
-    {
+    public void videoTranscode() throws Exception {
 
         tencentCloudCosService.videoTranscode();
     }
 
-    public void updateUrl() throws Exception
-    {
+    public void updateUrl() throws Exception {
 
         tencentCloudCosService.updateUrl();
     }
-    public void addPrescribeImg() throws Exception
-    {
-       List<Long> ids= fsPrescribeService.selectFsPrescribeByPrescribeIdByOrderType();
+
+    public void addPrescribeImg() throws Exception {
+        List<Long> ids = fsPrescribeService.selectFsPrescribeByPrescribeIdByOrderType();
         for (Long id : ids) {
             System.out.println(id);
             fsPrescribeService.PrescribeStoreImg(id);
         }
     }
 
-    public void addQwWatchLog() throws Exception
-    {
+    public void addQwWatchLog() throws Exception {
+        LocalDateTime now = LocalDateTime.now().withSecond(0);
         fsCourseWatchLogService.addCourseWatchLogDay();
     }
 
 
-    public void transferLog() throws Exception
-    {
+    public void addQwWatchLogMinute(Integer minute) throws Exception{
+        log.info("定时更新看课111");
+        if(minute == null) minute = 30;
+        LocalDateTime now = LocalDateTime.now().withSecond(0);
+        LocalDateTime start = now.minusMinutes(minute);
+        LocalDateTime end = now.minusSeconds(1);
+        fsCourseWatchLogService.addCourseWatchLogDayMinute(start, end);
+    }
+
+    public void transferLog() throws Exception {
         qwExternalContactTransferLogService.updateQwExternalContactTransferLogByStatus();
 
 
     }
 
-    public void isArtificial() throws Exception
-    {
+    public void isArtificial() throws Exception {
         fastGptChatSessionMapper.updateFastGptChatSessionByIsReply();
 
     }
-    public void expirationQwAppCountWay(){
+
+    public void expirationQwAppCountWay() {
         qwAppContactWayService.expirationQwAppCountWay();
 
     }
-    public void sendOrderMsg() throws Exception
-    {
+
+    public void sendOrderMsg() throws Exception {
         List<FsStoreOrder> fsStoreOrders = fsStoreOrderMapper.selectStoreOrderIdByFollow();
         for (FsStoreOrder fsStoreOrder : fsStoreOrders) {
 
@@ -458,72 +575,97 @@ public class Task {
         }
 
     }
-    public void redPacketSubMoney() throws Exception
-    {
+
+    public void redPacketSubMoney() throws Exception {
         List<RedPacketMoneyVO> redPacketMoneyVOS = fsCourseRedPacketLogMapper.selectFsCourseRedPacketLogByCompany();
         for (RedPacketMoneyVO redPacketMoneyVO : redPacketMoneyVOS) {
-            companyService.subtractCompanyMoney(redPacketMoneyVO.getMoney(),redPacketMoneyVO.getCompanyId());
+            companyService.subtractCompanyMoney(redPacketMoneyVO.getMoney(), redPacketMoneyVO.getCompanyId());
         }
     }
 
 
-    public void redPacketAddMoney() throws Exception
-    {
+    public void redPacketAddMoney() throws Exception {
         List<RedPacketMoneyVO> redPacketMoneyVOS = fsCourseRedPacketLogMapper.selectFsCourseAddRedPacketLogByCompany();
         for (RedPacketMoneyVO redPacketMoneyVO : redPacketMoneyVOS) {
-            companyService.addRedPacketCompanyMoney(redPacketMoneyVO.getMoney(),redPacketMoneyVO.getCompanyId());
+            companyService.addRedPacketCompanyMoney(redPacketMoneyVO.getMoney(), redPacketMoneyVO.getCompanyId());
         }
     }
 
-    public void updateCompanyUserStatus()
-    {
+    public void updateCompanyUserStatus() {
         CompanyUser user = new CompanyUser();
         user.setStatus("0");
         user.setDelFlag("0");
         List<CompanyUser> companyUsers = companyUserMapper.selectCompanyUserList(user);
         for (CompanyUser companyUser : companyUsers) {
-            if(SecurityUtils.matchesPassword("123456", companyUser.getPassword())){
+            if (SecurityUtils.matchesPassword("123456", companyUser.getPassword())) {
                 companyUser.setStatus("1");
                 companyUserMapper.updateCompanyUser(companyUser);
-                logger.info("密码为123456 停用账号:"+companyUser.getUserId()+":"+companyUser.getNickName());
+                logger.info("密码为123456 停用账号:" + companyUser.getUserId() + ":" + companyUser.getNickName());
             }
         }
     }
-    public void couponStatus()
-    {
+
+    public void couponStatus() {
         fsUserCouponMapper.updateFsUserCouponStatusByLimtTime();
     }
 
     //每10秒执行一次
-    public void auditPrescribe()
-    {
+    public void auditPrescribe() {
         SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.inquiryConfig");
         String configValue = sysConfig.getConfigValue();
         Map<String, Object> config = (Map<String, Object>) JSON.parse(configValue);
-        boolean isAudit = (boolean)config.get("isAutoPrescribeAudit");
-        if (isAudit){
+        boolean isAudit = (boolean) config.get("isAutoPrescribeAudit");
+        if (isAudit) {
             fsPrescribeService.auditPrescribe();
         }
     }
 
-    public void deliveryOp()
-    {
+    public void deliveryOp() {
         IErpOrderService erpOrderService = getErpService();
         List<FsStoreOrder> orders = null;
-        if (erpOrderService == gyOrderService){
+        if (erpOrderService == gyOrderService) {
             orders = fsStoreOrderMapper.selectOmsOrderdeliveryOp();
-        } else if (erpOrderService == wdtOrderService || erpOrderService == dfOrderService || erpOrderService == jSTOrderService){
+        } else if (erpOrderService == wdtOrderService || erpOrderService == dfOrderService || erpOrderService == jSTOrderService) {
             orders = fsStoreOrderMapper.selectWdtOmsOrderdeliveryOp();
         }
-
-
         for(FsStoreOrder order:orders){
-
             ErpOrderQueryRequert request=new ErpOrderQueryRequert();
+            request.setCode(order.getExtendOrderId());
+            if (erpOrderService != null) {
+                ErpOrderQueryResponse response = erpOrderService.getOrder(request);
+                if (erpOrderService != dfOrderService) {
+                    if (response.getOrders() != null && response.getOrders().size() > 0) {
+                        for (ErpOrderQuery orderQuery : response.getOrders()) {
+                            if (orderQuery.getDeliverys() != null && orderQuery.getDeliverys().size() > 0) {
+                                for (ErpDeliverys delivery : orderQuery.getDeliverys()) {
+                                    if (delivery.getDelivery() && StringUtils.isNotEmpty(delivery.getMail_no())) {
+                                        //更新商订单状态 删除REDIS
+                                        fsStoreOrderService.deliveryOrder(order.getOrderCode(), delivery.getMail_no(), delivery.getExpress_code(), delivery.getExpress_name());
+                                        redisCache.deleteObject("delivery" + ":" + order.getExtendOrderId());
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
 
+    public void deliveryOpScrm()
+    {
+        IErpOrderService erpOrderService = getErpService();
+        List<FsStoreOrderScrm> orders = null;
+        if (erpOrderService == gyOrderService){
+            orders = fsStoreOrderMapper.selectOmsOrderdeliveryOpScrm();
+        } else if (erpOrderService == wdtOrderService || erpOrderService == dfOrderService || erpOrderService == jSTOrderService){
+            orders = fsStoreOrderMapper.selectWdtOmsOrderdeliveryOpScrm();
+        }
+        for(FsStoreOrderScrm order:orders){
+            ErpOrderQueryRequert request=new ErpOrderQueryRequert();
             request.setCode(order.getExtendOrderId());
             if (erpOrderService != null){
-                ErpOrderQueryResponse response=erpOrderService.getOrder(request);
+                ErpOrderQueryResponse response=erpOrderService.getScrmOrder(request);
                 if (erpOrderService != dfOrderService){
                     if(response.getOrders()!=null&&response.getOrders().size()>0){
                         for(ErpOrderQuery orderQuery : response.getOrders()){
@@ -531,21 +673,18 @@ public class Task {
                                 for(ErpDeliverys delivery:orderQuery.getDeliverys()){
                                     if(delivery.getDelivery()&& StringUtils.isNotEmpty(delivery.getMail_no())){
                                         //更新商订单状态 删除REDIS
-                                        fsStoreOrderService.deliveryOrder(order.getOrderCode(),delivery.getMail_no(),delivery.getExpress_code(),delivery.getExpress_name());
+                                        fsStoreOrderService.deliveryOrderScrm(order.getOrderCode(),delivery.getMail_no(),delivery.getExpress_code(),delivery.getExpress_name());
                                         redisCache.deleteObject("delivery"+":"+order.getExtendOrderId());
                                     }
                                 }
-
                             }
                         }
                     }
                 }
             }
-
         }
 
 
-
     }
 
 
@@ -553,11 +692,11 @@ public class Task {
     {
         IErpOrderService erpOrderService = getErpService();
         List<FsStoreOrder> orders = null;
-        if (erpOrderService !=null && erpOrderService == dfOrderService){
+        if (erpOrderService != null && erpOrderService == dfOrderService) {
             orders = fsStoreOrderMapper.selectShippedOrder();
-            if(orders!=null&& !orders.isEmpty()){
+            if (orders != null && !orders.isEmpty()) {
                 List<CompletableFuture<Void>> futures = new ArrayList<>();
-                for(FsStoreOrder order:orders){
+                for (FsStoreOrder order : orders) {
                     CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                         erpOrderService.getOrderDeliveryStatus(order);
                     });
@@ -568,15 +707,14 @@ public class Task {
         }
     }
 
-    public void CreateOmsAndHis()
-    {
+    public void CreateOmsAndHis() {
         List<Long> omsList = fsStoreOrderMapper.selectFsStoreOrderNoCreateOms();
-        logger.info("推送订单id====>{}",omsList);
+        logger.info("推送订单id====>{}", omsList);
         for (Long l : omsList) {
             try {
                 fsStoreOrderService.createOmsOrder(l);
             } catch (Exception e) {
-                logger.error("推送订单异常:",e);
+                logger.error("推送订单异常:", e);
             }
         }
 //        List<Long> tuiOrderList = fsStoreOrderMapper.selectFsStoreOrderNoTuiOrder();
@@ -589,31 +727,30 @@ public class Task {
 //        }
     }
 
-    public void createFollow()
-    {
+    public void createFollow() {
         List<FsStoreOrder> orders = fsStoreOrderMapper.selectStoreOrderIdByFollow();
         for (FsStoreOrder order : orders) {
             try {
 
                 fsStoreOrderService.addFsFollowByStoreOrder(order);
-            }catch (Exception e){
-                logger.info("创建随访错误:"+order);
+            } catch (Exception e) {
+                logger.info("创建随访错误:" + order);
             }
         }
     }
+
     @Autowired
     IFsStoreSubOrderService fsStoreSubOrderService;
 
 
-    public void puSubStoreOrder()
-    {
+    public void puSubStoreOrder() {
         List<Long> longs = fsStoreSubOrderService.selectFsStoreSubOrderByNoPush();
-        int i=0;
+        int i = 0;
         for (Long aLong : longs) {
             FsSubOrderResultVO fsSubOrderResultVO = fsStoreSubOrderService.TuiFsStoreSubOrderByStoreOrder(aLong);
-            if (fsSubOrderResultVO!=null&&fsSubOrderResultVO.getCode()!=null&&fsSubOrderResultVO.getCode()==1){
+            if (fsSubOrderResultVO != null && fsSubOrderResultVO.getCode() != null && fsSubOrderResultVO.getCode() == 1) {
                 i++;
-                if (i>65){
+                if (i > 65) {
                     return;
                 }
             }
@@ -621,14 +758,13 @@ public class Task {
         }
     }
 
-    public void refundOp()
-    {
-        List<FsStoreAfterSales> list=fsStoreAfterSalesService.selectFsStoreAfterSalesByDoAudit();
-        if(list!=null){
-            for(FsStoreAfterSales afterSales:list){
+    public void refundOp() {
+        List<FsStoreAfterSales> list = fsStoreAfterSalesService.selectFsStoreAfterSalesByDoAudit();
+        if (list != null) {
+            for (FsStoreAfterSales afterSales : list) {
                 try {
                     fsStoreAfterSalesService.auditing(afterSales);
-                }catch (Exception e){
+                } catch (Exception e) {
 
                 }
 
@@ -636,16 +772,17 @@ public class Task {
         }
 
     }
+
     public void isAfterSales() {
         SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.store");
         String configValue = sysConfig.getConfigValue();
         Map<String, Object> config = (Map<String, Object>) JSON.parse(configValue);
-        Integer storeAfterSalesDay = (Integer)config.get("storeAfterSalesDay");
+        Integer storeAfterSalesDay = (Integer) config.get("storeAfterSalesDay");
         List<FsStoreOrder> fsStoreOrders = fsStoreOrderMapper.selectFsStoreOrderNoIsAfterSales(storeAfterSalesDay);
         for (FsStoreOrder fsStoreOrder : fsStoreOrders) {
             try {
                 fsStoreOrderService.addIntegralAndShareByStoreOrder(fsStoreOrder);
-            }catch (Exception e) {
+            } catch (Exception e) {
                 logger.info("分账错误: " + fsStoreOrder.getOrderCode());
             }
         }
@@ -653,26 +790,25 @@ public class Task {
     }
 
 
-    public void integralOrderStatus(){
+    public void integralOrderStatus() {
         integralOrderMapper.updatePackageOrderStatusByDeliveryTime();
     }
 
-    public void packageStatus()
-    {
+    public void packageStatus() {
         fsPackageOrderMapper.updatePackageOrderStatusByFinishTime();
         SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.store");
         String configValue = sysConfig.getConfigValue();
         Map<String, Object> config = (Map<String, Object>) JSON.parse(configValue);
-        Integer unPayTime = (Integer)config.get("unPayTime");
+        Integer unPayTime = (Integer) config.get("unPayTime");
         fsPackageOrderMapper.updatePackageOrderStatusByStatus(unPayTime);
     }
 
-    public void endFollow(){
+    public void endFollow() {
         fsStoreOrderService.endFollow();
     }
 
 
-    public void erDelivery(){
+    public void erDelivery() {
         fsStoreOrderService.endDeliveryOrder();
     }
 
@@ -680,15 +816,16 @@ public class Task {
 
     @Autowired
     private ICompanyService companyService;
-    public void addCompanyMoney(){
+
+    public void addCompanyMoney() {
         List<FsStoreOrder> orders = fsStoreOrderMapper.selectOrderIds();
-        for (FsStoreOrder order : orders){
+        for (FsStoreOrder order : orders) {
             CompanyMoneyLogs moneyLog1 = moneyLogsMapper.selectCompanyMoneyLogsByOrderId(order.getOrderId(), 5);
-            CompanyMoneyLogs moneyLog2 = moneyLogsMapper.selectCompanyMoneyLogsByOrderId(order.getOrderId(),3);
-            if (moneyLog1==null){
+            CompanyMoneyLogs moneyLog2 = moneyLogsMapper.selectCompanyMoneyLogsByOrderId(order.getOrderId(), 3);
+            if (moneyLog1 == null) {
                 companyService.subtractCompanyMoney(order);
             }
-            if (moneyLog2==null){
+            if (moneyLog2 == null) {
                 companyService.addCompanyMoney(order);
                 FsStoreOrder orderMap = new FsStoreOrder();
                 orderMap.setOrderId(order.getOrderId());
@@ -699,28 +836,26 @@ public class Task {
     }
 
     //每天执行一次
-    public void syncExpress()
-    {
-        List<Long> ids =fsStoreOrderMapper.selectSyncExpressIds();
+    public void syncExpress() {
+        List<Long> ids = fsStoreOrderMapper.selectSyncExpressIds();
         for (Long id : ids) {
             fsStoreOrderService.syncExpress(id);
         }
 
     }
 
-    public void refundCompanyMoney(){
+    public void refundCompanyMoney() {
         List<FsStoreOrder> list = fsStoreOrderMapper.selectOrders();
-        for (FsStoreOrder order : list ){
+        for (FsStoreOrder order : list) {
             companyService.refundCompanyMoney(order);
         }
     }
 
-    public void subIntegral()
-    {
+    public void subIntegral() {
         fsUserIntegralLogsService.subFsUserIntegralLogsByOrder5();
     }
 
-    public void finishInquiry(){
+    public void finishInquiry() {
         List<FsInquiryOrder> orders = inquiryOrderMapper.selectFsInquiryOrderByFinish();
         for (FsInquiryOrder order : orders) {
             // 订单已超过48小时,执行关闭操作
@@ -729,20 +864,20 @@ public class Task {
             param.setDoctorId(order.getDoctorId());
             try {
                 iFsInquiryOrderService.autoFinishOrder(param);
-            }catch (Exception e){
-                logger.info("订单已超过48小时关闭异常"+param);
+            } catch (Exception e) {
+                logger.info("订单已超过48小时关闭异常" + param);
             }
 
         }
     }
 
 
-    public void finishStoreOrderByXN(){
+    public void finishStoreOrderByXN() {
         List<FsStoreOrder> orders = fsStoreOrderMapper.selectFinishStoreOrderByXN();
-        if (orders!=null&&orders.size()>0){
+        if (orders != null && orders.size() > 0) {
             for (FsStoreOrder o : orders) {
                 FsStoreOrder order = fsStoreOrderMapper.selectFsStoreOrderByOrderId(o.getOrderId());
-                if (order.getStatus()!= 2) {
+                if (order.getStatus() != 2) {
                     continue;
                 }
                 FsStoreOrder o1 = new FsStoreOrder();
@@ -753,20 +888,20 @@ public class Task {
                 int i = fsStoreOrderMapper.updateFsStoreOrder(o1);
                 fsStoreOrderLogsService.create(order.getOrderId(), FsStoreOrderLogEnum.FINISH_ORDER.getValue(),
                         FsStoreOrderLogEnum.FINISH_ORDER.getDesc());
-                if (order.getCompanyId()!=null&&order.getTuiMoneyStatus()==0&&order.getPayType()==1){
+                if (order.getCompanyId() != null && order.getTuiMoneyStatus() == 0 && order.getPayType() == 1) {
                     companyService.addCompanyMoney(order);
                 }
             }
         }
     }
 
-    public void inquirySendSms(){
+    public void inquirySendSms() {
         List<FsInquiryOrder> orders = inquiryOrderMapper.selectFsInquiryOrderBySendSms();
-        for (FsInquiryOrder order : orders){
-            FsInquiryOrderPatientDTO patientDTO = JSON.parseObject(order.getPatientJson(),FsInquiryOrderPatientDTO.class);
-            if (patientDTO!=null&&patientDTO.getPatientName()!=null){
+        for (FsInquiryOrder order : orders) {
+            FsInquiryOrderPatientDTO patientDTO = JSON.parseObject(order.getPatientJson(), FsInquiryOrderPatientDTO.class);
+            if (patientDTO != null && patientDTO.getPatientName() != null) {
                 FsUser fsUser = fsUserMapper.selectFsUserByUserId(order.getUserId());
-                if (fsUser!=null&&fsUser.getPhone()!=null){
+                if (fsUser != null && fsUser.getPhone() != null) {
                     smsService.sendUserSms(fsUser.getPhone(), patientDTO.getPatientName(), "2");
                     order.setIsSendSms(1);
                     inquiryOrderMapper.updateFsInquiryOrder(order);
@@ -777,9 +912,9 @@ public class Task {
     }
 
     //处理30天问题件
-    public void clearProblemOrder(){
+    public void clearProblemOrder() {
         List<FsStoreOrder> orders = fsStoreOrderMapper.selectFsStoreOrderByProblemOrder();
-        for (FsStoreOrder order : orders){
+        for (FsStoreOrder order : orders) {
             FsStoreOrder map = new FsStoreOrder();
             map.setStatus(4);
             map.setOrderId(order.getOrderId());
@@ -790,14 +925,14 @@ public class Task {
 
 
     //30天无通话记录回收坐席
-    public void recoverCompanyCaller(){
+    public void recoverCompanyCaller() {
         SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.store");
         StoreConfig fsPayConfig = new Gson().fromJson(sysConfig.getConfigValue(), StoreConfig.class);
         Integer days = fsPayConfig.getStoreCall();
         List<CompanyVoiceCaller> list = companyVoiceCallerMapper.selectCompanyVoiceCallerByRecover(days);
-        for (CompanyVoiceCaller caller : list){
-            Long count = companyVoiceLogsMapper.selectCompanyVoiceLogsCountByCallerNo(caller.getCallerNo(),caller.getBindTime());
-            if (count==0){
+        for (CompanyVoiceCaller caller : list) {
+            Long count = companyVoiceLogsMapper.selectCompanyVoiceLogsCountByCallerNo(caller.getCallerNo(), caller.getBindTime());
+            if (count == 0) {
                 caller.setCompanyId(0l);
                 caller.setCompanyUserId(0l);
                 caller.setMobile("");
@@ -810,32 +945,27 @@ public class Task {
 
 
     public void tb() {
-        packageOrderService.payConfirm("", "1780763211956486144", "1075999515888117190", "14", 1,null,null);
+        packageOrderService.payConfirm("", "1780763211956486144", "1075999515888117190", "14", 1, null, null);
     }
 
 
-
-
-
-
-
-    public void addSend(){
-       String userId="4048905872";
-       String doctorId="147";
-        String storeOrderId="470920";
-        String followId="1062986";
+    public void addSend() {
+        String userId = "4048905872";
+        String doctorId = "147";
+        String storeOrderId = "470920";
+        String followId = "1062986";
         //发送给用户
-        MsgDTO msgDTO=new MsgDTO();
-        MsgCustomDTO customDTO=new MsgCustomDTO();
+        MsgDTO msgDTO = new MsgDTO();
+        MsgCustomDTO customDTO = new MsgCustomDTO();
         customDTO.setType("startDrugReport");
         customDTO.setImType(2);
         customDTO.setOrderId(storeOrderId);
         customDTO.setFollowId(followId);
         msgDTO.setCloudCustomData(JSONUtil.toJsonStr(customDTO));
-        msgDTO.setFrom_Account("U-"+userId);
-        msgDTO.setTo_Account("D-"+doctorId);
-        List<MsgDataDTO> msgs=new ArrayList<>();
-        MsgDataDTO msg=new MsgDataDTO();
+        msgDTO.setFrom_Account("U-" + userId);
+        msgDTO.setTo_Account("D-" + doctorId);
+        List<MsgDataDTO> msgs = new ArrayList<>();
+        MsgDataDTO msg = new MsgDataDTO();
         msg.setMsgType("TIMTextElem");
         msg.setMsgContent(new MsgDataFormatDTO("您好"));
         msgs.add(msg);
@@ -1114,7 +1244,7 @@ public class Task {
 //                iFsPackageOrderService.updateFsPackageOrder(order);
 //                num++;
 //            }
-////
+    /// /
 //        }
 //
 //        logger.info("所有订单同步完成:"+num);
@@ -1190,7 +1320,7 @@ public class Task {
 //}
 
 
-        //同步流水
+    //同步流水
 //    public void task(){
 //        CompanyMoneyLogs item = moneyLogsMapper.selectCompanyMoneyLogsById(248884L);
 //        String logsId=item.getLogsId().toString();
@@ -1293,27 +1423,27 @@ public class Task {
     private IErpOrderService getErpService() {
         FsSysConfig sysConfig = configUtil.getSysConfig();
         Integer erpOpen = sysConfig.getErpOpen();
-        if (erpOpen != null && erpOpen == 1){
+        if (erpOpen != null && erpOpen == 1) {
             //判断erp类型
             Integer erpType = sysConfig.getErpType();
-            if (erpType != null){
+            if (erpType != null) {
                 IErpOrderService erpOrderService = null;
-                if (erpType == 1){
+                if (erpType == 1) {
                     //管易
-                    erpOrderService =  gyOrderService;
-                } else if (erpType == 2){
+                    erpOrderService = gyOrderService;
+                } else if (erpType == 2) {
                     //旺店通
-                    erpOrderService =  wdtOrderService;
-                } else if (erpType == 3){
+                    erpOrderService = wdtOrderService;
+                } else if (erpType == 3) {
                     //
-                    erpOrderService =  hzOMSErpOrderService;
-                } else if (erpType == 4){
+                    erpOrderService = hzOMSErpOrderService;
+                } else if (erpType == 4) {
                     //代服
-                    erpOrderService =  dfOrderService;
-                }else if(erpType == 5){
-                    erpOrderService=jSTOrderService;
-                }else if(erpType == 6){
-                    erpOrderService=k9OrderService;
+                    erpOrderService = dfOrderService;
+                } else if (erpType == 5) {
+                    erpOrderService = jSTOrderService;
+                } else if (erpType == 6) {
+                    erpOrderService = k9OrderService;
                 }
                 return erpOrderService;
 
@@ -1322,4 +1452,71 @@ public class Task {
         }
         return null;
     }
+
+
+    /**
+     * 定时任务-im会员定时发课,每一分钟执行一次
+     */
+    public void sendOpenImCourse(){
+        String redisKey = "openIm:batchSendMsg:sendCourse";
+        Map<String, BatchSendCourseAllDTO> cacheMap = redisCache.getCacheMap(redisKey);
+        if(cacheMap == null || cacheMap.isEmpty()){
+            logger.info("=====================会员IM定时发课,不存在对应的redisKey==================");
+            return;
+        }
+        List<Map.Entry<String, BatchSendCourseAllDTO>> toSendMap = cacheMap.entrySet().parallelStream().filter((v) -> {
+            String[] split = v.getKey().split(":");
+            long timestamp = Long.parseLong(split[2]);
+            return timestamp < System.currentTimeMillis();
+        }).collect(Collectors.toList());
+
+        if(toSendMap.isEmpty()){
+            logger.info("=====================会员IM定时发课,不存在可执行的发课任务==================");
+            return;
+        }
+        for (Map.Entry<String, BatchSendCourseAllDTO> entry : toSendMap) {
+            //执行发送消息任务
+            BatchSendCourseAllDTO batchSendCourseAllDTO = entry.getValue();
+            openIMService.batchSendCourseTask(batchSendCourseAllDTO.getBatchSendCourseDTO(), batchSendCourseAllDTO.getOpenImBatchMsgDTO(), batchSendCourseAllDTO.getProject(), batchSendCourseAllDTO.getImMsgSendDetailList());
+
+            // 执行结束,删除
+            this.redisTemplate.<String, BatchSendCourseAllDTO>opsForHash().delete(redisKey, entry.getKey());
+
+        }
+
+    }
+
+
+    /**
+     * 定时任务-im 会员催课,每一分钟执行一次
+     */
+    public void urgeOpenImCourse(){
+        String redisKey = "openIm:batchSendMsg:urgeCourse";
+        Map<String, BatchSendCourseAllDTO> cacheMap = redisCache.getCacheMap(redisKey);
+        if(cacheMap == null || cacheMap.isEmpty()){
+            logger.info("===================== 会员-IM发消息催课,不存在对应的redisKey==================");
+            return;
+        }
+        List<Map.Entry<String, BatchSendCourseAllDTO>> toSendMap = cacheMap.entrySet().parallelStream().filter((v) -> {
+            String[] split = v.getKey().split(":");
+            long timestamp = Long.parseLong(split[2]);
+            return timestamp < System.currentTimeMillis();
+        }).collect(Collectors.toList());
+
+        if(toSendMap.isEmpty()){
+            logger.info("===================== 会员-IM发消息催课,不存在可发送的消息==================");
+            return;
+        }
+        for (Map.Entry<String, BatchSendCourseAllDTO> entry : toSendMap) {
+            //执行发送消息任务
+            BatchSendCourseAllDTO batchSendCourseAllDTO = entry.getValue();
+            openIMService.batchUrgeCourseTask(batchSendCourseAllDTO.getOpenImBatchMsgDTO(), batchSendCourseAllDTO.getImMsgSendDetailList());
+
+            // 执行结束,删除
+            this.redisTemplate.<String, BatchSendCourseAllDTO>opsForHash().delete(redisKey, entry.getKey());
+
+        }
+    }
+
+
 }

+ 93 - 14
fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreHealthOrderScrmController.java

@@ -9,24 +9,34 @@ 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.CloudHostUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.service.ICompanyMoneyLogsService;
 import com.fs.course.dto.FsOrderDeliveryNoteDTO;
 import com.fs.erp.service.IErpOrderService;
+import com.fs.his.domain.FsStoreOrderDf;
+import com.fs.his.service.IFsStoreOrderDfService;
 import com.fs.his.service.IFsUserService;
+import com.fs.his.vo.FsStoreOrderListAndStatisticsVo;
 import com.fs.hisStore.dto.StoreOrderProductDTO;
 import com.fs.hisStore.param.FsStoreOrderParam;
 import com.fs.hisStore.service.*;
+import com.fs.hisStore.vo.FsStoreOrderErpExportVO;
 import com.fs.hisStore.vo.FsStoreOrderExportVO;
 import com.fs.hisStore.vo.FsStoreOrderItemExportVO;
 import com.fs.hisStore.vo.FsStoreOrderVO;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 
 @RestController
 @RequestMapping("/store/store/storeOrder")
@@ -52,6 +62,9 @@ public class FsStoreHealthOrderScrmController extends BaseController {
     @Autowired
     private ICompanyMoneyLogsService moneyLogsService;
 
+    @Autowired
+    private IFsStoreOrderDfService fsStoreOrderDfService;
+
     // 允许的文件扩展名
     private static final String[] ALLOWED_EXCEL_EXTENSIONS = {".xlsx", ".xls"};
 
@@ -61,9 +74,9 @@ public class FsStoreHealthOrderScrmController extends BaseController {
     /**
      * 查询健康商城订单列表
      */
-    @PreAuthorize("@ss.hasPermi('store:healthStoreOrder:list')")
-    @GetMapping("/healthList")
-    public TableDataInfo healthStoreList(FsStoreOrderParam param) {
+//    @PreAuthorize("@ss.hasPermi('store:healthStoreOrder:list')")
+      @PostMapping("/healthList")
+      public TableDataInfo healthStoreList(@RequestBody FsStoreOrderParam param) {
         startPage();
         if(!StringUtils.isEmpty(param.getCreateTimeRange())){
             param.setCreateTimeList(param.getCreateTimeRange().split("--"));
@@ -79,16 +92,50 @@ public class FsStoreHealthOrderScrmController extends BaseController {
         }
         param.setIsHealth("1");
         List<FsStoreOrderVO> list = fsStoreOrderService.selectFsStoreOrderListVO(param);
+        //金牛需求 区别其他项目 status = 6 (金牛代服管家) ,其他项目请避免使用订单状态status = 6
+        TableDataInfo dataTable = getDataTable(list);
+        if (CloudHostUtils.hasCloudHostName("康年堂")){
+            dataTable.setMsg("knt");
+        }
         if (list != null) {
             for (FsStoreOrderVO vo : list) {
                 if(vo.getPhone()!=null){
                     vo.setPhone(vo.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
                     vo.setUserPhone(vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
                 }
+                if (CloudHostUtils.hasCloudHostName("康年堂")){
+                    //查询顺丰代服账号
+                    FsStoreOrderDf df = fsStoreOrderDfService.selectFsStoreOrderDfByOrderId(vo.getId());
+                    if (df != null){
+                        vo.setErpAccount(df.getLoginAccount());
+                    }
+                }
 
             }
         }
-        return getDataTable(list);
+        FsStoreOrderListAndStatisticsVo vo = new FsStoreOrderListAndStatisticsVo();
+        BeanUtils.copyProperties(dataTable, vo);
+        if (dataTable.getTotal()>0){
+            Map<String, BigDecimal> statistics= fsStoreOrderService.selectFsStoreOrderStatistics(param);
+            if (statistics != null && statistics.size() >= 3){
+                vo.setPayPriceTotal(statistics.get("pay_price").toString());
+                vo.setPayMoneyTotal(statistics.get("pay_money").toString());
+                vo.setPayRemainTotal(statistics.get("pay_remain").toString());
+            }else {
+                vo.setPayPriceTotal("0");
+                vo.setPayMoneyTotal("0");
+                vo.setPayRemainTotal("0");
+            }
+            //商品数量合计
+            String productStatistics= fsStoreOrderService.selectFsStoreOrderProductStatistics(param);
+            if (StringUtils.isNotBlank(productStatistics)){
+                vo.setProductInfo(productStatistics);
+            } else {
+                vo.setProductInfo("");
+            }
+
+        }
+        return vo;
     }
 
     /**
@@ -96,8 +143,8 @@ public class FsStoreHealthOrderScrmController extends BaseController {
      */
     @PreAuthorize("@ss.hasPermi('store:healthStoreOrder:export')")
     @Log(title = "健康商城订单", businessType = BusinessType.EXPORT)
-    @GetMapping("/healthExport")
-    public AjaxResult export1(FsStoreOrderParam param) {
+    @PostMapping("/healthExport")
+    public AjaxResult export1(@RequestBody FsStoreOrderParam param) {
         if ("".equals(param.getBeginTime()) && "".equals(param.getEndTime())){
             param.setBeginTime(null);
             param.setEndTime(null);
@@ -118,7 +165,7 @@ public class FsStoreHealthOrderScrmController extends BaseController {
             param.setDeliveryImportTimeList(param.getDeliveryImportTimeRange().split("--"));
         }
         param.setIsHealth("1");
-        List<FsStoreOrderExportVO> list = fsStoreOrderService.selectFsStoreOrderListVOByExport(param);
+        List<FsStoreOrderErpExportVO> list = fsStoreOrderService.selectFsStoreOrderListVOByExport(param);
         //对手机号脱敏
         if (list != null) {
             for (FsStoreOrderExportVO vo : list) {
@@ -131,8 +178,24 @@ public class FsStoreHealthOrderScrmController extends BaseController {
 
             }
         }
-        ExcelUtil<FsStoreOrderExportVO> util = new ExcelUtil<FsStoreOrderExportVO>(FsStoreOrderExportVO.class);
-        return util.exportExcel(list, "订单数据");
+        String filter = param.getFilter();
+        // 1. 处理filter参数:将逗号分隔的字符串拆分为ArrayList<String>
+        ArrayList<String> filterList = new ArrayList<>();
+        if (StringUtils.isNotBlank(filter)) {
+            // 按逗号拆分,同时去除可能的空格(如filter传"orderId, orderCode"时兼容)
+            String[] filterArr = filter.split("\\s*,\\s*");
+            filterList.addAll(Arrays.asList(filterArr));
+        }
+        // 动态导出:根据选中的字段生成Excel
+        ExcelUtil<FsStoreOrderErpExportVO> util = new ExcelUtil<FsStoreOrderErpExportVO>(FsStoreOrderErpExportVO.class);
+        AjaxResult result;
+        // 如果有选中的字段,只导出这些字段
+        if (filter != null && !filter.isEmpty()) {
+            return util.exportExcelSelectedColumns(list, "订单数据", filterList);
+        } else {
+            // 导出所有字段
+            return util.exportExcel(list, "订单数据");
+        }
     }
 
     /**
@@ -140,8 +203,8 @@ public class FsStoreHealthOrderScrmController extends BaseController {
      */
     @PreAuthorize("@ss.hasPermi('store:healthStoreOrder:export:details')")
     @Log(title = "健康商城订单", businessType = BusinessType.EXPORT)
-    @GetMapping("/healthExportDetails")
-    public AjaxResult healthExportDetails(FsStoreOrderParam param) {
+    @PostMapping("/healthExportDetails")
+    public AjaxResult healthExportDetails(@RequestBody FsStoreOrderParam param) {
         if ("".equals(param.getBeginTime()) && "".equals(param.getEndTime())){
             param.setBeginTime(null);
             param.setEndTime(null);
@@ -162,9 +225,25 @@ public class FsStoreHealthOrderScrmController extends BaseController {
             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, "订单数据");
+        List<FsStoreOrderErpExportVO> list = fsStoreOrderService.selectFsStoreOrderListVOByExport(param);
+        String filter = param.getFilter();
+        // 1. 处理filter参数:将逗号分隔的字符串拆分为ArrayList<String>
+        ArrayList<String> filterList = new ArrayList<>();
+        if (StringUtils.isNotBlank(filter)) {
+            // 按逗号拆分,同时去除可能的空格(如filter传"orderId, orderCode"时兼容)
+            String[] filterArr = filter.split("\\s*,\\s*");
+            filterList.addAll(Arrays.asList(filterArr));
+        }
+        // 动态导出:根据选中的字段生成Excel
+        ExcelUtil<FsStoreOrderErpExportVO> util = new ExcelUtil<FsStoreOrderErpExportVO>(FsStoreOrderErpExportVO.class);
+        AjaxResult result;
+        // 如果有选中的字段,只导出这些字段
+        if (filter != null && !filter.isEmpty()) {
+            return util.exportExcelSelectedColumns(list, "订单数据", filterList);
+        } else {
+            // 导出所有字段
+            return util.exportExcel(list, "订单数据");
+        }
     }
 
 

+ 305 - 19
fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java

@@ -2,6 +2,7 @@ package com.fs.hisStore.controller;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
@@ -10,6 +11,7 @@ import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.model.LoginUser;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.CloudHostUtils;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
@@ -21,12 +23,22 @@ import com.fs.erp.domain.ErpDeliverys;
 import com.fs.erp.domain.ErpOrderQuery;
 import com.fs.erp.dto.ErpOrderQueryRequert;
 import com.fs.erp.dto.ErpOrderQueryResponse;
+import com.fs.erp.dto.df.DFConfigVo;
 import com.fs.erp.service.IErpOrderService;
 import com.fs.framework.web.service.TokenService;
+import com.fs.his.domain.FsDfAccount;
+import com.fs.his.domain.FsStoreOrderDf;
 import com.fs.his.domain.FsUser;
+import com.fs.his.enums.FsStoreOrderLogEnum;
+import com.fs.his.param.FsStoreOrderSetErpPhoneParam;
+import com.fs.his.service.IFsDfAccountService;
 import com.fs.his.service.IFsExpressService;
+import com.fs.his.service.IFsStoreOrderDfService;
 import com.fs.his.service.IFsUserService;
+import com.fs.his.service.impl.FsDfAccountServiceImpl;
 import com.fs.his.utils.ConfigUtil;
+import com.fs.his.vo.FsStoreOrderListAndStatisticsVo;
+import com.fs.his.vo.FsStoreOrderListVO;
 import com.fs.hisStore.config.FsErpConfig;
 import com.fs.hisStore.domain.FsStoreOrderItemScrm;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
@@ -39,6 +51,8 @@ import com.fs.hisStore.enums.ShipperCodeEnum;
 import com.fs.hisStore.param.*;
 import com.fs.hisStore.service.*;
 import com.fs.hisStore.vo.*;
+import com.fs.system.domain.SysConfig;
+import com.fs.system.mapper.SysConfigMapper;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -49,9 +63,12 @@ import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletRequest;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static com.fs.his.utils.PhoneUtil.encryptPhone;
 
 /**
  * 订单Controller
@@ -107,6 +124,18 @@ public class FsStoreOrderScrmController extends BaseController {
     @Autowired
     private TokenService tokenService;
 
+    @Autowired
+    SysConfigMapper sysConfigMapper;
+
+    @Autowired
+    private IFsDfAccountService fsDfAccountService;
+
+    @Autowired
+    private IFsStoreOrderDfService fsStoreOrderDfService;
+
+    @Autowired
+    private IFsStoreOrderLogsScrmService fsStoreOrderLogsService;
+
     private IErpOrderService getErpService(){
         //判断是否开启erp
         IErpOrderService erpOrderService = null;
@@ -142,8 +171,8 @@ public class FsStoreOrderScrmController extends BaseController {
      * 查询订单列表
      */
     @PreAuthorize("@ss.hasPermi('store:storeOrder:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(FsStoreOrderParam param) {
+    @PostMapping("/list")
+    public TableDataInfo list(@RequestBody FsStoreOrderParam param) {
         startPage();
         if(!StringUtils.isEmpty(param.getCreateTimeRange())){
             param.setCreateTimeList(param.getCreateTimeRange().split("--"));
@@ -159,15 +188,49 @@ public class FsStoreOrderScrmController extends BaseController {
         }
         param.setNotHealth(1);
         List<FsStoreOrderVO> list = fsStoreOrderService.selectFsStoreOrderListVO(param);
+        //金牛需求 区别其他项目 status = 6 (金牛代服管家) ,其他项目请避免使用订单状态status = 6
+        TableDataInfo dataTable = getDataTable(list);
+        if (CloudHostUtils.hasCloudHostName("康年堂")){
+            dataTable.setMsg("knt");
+        }
         if (list != null) {
             for (FsStoreOrderVO vo : list) {
                 if(vo.getPhone()!=null){
                     vo.setPhone(vo.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
                     vo.setUserPhone(vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
                 }
+                if (CloudHostUtils.hasCloudHostName("康年堂")){
+                    //查询顺丰代服账号
+                    FsStoreOrderDf df = fsStoreOrderDfService.selectFsStoreOrderDfByOrderId(vo.getId());
+                    if (df != null){
+                        vo.setErpAccount(df.getLoginAccount());
+                    }
+                }
             }
         }
-        return getDataTable(list);
+        FsStoreOrderListAndStatisticsVo vo = new FsStoreOrderListAndStatisticsVo();
+        BeanUtils.copyProperties(dataTable, vo);
+        if (dataTable.getTotal()>0){
+            Map<String, BigDecimal> statistics= fsStoreOrderService.selectFsStoreOrderStatistics(param);
+            if (statistics != null && statistics.size() >= 3){
+                vo.setPayPriceTotal(statistics.get("pay_price").toString());
+                vo.setPayMoneyTotal(statistics.get("pay_money").toString());
+                vo.setPayRemainTotal(statistics.get("pay_remain").toString());
+            }else {
+                vo.setPayPriceTotal("0");
+                vo.setPayMoneyTotal("0");
+                vo.setPayRemainTotal("0");
+            }
+            //商品数量合计
+            String productStatistics= fsStoreOrderService.selectFsStoreOrderProductStatistics(param);
+            if (StringUtils.isNotBlank(productStatistics)){
+                vo.setProductInfo(productStatistics);
+            } else {
+                vo.setProductInfo("");
+            }
+
+        }
+        return vo;
     }
 
     @PreAuthorize("@ss.hasPermi('store:storeOrder:payRemainList')")
@@ -236,8 +299,8 @@ public class FsStoreOrderScrmController extends BaseController {
      */
     @PreAuthorize("@ss.hasPermi('store:storeOrder:export')")
     @Log(title = "订单", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(FsStoreOrderParam param) {
+    @PostMapping("/export")
+    public AjaxResult export(@RequestBody FsStoreOrderParam param) {
         if ("".equals(param.getBeginTime()) && "".equals(param.getEndTime())){
             param.setBeginTime(null);
             param.setEndTime(null);
@@ -258,13 +321,13 @@ public class FsStoreOrderScrmController extends BaseController {
             param.setDeliveryImportTimeList(param.getDeliveryImportTimeRange().split("--"));
         }
         param.setNotHealth(1);
-        List<FsStoreOrderExportVO> list = fsStoreOrderService.selectFsStoreOrderListVOByExport(param);
+        List<FsStoreOrderErpExportVO> list = fsStoreOrderService.selectFsStoreOrderListVOByExport(param);
         //对手机号脱敏
         if (list != null) {
             //获取当前账号角色权限
             LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
 
-            for (FsStoreOrderExportVO vo : list) {
+            for (FsStoreOrderErpExportVO vo : list) {
                 if (vo.getPhone() != null) {
                     vo.setPhone(vo.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
                 }
@@ -276,8 +339,24 @@ public class FsStoreOrderScrmController extends BaseController {
                 }
             }
         }
-        ExcelUtil<FsStoreOrderExportVO> util = new ExcelUtil<FsStoreOrderExportVO>(FsStoreOrderExportVO.class);
-        return util.exportExcel(list, "订单数据");
+        String filter = param.getFilter();
+        // 1. 处理filter参数:将逗号分隔的字符串拆分为ArrayList<String>
+        ArrayList<String> filterList = new ArrayList<>();
+        if (StringUtils.isNotBlank(filter)) {
+            // 按逗号拆分,同时去除可能的空格(如filter传"orderId, orderCode"时兼容)
+            String[] filterArr = filter.split("\\s*,\\s*");
+            filterList.addAll(Arrays.asList(filterArr));
+        }
+        // 动态导出:根据选中的字段生成Excel
+        ExcelUtil<FsStoreOrderErpExportVO> util = new ExcelUtil<FsStoreOrderErpExportVO>(FsStoreOrderErpExportVO.class);
+        AjaxResult result;
+        // 如果有选中的字段,只导出这些字段
+        if (filter != null && !filter.isEmpty()) {
+            return util.exportExcelSelectedColumns(list, "订单数据", filterList);
+        } else {
+            // 导出所有字段
+            return util.exportExcel(list, "订单数据");
+        }
     }
 
 
@@ -286,8 +365,8 @@ public class FsStoreOrderScrmController extends BaseController {
      */
     @PreAuthorize("@ss.hasPermi('store:storeOrder:export:details')")
     @Log(title = "订单", businessType = BusinessType.EXPORT)
-    @GetMapping("/exportDetails")
-    public AjaxResult exportDetails(FsStoreOrderParam param) {
+    @PostMapping("/exportDetails")
+    public AjaxResult exportDetails(@RequestBody FsStoreOrderParam param) {
         if ("".equals(param.getBeginTime()) && "".equals(param.getEndTime())){
             param.setBeginTime(null);
             param.setEndTime(null);
@@ -308,9 +387,25 @@ public class FsStoreOrderScrmController extends BaseController {
             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, "订单数据");
+        List<FsStoreOrderErpExportVO> list = fsStoreOrderService.selectFsStoreOrderListVOByExport(param);
+        String filter = param.getFilter();
+        // 1. 处理filter参数:将逗号分隔的字符串拆分为ArrayList<String>
+        ArrayList<String> filterList = new ArrayList<>();
+        if (StringUtils.isNotBlank(filter)) {
+            // 按逗号拆分,同时去除可能的空格(如filter传"orderId, orderCode"时兼容)
+            String[] filterArr = filter.split("\\s*,\\s*");
+            filterList.addAll(Arrays.asList(filterArr));
+        }
+        // 动态导出:根据选中的字段生成Excel
+        ExcelUtil<FsStoreOrderErpExportVO> util = new ExcelUtil<FsStoreOrderErpExportVO>(FsStoreOrderErpExportVO.class);
+        AjaxResult result;
+        // 如果有选中的字段,只导出这些字段
+        if (filter != null && !filter.isEmpty()) {
+            return util.exportExcelSelectedColumns(list, "订单数据", filterList);
+        } else {
+            // 导出所有字段
+            return util.exportExcel(list, "订单数据");
+        }
     }
 
     @PreAuthorize("@ss.hasPermi('store:storeOrder:exportItems')")
@@ -541,7 +636,7 @@ public class FsStoreOrderScrmController extends BaseController {
         IErpOrderService erpOrderService = getErpService();
         ErpOrderQueryRequert request = new ErpOrderQueryRequert();
         request.setCode(order.getExtendOrderId());
-        ErpOrderQueryResponse response = erpOrderService.getOrder(request);
+        ErpOrderQueryResponse response = erpOrderService.getScrmOrder(request);
         if(response.getOrders()!=null&&response.getOrders().size()>0){
             for(ErpOrderQuery orderQuery : response.getOrders()){
                 if(orderQuery.getDeliverys()!=null&&orderQuery.getDeliverys().size()>0){
@@ -632,7 +727,7 @@ public class FsStoreOrderScrmController extends BaseController {
         IErpOrderService erpOrderService = getErpService();
         ErpOrderQueryRequert request = new ErpOrderQueryRequert();
         request.setCode(extendOrderId);
-        ErpOrderQueryResponse response = erpOrderService.getOrder(request);
+        ErpOrderQueryResponse response = erpOrderService.getScrmOrder(request);
         return R.ok().put("data",response);
     }
 
@@ -739,4 +834,195 @@ public class FsStoreOrderScrmController extends BaseController {
         }
         return resultList;
     }
+
+    /**
+     * 查询erp默认手机号
+     * @return
+     */
+    @GetMapping(value = "/queryErpPhone")
+    public AjaxResult queryErpPhone()
+    {
+        SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("erp.phone");
+        List<String> list = new ArrayList<>();
+        if(sysConfig!=null){
+            String configValue = sysConfig.getConfigValue();
+            if(StringUtils.isNotEmpty(configValue)){
+                list = JSON.parseArray(configValue, String.class);
+            }
+        }
+        return AjaxResult.success(list);
+    }
+
+    /**
+     * 设置erp默认手机号
+     * @param phoneList
+     * @return
+     */
+    @PostMapping(value = "/saveErpPhone")
+    public AjaxResult saveErpPhone(@RequestBody List<String> phoneList)
+    {
+        //去重
+        phoneList = phoneList.stream().distinct().collect(Collectors.toList());
+        SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("erp.phone");
+        sysConfig.setConfigValue(JSON.toJSONString(phoneList));
+        return AjaxResult.success(sysConfigMapper.updateConfig(sysConfig));
+    }
+
+    /**
+     * 批量设置erp手机号
+     */
+    @PreAuthorize("@ss.hasPermi('his:storeOrder:createErpOrder')")
+    @Log(title = "订单", businessType = BusinessType.UPDATE)
+    @PostMapping("/editErpPhone")
+    public AjaxResult editErpPhone(@RequestBody FsStoreOrderScrmSetErpPhoneParam param)
+    {
+        param.setOpeName(getLoginUser().getUser().getNickName());
+        List<String> erpPhone = param.getErpPhone();
+        if (erpPhone == null || erpPhone.isEmpty()) {
+            return AjaxResult.error("请选择手机号");
+        }
+        return toAjax(fsStoreOrderService.batchUpdateErpByOrderIds(param));
+    }
+
+    /**
+     * 获取erp账户
+     */
+    @GetMapping("/getErpAccount")
+    public R getErpAccount()
+    {
+        List<String> list = new ArrayList<>();
+        if (CloudHostUtils.hasCloudHostName("金牛明医","康年堂")) {
+            List<FsDfAccount> erpAccounts = fsDfAccountService.selectFsDfAccountList(null);
+            list = erpAccounts.stream().map(FsDfAccount::getLoginAccount).collect(Collectors.toList());
+        }
+        return R.ok().put("data", list);
+    }
+
+    @Log(title = "手动推管易", businessType = BusinessType.INSERT)
+    @ApiOperation("批量创建ERP订单")
+    @PreAuthorize("@ss.hasPermi('his:storeOrder:createErpOrder')")
+    @PostMapping(value = "/batchCreateErpOrder")
+    public R batchCreateErpOrder(@RequestBody FsStoreOrderScrmSetErpPhoneParam param)
+    {
+        String nickName = getLoginUser().getUser().getNickName();
+        String loginAccount = param.getLoginAccount();
+        if (StringUtils.isBlank(loginAccount)){
+            return R.error("未选择推送erp账户");
+        }
+        FsStoreOrderDf df = getDFInfo(loginAccount);
+        if (df.getLoginAccount() == null){
+            return R.error("未查询到所选erp账户");
+        }
+        List<Long> orderIds = param.getOrderIds();
+        if (orderIds  == null || orderIds.isEmpty()) {
+            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<FsStoreOrderVO> list = fsStoreOrderService.selectFsStoreOrderListVO(param);
+            orderIds = list.stream().map(FsStoreOrderVO::getId).collect(Collectors.toList());
+        }
+        if (orderIds.isEmpty()){
+            return R.ok();
+        }
+        orderIds.forEach(orderId->{
+            try {
+                df.setOrderId(orderId);
+                FsStoreOrderDf temp = fsStoreOrderDfService.selectFsStoreOrderDfByOrderId(df.getOrderId());
+                if (temp == null){
+                    df.setParcelQuantity(param.getParcelQuantity()); //设置包裹数量
+                    fsStoreOrderDfService.insertFsStoreOrderDf(df);
+                    fsStoreOrderLogsService.create(orderId, FsStoreOrderLogEnum.SET_PUSH_ACCOUNT.getValue(),
+                            nickName + " " +FsStoreOrderLogEnum.SET_PUSH_ACCOUNT.getDesc() + ":" + df.getLoginAccount());
+                }
+                fsStoreOrderService.createOmsOrder(orderId);
+                fsStoreOrderLogsService.create(orderId, FsStoreOrderLogEnum.PUSH_ORDER_ERP.getValue(),
+                        nickName + " " +FsStoreOrderLogEnum.PUSH_ORDER_ERP.getDesc() + ":" + df.getLoginAccount());
+            } catch (ParseException e) {
+                throw new RuntimeException(e);
+            }
+
+        });
+        return R.ok();
+    }
+
+
+    @ApiOperation("批量设置订单账户")
+    @PreAuthorize("@ss.hasPermi('his:storeOrder:createErpOrder')")
+    @PostMapping(value = "/batchSetErpOrder")
+    public R batchSetErpOrder(@RequestBody FsStoreOrderScrmSetErpPhoneParam param)
+    {
+        String nickName = getLoginUser().getUser().getNickName();
+        String loginAccount = param.getLoginAccount();
+        if (StringUtils.isBlank(loginAccount)){
+            return R.error("未选择erp账户");
+        }
+        FsStoreOrderDf df = getDFInfo(loginAccount);
+        if (df.getLoginAccount() == null){
+            return R.error("未查询到所选erp账户");
+        }
+        List<Long> orderIds = param.getOrderIds();
+        if (orderIds  == null || orderIds.isEmpty()) {
+            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<FsStoreOrderVO> list = fsStoreOrderService.selectFsStoreOrderListVO(param);
+            orderIds = list.stream().map(FsStoreOrderVO::getId).collect(Collectors.toList());
+        }
+        if (orderIds.isEmpty()){
+            return R.ok();
+        }
+        orderIds.forEach(orderId->{
+            df.setOrderId(orderId);
+            FsStoreOrderDf temp = fsStoreOrderDfService.selectFsStoreOrderDfByOrderId(df.getOrderId());
+            df.setParcelQuantity(param.getParcelQuantity());
+            if (temp != null){
+                df.setUpdateTime(new Date());
+                fsStoreOrderDfService.updateFsStoreOrderDf(df);
+            } else {
+                fsStoreOrderDfService.insertFsStoreOrderDf(df);
+            }
+            fsStoreOrderLogsService.create(orderId, FsStoreOrderLogEnum.SET_PUSH_ACCOUNT.getValue(),
+                    nickName + " " +FsStoreOrderLogEnum.SET_PUSH_ACCOUNT.getDesc() + ":" + df.getLoginAccount());
+        });
+        return R.ok();
+    }
+
+    private FsStoreOrderDf getDFInfo(String loginAccount) {
+        //查询订单账户 判断是否存在该订单账户
+        List<FsDfAccount> erpAccounts = fsDfAccountService.selectFsDfAccountList(null);
+        FsStoreOrderDf df = new FsStoreOrderDf();
+        for (FsDfAccount erpAccount : erpAccounts) {
+            if (loginAccount.equals(erpAccount.getLoginAccount())){
+                //添加df记录
+                df.setAppKey(erpAccount.getDfAppKey());
+                df.setAppSecret(erpAccount.getDfAppsecret());
+                df.setLoginAccount(loginAccount);
+                df.setMonthlyCard(erpAccount.getMonthlyCard());
+                df.setExpressProductCode(erpAccount.getExpressProductCode());
+                df.setStatus(0);
+                break;
+            }
+        }
+        return df;
+    }
 }

+ 29 - 1
fs-admin/src/main/java/com/fs/hisStore/controller/FsStorePaymentScrmController.java

@@ -1,6 +1,7 @@
 package com.fs.hisStore.controller;
 
 import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSON;
 import com.alipay.api.AlipayApiException;
 import com.alipay.api.domain.AlipayTradeRefundModel;
 import com.fs.bean.AliPayBean;
@@ -13,7 +14,12 @@ import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.utils.spring.SpringUtils;
 import com.fs.company.service.ICompanyService;
+import com.fs.config.cloud.CloudHostProper;
+import com.fs.his.domain.FsHfpayConfig;
+import com.fs.his.mapper.FsHfpayConfigMapper;
+import com.fs.hisStore.domain.FsPayConfigScrm;
 import com.fs.huifuPay.domain.HuiFuQueryOrderResult;
 import com.fs.huifuPay.domain.HuiFuRefundResult;
 import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayQueryRequest;
@@ -24,6 +30,7 @@ import com.fs.hisStore.param.FsStorePaymentParam;
 import com.fs.hisStore.service.IFsStoreOrderScrmService;
 import com.fs.hisStore.service.IFsStorePaymentScrmService;
 import com.fs.hisStore.vo.FsStorePaymentVO;
+import com.fs.system.service.ISysConfigService;
 import com.ijpay.alipay.AliPayApi;
 import com.ijpay.alipay.AliPayApiConfig;
 import com.ijpay.alipay.AliPayApiConfigKit;
@@ -63,6 +70,10 @@ public class FsStorePaymentScrmController extends BaseController
     private IFsStoreOrderScrmService orderService;
     @Autowired
     HuiFuService huiFuService;
+    @Autowired
+    private CloudHostProper cloudHostProper;
+    @Autowired
+    private ISysConfigService configService;
     /**
      * 查询支付明细列表
      */
@@ -179,10 +190,27 @@ public class FsStorePaymentScrmController extends BaseController
         if(payment.getPayMoney().compareTo(fsStorePayment.getRefundMoney())==-1){
             return R.error("退款金额必须小于等于付款金额");
         }
-        if(payment.getPayTypeCode().equals("weixin")){
 
+        if(payment.getPayTypeCode().equals("weixin")){
+            String json = configService.selectConfigByKey("store.pay");
+            FsPayConfigScrm fsPayConfig = JSON.parseObject(json, FsPayConfigScrm.class);
             if (payment.getPayMode()!=null&&payment.getPayMode().equals("hf")){
+                String huifuId="";
+                FsHfpayConfigMapper fsHfpayConfigMapper = SpringUtils.getBean(FsHfpayConfigMapper.class);
+                if (payment.getAppId() != null) {
+                    FsHfpayConfig fsHfpayConfig = fsHfpayConfigMapper.selectByAppId(payment.getAppId());
+                    huifuId = fsHfpayConfig.getHuifuId();
+                } else {
+                    if (("益善缘".equals(cloudHostProper.getCompanyName()))) {
+
+                        FsHfpayConfig fsPayConfig2 = fsHfpayConfigMapper.selectByAppId("wx0d1a3dd485268521");
+                        huifuId = fsPayConfig2.getHuifuId();
+                    }else {
+                        huifuId=fsPayConfig.getHuifuId();
+                    }
+                }
                 V2TradePaymentScanpayRefundRequest request = new V2TradePaymentScanpayRefundRequest();
+                request.setHuifuId(huifuId);
                 request.setOrdAmt(payment.getPayMoney().toString());
                 request.setOrgReqDate(new SimpleDateFormat("yyyyMMdd").format(payment.getCreateTime()));
                 request.setReqSeqId("refund-"+payment.getPayCode());

+ 1 - 1
fs-admin/src/main/java/com/fs/hisStore/task/ErpTask.java

@@ -8,7 +8,7 @@ import com.fs.erp.service.IErpOrderService;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
 import com.fs.hisStore.service.IFsStoreOrderScrmService;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 

+ 71 - 17
fs-admin/src/main/java/com/fs/hisStore/task/MallStoreTask.java

@@ -17,7 +17,9 @@ import com.fs.erp.dto.ErpOrderQueryResponse;
 import com.fs.erp.service.IErpGoodsService;
 import com.fs.erp.service.IErpOrderService;
 import com.fs.his.config.FsSysConfig;
+import com.fs.his.domain.FsStoreProductAttrValue;
 import com.fs.his.dto.ExpressInfoDTO;
+import com.fs.his.mapper.FsStoreProductAttrValueMapper;
 import com.fs.his.service.IFsExpressService;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.utils.ConfigUtil;
@@ -49,6 +51,7 @@ import java.time.LocalTime;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.CompletableFuture;
 
 import static com.fs.hisStore.constants.StoreConstants.DELIVERY;
 
@@ -93,7 +96,7 @@ public class MallStoreTask
     @Autowired
     private ISysConfigService configService;
     @Autowired
-    private FsStoreProductAttrValueScrmMapper fsStoreProductAttrValueMapper;
+    private FsStoreProductAttrValueMapper fsStoreProductAttrValueMapper;
     @Autowired
     private FsStorePaymentScrmMapper paymentMapper;
     @Autowired
@@ -205,23 +208,24 @@ public class MallStoreTask
             ErpOrderQueryRequert request = new ErpOrderQueryRequert();
             request.setCode(order.getExtendOrderId());
             IErpOrderService erpOrderService = getErpOrderService();
-            ErpOrderQueryResponse response = erpOrderService.getOrder(request);
-            if(response.getOrders()!=null&&response.getOrders().size()>0){
-                for(ErpOrderQuery orderQuery : response.getOrders()){
-                    if(orderQuery.getDeliverys()!=null&&orderQuery.getDeliverys().size()>0){
-                        for(ErpDeliverys delivery:orderQuery.getDeliverys()){
-                            if(delivery.getDelivery()&&StringUtils.isNotEmpty(delivery.getMail_no())){
-                                //更新商订单状态 删除REDIS
-                                orderService.deliveryOrder(order.getOrderCode(),delivery.getMail_no(),delivery.getExpress_code(),delivery.getExpress_name());
-                                redisCache.deleteObject(DELIVERY+":"+order.getExtendOrderId());
+            ErpOrderQueryResponse response = erpOrderService.getScrmOrder(request);
+            if (erpOrderService != dfOrderService) {
+                if(response.getOrders()!=null && !response.getOrders().isEmpty()){
+                    for(ErpOrderQuery orderQuery : response.getOrders()){
+                        if(orderQuery.getDeliverys()!=null&&orderQuery.getDeliverys().size()>0){
+                            for(ErpDeliverys delivery:orderQuery.getDeliverys()){
+                                if(delivery.getDelivery()&&StringUtils.isNotEmpty(delivery.getMail_no())){
+                                    //更新商订单状态 删除REDIS
+                                    orderService.deliveryOrder(order.getOrderCode(),delivery.getMail_no(),delivery.getExpress_code(),delivery.getExpress_name());
+                                    redisCache.deleteObject(DELIVERY+":"+order.getExtendOrderId());
+                                }
                             }
-                        }
 
+                        }
                     }
-                }
 
+                }
             }
-
         }
 
     }
@@ -232,8 +236,8 @@ public class MallStoreTask
         String json=configService.selectConfigByKey("store.config");
         StoreConfig config=JSONUtil.toBean(json,StoreConfig.class);
 
-        List<FsStoreProductAttrValueScrm> values = fsStoreProductAttrValueMapper.selectFsStoreProductAttrValueList(new FsStoreProductAttrValueScrm());
-        for (FsStoreProductAttrValueScrm value : values) {
+        List<FsStoreProductAttrValue> values = fsStoreProductAttrValueMapper.selectFsStoreProductAttrValueList(new FsStoreProductAttrValue());
+        for (FsStoreProductAttrValue value : values) {
             ErpGoodsQueryRequert query = new ErpGoodsQueryRequert();
             query.setCode(value.getBarCode());
             ErpGoodsQueryResponse goods = erpGoodsService.getGoods(query);
@@ -246,7 +250,7 @@ public class MallStoreTask
                     BigDecimal divide = salesPrice.multiply(new BigDecimal(config.getSalesPriceRate())).divide(new BigDecimal("100"));
                     System.out.println("代理价格"+divide);
                     System.out.println("成本价"+salesPrice);
-                    FsStoreProductAttrValueScrm va = new FsStoreProductAttrValueScrm();
+                    FsStoreProductAttrValue va = new FsStoreProductAttrValue();
                     va.setCost(salesPrice);
                     va.setAgentPrice(divide);
                     va.setId(value.getId());
@@ -255,9 +259,40 @@ public class MallStoreTask
             }
             System.out.println(goods);
         }
+    }
+
+
+    @Autowired
+    private FsStoreProductAttrValueScrmMapper fsStoreProductAttrValueScrmMapper;
 
+    public void storeProdUpdateCostPriceScrm()
+    {
+        String json=configService.selectConfigByKey("store.config");
+        StoreConfig config=JSONUtil.toBean(json,StoreConfig.class);
 
+        List<FsStoreProductAttrValueScrm> values = fsStoreProductAttrValueScrmMapper.selectFsStoreProductAttrValueList(new FsStoreProductAttrValueScrm());
+        for (FsStoreProductAttrValueScrm value : values) {
+            ErpGoodsQueryRequert query = new ErpGoodsQueryRequert();
+            query.setCode(value.getBarCode());
+            ErpGoodsQueryResponse goods = erpGoodsService.getGoodsScrm(query);
+            List<ErpGoods> items = goods.getItems();
 
+            if (items!=null&&items.size()>0){
+                ErpGoods erpGoods = items.get(0);
+                BigDecimal salesPrice = erpGoods.getSales_price();
+                if (salesPrice!=null&&salesPrice.compareTo(BigDecimal.ZERO) != 0){
+                    BigDecimal divide = salesPrice.multiply(new BigDecimal(config.getSalesPriceRate())).divide(new BigDecimal("100"));
+                    System.out.println("代理价格"+divide);
+                    System.out.println("成本价"+salesPrice);
+                    FsStoreProductAttrValueScrm va = new FsStoreProductAttrValueScrm();
+                    va.setCost(salesPrice);
+                    va.setAgentPrice(divide);
+                    va.setId(value.getId());
+                    fsStoreProductAttrValueScrmMapper.updateFsStoreProductAttrValue(va);
+                }
+            }
+            System.out.println(goods);
+        }
     }
     public void couponOp()
     {
@@ -473,7 +508,7 @@ public class MallStoreTask
                     //旺店通
                     erpOrderService = wdtOrderService;
                 } else if (erpType == 3) {
-                    //瀚智
+                    //代服
                     erpOrderService = hzOMSOrderService;
                 } else if (erpType == 4) {
                     //瀚智
@@ -591,4 +626,23 @@ public class MallStoreTask
         });
     }
 
+    public void getOrderDeliveryStatus()
+    {
+        IErpOrderService erpOrderService = getErpOrderService();
+        List<FsStoreOrderScrm> orders = null;
+        if (erpOrderService != null && erpOrderService == dfOrderService) {
+            orders = fsStoreOrderMapper.selectShippedOrder();
+            if (orders != null && !orders.isEmpty()) {
+                List<CompletableFuture<Void>> futures = new ArrayList<>();
+                for (FsStoreOrderScrm order : orders) {
+                    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
+                        erpOrderService.getOrderScrmDeliveryStatus(order);
+                    });
+                    futures.add(future);
+                }
+                CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
+            }
+        }
+    }
+
 }

+ 0 - 109
fs-admin/src/main/java/com/fs/hospital/controller/HospitalController.java

@@ -1,109 +0,0 @@
-package com.fs.hospital.controller;
-
-import java.util.List;
-
-import com.fs.common.core.domain.R;
-import com.fs.common.utils.SecurityUtils;
-import com.fs.hospital.param.HospitalParam;
-import com.fs.hospital.vo.HospitalHVO;
-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.hospital.domain.Hospital;
-import com.fs.hospital.service.IHospitalService;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.common.core.page.TableDataInfo;
-
-/**
- * 诊所Controller
- *
- * @author fs
- * @date 2024-02-26
- */
-@RestController
-@RequestMapping("/hospital/hospital")
-public class HospitalController extends BaseController
-{
-    @Autowired
-    private IHospitalService hospitalService;
-
-    /**
-     * 查询诊所列表
-     */
-    @PreAuthorize("@ss.hasPermi('hospital:hospital:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(HospitalParam hospital)
-    {
-        startPage();
-        List<HospitalHVO> list = hospitalService.selectHospitalListVO(hospital);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出诊所列表
-     */
-    @PreAuthorize("@ss.hasPermi('hospital:hospital:export')")
-    @Log(title = "诊所", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(HospitalParam hospital)
-    {
-        List<HospitalHVO> list = hospitalService.selectHospitalListVO(hospital);
-        ExcelUtil<HospitalHVO> util = new ExcelUtil<HospitalHVO>(HospitalHVO.class);
-        return util.exportExcel(list, "诊所数据");
-    }
-
-    /**
-     * 获取诊所详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('hospital:hospital:query')")
-    @GetMapping(value = "/{hospitalId}")
-    public AjaxResult getInfo(@PathVariable("hospitalId") Long hospitalId)
-    {
-        return AjaxResult.success(hospitalService.selectHospitalByHospitalId(hospitalId));
-    }
-
-    /**
-     * 新增诊所
-     */
-    @PreAuthorize("@ss.hasPermi('hospital:hospital:add')")
-    @Log(title = "诊所", businessType = BusinessType.INSERT)
-    @PostMapping
-    public R add(@RequestBody Hospital hospital)
-    {
-        hospital.setPassword(SecurityUtils.encryptPassword(hospital.getPassword()));
-        return hospitalService.insertHospital(hospital);
-    }
-
-    /**
-     * 修改诊所
-     */
-    @PreAuthorize("@ss.hasPermi('hospital:hospital:edit')")
-    @Log(title = "诊所", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody Hospital hospital)
-    {
-        return toAjax(hospitalService.updateHospital(hospital));
-    }
-
-    /**
-     * 删除诊所
-     */
-    @PreAuthorize("@ss.hasPermi('hospital:hospital:remove')")
-    @Log(title = "诊所", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{hospitalIds}")
-    public AjaxResult remove(@PathVariable Long[] hospitalIds)
-    {
-        return toAjax(hospitalService.deleteHospitalByHospitalIds(hospitalIds));
-    }
-}

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

@@ -10,7 +10,7 @@ import com.fs.system.mapper.SysConfigMapper;
 import io.jsonwebtoken.lang.Assert;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.http.util.Asserts;
 import org.redisson.api.RLock;
 import org.redisson.api.RedissonClient;
@@ -80,7 +80,7 @@ public class FsCourseTask {
             sysConfigMapper.updateConfig(sysConfig);
 
         }catch (Exception e){
-            log.error("充值失败 原因:{}", ExceptionUtils.getFullStackTrace(e),e);
+            log.error("充值失败 原因:{}", ExceptionUtils.getMessage(e),e);
             throw new RuntimeException(e);
         }finally {
             if (lock.isHeldByCurrentThread()) {

+ 1 - 4
fs-admin/src/main/java/com/fs/qw/controller/QwExternalContactController.java

@@ -57,11 +57,8 @@ public class QwExternalContactController extends BaseController
     @GetMapping("/list")
     public TableDataInfo list(QwExternalContactParam qwExternalContact)
     {
-        if(ObjectUtil.isEmpty(qwExternalContact.getCompanyId())){
-            throw new ServiceException("操作失败,请选择企业!");
-        }
         startPage();
-        List<QwExternalContactVO> list = qwExternalContactService.selectQwExternalContactListVO(qwExternalContact);
+        List<QwExternalContactVO> list = qwExternalContactService.selectQwExternalContactListVONewSys(qwExternalContact);
         list.forEach(item->{
 
             if (!Objects.equals(item.getTagIds(), "[]") && item.getTagIds()!=null) {

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

@@ -6,6 +6,7 @@ import com.fs.common.core.domain.model.LoginUser;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.utils.SecurityUtils;
 import com.fs.qw.domain.QwExternalContactTransferCompanyAudit;
+import com.fs.qw.domain.QwExternalContactTransferCompanyAuditUser;
 import com.fs.qw.dto.CompanyTransferAuditDTO;
 import com.fs.qw.service.IQwExternalContactTransferCompanyAuditService;
 import com.fs.qw.service.IQwExternalContactTransferCompanyAuditUserService;
@@ -35,8 +36,10 @@ public class QwExternalContactTransferCompanyAuditController extends BaseControl
 
     @PreAuthorize("@ss.hasPermi('qw:externalContactTransferCompanyAudit:detail')")
     @GetMapping("/detail/{auditId}")
-    public AjaxResult detail(@PathVariable Long auditId) {
-        return AjaxResult.success(auditUserService.getListByAuditId(auditId));
+    public TableDataInfo detail(@PathVariable Long auditId) {
+        startPage();
+        List<QwExternalContactTransferCompanyAuditUser> listByAuditId = auditUserService.getListByAuditId(auditId);
+        return getDataTable(listByAuditId);
     }
 
     @PreAuthorize("@ss.hasPermi('qw:externalContactTransferCompanyAudit:audit')")

+ 48 - 0
fs-admin/src/main/java/com/fs/qw/controller/QwPushCountController.java

@@ -1,11 +1,15 @@
 package com.fs.qw.controller;
 
 import com.fs.common.annotation.Log;
+import com.fs.common.constant.HttpStatus;
 import com.fs.common.core.controller.BaseController;
 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.TableSupport;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.fastGpt.domain.FastGptPushTokenTotal;
 import com.fs.qw.domain.QwPushCount;
 import com.fs.qw.service.IQwPushCountService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -151,4 +155,48 @@ public class QwPushCountController extends BaseController {
     public AjaxResult remove(@PathVariable Long[] ids) {
         return toAjax(qwPushCountService.deleteQwPushCountByIds(ids));
     }
+
+    @PreAuthorize("@ss.hasPermi('qw:qwPushCount:tokenList')")
+    @GetMapping("/tokenList")
+    public TableDataInfo tokenList(FastGptPushTokenTotal pushTokenInfo) {
+        List<FastGptPushTokenTotal> list = qwPushCountService.selectFastGptPushTokenTotalList(pushTokenInfo);
+
+
+        // 计算总和
+        FastGptPushTokenTotal sumTotal = new FastGptPushTokenTotal();
+        sumTotal.setCompanyName("合计"); // 假设有一个字段用于显示“合计”标签,具体字段名根据实际情况替换
+        Long sum = list.stream().mapToLong(FastGptPushTokenTotal::getCount).sum(); // 假设有一个数字字段需要求和,具体字段名根据实际情况替换
+        sumTotal.setCount(sum); // 设置合计值,具体字段名根据实际情况替换
+
+        // 获取分页参数
+        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<>(); // 返回空列表
+            }
+        }
+
+
+
+        list.add(sumTotal); // 将合计行添加到列表末尾
+
+        // 构造返回结果
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(HttpStatus.SUCCESS);
+        rspData.setMsg("查询成功");
+        rspData.setRows(list);
+        rspData.setTotal(total);
+        return rspData;
+    }
 }

+ 103 - 0
fs-admin/src/main/java/com/fs/qw/controller/QwUserComplainRecordController.java

@@ -0,0 +1,103 @@
+package com.fs.qw.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.qw.domain.QwUserComplainRecord;
+import com.fs.qw.service.IQwUserComplainRecordService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 企微员工投诉记录Controller
+ *
+ * @author fs
+ * @date 2025-10-22
+ */
+@RestController
+@RequestMapping("/qw/record")
+public class QwUserComplainRecordController extends BaseController
+{
+    @Autowired
+    private IQwUserComplainRecordService qwUserComplainRecordService;
+
+    /**
+     * 查询企微员工投诉记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:record:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(QwUserComplainRecord qwUserComplainRecord)
+    {
+        startPage();
+        List<QwUserComplainRecord> list = qwUserComplainRecordService.selectQwUserComplainRecordList(qwUserComplainRecord);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出企微员工投诉记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:record:export')")
+    @Log(title = "企微员工投诉记录", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(QwUserComplainRecord qwUserComplainRecord)
+    {
+        List<QwUserComplainRecord> list = qwUserComplainRecordService.selectQwUserComplainRecordList(qwUserComplainRecord);
+        ExcelUtil<QwUserComplainRecord> util = new ExcelUtil<QwUserComplainRecord>(QwUserComplainRecord.class);
+        return util.exportExcel(list, "企微员工投诉记录数据");
+    }
+
+    /**
+     * 获取企微员工投诉记录详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('qw:record:query')")
+    @GetMapping(value = "/{recordId}")
+    public AjaxResult getInfo(@PathVariable("recordId") Long recordId)
+    {
+        return AjaxResult.success(qwUserComplainRecordService.selectQwUserComplainRecordByRecordId(recordId));
+    }
+
+    /**
+     * 新增企微员工投诉记录
+     */
+    @PreAuthorize("@ss.hasPermi('qw:record:add')")
+    @Log(title = "企微员工投诉记录", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody QwUserComplainRecord qwUserComplainRecord)
+    {
+        return toAjax(qwUserComplainRecordService.insertQwUserComplainRecord(qwUserComplainRecord));
+    }
+
+    /**
+     * 修改企微员工投诉记录
+     */
+    @PreAuthorize("@ss.hasPermi('qw:record:edit')")
+    @Log(title = "企微员工投诉记录", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody QwUserComplainRecord qwUserComplainRecord)
+    {
+        return toAjax(qwUserComplainRecordService.updateQwUserComplainRecord(qwUserComplainRecord));
+    }
+
+    /**
+     * 删除企微员工投诉记录
+     */
+    @PreAuthorize("@ss.hasPermi('qw:record:remove')")
+    @Log(title = "企微员工投诉记录", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{recordIds}")
+    public AjaxResult remove(@PathVariable Long[] recordIds)
+    {
+        return toAjax(qwUserComplainRecordService.deleteQwUserComplainRecordByRecordIds(recordIds));
+    }
+}

+ 17 - 1
fs-admin/src/main/java/com/fs/qw/controller/QwUserController.java

@@ -3,13 +3,21 @@ package com.fs.qw.controller;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.model.LoginUser;
+import com.fs.common.utils.ServletUtils;
+import com.fs.qw.domain.QwExternalContactTransferCompanyAudit;
 import com.fs.qw.param.QwFsUserParam;
+import com.fs.qw.service.IQwExternalContactTransferCompanyAuditService;
 import com.fs.qw.service.IQwUserService;
+import com.fs.qw.vo.QwOptionsVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.List;
+
 /**
  * 企微用户Controller
  *
@@ -21,7 +29,8 @@ import org.springframework.web.bind.annotation.RestController;
 public class QwUserController extends BaseController {
     @Autowired
     private IQwUserService qwUserService;
-
+    @Autowired
+    private IQwExternalContactTransferCompanyAuditService auditService;
     @GetMapping("/getQwUserAll")
     public AjaxResult getQwUserAll(){
         return AjaxResult.success(qwUserService.getQwUserAll());
@@ -34,4 +43,11 @@ public class QwUserController extends BaseController {
     public R getQwUserInfo(QwFsUserParam param){
         return R.ok().put("data",qwUserService.getQwUserInfo(param));
     }
+
+   @GetMapping("/getMyQwCompanyList")
+    public R getMyQwCompanyList()
+    {
+        List<QwOptionsVO> list = qwUserService.selectQwCompanyListOptionsVOBySys();
+        return  R.ok().put("data",list);
+    }
 }

+ 27 - 0
fs-admin/src/main/java/com/fs/task/SgTestController.java

@@ -0,0 +1,27 @@
+package com.fs.task;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+/**
+ * @description:
+ * @author: Guos
+ * @time: 2025/10/23 下午2:18
+ */
+@RestController
+@RequestMapping("/sg/test")
+public class SgTestController {
+
+    @Resource
+    private SyncTuLinStudentInfoTask syncTuLinStudentInfoTask;
+
+
+    @RequestMapping("/execute")
+    public void execute(){
+        syncTuLinStudentInfoTask.execute();
+    }
+
+
+}

+ 25 - 0
fs-admin/src/main/java/com/fs/task/SyncTuLinStudentInfoTask.java

@@ -0,0 +1,25 @@
+package com.fs.task;
+
+import com.fs.tulin.service.ITulinInfoSyncLogService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Component;
+import javax.annotation.Resource;
+
+/**
+ * @description: 同步TuLin学生信息定时任务
+ * @author: Guos
+ * @time: 2025/10/23 上午10:26
+ */
+@AllArgsConstructor
+@Component("syncTuLinStudentInfoTask")
+public class SyncTuLinStudentInfoTask {
+
+
+    @Resource
+    private final ITulinInfoSyncLogService tulinInfoSyncLogService;
+
+    public void execute() {
+        tulinInfoSyncLogService.syncInfo();
+    }
+
+}

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

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

+ 26 - 7
fs-admin/src/main/java/com/fs/web/controller/system/SysLoginController.java

@@ -94,20 +94,39 @@ public class SysLoginController
             ajax.put("medicalMallConfig", medicalMallConfig);
         }
         ajax.put("user", user);
-        Integer isAdmin = 0;
+        SysRole isAdmin = new SysRole();
+        getIsAdmin(isAdmin, permissions, user);
+        ajax.put("isAdmin", isAdmin);
+        ajax.put("roles", roles);
+        ajax.put("permissions", permissions);
+
+        return ajax;
+    }
+
+    /**
+     * 获取电话地址权限
+     * @param isAdmin
+     * @param permissions
+     * @param user
+     */
+    private void getIsAdmin(SysRole isAdmin, Set<String> permissions, SysUser user) {
+        isAdmin.setIsCheckAddress(0);
+        isAdmin.setIsCheckPhone(0);
         if (permissions.contains("*:*:*")){
-            isAdmin = 1;
+            isAdmin.setIsCheckAddress(1);
+            isAdmin.setIsCheckPhone(1);
         }else {
             List<SysRole> roleList = user.getRoles();
             if (roleList != null && !roleList.isEmpty()) {
                 Long[] roleIds = roleList.stream().map(SysRole::getRoleId).toArray(Long[]::new);
-                isAdmin = roleService.getIsCheckPhone(roleIds)?1:0;
+//                isAdmin = roleService.getIsCheckPhone(roleIds)?1:0;
+                SysRole isCheckPermission = roleService.getIsCheckPermission(roleIds);
+                if (isCheckPermission != null) {
+                    isAdmin.setIsCheckPhone(isCheckPermission.getIsCheckPhone());
+                    isAdmin.setIsCheckAddress(isCheckPermission.getIsCheckAddress());
+                }
             }
         }
-        ajax.put("roles", roles);
-        ajax.put("permissions", permissions);
-        ajax.put("isAdmin", isAdmin);
-        return ajax;
     }
 
     /**

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

@@ -4,10 +4,10 @@ server:
 # Spring配置
 spring:
   profiles:
-    active: druid-jnmy-test
+#    active: dev
 #    active: druid-hdt
 #    active: druid-yzt
-#    active: druid-sxjz
+    active: druid-sxjz-test
 #    active: druid-sft
 #    active: druid-fby
 #    active: dev

+ 1 - 1
fs-admin/src/main/resources/logback.xml

@@ -72,7 +72,7 @@
     </appender>
 
 	<!-- 系统模块日志级别控制  -->
-	<logger name="com.fs" level="info" />
+	<logger name="com.fs" level="debug" />
 	<!-- Spring日志级别控制  -->
 	<logger name="org.springframework" level="warn" />
 

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

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

+ 7 - 0
fs-common/src/main/java/com/fs/common/constant/FsConstants.java

@@ -11,4 +11,11 @@ public interface FsConstants {
 
     String FRIEND_WELCOME_VIDEO_KEY = "friend:welcome:";
     String REDIS_INTEGRAL_ORDER_UNPAY = "integral:order:unpay:";
+
+    // 公司余额redis key "company:money:" + company.getCompanyId()
+    String COMPANY_MONEY_KEY = "company:money:";
+    // 公司余额redis 锁
+    String COMPANY_MONEY_LOCK = "company_money_lock:";
+    // 看客统计  按公司分组 按TimeType 0-今天,1-昨天,2-本周,3-本月,4-上月;
+    String WATCH_COURSE_STATISTICS_GROUP_COMPANY = "watch_course_statistics:group_company:";
 }

+ 7 - 0
fs-common/src/main/java/com/fs/common/enums/ImTypeEnum.java

@@ -0,0 +1,7 @@
+package com.fs.common.enums;
+
+public enum ImTypeEnum {
+    NONE,
+    TENCENT,
+    OPENIM;
+}

+ 59 - 0
fs-common/src/main/java/com/fs/common/utils/DateUtils.java

@@ -6,8 +6,12 @@ import java.text.SimpleDateFormat;
 import java.time.*;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoUnit;
+import java.time.temporal.TemporalAdjusters;
 import java.util.Calendar;
 import java.util.Date;
+import java.util.Map;
+
+import com.fs.common.utils.model.DateTimeEntity;
 import org.apache.commons.lang3.time.DateFormatUtils;
 
 /**
@@ -296,4 +300,59 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
         return calendar.getTimeInMillis();
     }
 
+
+    /**
+     * @Description: 根据类型返回开始时间和结束时间 最大时间是今天23:59:59 如本月 是1号00:00:00到今天的23:59:59
+     * @Param:  type: 0-今天 1-昨天 2-本周 3-本月 4-上月
+     * @Param:
+     * @Return:
+     * @Author xgb
+     * @Date 2025/10/27 14:09
+     */
+    public static DateTimeEntity getBetweenTime(int type){
+        // 根据type计算出时间范围
+        String startDate = "";
+        String endDate = "";
+
+        LocalDateTime now = LocalDateTime.now();
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        LocalTime startOfDayTime = LocalTime.MIN;
+        LocalTime endOfDayTime = LocalTime.of(23, 59, 59);
+        if(0 == type){
+            LocalDateTime startOfDay = now.with(startOfDayTime);
+            LocalDateTime endOfDay = now.with(endOfDayTime);
+            startDate = startOfDay.format(formatter);
+            endDate = endOfDay.format(formatter);
+        } else if(1 == type){
+            LocalDateTime yesterday = now.minusDays(1);
+            LocalDateTime startOfYesterday = yesterday.with(startOfDayTime);
+            LocalDateTime endOfYesterday = yesterday.with(endOfDayTime);
+            startDate = startOfYesterday.format(formatter);
+            endDate = endOfYesterday.format(formatter);
+        } else if(2 == type) {
+            LocalDateTime startOfWeek = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
+            LocalDateTime startOfStartOfWeek = startOfWeek.with(startOfDayTime);
+            LocalDateTime endOfToday = now.with(endOfDayTime);
+            startDate = startOfStartOfWeek.format(formatter);
+            endDate = endOfToday.format(formatter);
+        } else if(3 == type) {
+            LocalDateTime startOfMonth = now.withDayOfMonth(1);
+            LocalDateTime startOfStartOfMonth = startOfMonth.with(startOfDayTime);
+            LocalDateTime endOfToday = now.with(endOfDayTime);
+            startDate = startOfStartOfMonth.format(formatter);
+            endDate = endOfToday.format(formatter);
+        } else if(4 == type) {
+            LocalDateTime firstDayOfPreviousMonth = now.minusMonths(1).withDayOfMonth(1);
+            LocalDateTime lastDayOfPreviousMonth = now.withDayOfMonth(1).minusDays(1);
+
+            LocalDateTime startOfPrevMonthStart = firstDayOfPreviousMonth.with(startOfDayTime);
+            LocalDateTime endOfPrevMonthEnd = lastDayOfPreviousMonth.with(endOfDayTime);
+
+            startDate = startOfPrevMonthStart.format(formatter);
+            endDate = endOfPrevMonthEnd.format(formatter);
+        }
+
+        return new DateTimeEntity(startDate, endDate);
+    }
+
 }

+ 26 - 0
fs-common/src/main/java/com/fs/common/utils/model/DateTimeEntity.java

@@ -0,0 +1,26 @@
+package com.fs.common.utils.model;
+
+import lombok.Data;
+
+/**
+ * @description: 时间对象
+ * @author: Xgb
+ * @createDate: 2025/10/27
+ * @version: 1.0
+ */
+
+@Data
+public class DateTimeEntity {
+
+    private String startTime;
+
+    private String endTime;
+
+    public DateTimeEntity(String startTime, String endTime) {
+        this.startTime = startTime;
+        this.endTime = endTime;
+    }
+
+    public DateTimeEntity() {
+    }
+}

+ 37 - 0
fs-company-app/src/main/java/com/fs/app/controller/AppBaseController.java

@@ -4,15 +4,24 @@ package com.fs.app.controller;
 import cn.hutool.core.util.ObjectUtil;
 import com.fs.app.exception.FSException;
 import com.fs.app.utils.JwtUtils;
+import com.fs.common.constant.HttpStatus;
+import com.fs.common.core.page.PageDomain;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.core.page.TableSupport;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
+import com.fs.common.utils.sql.SqlUtil;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.his.domain.FsUser;
 import com.fs.his.service.IFsUserService;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
 import io.jsonwebtoken.Claims;
 import org.springframework.beans.factory.annotation.Autowired;
 
+import java.util.List;
 import java.util.concurrent.TimeUnit;
 
 
@@ -67,5 +76,33 @@ public class AppBaseController {
 		}
 		return user.getUserId();
 	}
+    /**
+     * 设置请求分页数据
+     */
+    protected void startPage()
+    {
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Integer pageNum = pageDomain.getPageNum();
+        Integer pageSize = pageDomain.getPageSize();
+        if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize))
+        {
+            String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
+            Boolean reasonable = pageDomain.getReasonable();
+            PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
+        }
+    }
 
+    /**
+     * 响应请求分页数据
+     */
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    protected TableDataInfo getDataTable(List<?> list)
+    {
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(HttpStatus.SUCCESS);
+        rspData.setMsg("查询成功");
+        rspData.setRows(list);
+        rspData.setTotal(new PageInfo(list).getTotal());
+        return rspData;
+    }
 }

+ 222 - 6
fs-company-app/src/main/java/com/fs/app/controller/CompanyUserController.java

@@ -2,6 +2,7 @@ package com.fs.app.controller;
 
 import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.app.annotation.Login;
@@ -11,19 +12,32 @@ import com.fs.app.vo.CompanySubUserVO;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.constant.UserConstants;
 import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.core.redis.RedisCache;
 import com.fs.common.exception.ServiceException;
 import com.fs.common.utils.PatternUtils;
 import com.fs.common.utils.bean.BeanUtils;
 import com.fs.company.domain.*;
 import com.fs.company.mapper.CompanyRoleMapper;
+import com.fs.company.mapper.CompanyUserMapper;
+import com.fs.company.param.companyUserAddPrintParam;
 import com.fs.company.service.*;
 import com.fs.company.vo.CompanyTagUserVO;
 import com.fs.company.vo.CompanyUserChangeApplyVO;
+import com.fs.config.ai.AiHostProper;
 import com.fs.core.security.SecurityUtils;
 import com.fs.course.service.IFsCourseRedPacketLogService;
 import com.fs.course.service.IFsCourseWatchLogService;
 import com.fs.course.service.IFsUserCompanyUserService;
+import com.fs.fastGpt.domain.FastgptChatVoiceHomo;
+import com.fs.fastGpt.mapper.FastgptChatVoiceHomoMapper;
+import com.fs.fastgptApi.util.AudioUtils;
+import com.fs.fastgptApi.vo.AudioVO;
 import com.fs.qw.dto.UserProjectDTO;
+import com.fs.sop.domain.QwSopTempVoice;
+import com.fs.sop.service.IQwSopTempVoiceService;
+import com.fs.system.oss.CloudStorageService;
+import com.fs.system.oss.OSSFactory;
 import com.fs.system.service.ISysDictDataService;
 import com.fs.system.vo.DictVO;
 import com.github.pagehelper.PageHelper;
@@ -34,10 +48,19 @@ import io.swagger.annotations.ApiParam;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.apache.ibatis.annotations.Param;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.Valid;
+import java.io.File;
+import java.io.FileInputStream;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.time.LocalDate;
@@ -59,12 +82,15 @@ public class CompanyUserController extends AppBaseController {
     private final ICompanyUserChangeApplyService companyUserChangeApplyService;
     private final CompanyRoleMapper companyRoleMapper;
     private final IAppService appService;
-    @Autowired
-    private ISysDictDataService dictDataService;
-    @Autowired
-    private IFsUserCompanyUserService fsUserCompanyUserService;
-    @Autowired
-    private ICompanyTagUserService companyTagUserService;
+    private final RedisCache redisCache;
+    private final CompanyUserMapper companyUserMapper;
+    private final IQwSopTempVoiceService voiceService;
+    private final AiHostProper aiHostProper;
+    private final ISysDictDataService dictDataService;
+    private final IFsUserCompanyUserService fsUserCompanyUserService;
+    private final ICompanyTagUserService companyTagUserService;
+    private final FastgptChatVoiceHomoMapper fastgptChatVoiceHomoMapper;
+    public static final String SOP_TEMP_VOICE_KEY = "sop:tempVoice";
 
     @Login
     @ApiOperation("查询用户列表")
@@ -394,4 +420,194 @@ public class CompanyUserController extends AppBaseController {
                 .collect(Collectors.toList());
         return R.ok().put("data",filteredDictVOS);
     }
+
+    @ApiOperation("查询所有项目")
+    @GetMapping("/getDictProject")
+    public R getDictProject(){
+        List<DictVO> dictVOS = dictDataService.selectDictDataListByType("sys_course_project");
+        return R.ok().put("data",dictVOS);
+    }
+
+    /**
+     * 当只有模板文字text时,生成表中对应条的voice_url和user_voice_url
+     * @param id            qw_sop_temp_voice的id
+     * @return
+     */
+    @GetMapping("/companyUserVoice")
+    public R companyUserVoice(@RequestParam("id") Long id){
+        AudioVO audioVO = new AudioVO();
+        Long companyUserId = getCompanyUserId();
+        List<QwSopTempVoice> sopTempVoices = redisCache.getVoiceAllList(SOP_TEMP_VOICE_KEY + ":" + companyUserId);
+        if(sopTempVoices != null && !sopTempVoices.isEmpty()){
+            List<Long> collect = sopTempVoices.stream().map(QwSopTempVoice::getId).collect(Collectors.toList());
+            if (collect.contains(id)){
+                return R.ok().put("code",202).put("msg","该语音已进入转换,请完成后再试。");
+            }
+        }
+
+        if(companyUserId != null){
+            CompanyUser companyUser = companyUserMapper.selectCompanyUserByCompanyUserId(companyUserId);
+            if(companyUser != null && companyUser.getVoicePrintUrl() == null){
+                return R.ok().put("code",201).put("msg","账号未录制声纹,请录制后再试!");
+            }
+        }
+
+        QwSopTempVoice qwSopTempVoice = voiceService.selectQwSopTempVoiceById(id);
+        if(qwSopTempVoice != null && qwSopTempVoice.getCompanyUserId() != null){
+            List<FastgptChatVoiceHomo> homos = fastgptChatVoiceHomoMapper.selectFastgptChatVoiceHomoList(new FastgptChatVoiceHomo());
+            audioVO = AudioUtils.createUserUrlAndUrl(homos,qwSopTempVoice.getCompanyUserId(), qwSopTempVoice.getVoiceTxt().replace(" ",""));
+            if(audioVO != null && audioVO.getWavUrl() != null &&  audioVO.getUrl() != null){
+                qwSopTempVoice.setVoiceUrl(audioVO.getUrl());
+                qwSopTempVoice.setUserVoiceUrl(audioVO.getWavUrl());
+                qwSopTempVoice.setDuration(audioVO.getDuration());
+                qwSopTempVoice.setRecordType(1);
+                voiceService.updateQwSopTempVoice(qwSopTempVoice);
+            }
+        }
+        return R.ok().put("data", audioVO);
+    }
+    @Login
+    @ApiOperation("上传声纹")
+    @PostMapping("/addVoicePrintUrl")
+    public R addVoicePrintUrl(@RequestBody companyUserAddPrintParam param) throws Exception {
+        Long userId=getCompanyUserId();
+        if(userId==null){
+            return R.error(403,"用户失效");
+        }
+        CompanyUser companyUser = new CompanyUser();
+        companyUser.setUserId(userId);
+        companyUser.setVoicePrintUrl(param.getVoicePrintUrl());
+
+        //转换音频格式 mp3-wav
+        String s = AudioUtils.audioWAVFromUrl(param.getVoicePrintUrl());
+
+        //保存文件并且上传存储桶
+        System.out.println(s);
+        File file = new File(s);
+        FileInputStream fileInputStream = new FileInputStream(file);
+        CloudStorageService storage = OSSFactory.build();
+        String wavUrl = storage.uploadSuffix(fileInputStream, ".wav");
+
+        //更新销售员工声纹
+        companyUser.setVoicePrintUrl(wavUrl);
+        companyUserMapper.updateCompanyUser(companyUser);
+
+        try {
+            CloseableHttpClient httpClient = HttpClients.createDefault();
+            HttpPost httpPost = new HttpPost(aiHostProper.getCommonApi()+"/app/common/addCompanyAudio");
+            String json = "{\"url\":\""+wavUrl+"\",\"id\":\""+userId+"\"}";
+            StringEntity entity = new StringEntity(json);
+            httpPost.setEntity(entity);
+            httpPost.setHeader("Content-type", "application/json");
+            HttpResponse response = httpClient.execute(httpPost);
+
+            if (response.getStatusLine().getStatusCode() == 200) {
+                String responseBody = EntityUtils.toString(response.getEntity());
+                JSONObject jsonObject = JSON.parseObject(responseBody);
+                Integer code = (Integer)jsonObject.get("code");
+                if (code==200){
+                    voiceService.insertQwSopTempVoiceModel(userId);
+                    return R.ok();
+                }
+            } else {
+                return R.error();
+            }
+
+            httpClient.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return R.error();
+
+    }
+
+    /**
+     * 当只有user_voice_url时,生成表中对应条的voice_url
+     * @param userVoiceUrl  wav格式的语音文件
+     * @param id            qw_sop_temp_voice的id
+     * @return
+     */
+    @GetMapping("/companyUserVoiceNew")
+    public R companyUserVoiceNew( @RequestParam("id") Long id,@RequestParam("userVoiceUrl") String userVoiceUrl){
+
+        AudioVO audioVO = new AudioVO();
+        Long companyUserId = getCompanyUserId();
+        List<QwSopTempVoice> sopTempVoices = redisCache.getVoiceAllList(SOP_TEMP_VOICE_KEY + ":" + companyUserId);
+        if(sopTempVoices != null && !sopTempVoices.isEmpty()){
+            List<Long> collect = sopTempVoices.stream().map(QwSopTempVoice::getId).collect(Collectors.toList());
+            if (collect.contains(id)){
+                return R.ok().put("code",202).put("msg","该语音已进入转换,请完成后再试。");
+            }
+        }
+
+        QwSopTempVoice qwSopTempVoice = voiceService.selectQwSopTempVoiceByIdAndUserVoiceUrl(id);
+        if(qwSopTempVoice != null && qwSopTempVoice.getId() != null){
+            audioVO = AudioUtils.createVoiceUrl(qwSopTempVoice.getCompanyUserId(), userVoiceUrl);
+            if(audioVO != null && audioVO.getUrl() != null){
+                qwSopTempVoice.setVoiceUrl(audioVO.getUrl());
+                qwSopTempVoice.setUserVoiceUrl(userVoiceUrl);
+                qwSopTempVoice.setDuration(audioVO.getDuration());
+                qwSopTempVoice.setRecordType(1);
+                voiceService.updateQwSopTempVoice(qwSopTempVoice);
+            }
+        }
+        return R.ok().put("data", audioVO);
+    }
+    @GetMapping("/querySopVoiceList")
+    public TableDataInfo querySopVoiceList(@Param("recordType") Integer recordType){
+        startPage();
+        QwSopTempVoice sopTempVoice = new QwSopTempVoice();
+        sopTempVoice.setRecordType(recordType);
+        sopTempVoice.setCompanyUserId(getCompanyUserId());
+        List<QwSopTempVoice> sopTempVoices = voiceService.selectQwSopTempVoiceNewList(sopTempVoice);
+        return getDataTable(sopTempVoices);
+    }
+    @GetMapping("/query/{id}")
+    public R querySopVoiceById(@PathVariable("id") Long id){
+        QwSopTempVoice tempVoice = voiceService.selectQwSopTempVoiceById(id);
+        AudioVO audioVO = new AudioVO();
+        if(tempVoice != null){
+            audioVO.setId(tempVoice.getId());
+            audioVO.setVoiceTxt(tempVoice.getVoiceTxt());
+            audioVO.setUrl(tempVoice.getVoiceUrl());
+            audioVO.setWavUrl(tempVoice.getUserVoiceUrl());
+            audioVO.setDuration(tempVoice.getDuration());
+            audioVO.setRecordType(tempVoice.getRecordType());
+        }
+        return R.ok().put("data", audioVO);
+    }
+    /**
+     * 一键转换
+     * @return
+     */
+    @GetMapping("/createUserAllVoice")
+    public R createUserAllVoice(){
+        QwSopTempVoice sopTempVoice = new QwSopTempVoice();
+        sopTempVoice.setRecordType(0);
+        Long companyUserId = getCompanyUserId();
+
+
+        if(companyUserId != null){
+            CompanyUser companyUser = companyUserMapper.selectCompanyUserByCompanyUserId(companyUserId);
+            if(companyUser != null && companyUser.getVoicePrintUrl() == null){
+                return R.ok().put("code",201).put("msg","账号未录制声纹,请录制后再试!");
+            }
+        }
+
+        sopTempVoice.setCompanyUserId(companyUserId);
+        List<QwSopTempVoice> sopTempVoices = voiceService.selectQwSopTempVoiceNewList(sopTempVoice);
+        if(sopTempVoices != null && !sopTempVoices.isEmpty()){
+            List<Long> newCompanyUserId = redisCache.getVoiceAllList(SOP_TEMP_VOICE_KEY);
+            if(newCompanyUserId != null && newCompanyUserId.contains(companyUserId)){
+                return R.error().put("code",202).put("msg","语音还未转换完成,请完成后再添加!");
+            }else{
+                redisCache.setVoice(SOP_TEMP_VOICE_KEY,companyUserId);
+                sopTempVoices.forEach(m -> m.setVoiceTxt(m.getVoiceTxt().replace(" ","")));
+                redisCache.setVoiceList(SOP_TEMP_VOICE_KEY + ":" + companyUserId, sopTempVoices);
+                return R.ok().put("msg","语音已加入队列进行转换,请耐心等待!");
+            }
+        }
+        return null;
+    }
 }

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

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

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

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

+ 28 - 32
fs-company-app/src/main/java/com/fs/core/aspectj/DataScopeAspect.java

@@ -1,27 +1,20 @@
 package com.fs.core.aspectj;
 
-import com.fs.app.utils.JwtUtils;
 import com.fs.common.annotation.DataScope;
 import com.fs.common.core.domain.BaseEntity;
+import com.fs.common.core.domain.entity.SysRole;
+import com.fs.common.core.domain.entity.SysUser;
+import com.fs.common.core.domain.model.LoginUser;
+import com.fs.common.utils.SecurityUtils;
 import com.fs.common.utils.StringUtils;
-import com.fs.common.utils.spring.SpringUtils;
-import com.fs.company.domain.CompanyRole;
-import com.fs.company.domain.CompanyUser;
-import com.fs.company.service.ICompanyUserService;
-import io.jsonwebtoken.Claims;
 import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.Signature;
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Before;
 import org.aspectj.lang.annotation.Pointcut;
 import org.aspectj.lang.reflect.MethodSignature;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
-import org.springframework.web.context.request.RequestAttributes;
-import org.springframework.web.context.request.RequestContextHolder;
-import org.springframework.web.context.request.ServletRequestAttributes;
 
-import javax.servlet.http.HttpServletRequest;
 import java.lang.reflect.Method;
 
 /**
@@ -33,9 +26,6 @@ import java.lang.reflect.Method;
 @Component
 public class DataScopeAspect
 {
-    @Autowired
-    JwtUtils jwtUtils;
-
     /**
      * 全部数据权限
      */
@@ -75,6 +65,7 @@ public class DataScopeAspect
     @Before("dataScopePointCut()")
     public void doBefore(JoinPoint point) throws Throwable
     {
+        clearDataScope(point);
         handleDataScope(point);
     }
 
@@ -86,22 +77,15 @@ public class DataScopeAspect
         {
             return;
         }
-        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
-        ServletRequestAttributes sra = (ServletRequestAttributes)ra;
-        HttpServletRequest request = sra.getRequest();
-
-        String headValue = request.getHeader("APPToken");
-        Claims claims = jwtUtils.getClaimByToken(headValue);
-        Long userId =Long.parseLong( claims.getSubject().toString());
-
         // 获取当前的用户
-        CompanyUser user = SpringUtils.getBean(ICompanyUserService.class).selectCompanyUserById(userId);
-        if (StringUtils.isNotNull(user))
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        if (StringUtils.isNotNull(loginUser))
         {
+            SysUser currentUser = loginUser.getUser();
             // 如果是超级管理员,则不过滤数据
-            if (StringUtils.isNotNull(user) && !user.isAdmin())
+            if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
             {
-                dataScopeFilter(joinPoint, user, controllerDataScope.deptAlias(),
+                dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
                         controllerDataScope.userAlias());
             }
         }
@@ -114,11 +98,11 @@ public class DataScopeAspect
      * @param user 用户
      * @param userAlias 别名
      */
-    public static void dataScopeFilter(JoinPoint joinPoint, CompanyUser user, String deptAlias, String userAlias)
+    public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
     {
         StringBuilder sqlString = new StringBuilder();
 
-        for (CompanyRole role : user.getRoles())
+        for (SysRole role : user.getRoles())
         {
             String dataScope = role.getDataScope();
             if (DATA_SCOPE_ALL.equals(dataScope))
@@ -129,7 +113,7 @@ public class DataScopeAspect
             else if (DATA_SCOPE_CUSTOM.equals(dataScope))
             {
                 sqlString.append(StringUtils.format(
-                        " OR {}.dept_id IN ( SELECT dept_id FROM company_role_dept WHERE role_id = {} ) ", deptAlias,
+                        " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
                         role.getRoleId()));
             }
             else if (DATA_SCOPE_DEPT.equals(dataScope))
@@ -139,7 +123,7 @@ public class DataScopeAspect
             else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
             {
                 sqlString.append(StringUtils.format(
-                        " OR {}.dept_id IN ( SELECT dept_id FROM company_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
+                        " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
                         deptAlias, user.getDeptId(), user.getDeptId()));
             }
             else if (DATA_SCOPE_SELF.equals(dataScope))
@@ -151,8 +135,7 @@ public class DataScopeAspect
                 else
                 {
                     // 数据权限为仅本人且没有userAlias别名不查询任何数据
-//                    sqlString.append(" OR 1=0 ");
-                    sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
+                    sqlString.append(" OR 1=0 ");
                 }
             }
         }
@@ -183,4 +166,17 @@ public class DataScopeAspect
         }
         return null;
     }
+
+    /**
+     * 拼接权限sql前先清空params.dataScope参数防止注入
+     */
+    private void clearDataScope(final JoinPoint joinPoint)
+    {
+        Object params = joinPoint.getArgs()[0];
+        if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
+        {
+            BaseEntity baseEntity = (BaseEntity) params;
+            baseEntity.getParams().put(DATA_SCOPE, "");
+        }
+    }
 }

+ 3 - 3
fs-hospital/src/main/java/com/fs/framework/aspectj/DataSourceAspect.java → fs-company-app/src/main/java/com/fs/core/aspectj/DataSourceAspect.java

@@ -1,8 +1,8 @@
-package com.fs.framework.aspectj;
+package com.fs.core.aspectj;
 
 import com.fs.common.annotation.DataSource;
 import com.fs.common.utils.StringUtils;
-import com.fs.framework.datasource.DynamicDataSourceContextHolder;
+import com.fs.core.datasource.DynamicDataSourceContextHolder;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
 import org.aspectj.lang.annotation.Aspect;
@@ -18,7 +18,7 @@ import java.util.Objects;
 
 /**
  * 多数据源处理
- *
+ * 
 
  */
 @Aspect

+ 44 - 19
fs-hospital/src/main/java/com/fs/framework/aspectj/LogAspect.java → fs-company-app/src/main/java/com/fs/core/aspectj/LogAspect.java

@@ -1,18 +1,17 @@
-package com.fs.framework.aspectj;
+package com.fs.core.aspectj;
 
 import com.alibaba.fastjson.JSON;
 import com.fs.common.annotation.Log;
+import com.fs.common.core.domain.model.LoginUser;
 import com.fs.common.enums.BusinessStatus;
 import com.fs.common.enums.HttpMethod;
+import com.fs.common.utils.SecurityUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.ip.IpUtils;
-import com.fs.common.utils.spring.SpringUtils;
-import com.fs.hospital.domain.HospitalOperLog;
-import com.fs.framework.manager.AsyncManager;
-import com.fs.framework.manager.factory.AsyncFactory;
-import com.fs.framework.security.LoginUser;
-import com.fs.framework.service.TokenService;
+import com.fs.core.manager.AsyncManager;
+import com.fs.core.manager.factory.AsyncFactory;
+import com.fs.system.domain.SysOperLog;
 import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.Signature;
 import org.aspectj.lang.annotation.AfterReturning;
@@ -23,17 +22,20 @@ import org.aspectj.lang.reflect.MethodSignature;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
+import org.springframework.validation.BindingResult;
 import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.servlet.HandlerMapping;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Iterator;
 import java.util.Map;
 
 /**
  * 操作日志记录处理
- *
+ * 
 
  */
 @Aspect
@@ -61,7 +63,7 @@ public class LogAspect
 
     /**
      * 拦截异常操作
-     *
+     * 
      * @param joinPoint 切点
      * @param e 异常
      */
@@ -83,11 +85,10 @@ public class LogAspect
             }
 
             // 获取当前的用户
-            LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
+            LoginUser loginUser = SecurityUtils.getLoginUser();
 
             // *========数据库日志=========*//
-            HospitalOperLog operLog = new HospitalOperLog();
-            operLog.setHospitalId(1L);
+            SysOperLog operLog = new SysOperLog();
             operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
             // 请求的地址
             String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
@@ -128,12 +129,12 @@ public class LogAspect
 
     /**
      * 获取注解中对方法的描述信息 用于Controller层注解
-     *
+     * 
      * @param log 日志
      * @param operLog 操作日志
      * @throws Exception
      */
-    public void getControllerMethodDescription(JoinPoint joinPoint, Log log, HospitalOperLog operLog) throws Exception
+    public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog) throws Exception
     {
         // 设置action动作
         operLog.setBusinessType(log.businessType().ordinal());
@@ -151,11 +152,11 @@ public class LogAspect
 
     /**
      * 获取请求的参数,放到log中
-     *
+     * 
      * @param operLog 操作日志
      * @throws Exception 异常
      */
-    private void setRequestValue(JoinPoint joinPoint, HospitalOperLog operLog) throws Exception
+    private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception
     {
         String requestMethod = operLog.getRequestMethod();
         if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod))
@@ -196,7 +197,7 @@ public class LogAspect
         {
             for (int i = 0; i < paramsArray.length; i++)
             {
-                if (!isFilterObject(paramsArray[i]))
+                if (StringUtils.isNotNull(paramsArray[i]) && !isFilterObject(paramsArray[i]))
                 {
                     Object jsonObj = JSON.toJSON(paramsArray[i]);
                     params += jsonObj.toString() + " ";
@@ -208,12 +209,36 @@ public class LogAspect
 
     /**
      * 判断是否需要过滤的对象。
-     *
+     * 
      * @param o 对象信息。
      * @return 如果是需要过滤的对象,则返回true;否则返回false。
      */
+    @SuppressWarnings("rawtypes")
     public boolean isFilterObject(final Object o)
     {
-        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse;
+        Class<?> clazz = o.getClass();
+        if (clazz.isArray())
+        {
+            return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
+        }
+        else if (Collection.class.isAssignableFrom(clazz))
+        {
+            Collection collection = (Collection) o;
+            for (Iterator iter = collection.iterator(); iter.hasNext();)
+            {
+                return iter.next() instanceof MultipartFile;
+            }
+        }
+        else if (Map.class.isAssignableFrom(clazz))
+        {
+            Map map = (Map) o;
+            for (Iterator iter = map.entrySet().iterator(); iter.hasNext();)
+            {
+                Map.Entry entry = (Map.Entry) iter.next();
+                return entry.getValue() instanceof MultipartFile;
+            }
+        }
+        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
+                || o instanceof BindingResult;
     }
 }

+ 19 - 48
fs-hospital/src/main/java/com/fs/framework/config/DruidConfig.java → fs-company-app/src/main/java/com/fs/core/config/DataSourceConfig.java

@@ -1,13 +1,11 @@
-package com.fs.framework.config;
+package com.fs.core.config;
 
 import com.alibaba.druid.pool.DruidDataSource;
-import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
 import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
 import com.alibaba.druid.util.Utils;
-import com.fs.framework.datasource.DynamicDataSource;
 import com.fs.common.enums.DataSourceType;
-import com.fs.common.utils.spring.SpringUtils;
-import com.fs.framework.config.properties.DruidProperties;
+import com.fs.core.datasource.DynamicDataSource;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.boot.web.servlet.FilterRegistrationBean;
@@ -16,65 +14,38 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Primary;
 
 import javax.servlet.*;
+import javax.servlet.FilterConfig;
 import javax.sql.DataSource;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 
-/**
- * druid 配置多数据源
- *
-
- */
 @Configuration
-public class DruidConfig
-{
+public class DataSourceConfig {
+
     @Bean
-    @ConfigurationProperties("spring.datasource.mysql.druid.master")
-    public DataSource masterDataSource(DruidProperties druidProperties)
-    {
-        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
-        return druidProperties.dataSource(dataSource);
+    @ConfigurationProperties(prefix = "spring.datasource.sop.druid.master")
+    public DataSource sopDataSource() {
+        return new DruidDataSource();
     }
 
     @Bean
-    @ConfigurationProperties("spring.datasource.mysql.druid.slave")
-    @ConditionalOnProperty(prefix = "spring.datasource.mysql.druid.slave", name = "enabled", havingValue = "true")
-    public DataSource slaveDataSource(DruidProperties druidProperties)
-    {
-        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
-        return druidProperties.dataSource(dataSource);
+    @ConfigurationProperties(prefix = "spring.datasource.mysql.druid.master")
+    public DataSource masterDataSource() {
+        return new DruidDataSource();
     }
 
-    @Bean(name = "dynamicDataSource")
+
+
+    @Bean
     @Primary
-    public DynamicDataSource dataSource(DataSource masterDataSource)
-    {
+    public DynamicDataSource dataSource(@Qualifier("masterDataSource") DataSource masterDataSource, @Qualifier("sopDataSource") DataSource sopDataSource) {
         Map<Object, Object> targetDataSources = new HashMap<>();
-        targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
-        setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
+        targetDataSources.put(DataSourceType.MASTER, masterDataSource);
+        targetDataSources.put(DataSourceType.SOP.name(), sopDataSource);
         return new DynamicDataSource(masterDataSource, targetDataSources);
     }
 
-    /**
-     * 设置数据源
-     *
-     * @param targetDataSources 备选数据源集合
-     * @param sourceName 数据源名称
-     * @param beanName bean名称
-     */
-    public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName)
-    {
-        try
-        {
-            DataSource dataSource = SpringUtils.getBean(beanName);
-            targetDataSources.put(sourceName, dataSource);
-        }
-        catch (Exception e)
-        {
-        }
-    }
-
     /**
      * 去除监控页面底部的广告
      */
@@ -92,7 +63,7 @@ public class DruidConfig
         // 创建filter进行过滤
         Filter filter = new Filter()
         {
-
+            @Override
             public void init(FilterConfig filterConfig) throws ServletException
             {
             }

+ 123 - 123
fs-company-app/src/main/java/com/fs/core/config/DruidConfig.java

@@ -1,123 +1,123 @@
-package com.fs.core.config;
-
-import com.alibaba.druid.pool.DruidDataSource;
-import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
-import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
-import com.alibaba.druid.util.Utils;
-import com.fs.common.enums.DataSourceType;
-import com.fs.common.utils.spring.SpringUtils;
-import com.fs.core.config.properties.DruidProperties;
-import com.fs.core.datasource.DynamicDataSource;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Primary;
-
-import javax.servlet.*;
-import javax.sql.DataSource;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * druid 配置多数据源
- * 
-
- */
-@Configuration
-public class DruidConfig
-{
-    @Bean
-    @ConfigurationProperties("spring.datasource.mysql.druid.master")
-    public DataSource masterDataSource(DruidProperties druidProperties)
-    {
-        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
-        return druidProperties.dataSource(dataSource);
-    }
-
-    @Bean
-    @ConfigurationProperties("spring.datasource.mysql.druid.slave")
-    @ConditionalOnProperty(prefix = "spring.datasource.mysql.druid.slave", name = "enabled", havingValue = "true")
-    public DataSource slaveDataSource(DruidProperties druidProperties)
-    {
-        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
-        return druidProperties.dataSource(dataSource);
-    }
-
-    @Bean(name = "dynamicDataSource")
-    @Primary
-    public DynamicDataSource dataSource(DataSource masterDataSource)
-    {
-        Map<Object, Object> targetDataSources = new HashMap<>();
-        targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
-        setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
-        return new DynamicDataSource(masterDataSource, targetDataSources);
-    }
-    
-    /**
-     * 设置数据源
-     * 
-     * @param targetDataSources 备选数据源集合
-     * @param sourceName 数据源名称
-     * @param beanName bean名称
-     */
-    public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName)
-    {
-        try
-        {
-            DataSource dataSource = SpringUtils.getBean(beanName);
-            targetDataSources.put(sourceName, dataSource);
-        }
-        catch (Exception e)
-        {
-        }
-    }
-
-    /**
-     * 去除监控页面底部的广告
-     */
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    @Bean
-    @ConditionalOnProperty(name = "spring.datasource.mysql.druid.statViewServlet.enabled", havingValue = "true")
-    public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties)
-    {
-        // 获取web监控页面的参数
-        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
-        // 提取common.js的配置路径
-        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
-        String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
-        final String filePath = "support/http/resources/js/common.js";
-        // 创建filter进行过滤
-        Filter filter = new Filter()
-        {
-            @Override
-            public void init(javax.servlet.FilterConfig filterConfig) throws ServletException
-            {
-            }
-            @Override
-            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
-                    throws IOException, ServletException
-            {
-                chain.doFilter(request, response);
-                // 重置缓冲区,响应头不会被重置
-                response.resetBuffer();
-                // 获取common.js
-                String text = Utils.readFromResource(filePath);
-                // 正则替换banner, 除去底部的广告信息
-                text = text.replaceAll("<a.*?banner\"></a><br/>", "");
-                text = text.replaceAll("powered.*?shrek.wang</a>", "");
-                response.getWriter().write(text);
-            }
-            @Override
-            public void destroy()
-            {
-            }
-        };
-        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
-        registrationBean.setFilter(filter);
-        registrationBean.addUrlPatterns(commonJsPattern);
-        return registrationBean;
-    }
-}
+//package com.fs.core.config;
+//
+//import com.alibaba.druid.pool.DruidDataSource;
+//import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
+//import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
+//import com.alibaba.druid.util.Utils;
+//import com.fs.common.enums.DataSourceType;
+//import com.fs.common.utils.spring.SpringUtils;
+//import com.fs.core.config.properties.DruidProperties;
+//import com.fs.core.datasource.DynamicDataSource;
+//import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+//import org.springframework.boot.context.properties.ConfigurationProperties;
+//import org.springframework.boot.web.servlet.FilterRegistrationBean;
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.context.annotation.Primary;
+//
+//import javax.servlet.*;
+//import javax.sql.DataSource;
+//import java.io.IOException;
+//import java.util.HashMap;
+//import java.util.Map;
+//
+///**
+// * druid 配置多数据源
+// *
+//
+// */
+//@Configuration
+//public class DruidConfig
+//{
+//    @Bean
+//    @ConfigurationProperties("spring.datasource.mysql.druid.master")
+//    public DataSource masterDataSource(DruidProperties druidProperties)
+//    {
+//        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
+//        return druidProperties.dataSource(dataSource);
+//    }
+//
+//    @Bean
+//    @ConfigurationProperties("spring.datasource.mysql.druid.slave")
+//    @ConditionalOnProperty(prefix = "spring.datasource.mysql.druid.slave", name = "enabled", havingValue = "true")
+//    public DataSource slaveDataSource(DruidProperties druidProperties)
+//    {
+//        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
+//        return druidProperties.dataSource(dataSource);
+//    }
+//
+//    @Bean(name = "dynamicDataSource")
+//    @Primary
+//    public DynamicDataSource dataSource(DataSource masterDataSource)
+//    {
+//        Map<Object, Object> targetDataSources = new HashMap<>();
+//        targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
+//        setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
+//        return new DynamicDataSource(masterDataSource, targetDataSources);
+//    }
+//
+//    /**
+//     * 设置数据源
+//     *
+//     * @param targetDataSources 备选数据源集合
+//     * @param sourceName 数据源名称
+//     * @param beanName bean名称
+//     */
+//    public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName)
+//    {
+//        try
+//        {
+//            DataSource dataSource = SpringUtils.getBean(beanName);
+//            targetDataSources.put(sourceName, dataSource);
+//        }
+//        catch (Exception e)
+//        {
+//        }
+//    }
+//
+//    /**
+//     * 去除监控页面底部的广告
+//     */
+//    @SuppressWarnings({ "rawtypes", "unchecked" })
+//    @Bean
+//    @ConditionalOnProperty(name = "spring.datasource.mysql.druid.statViewServlet.enabled", havingValue = "true")
+//    public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties)
+//    {
+//        // 获取web监控页面的参数
+//        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
+//        // 提取common.js的配置路径
+//        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
+//        String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
+//        final String filePath = "support/http/resources/js/common.js";
+//        // 创建filter进行过滤
+//        Filter filter = new Filter()
+//        {
+//            @Override
+//            public void init(javax.servlet.FilterConfig filterConfig) throws ServletException
+//            {
+//            }
+//            @Override
+//            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+//                    throws IOException, ServletException
+//            {
+//                chain.doFilter(request, response);
+//                // 重置缓冲区,响应头不会被重置
+//                response.resetBuffer();
+//                // 获取common.js
+//                String text = Utils.readFromResource(filePath);
+//                // 正则替换banner, 除去底部的广告信息
+//                text = text.replaceAll("<a.*?banner\"></a><br/>", "");
+//                text = text.replaceAll("powered.*?shrek.wang</a>", "");
+//                response.getWriter().write(text);
+//            }
+//            @Override
+//            public void destroy()
+//            {
+//            }
+//        };
+//        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
+//        registrationBean.setFilter(filter);
+//        registrationBean.addUrlPatterns(commonJsPattern);
+//        return registrationBean;
+//    }
+//}

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

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

+ 3 - 3
fs-company-app/src/main/java/com/fs/core/datasource/DynamicDataSource.java

@@ -7,8 +7,8 @@ import java.util.Map;
 
 /**
  * 动态数据源
- * 
- 
+ *
+
  */
 public class DynamicDataSource extends AbstractRoutingDataSource
 {
@@ -24,4 +24,4 @@ public class DynamicDataSource extends AbstractRoutingDataSource
     {
         return DynamicDataSourceContextHolder.getDataSourceType();
     }
-}
+}

+ 4 - 5
fs-company-app/src/main/java/com/fs/core/datasource/DynamicDataSourceContextHolder.java

@@ -5,11 +5,10 @@ import org.slf4j.LoggerFactory;
 
 /**
  * 数据源切换处理
- * 
- 
+ *
+
  */
-public class DynamicDataSourceContextHolder
-{
+public class DynamicDataSourceContextHolder {
     public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);
 
     /**
@@ -23,7 +22,7 @@ public class DynamicDataSourceContextHolder
      */
     public static void setDataSourceType(String dsType)
     {
-        log.info("切换到{}数据源", dsType);
+//        log.info("切换到{}数据源", dsType);
         CONTEXT_HOLDER.set(dsType);
     }
 

+ 3 - 3
fs-hospital/src/main/java/com/fs/framework/manager/AsyncManager.java → fs-company-app/src/main/java/com/fs/core/manager/AsyncManager.java

@@ -1,4 +1,4 @@
-package com.fs.framework.manager;
+package com.fs.core.manager;
 
 import com.fs.common.utils.Threads;
 import com.fs.common.utils.spring.SpringUtils;
@@ -9,7 +9,7 @@ import java.util.concurrent.TimeUnit;
 
 /**
  * 异步任务管理器
- *
+ * 
 
  */
 public class AsyncManager
@@ -38,7 +38,7 @@ public class AsyncManager
 
     /**
      * 执行任务
-     *
+     * 
      * @param task 任务
      */
     public void execute(TimerTask task)

+ 1 - 1
fs-hospital/src/main/java/com/fs/framework/manager/ShutdownManager.java → fs-company-app/src/main/java/com/fs/core/manager/ShutdownManager.java

@@ -1,4 +1,4 @@
-package com.fs.framework.manager;
+package com.fs.core.manager;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

+ 15 - 24
fs-hospital/src/main/java/com/fs/framework/manager/factory/AsyncFactory.java → fs-company-app/src/main/java/com/fs/core/manager/factory/AsyncFactory.java

@@ -1,30 +1,25 @@
-package com.fs.framework.manager.factory;
+package com.fs.core.manager.factory;
 
 import com.fs.common.constant.Constants;
 import com.fs.common.utils.LogUtils;
 import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.ip.AddressUtils;
 import com.fs.common.utils.ip.IpUtils;
 import com.fs.common.utils.spring.SpringUtils;
-import com.fs.company.domain.CompanyLogininfor;
-import com.fs.company.domain.CompanyOperLog;
-import com.fs.company.service.ICompanyLogininforService;
-import com.fs.company.service.ICompanyOperLogService;
-import com.fs.hospital.domain.Hospital;
-import com.fs.hospital.domain.HospitalLogininfor;
-import com.fs.hospital.domain.HospitalOperLog;
-import com.fs.hospital.service.IHospitalLogininforService;
-import com.fs.hospital.service.IHospitalOperLogService;
+import com.fs.system.domain.SysLogininfor;
+import com.fs.system.domain.SysOperLog;
+import com.fs.system.service.ISysLogininforService;
+import com.fs.system.service.ISysOperLogService;
 import eu.bitwalker.useragentutils.UserAgent;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.Date;
 import java.util.TimerTask;
 
 /**
  * 异步工厂(产生任务用)
- *
+ * 
 
  */
 public class AsyncFactory
@@ -33,14 +28,14 @@ public class AsyncFactory
 
     /**
      * 记录登录信息
-     *
+     * 
      * @param username 用户名
      * @param status 状态
      * @param message 消息
      * @param args 列表
      * @return 任务task
      */
-    public static TimerTask recordLogininfor(final Long hospitalId,final String username, final String status, final String message,
+    public static TimerTask recordLogininfor(final String username, final String status, final String message,
             final Object... args)
     {
         final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
@@ -64,8 +59,7 @@ public class AsyncFactory
                 // 获取客户端浏览器
                 String browser = userAgent.getBrowser().getName();
                 // 封装对象
-                HospitalLogininfor logininfor = new HospitalLogininfor();
-                logininfor.setInfoId(hospitalId);
+                SysLogininfor logininfor = new SysLogininfor();
                 logininfor.setUserName(username);
                 logininfor.setIpaddr(ip);
                 logininfor.setLoginLocation(address);
@@ -73,7 +67,7 @@ public class AsyncFactory
                 logininfor.setOs(os);
                 logininfor.setMsg(message);
                 // 日志状态
-                if (Constants.LOGIN_SUCCESS.equals(status) || Constants.LOGOUT.equals(status))
+                if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
                 {
                     logininfor.setStatus(Constants.SUCCESS);
                 }
@@ -81,21 +75,19 @@ public class AsyncFactory
                 {
                     logininfor.setStatus(Constants.FAIL);
                 }
-                logininfor.setLoginTime(new Date());
                 // 插入数据
-                SpringUtils.getBean(IHospitalLogininforService.class).insertHospitalLogininfor(logininfor);
+                SpringUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor);
             }
         };
-
     }
 
     /**
      * 操作日志记录
-     *
+     * 
      * @param operLog 操作日志信息
      * @return 任务task
      */
-    public static TimerTask recordOper(final HospitalOperLog operLog)
+    public static TimerTask recordOper(final SysOperLog operLog)
     {
         return new TimerTask()
         {
@@ -103,9 +95,8 @@ public class AsyncFactory
             public void run()
             {
                 // 远程查询操作地点
-                operLog.setOperTime(new Date());
                 operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
-                SpringUtils.getBean(IHospitalOperLogService.class).insertHospitalOperLog(operLog);
+                SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog);
             }
         };
     }

+ 1 - 1
fs-company-app/src/main/resources/application.yml

@@ -6,4 +6,4 @@ server:
 spring:
   profiles:
 #    active: druid-fcky-test
-    active: dev
+    active: dev-jnlzjk

+ 39 - 0
fs-company/src/main/java/com/fs/company/controller/common/CommonController.java

@@ -1,22 +1,30 @@
 package com.fs.company.controller.common;
 
+import cn.hutool.json.JSONUtil;
 import com.fs.common.config.FSConfig;
 import com.fs.common.constant.Constants;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.exception.file.OssException;
+import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.file.FileUploadUtils;
 import com.fs.common.utils.file.FileUtils;
 import com.fs.company.utils.AudioUtils;
 import com.fs.company.vo.WangUploadVO;
 import com.fs.framework.config.ServerConfig;
+import com.fs.framework.security.LoginUser;
+import com.fs.framework.service.TokenService;
 import com.fs.his.domain.FsExportTask;
+import com.fs.his.dto.InquiryConfigDTO;
 import com.fs.his.service.IFsExportTaskService;
+import com.fs.im.dto.OpenImResponseDTO;
+import com.fs.im.service.OpenIMService;
 import com.fs.qw.service.IQwWorkTaskService;
 import com.fs.qwApi.service.QwApiService;
 import com.fs.system.oss.CloudStorageService;
 import com.fs.system.oss.OSSFactory;
+import com.fs.system.service.ISysConfigService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -32,6 +40,7 @@ import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 通用请求处理
@@ -53,7 +62,14 @@ public class CommonController
     private QwApiService qwApiService;
 
 
+    @Autowired
+    private ISysConfigService configService;
+
+    @Autowired
+    private OpenIMService openIMService;
 
+    @Autowired
+    private TokenService tokenService;
 //    @Autowired
 //    private TestTwoService testService2;
 ////
@@ -276,6 +292,29 @@ public class CommonController
         }
     }
 
+    @GetMapping(value = "/common/getInquiryConfig")
+    public AjaxResult getInquiryConfig()
+    {
+        String json=configService.selectConfigByKey("his.inquiryConfig");
+        InquiryConfigDTO configDTO= JSONUtil.toBean(json, InquiryConfigDTO.class);
+        String inquirySubType = configDTO.getInquirySubType();
+        return AjaxResult.success(inquirySubType);
+    }
+
+    //分享会诊
+    @PostMapping(value = "/common/sendInquiry")
+    public AjaxResult sendInquiry(@RequestBody Map<String,String> map){
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyUserId = loginUser.getUser().getUserId();
+        Long companyId = loginUser.getCompany().getCompanyId();
+        String inquiryName = map.get("inquiryName");
+        String type = map.get("type");
+        String sendID = map.get("sendID");
+        String recvID = map.get("recvID");
+        String doctorId = map.get("doctorId");
+        OpenImResponseDTO inquirySelect = openIMService.sendInquiryUtil(sendID, recvID, 110, "inquirySelect", inquiryName, type,companyId,companyUserId,doctorId);
+        return AjaxResult.success(inquirySelect);
+    }
 
 
 }

+ 222 - 9
fs-company/src/main/java/com/fs/company/controller/common/Test.java

@@ -4,19 +4,56 @@ import com.alibaba.fastjson.JSON;
 import com.fs.ad.enums.AdUploadType;
 import com.fs.common.annotation.DataSource;
 import com.fs.common.core.domain.R;
+import com.fs.common.core.redis.RedisCache;
 import com.fs.common.enums.DataSourceType;
+import com.fs.common.service.impl.SmsServiceImpl;
+import com.fs.company.mapper.*;
+import com.fs.company.service.ICompanyService;
+import com.fs.company.service.ICompanyUserService;
+import com.fs.company.vo.RedPacketMoneyVO;
+import com.fs.course.mapper.FsCourseRedPacketLogMapper;
+import com.fs.course.service.IFsCourseWatchLogService;
+import com.fs.course.service.ITencentCloudCosService;
+import com.fs.erp.domain.ErpDeliverys;
+import com.fs.erp.domain.ErpOrderQuery;
+import com.fs.erp.dto.ErpOrderQueryRequert;
+import com.fs.erp.dto.ErpOrderQueryResponse;
+import com.fs.erp.service.IErpOrderService;
+import com.fs.fastGpt.mapper.FastGptChatSessionMapper;
+import com.fs.fastGpt.service.IFastgptEventLogTotalService;
+import com.fs.his.config.FsSysConfig;
+import com.fs.his.mapper.*;
+import com.fs.his.service.*;
+import com.fs.his.service.impl.FsPackageOrderServiceImpl;
+import com.fs.his.utils.ConfigUtil;
 import com.fs.his.utils.qrcode.QRCodeUtils;
+import com.fs.hisStore.domain.FsStoreOrderScrm;
+import com.fs.im.service.IImService;
+import com.fs.im.service.OpenIMService;
+import com.fs.qw.service.IQwAppContactWayService;
+import com.fs.qw.service.IQwCompanyService;
+import com.fs.qw.service.IQwExternalContactTransferLogService;
+import com.fs.qw.service.IQwUserService;
 import com.fs.qw.vo.AdUploadVo;
+import com.fs.qwApi.service.QwApiService;
 import com.fs.sop.service.IQwSopTempContentService;
 import com.fs.sop.service.IQwSopTempDayService;
 import com.fs.sop.service.IQwSopTempRulesService;
 import com.fs.sop.service.IQwSopTempService;
+import com.fs.system.mapper.SysConfigMapper;
 import com.google.zxing.WriterException;
 import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.rocketmq.spring.core.RocketMQTemplate;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.List;
+
 import javax.imageio.ImageIO;
 import java.awt.image.BufferedImage;
 import java.io.ByteArrayInputStream;
@@ -24,18 +61,194 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 
 @RestController
-@AllArgsConstructor
 public class Test {
+    @Autowired
+    private ConfigUtil configUtil;
+
+    @Autowired
+    private FsCourseRedPacketLogMapper fsCourseRedPacketLogMapper;
+    @Autowired
+    private ICompanyService companyService;
+    @Autowired
+    @Qualifier("erpOrderServiceImpl")
+    private IErpOrderService gyOrderService;
+    @Autowired
+    private FsUserCouponMapper fsUserCouponMapper;
+    @Autowired
+    private SysConfigMapper sysConfigMapper;
+    @Autowired
+    private IFsPrescribeService fsPrescribeService;
+    @Autowired
+    IFsStoreOrderService fsStoreOrderService;
+    @Autowired
+    FsStoreOrderMapper fsStoreOrderMapper;
+    @Autowired
+    private RedisCache redisCache;
+    @Autowired
+    private FsPackageOrderMapper fsPackageOrderMapper;
+    @Autowired
+    private IFsFollowService fsFollowService;
+    @Autowired
+    private IFsStoreAfterSalesService fsStoreAfterSalesService;
+    //    @Autowired
+//    IErpOrderService erpOrderService;
+    @Autowired
+    FsIntegralOrderMapper integralOrderMapper;
+    @Autowired
+    IFsInquiryOrderService iFsInquiryOrderService;
+    @Autowired
+    FsPackageMapper fsPackageMapper;
+    @Autowired
+    FsStoreProductMapper fsStoreProductMapper;
+    @Autowired
+    CompanyMapper companyMapper;
+    @Autowired
+    private CompanyMoneyLogsMapper moneyLogsMapper;
+    @Autowired
+    FsUserMapper fsUserMapper;
+    @Autowired
+    IFsUserIntegralLogsService fsUserIntegralLogsService;
+    @Autowired
+    SmsServiceImpl smsService;
+    @Autowired
+    FsStoreOrderItemMapper fsStoreOrderItemMapper;
+
+    @Autowired
+    FsPatientMapper fsPatientMapper;
+    @Autowired
+    FsPrescribeDrugMapper fsPrescribeDrugMapper;
+    @Autowired
+    FsFollowMapper fsFollowMapper;
+    @Autowired
+    private IImService imService;
+    @Autowired
+    private FsInquiryOrderMapper inquiryOrderMapper;
+    @Autowired
+    private CompanyVoiceCallerMapper companyVoiceCallerMapper;
+    @Autowired
+    private CompanyVoiceLogsMapper companyVoiceLogsMapper;
+    @Autowired
+    FsPackageOrderServiceImpl packageOrderService;
+    @Autowired
+    private IFsStoreOrderLogsService fsStoreOrderLogsService;
+    org.slf4j.Logger logger= LoggerFactory.getLogger(getClass());
+    @Autowired
+    IFsDoctorService doctorService;
+    @Autowired
+    CompanyUserMapper companyUserMapper;
+    @Autowired
+    FsInquiryOrderMapper fsInquiryOrderMapper;
+    @Autowired
+    QwApiService qwApiService;
+    //每天执行一次
+    @Autowired
+    IQwAppContactWayService qwAppContactWayService;
+
+    @Autowired
+    FastGptChatSessionMapper fastGptChatSessionMapper;
+
+    @Autowired
+    IQwExternalContactTransferLogService qwExternalContactTransferLogService;
+
+
+
+    @Autowired
+    ITencentCloudCosService tencentCloudCosService;
+
 
-    private final IQwSopTempService qwSopTempService;
-    private final IQwSopTempRulesService qwSopTempRulesService;
-    private final IQwSopTempDayService qwSopTempDayService;
-    private final IQwSopTempContentService qwSopTempContentService;
-    private final RocketMQTemplate rocketMQTemplate;
+    @Autowired
+    public RedisTemplate redisTemplate;
+
+    @Autowired
+    @Qualifier("wdtErpOrderServiceImpl")
+    private IErpOrderService wdtOrderService;
+    @Autowired
+    @Qualifier("hzOMSErpOrderServiceImpl")
+    private IErpOrderService hzOMSErpOrderService;
+    @Autowired
+    @Qualifier("dfOrderServiceImpl")
+    private IErpOrderService dfOrderService;
+
+    @Autowired
+    @Qualifier("JSTErpOrderServiceImpl")
+    private IErpOrderService jSTOrderService;
+    @Autowired
+    @Qualifier("k9OrderScrmServiceImpl")
+    private IErpOrderService k9OrderService;
+    @Autowired
+    IErpOrderService erpOrderService;
     @GetMapping("test")
-    @DataSource(DataSourceType.SOP)
-    public void fileDownload(){
-        rocketMQTemplate.syncSend("ad-upload", JSON.toJSONString(AdUploadVo.builder().state("测试").type(AdUploadType.ADD_WX).build()));
+    public void fileDownload() {
+        deliveryOpScrm();
+    }
+    private IErpOrderService getErpService() {
+
+        FsSysConfig sysConfig = configUtil.getSysConfig();
+        Integer erpOpen = sysConfig.getErpOpen();
+        if (erpOpen != null && erpOpen == 1){
+            //判断erp类型
+            Integer erpType = sysConfig.getErpType();
+            if (erpType != null){
+                IErpOrderService erpOrderService = null;
+                if (erpType == 1){
+                    //管易
+                    erpOrderService =  gyOrderService;
+                } else if (erpType == 2){
+                    //旺店通
+                    erpOrderService =  wdtOrderService;
+                } else if (erpType == 3){
+                    //
+                    erpOrderService =  hzOMSErpOrderService;
+                } else if (erpType == 4){
+                    //代服
+                    erpOrderService =  dfOrderService;
+                }else if(erpType == 5){
+                    erpOrderService=jSTOrderService;
+                }else if(erpType == 6){
+                    erpOrderService=k9OrderService;
+                }
+                return erpOrderService;
+
+
+            }
+        }
+        return null;
+    }
+    public void deliveryOpScrm()
+    {
+        System.out.println("deliveryOpScrm");
+        IErpOrderService erpOrderService = getErpService();
+        List<FsStoreOrderScrm> orders = null;
+        if (erpOrderService == gyOrderService){
+            orders = fsStoreOrderMapper.selectOmsOrderdeliveryOpScrm();
+        } else if (erpOrderService == wdtOrderService || erpOrderService == dfOrderService || erpOrderService == jSTOrderService){
+            orders = fsStoreOrderMapper.selectWdtOmsOrderdeliveryOpScrm();
+        }
+        logger.info("查询到的"+orders.size());
+        for(FsStoreOrderScrm order:orders){
+            ErpOrderQueryRequert request=new ErpOrderQueryRequert();
+            request.setCode(order.getExtendOrderId());
+            if (erpOrderService != null){
+                ErpOrderQueryResponse response=erpOrderService.getOrder(request);
+                if (erpOrderService != dfOrderService){
+                    if(response.getOrders()!=null&&response.getOrders().size()>0){
+                        for(ErpOrderQuery orderQuery : response.getOrders()){
+                            if(orderQuery.getDeliverys()!=null&&orderQuery.getDeliverys().size()>0){
+                                for(ErpDeliverys delivery:orderQuery.getDeliverys()){
+                                    if(delivery.getDelivery()&& StringUtils.isNotEmpty(delivery.getMail_no())){
+                                        //更新商订单状态 删除REDIS
+                                        logger.info("查询到的"+delivery);
+
+                                        fsStoreOrderService.deliveryOrderScrm(order.getOrderCode(),delivery.getMail_no(),delivery.getExpress_code(),delivery.getExpress_name());
+                                        redisCache.deleteObject("delivery"+":"+order.getExtendOrderId());
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
     }
 
 }

+ 7 - 12
fs-company/src/main/java/com/fs/company/controller/company/CompanyDeptController.java

@@ -149,21 +149,16 @@ public class CompanyDeptController extends BaseController
     @PreAuthorize("@ss.hasPermi('company:dept:edit')")
     @Log(title = "部门管理", businessType = BusinessType.UPDATE)
     @PutMapping
-    public AjaxResult edit(@Validated @RequestBody CompanyDept dept)
-    {
+    public AjaxResult edit(@Validated @RequestBody CompanyDept dept) {
+        if(dept.getParentId().equals(dept.getDeptId())) {
+            return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己");
+        }
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         dept.setCompanyId(loginUser.getCompany().getCompanyId());
-        if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept)))
-        {
+        if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) {
             return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
-        }
-        else if (dept.getParentId().equals(dept.getDeptId()))
-        {
-            return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己");
-        }
-        else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus())
-                && deptService.selectNormalChildrenDeptById(dept.getDeptId()) > 0)
-        {
+        } else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus())
+                && deptService.selectNormalChildrenDeptById(dept.getDeptId()) > 0) {
             return AjaxResult.error("该部门包含未停用的子部门!");
         }
         dept.setUpdateBy(SecurityUtils.getUsername());

+ 9 - 0
fs-company/src/main/java/com/fs/company/controller/company/CompanyProfileController.java

@@ -6,6 +6,7 @@ import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.enums.ImTypeEnum;
 import com.fs.common.utils.PatternUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.file.FileUploadUtils;
@@ -15,6 +16,8 @@ import com.fs.company.service.ICompanyUserService;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.security.SecurityUtils;
 import com.fs.framework.service.TokenService;
+import com.fs.im.config.ImTypeConfig;
+import com.fs.im.service.OpenIMService;
 import com.fs.system.service.ISysConfigService;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -39,6 +42,8 @@ public class CompanyProfileController extends BaseController
     @Autowired
     private RedisCache redisCache;
 
+    @Autowired
+    private OpenIMService openIMService;
     /**
      * 个人信息
      */
@@ -67,6 +72,10 @@ public class CompanyProfileController extends BaseController
 
         if (userService.updateUserProfile(user) > 0)
         {
+            //修改im用户信息
+            if (ImTypeConfig.IMTYPE== ImTypeEnum.OPENIM){
+                openIMService.updateUserInfo(user);
+            }
             LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
             // 更新缓存用户信息
             loginUser.getUser().setNickName(user.getNickName());

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

@@ -22,6 +22,8 @@ import com.fs.company.param.CompanyUserCodeParam;
 import com.fs.company.param.CompanyUserQwParam;
 import com.fs.company.service.*;
 import com.fs.company.utils.DomainUtil;
+import com.fs.company.utils.QwStatusEnum;
+import com.fs.company.vo.BatchUserRolesVO;
 import com.fs.company.vo.CompanyUserImportVO;
 import com.fs.company.vo.CompanyUserQwListVO;
 import com.fs.company.vo.CompanyUserVO;
@@ -32,9 +34,12 @@ import com.fs.framework.service.TokenService;
 import com.fs.his.utils.qrcode.QRCodeUtils;
 import com.fs.his.vo.OptionsVO;
 import com.fs.hisStore.vo.FsStoreProductExportVO;
+import com.fs.im.config.IMConfig;
+import com.fs.im.dto.OpenImResponseDTO;
 import com.fs.im.service.OpenIMService;
 import com.fs.qw.domain.QwCompany;
 import com.fs.qw.service.IQwCompanyService;
+import com.fs.qw.service.IQwUserService;
 import com.fs.qw.vo.CompanyUserQwVO;
 import com.fs.qw.vo.QwUserVO;
 import com.fs.system.service.ISysConfigService;
@@ -46,6 +51,7 @@ import org.json.JSONArray;
 import org.json.JSONObject;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.util.Assert;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
@@ -53,18 +59,16 @@ import org.springframework.web.multipart.MultipartFile;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.*;
+import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
 
 
 /**
  * 用户信息
- *
-
  */
 @RestController
 @RequestMapping("/company/user")
-public class CompanyUserController extends BaseController
-{
+public class CompanyUserController extends BaseController {
 
     @Autowired
     private ICompanyRoleService roleService;
@@ -77,19 +81,28 @@ public class CompanyUserController extends BaseController
 
     @Autowired
     private ICompanyUserService companyUserService;
+
     @Autowired
     private ICompanyService companyService;
+
     @Autowired
     private ICompanyUserDelayTimeService companyUserDelayTimeService;
+
     @Autowired
     private ISysConfigService configService;
+
     @Autowired
     private RedisCache redisCache;
+
     @Autowired
     private OpenIMService openIMService;
+
     @Autowired
     IQwCompanyService iQwCompanyService;
 
+    @Autowired
+    private IQwUserService qwUserService;
+
     private static final String appLink = "https://jump.ylrztop.com/jumpapp/pages/index/index?link=";
 
     /**
@@ -123,24 +136,41 @@ public class CompanyUserController extends BaseController
         return getDataTable(list);
     }
     @GetMapping("/qwList")
-    public TableDataInfo qwList(CompanyUserQwParam user)
-    {
+    public TableDataInfo qwList(CompanyUserQwParam user) {
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         user.setCompanyId(loginUser.getCompany().getCompanyId());
-        startPage();
         List<CompanyUserQwListVO> list = companyUserService.selectCompanyUserQwListVO(user);
-        for (CompanyUserQwListVO companyUserQwListVO : list) {
-             CompanyUserDelayTime companyUserDelayTime = companyUserDelayTimeService.selectCompanyUserDelayTimeByCompanyUser(companyUserQwListVO.getCompanyId(),companyUserQwListVO.getUserId());
-            if (ObjectUtil.isEmpty(companyUserDelayTime)){
-                String json = configService.selectConfigByKey("course.config");
-                CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-                companyUserQwListVO.setSendDelayTime(config.getSendDelayTime());
-            }else {
-                companyUserQwListVO.setSendDelayTime(companyUserDelayTime.getSendDelayTime());
+        if (!list.isEmpty()){
+            String json = configService.selectConfigByKey("course.config");
+            CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+            Long sendDelayTime = config.getSendDelayTime();
+            List<CompletableFuture<Void>> futures = new ArrayList<>();
+            for (CompanyUserQwListVO companyUserQwListVO : list) {
+                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
+                    CompanyUserDelayTime companyUserDelayTime = companyUserDelayTimeService.selectCompanyUserDelayTimeByCompanyUser(companyUserQwListVO.getCompanyId(), companyUserQwListVO.getUserId());
+                    if (ObjectUtil.isEmpty(companyUserDelayTime)) {
+                        companyUserQwListVO.setSendDelayTime(sendDelayTime);
+                    } else {
+                        companyUserQwListVO.setSendDelayTime(companyUserDelayTime.getSendDelayTime());
+                    }
+                    //是否绑定
+                    if(QwStatusEnum.BOUND.getCode() == companyUserQwListVO.getQwStatus()){
+                        if(!companyUserQwListVO.getQwUserId().isEmpty()){
+                            Long[] ids = Arrays.stream(companyUserQwListVO.getQwUserId().split(","))
+                                    .map(Long::parseLong)
+                                    .toArray(Long[]::new);
+                            List<QwUserVO> qwUserVOS = qwUserService.selectQwUserVOByIds(ids);
+                            companyUserQwListVO.setQwUsers(qwUserVOS);
+                        }
+                    }
+                });
+                futures.add(future);
             }
+            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
         }
         return getDataTable(list);
     }
+
     @Log(title = "用户管理导出", businessType = BusinessType.EXPORT)
     @PreAuthorize("@ss.hasPermi('company:user:export')")
     @GetMapping("/export")
@@ -565,6 +595,20 @@ public class CompanyUserController extends BaseController
         return companyUserService.bindDoctor(companyUser);
     }
 
+    /**
+     * 批量修改角色
+     * @param batchUserRolesVO
+     */
+    @PreAuthorize("@ss.hasPermi('company:user:edit')")
+    @Log(title = "批量修改角色", businessType = BusinessType.UPDATE)
+    @PostMapping("/updateBatchUserRoles")
+    public R updateBatchUserRoles(@RequestBody BatchUserRolesVO batchUserRolesVO){
+        Assert.notEmpty(batchUserRolesVO.getRoleIds(), "角色不能为空");
+        Assert.notEmpty(batchUserRolesVO.getUserIds(), "用户不能为空");
+        return companyUserService.updateBatchUserRoles(batchUserRolesVO);
+    }
+
+
     @ApiOperation("校验客服是否注册新的im")
     @PostMapping("/accountCheck")
     public R accountCheck(@RequestBody Map<String, String> userIdMap){
@@ -579,7 +623,7 @@ public class CompanyUserController extends BaseController
             requestBody = new JSONObject();
             userIds.add(userId);
             requestBody.put("checkUserIDs", userIds);
-            String body = HttpRequest.post("https://web.im.cdwjyyh.com/api/user/account_check")
+            String body = HttpRequest.post(IMConfig.URL+"/user/account_check")
                     .header("operationID", String.valueOf(System.currentTimeMillis()))
                     .header("token", adminToken)
                     .body(requestBody.toString())
@@ -600,13 +644,13 @@ public class CompanyUserController extends BaseController
                     ArrayList<Object> users = new ArrayList<>();
                     HashMap<String, String> map = new HashMap<>();
                     map.put("userID",userId);
-                    map.put("nickname",companyUser.getImNickName());
+                    map.put("nickname",companyUser.getNickName());
                     map.put("faceURL",companyUser.getAvatar());
                     users.add(map);
                     requestBody = new JSONObject();
-                    userIds.add(userId);
+                    //userIds.add(userId);
                     requestBody.put("users", users);
-                    HttpRequest.post("https://web.im.cdwjyyh.com/api/user/user_register")
+                    String registerBody = HttpRequest.post(IMConfig.URL+"/user/user_register")
                             .header("operationID", String.valueOf(System.currentTimeMillis()))
                             .header("token", adminToken).body(requestBody.toString()).execute().body();
                 }
@@ -619,7 +663,7 @@ public class CompanyUserController extends BaseController
             requestBody = new JSONObject();
             requestBody.put("platformID",5);
             requestBody.put("userID",userId);
-            String body1 = HttpRequest.post("https://web.im.cdwjyyh.com/api/auth/get_user_token")
+            String body1 = HttpRequest.post(IMConfig.URL+"/auth/get_user_token")
                     .header("operationID", String.valueOf(System.currentTimeMillis()))
                     .header("token", adminToken)
                     .body(requestBody.toString()).execute().body();
@@ -631,5 +675,12 @@ public class CompanyUserController extends BaseController
             return R.error("获取管理员token失败");
         }
     }
-
+    @ApiOperation("添加好友")
+    @PostMapping("/importFriend")
+    public R importFriend(@RequestBody HashMap<String,Object> map){
+        String ownerUserID = (String) map.get("ownerUserID");
+        List<String> friendUserIDs = (List<String>)map.get("friendUserIDs");
+        OpenImResponseDTO openImResponseDTO = openIMService.importFriend(ownerUserID, friendUserIDs);
+        return R.ok().put("data",openImResponseDTO);
+    }
 }

+ 26 - 2
fs-company/src/main/java/com/fs/company/controller/company/IndexStatisticsController.java

@@ -7,8 +7,7 @@ import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
 import com.fs.statis.StatisticsRedisConstant;
 import com.fs.statis.dto.*;
-import com.fs.system.domain.SysConfig;
-import com.fs.system.service.ISysConfigService;
+import com.fs.statis.service.IStatisticsService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -28,6 +27,10 @@ public class IndexStatisticsController {
 
     @Autowired
     private TokenService tokenService;
+
+    @Autowired
+    private IStatisticsService statisticsService;
+
     /**
      * 分析概览
      */
@@ -239,4 +242,25 @@ public class IndexStatisticsController {
         R result = redisCache.getCacheObject(String.format("%s:%d",StatisticsRedisConstant.THIS_MONTH_RECV_COUNT,companyId));
         return result;
     }
+
+    /**
+     * @Description: 看课统计按公司
+     * @Param:
+     * @Return:
+     * @Author xgb
+     * @Date 2025/10/27 16:29
+     */
+    @PostMapping("/getWatchCourseStatisticsData")
+    public R getWatchCourseStatisticsData(@RequestBody AnalysisPreviewQueryDTO param){
+        // 获取公司ID
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyId = loginUser.getCompany().getCompanyId();
+        if(param.getCompanyId()==null){
+            param.setCompanyId(companyId);
+        }
+        // 从缓存获取看客统计数据
+        List<WatchCourseStatisticsResultDTO> data=statisticsService.getWatchCourseStatisticsData(param);
+
+        return R.ok().put("data", data);
+    }
 }

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

@@ -82,7 +82,7 @@ public class FsCourseAnswerLogsController extends BaseController
 
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         param.setCompanyId( loginUser.getCompany().getCompanyId());
-        param.setCompanyUserId(loginUser.getUser().getUserId());
+        //param.setCompanyUserId(loginUser.getUser().getUserId());
         if (param.getPhoneMk() != null && param.getPhoneMk() != "") {
             param.setPhone(param.getPhoneMk());
         }

+ 13 - 0
fs-company/src/main/java/com/fs/company/controller/course/FsCourseFinishTempController.java

@@ -1,10 +1,12 @@
 package com.fs.company.controller.course;
 
+import com.alibaba.fastjson.JSON;
 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.DateUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.course.domain.FsCourseFinishTemp;
 import com.fs.course.service.IFsCourseFinishTempService;
@@ -104,4 +106,15 @@ public class FsCourseFinishTempController extends BaseController
     {
         return toAjax(fsCourseFinishTempService.deleteFsCourseFinishTempByIds(ids));
     }
+
+
+    @Log(title = "完课模板", businessType = BusinessType.UPDATE)
+    @PostMapping("/updateStatusBatch")
+    public AjaxResult updateStatusBatch(@RequestBody FsCourseFinishTemp fsCourseFinishTemp)
+    {
+        fsCourseFinishTemp.setUpdateTime(DateUtils.getNowDate());
+
+        return toAjax(fsCourseFinishTempService.updateFsCourseFinishTempBatch(fsCourseFinishTemp));
+    }
+
 }

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

@@ -89,7 +89,7 @@ public class FsCourseRedPacketLogController extends BaseController
         startPage();
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         fsCourseRedPacketLog.setCompanyId( loginUser.getCompany().getCompanyId());
-        fsCourseRedPacketLog.setCompanyUserId(loginUser.getUser().getUserId());
+        //fsCourseRedPacketLog.setCompanyUserId(loginUser.getUser().getUserId());
         if (fsCourseRedPacketLog.getPhoneMk() != null && fsCourseRedPacketLog.getPhoneMk() != "") {
             fsCourseRedPacketLog.setPhone(encryptPhone(fsCourseRedPacketLog.getPhoneMk()));
         }

+ 65 - 6
fs-company/src/main/java/com/fs/company/controller/course/FsCourseWatchLogController.java

@@ -1,5 +1,6 @@
 package com.fs.company.controller.course;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
@@ -9,11 +10,10 @@ import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.service.impl.CompanyDeptServiceImpl;
 import com.fs.course.domain.FsCourseWatchLog;
-import com.fs.course.param.FsCourseOverParam;
-import com.fs.course.param.FsCourseUserStatisticsListParam;
-import com.fs.course.param.FsCourseWatchLogListParam;
-import com.fs.course.param.FsCourseWatchLogStatisticsListParam;
+import com.fs.course.param.*;
 import com.fs.course.service.IFsCourseWatchLogService;
+import com.fs.course.service.IFsUserCoursePeriodDaysService;
+import com.fs.course.service.IFsUserCoursePeriodService;
 import com.fs.course.vo.FsCourseOverVO;
 import com.fs.course.vo.FsCourseUserStatisticsListVO;
 import com.fs.course.vo.FsCourseWatchLogListVO;
@@ -54,6 +54,12 @@ public class FsCourseWatchLogController extends BaseController
     @Autowired
     private CompanyDeptServiceImpl companyDeptService;
 
+    @Autowired
+    private IFsUserCoursePeriodService userCoursePeriodService;
+
+    @Autowired
+    private IFsUserCoursePeriodDaysService userCoursePeriodDaysService;
+
     /**
      * 查询短链课程看课记录列表
      */
@@ -62,9 +68,26 @@ public class FsCourseWatchLogController extends BaseController
     public TableDataInfo list(FsCourseWatchLogListParam param)
     {
 
-        startPage();
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         param.setCompanyId( loginUser.getCompany().getCompanyId());
+
+        if (param.getSendType()==1&& param.getPeriodETime()!=null && param.getPeriodSTime()!=null) {
+            List<Long> periodIds = userCoursePeriodDaysService.selectFsUserCoursePeriodDaysByTime(param.getPeriodSTime(), param.getPeriodETime());
+
+            if (!periodIds.isEmpty()){
+                List<Long> longs = userCoursePeriodService.selectFsUserCoursePeriodListByPeriodId(periodIds, loginUser.getCompany().getCompanyId());
+                if (!longs.isEmpty()){
+                    param.setPeriodIds(longs);
+                }else {
+                    return getDataTable(new ArrayList<>());
+                }
+            }else {
+                return getDataTable(new ArrayList<>());
+            }
+
+        }
+
+        startPage();
         List<FsCourseWatchLogListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogListVO(param);
         return getDataTable(list);
     }
@@ -96,6 +119,24 @@ public class FsCourseWatchLogController extends BaseController
         param.setUserType(loginUser.getUser().getUserType());
         param.setCompanyId(loginUser.getCompany().getCompanyId());
 
+
+        if (ObjectUtil.isNotEmpty(param.getSendType()) &&param.getSendType()==1&& param.getPeriodETime()!=null && param.getPeriodSTime()!=null) {
+            List<Long> periodIds = userCoursePeriodDaysService.selectFsUserCoursePeriodDaysByTime(param.getPeriodSTime(), param.getPeriodETime());
+
+            if (!periodIds.isEmpty()){
+                List<Long> longs = userCoursePeriodService.selectFsUserCoursePeriodListByPeriodId(periodIds, loginUser.getCompany().getCompanyId());
+                if (!longs.isEmpty()){
+                    param.setPeriodIds(longs);
+                }else {
+                    return getDataTable(new ArrayList<>());
+                }
+            }else {
+                return getDataTable(new ArrayList<>());
+            }
+
+        }
+
+
         startPage();
         List<FsCourseWatchLogListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogListVO(param);
 
@@ -108,9 +149,27 @@ public class FsCourseWatchLogController extends BaseController
     @GetMapping("/myList")
     public TableDataInfo myList(FsCourseWatchLogListParam param)
     {
-        startPage();
+
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         param.setCompanyUserId( loginUser.getUser().getUserId());
+
+        if (param.getSendType()==1&& param.getPeriodETime()!=null && param.getPeriodSTime()!=null) {
+            List<Long> periodIds = userCoursePeriodDaysService.selectFsUserCoursePeriodDaysByTime(param.getPeriodSTime(), param.getPeriodETime());
+            if (!periodIds.isEmpty()){
+                List<Long> longs = userCoursePeriodService.selectFsUserCoursePeriodListByPeriodId(periodIds, loginUser.getCompany().getCompanyId());
+                if (!longs.isEmpty()){
+                    param.setPeriodIds(longs);
+                }else {
+                    return getDataTable(new ArrayList<>());
+                }
+            }else {
+                return getDataTable(new ArrayList<>());
+            }
+
+        }
+
+        startPage();
+
         List<FsCourseWatchLogListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogListVO(param);
         return getDataTable(list);
     }

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

@@ -1,11 +1,13 @@
 package com.fs.company.controller.course;
 
+import cn.hutool.core.util.ObjectUtil;
 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.exception.CustomException;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.course.domain.FsUserCoursePeriod;
@@ -74,6 +76,9 @@ public class FsUserCoursePeriodController extends BaseController {
     @ApiOperation("自定义查询主列表分页")
     public R pageList(@RequestBody FsUserCoursePeriod fsUserCoursePeriod)
     {
+        if (ObjectUtil.isNotEmpty(fsUserCoursePeriod.getTrainingCampId())){
+            throw new CustomException("训练营不能为空!");
+        }
 //        startPage();
         PageHelper.startPage(fsUserCoursePeriod.getPageNum(), fsUserCoursePeriod.getPageSize());
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
@@ -120,6 +125,9 @@ public class FsUserCoursePeriodController extends BaseController {
     @PostMapping
     public AjaxResult add(@RequestBody FsUserCoursePeriod fsUserCoursePeriod)
     {
+        if (ObjectUtil.isNotEmpty(fsUserCoursePeriod.getTrainingCampId())){
+            throw new CustomException("训练营不能为空!");
+        }
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         fsUserCoursePeriod.setCompanyId(loginUser.getCompany().getCompanyId().toString());
         return toAjax(fsUserCoursePeriodService.insertFsUserCoursePeriod(fsUserCoursePeriod));

+ 20 - 2
fs-company/src/main/java/com/fs/company/controller/course/qw/FsQwCourseWatchLogController.java

@@ -19,6 +19,7 @@ import com.fs.framework.service.TokenService;
 import com.fs.qw.param.QwWatchLogStatisticsListParam;
 import com.fs.qw.service.IQwWatchLogService;
 import com.fs.qw.vo.QwWatchLogAllStatisticsListVO;
+import com.fs.qw.vo.QwWatchLogStatisticsListVO;
 import com.fs.sop.mapper.SopUserLogsMapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -81,6 +82,21 @@ public class FsQwCourseWatchLogController extends BaseController
         List<FsCourseWatchLogStatisticsListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogStatisticsListVO(param);
         return getDataTable(list);
     }
+    @PreAuthorize("@ss.hasPermi('course:courseWatchLog:statisticsList')")
+    @GetMapping("/statisticsExport")
+    public AjaxResult statisticsExport(FsCourseWatchLogStatisticsListParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId( loginUser.getCompany().getCompanyId());
+        if (param.getSTime()==null||param.getETime()==null){
+            return AjaxResult.error("请选择时间");
+        }
+        param.setSendType(2);
+        List<FsCourseWatchLogStatisticsListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogStatisticsListVO(param);
+        ExcelUtil<FsCourseWatchLogStatisticsListVO> util = new ExcelUtil<FsCourseWatchLogStatisticsListVO>(FsCourseWatchLogStatisticsListVO.class);
+        return util.exportExcel(list, "企微看课统计");
+
+    }
 
     @GetMapping("/qwWatchLogStatisticsList")
     public TableDataInfo qwWatchLogStatisticsList(QwWatchLogStatisticsListParam param)
@@ -196,8 +212,10 @@ public class FsQwCourseWatchLogController extends BaseController
     {
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         param.setCompanyId( loginUser.getCompany().getCompanyId());
-        List<FsCourseWatchLogListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogListVO(param);
-        ExcelUtil<FsCourseWatchLogListVO> util = new ExcelUtil<FsCourseWatchLogListVO>(FsCourseWatchLogListVO.class);
+
+        List<QwWatchLogStatisticsListVO> list = qwWatchLogService.selectQwWatchLogStatisticsListVOExport(param);
+
+        ExcelUtil<QwWatchLogStatisticsListVO> util = new ExcelUtil<QwWatchLogStatisticsListVO>(QwWatchLogStatisticsListVO.class);
         return util.exportExcel(list, "短链课程看课记录数据");
     }
 

+ 59 - 0
fs-company/src/main/java/com/fs/company/controller/qw/QwExternalContactController.java

@@ -14,13 +14,16 @@ import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.impl.CompanyDeptServiceImpl;
 import com.fs.course.param.FsUserCourseListUParam;
+import com.fs.course.service.IFsUserCompanyBindService;
 import com.fs.course.service.IFsUserCourseStudyService;
 import com.fs.course.vo.FsUserCourseStudyListUVO;
+import com.fs.course.vo.UserWatchLogListVo;
 import com.fs.crm.param.CrmMyCustomerListQueryParam;
 import com.fs.crm.service.ICrmCustomerService;
 import com.fs.crm.vo.CrmMyCustomerListQueryVO;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
+import com.fs.his.domain.FsUser;
 import com.fs.his.service.IFsUserService;
 import com.fs.qw.domain.QwContactWay;
 import com.fs.qw.domain.QwExternalContact;
@@ -36,6 +39,7 @@ import com.github.pagehelper.PageHelper;
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
 import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections.CollectionUtils;
 import org.codehaus.jettison.json.JSONException;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -56,6 +60,7 @@ import static com.fs.his.utils.PhoneUtil.encryptPhone;
  * @author fs
  * @date 2024-06-20
  */
+@Slf4j
 @RestController
 @RequestMapping("/qw/externalContact")
 public class QwExternalContactController extends BaseController
@@ -89,6 +94,9 @@ public class QwExternalContactController extends BaseController
     @Autowired
     private IQwContactWayService qwContactWayService;
 
+    @Autowired
+    private IFsUserCompanyBindService fsUserCompanyBindService;
+
     /**
      * 查询企业微信客户列表
      */
@@ -272,10 +280,34 @@ public class QwExternalContactController extends BaseController
             if (!StringUtil.strIsNullOrEmpty(item.getState()) && !wayList.isEmpty()) {
                 item.setState(item.getState()+"-"+getContactWayNameStream(item.getState(), wayList));
             }
+            //获取用户下单次数
+            try {
+                fillOrderCount(item);
+            }catch (Exception e){
+                log.error("获取用户下单次数异常:{}",e.getMessage());
+            }
+
         });
 
         return getDataTable(list);
     }
+    /**
+     * 根据用户ID查询并设置下单次数(若用户不存在或ID无效,则设为0)
+     */
+    private void fillOrderCount(QwExternalContactVO item){
+        Long fsUserId = item.getFsUserId();
+        if (fsUserId==null){
+            item.setOrderCount(0L);
+            return;
+        }
+        FsUser fsUser = fsUserService.selectFsUserById(fsUserId);
+        if (fsUser == null) {
+            item.setOrderCount(0L);
+            return;
+        }
+        Long orderCount = fsUser.getOrderCount();
+        item.setOrderCount(orderCount != null ? orderCount : 0);
+    }
 
 
     @Log(title = "同步我的企业微信客户", businessType = BusinessType.INSERT)
@@ -557,6 +589,14 @@ public class QwExternalContactController extends BaseController
     {
         return qwExternalContactService.updateQwExternalContactUnBindUserId(id);
     }
+    @PreAuthorize("@ss.hasPermi('qw:externalContact:changeStatus')")
+    @Log(title = "修改用户状态", businessType = BusinessType.UPDATE)
+    @GetMapping("/status")
+    public R changeStatus(QwExternalContact qwExternalContact)
+    {
+        qwExternalContactService.updateQwExternalContactStatusById(qwExternalContact);
+        return R.ok();
+    }
     /**
      * 删除企业微信客户
      */
@@ -774,4 +814,23 @@ public class QwExternalContactController extends BaseController
         return R.ok();
     }
 
+    /**
+     * 重粉客服查询
+     */
+    @GetMapping("/getRepeat")
+    public R getRepeat(RepeatParam param){
+        return  qwExternalContactService.getRepeat(param);
+    }
+    /**
+     * 重粉看课记录查询
+     */
+    @GetMapping("/getWatchLogList")
+    public TableDataInfo getWatchLogList(UserWatchLogParam param){
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setUserId(loginUser.getUser().getUserId());
+        List<UserWatchLogListVo> list= fsUserCompanyBindService.getWatchLogList(param);
+        return getDataTable(list);
+    }
+
 }

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

@@ -10,6 +10,7 @@ import com.fs.common.utils.ServletUtils;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
 import com.fs.qw.domain.QwExternalContactTransferCompanyAudit;
+import com.fs.qw.domain.QwExternalContactTransferCompanyAuditUser;
 import com.fs.qw.service.IQwExternalContactTransferCompanyAuditService;
 import com.fs.qw.service.IQwExternalContactTransferCompanyAuditUserService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -50,7 +51,9 @@ public class QwExternalContactTransferCompanyAuditController extends BaseControl
 
     @PreAuthorize("@ss.hasPermi('qw:externalContactTransferCompanyAudit:detail')")
     @GetMapping("/detail/{auditId}")
-    public AjaxResult detail(@PathVariable Long auditId) {
-        return AjaxResult.success(auditUserService.getListByAuditId(auditId));
+    public TableDataInfo detail(@PathVariable Long auditId) {
+        startPage();
+        List<QwExternalContactTransferCompanyAuditUser> list = auditUserService.getListByAuditId(auditId);
+        return getDataTable(list);
     }
 }

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

@@ -116,8 +116,10 @@ public class QwExternalContactTransferLogController extends BaseController
     @GetMapping("/sync/{corpId}")
     public R syncTag(@PathVariable("corpId") String corpId)
     {
-
-        return qwExternalContactTransferLogService.syncQwExternalContactTransferLog(corpId);
+//        transferService.syncQwExternalContactTransferLog(corpId);
+//
+         qwExternalContactTransferLogService.syncQwExternalContactTransferLog(corpId);
+        return R.ok();
     }
     /**
      * 获取转接记录详细信息

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

@@ -1,10 +1,12 @@
 package com.fs.company.controller.qw;
 
+import cn.hutool.core.util.ObjectUtil;
 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.core.redis.RedisCache;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
@@ -60,7 +62,8 @@ public class QwSopLogsController extends BaseController
 
     @Autowired
     private ICompanyUserService iCompanyUserService;
-
+    @Autowired
+    private RedisCache redisCache;
     @Autowired
     private CompanyDeptServiceImpl companyDeptService;
 
@@ -266,6 +269,12 @@ public class QwSopLogsController extends BaseController
     @PutMapping("/editCourseQwSopLogs/{ids}")
     public AjaxResult editCourseQwSopLogs(@PathVariable String[] ids)
     {
+       if (ObjectUtil.isNotEmpty(ids)){
+           for (String id : ids) {
+               String key = "qw:logs:pad:send:id:" + id;
+               redisCache.deleteObject(key);
+           }
+       }
         return toAjax(iQwSopLogsService.editCourseQwSopLogs(ids));
     }
 

+ 15 - 14
fs-company/src/main/java/com/fs/company/controller/qw/QwSopTempController.java

@@ -63,6 +63,21 @@ public class QwSopTempController extends BaseController
         return getDataTable(list);
     }
 
+    /**
+     * 导出sop模板列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:sopTemp:export') or @ss.hasPermi('qw:sopTemp:myExport') or @ss.hasPermi('qw:sopTemp:deptExport')")
+    @Log(title = "sop模板", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(QwSopTemp qwSopTemp)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        qwSopTemp.setCompanyId(loginUser.getCompany().getCompanyId());
+        List<QwSopTemp> list = qwSopTempService.selectQwSopTempListNew(qwSopTemp);
+        ExcelUtil<QwSopTemp> util = new ExcelUtil<QwSopTemp>(QwSopTemp.class);
+        return util.exportExcel(list, "sop模板数据");
+    }
+
     /**
      * 查询我创建的sop模板列表
      */
@@ -111,20 +126,6 @@ public class QwSopTempController extends BaseController
         return getDataTable(list);
     }
 
-
-    /**
-     * 导出sop模板列表
-     */
-    @PreAuthorize("@ss.hasPermi('qw:sopTemp:export') or @ss.hasPermi('qw:sopTemp:myExport') or @ss.hasPermi('qw:sopTemp:deptExport')")
-    @Log(title = "sop模板", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(QwSopTemp qwSopTemp)
-    {
-        List<QwSopTemp> list = qwSopTempService.selectQwSopTempList(qwSopTemp);
-        ExcelUtil<QwSopTemp> util = new ExcelUtil<QwSopTemp>(QwSopTemp.class);
-        return util.exportExcel(list, "sop模板数据");
-    }
-
     /**
      * 获取sop模板详细信息
      */

+ 54 - 12
fs-company/src/main/java/com/fs/company/controller/qw/QwUserController.java

@@ -1,5 +1,6 @@
 package com.fs.company.controller.qw;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
 import com.fs.common.annotation.Log;
 import com.fs.common.annotation.RepeatSubmit;
@@ -69,16 +70,22 @@ import java.util.stream.Collectors;
 public class QwUserController extends BaseController
 {
     private static final org.slf4j.Logger logger = LoggerFactory.getLogger(QwUserController.class);
+
     @Autowired
     private IQwUserService qwUserService;
+
     @Autowired
     private TokenService tokenService;
+
     @Autowired
     private ICompanyUserService companyUserService;
+
     @Autowired
     private IQwExternalContactService qwExternalContactService;
+
     @Autowired
     private QwCompanyMapper qwCompanyMapper;
+
     @Autowired
     private QwExternalContactMapper qwExternalContactMapper;
 
@@ -105,16 +112,45 @@ public class QwUserController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('qw:user:staffList')")
     @GetMapping("/staffList")
-    public TableDataInfo staffList(QwUserListParam qwUser)
-    {
+    public TableDataInfo staffList(QwUserListParam qwUser) {
         startPage();
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         qwUser.setCompanyId(loginUser.getCompany().getCompanyId());
-
         List<QwUserVO> list = qwUserService.selectQwUserListStaffVO(qwUser);
         return getDataTable(list);
     }
 
+    /**
+     * 导出企微员工列表
+     * @param qwUser
+     * @return AjaxResult
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:export')")
+    @Log(title = "企微员工", businessType = BusinessType.EXPORT)
+    @GetMapping("/exportStaff")
+    public AjaxResult export(QwUserListParam qwUser) {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        qwUser.setCompanyId(loginUser.getCompany().getCompanyId());
+        List<QwUserVO> list = qwUserService.selectQwUserListStaffVO(qwUser);
+        ExcelUtil<QwUserVO> util = new ExcelUtil<QwUserVO>(QwUserVO.class);
+        return util.exportExcel(list, "企微员工数据");
+    }
+
+    /**
+     * 导出企微用户列表
+     */
+    @PreAuthorize("@ss.hasPermi('qw:user:export')")
+    @Log(title = "企微用户", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(QwUser qwUser) {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        qwUser.setCompanyId(loginUser.getCompany().getCompanyId());
+        List<QwUser> list = qwUserService.selectQwUserList(qwUser);
+        ExcelUtil<QwUser> util = new ExcelUtil<QwUser>(QwUser.class);
+        return util.exportExcel(list, "企微用户数据");
+    }
+
+
     /**
      * 查询我的部门 企业微信员工列表
      */
@@ -392,6 +428,12 @@ public class QwUserController extends BaseController
         startPage();
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         qwUser.setCompanyId(loginUser.getCompany().getCompanyId());
+        if (ObjectUtil.isNotEmpty(qwUser.getIsRemark())&&qwUser.getIsRemark().equals("1")){
+            qwUser.setCompanyUserId(loginUser.getUser().getUserId());
+        }else if (ObjectUtil.isNotEmpty(qwUser.getIsRemark())&&qwUser.getIsRemark().equals("2")){
+            qwUser.setDeptId(loginUser.getUser().getDeptId());
+            qwUser.setCorpId(null);
+        }
 
         List<QwUserVO> list = qwUserService.selectQwUserListVO(qwUser);
         return getDataTable(list);
@@ -427,20 +469,20 @@ public class QwUserController extends BaseController
 //    }
 
     /**
-     * 导出企微用户列表
+     * 查询企微用户列表-下拉框
      */
-    @PreAuthorize("@ss.hasPermi('qw:user:export')")
-    @Log(title = "企微用户", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(QwUser qwUser)
+    @GetMapping("/qwList")
+    public TableDataInfo getQwList(QwUser qwUser)
     {
+        startPage();
+
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        qwUser.setCompanyId(loginUser.getCompany().getCompanyId());
 
+        if(ObjectUtil.notEqual(qwUser.getDisableCompanyId(),1)){
+            qwUser.setCompanyId(loginUser.getCompany().getCompanyId());
+        }
         List<QwUser> list = qwUserService.selectQwUserList(qwUser);
-
-        ExcelUtil<QwUser> util = new ExcelUtil<QwUser>(QwUser.class);
-        return util.exportExcel(list, "企微用户数据");
+        return getDataTable(list);
     }
     /**
     * 查询企微员工列表-用于员工管理绑定

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

@@ -22,6 +22,7 @@ import com.fs.sop.dto.SopUserLogsParamDTO;
 import com.fs.sop.mapper.QwSopMapper;
 import com.fs.sop.params.SopUserLogsParam;
 import com.fs.sop.service.ISopUserLogsService;
+import com.fs.sop.vo.ReplaceUserDto;
 import com.fs.voice.utils.StringUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -31,6 +32,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * sopUserLogsController
@@ -101,7 +103,11 @@ public class SopUserLogsController extends BaseController
         if (!list.isEmpty()){
             // 收集所有需要查询的 qwUserId 和 corpId 组合
             List<SopUserLogsParamDTO> queryList = list.stream()
-                    .map(item -> new SopUserLogsParamDTO(item.getQwUserId(), item.getCorpId()))
+                    .flatMap(item -> Stream.of(
+                            new SopUserLogsParamDTO(item.getQwUserId(), item.getCorpId()),
+                            new SopUserLogsParamDTO(item.getActualQwUserId(), item.getCorpId())
+                    ))
+                    .filter(dto -> dto.getQwUserId() != null) // 过滤掉null的qwUserId
                     .distinct()  // 去重
                     .collect(Collectors.toList());
 
@@ -115,7 +121,9 @@ public class SopUserLogsController extends BaseController
             // 设置用户名
             list.forEach(item -> {
                 String key = item.getQwUserId() + "_" + item.getCorpId();
+                String key2 = item.getActualQwUserId() + "_" + item.getCorpId();
                 item.setQwUserName(userMap.get(key));
+                item.setActualQwUserName(userMap.get(key2));
             });
         }
         return getDataTable(list);
@@ -180,4 +188,11 @@ public class SopUserLogsController extends BaseController
         sopUserLogsService.addGroupChat(vo);
         return R.ok();
     }
+
+    @Log(title = "更换实际发送人", businessType = BusinessType.UPDATE)
+    @PostMapping("/replaceUser")
+    public R replaceUser(@RequestBody ReplaceUserDto vo){
+        sopUserLogsService.replaceUser(vo);
+        return R.ok();
+    }
 }

+ 71 - 0
fs-company/src/main/java/com/fs/company/controller/store/FsPrescribeController.java

@@ -1,15 +1,20 @@
 package com.fs.company.controller.store;
 
+import cn.hutool.json.JSONObject;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 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.enums.ImTypeEnum;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.security.SecurityUtils;
 import com.fs.his.domain.FsExportTask;
 import com.fs.his.domain.FsPrescribe;
+import com.fs.his.dto.PayloadDTO;
 import com.fs.his.param.FsPrescribeParam;
 import com.fs.his.service.IFsExportTaskService;
 import com.fs.his.service.IFsPrescribeService;
@@ -17,6 +22,11 @@ import com.fs.his.vo.FsMessageFeedbackExportListVO;
 import com.fs.his.vo.FsPrescribeExcelListVO;
 import com.fs.his.vo.FsPrescribeListVO;
 import com.fs.his.vo.FsPrescribeVO;
+import com.fs.im.config.ImTypeConfig;
+import com.fs.im.dto.OpenImMsgDTO;
+import com.fs.im.dto.OpenImResponseDTO;
+import com.fs.im.service.OpenIMService;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.transaction.annotation.Transactional;
@@ -31,6 +41,7 @@ import java.util.List;
  * @author fs
  * @date 2023-06-13
  */
+@Slf4j
 @RestController
 @RequestMapping("/store/prescribe")
 public class FsPrescribeController extends BaseController
@@ -39,6 +50,8 @@ public class FsPrescribeController extends BaseController
     private IFsPrescribeService fsPrescribeService;
     @Autowired
     private IFsExportTaskService exportTaskService;
+    @Autowired
+    private OpenIMService openIMService;
     /**
      * 查询处方列表
      */
@@ -72,6 +85,64 @@ public class FsPrescribeController extends BaseController
         return getDataTable(list);
     }
 
+    @GetMapping("/myImList")
+    public TableDataInfo myImList(FsPrescribeParam fsPrescribe)
+    {
+        startPage();
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        //fsPrescribe.setCompanyUserId(loginUser.getUser().getUserId());
+        List<FsPrescribeListVO> list = fsPrescribeService.selectFsPrescribeListVO(fsPrescribe);
+        for (FsPrescribeListVO vo : list) {
+            if (vo.getPatientTel()!=null){
+                vo.setPatientTel(vo.getPatientTel().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+            }
+        }
+        return getDataTable(list);
+    }
+
+    @PostMapping("/sendPrescribe")
+    public AjaxResult sendPrescribe(@RequestBody FsPrescribeParam fsPrescribe) throws JsonProcessingException {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        if(ImTypeConfig.IMTYPE== ImTypeEnum.OPENIM){
+            log.info("拼接消息体");
+            //部署到正式环境以后下面这段代码要注释,使用定时任务执行auditPrescribe审核处方以后发送消息
+            ObjectMapper objectMapper = new ObjectMapper();
+            OpenImMsgDTO openImMsgDTO = new OpenImMsgDTO();
+            openImMsgDTO.setSendID("C"+loginUser.getUser().getUserId());
+            openImMsgDTO.setRecvID("U"+fsPrescribe.getUserId());
+            openImMsgDTO.setContentType(110);
+            openImMsgDTO.setSenderPlatformID(5);
+            openImMsgDTO.setSessionType(1);
+            OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
+            //content.setContent(ext);
+            PayloadDTO payload = new PayloadDTO();
+            payload.setData("prescribe");
+            PayloadDTO.Extension extension = new PayloadDTO.Extension();
+            extension.setDiagnose(fsPrescribe.getDiagnose());
+            extension.setPrescribeId(fsPrescribe.getPrescribeId().toString());
+            payload.setExtension(extension);
+            extension.setStatus(fsPrescribe.getStatus());
+            OpenImMsgDTO.ImData imData = new OpenImMsgDTO.ImData();
+
+            imData.setPayload(payload);
+
+            String imJson = objectMapper.writeValueAsString(imData);
+            content.setData(imJson);
+            openImMsgDTO.setContent(content);
+
+            JSONObject jsonObject = new JSONObject(openImMsgDTO);
+            log.info("开始发送消息");
+//            OpenImMsgDTO.OfflinePushInfo offlinePushInfo = new OpenImMsgDTO.OfflinePushInfo();
+//            offlinePushInfo.setDesc("处方单");
+//            offlinePushInfo.setTitle(doctor.getDoctorName());
+//            offlinePushInfo.setIOSBadgeCount(true);
+//            offlinePushInfo.setIOSPushSound("");
+//            openImMsgDTO.setOfflinePushInfo(offlinePushInfo);
+            OpenImResponseDTO openImResponseDTO = openIMService.openIMSendMsg(openImMsgDTO);
+            return AjaxResult.success(openImResponseDTO);
+        }
+        return AjaxResult.success(null);
+    }
 
     /**
      * 导出处方列表

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

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

+ 29 - 0
fs-company/src/main/java/com/fs/company/utils/QwStatusEnum.java

@@ -0,0 +1,29 @@
+package com.fs.company.utils;
+
+/**
+ * @description:
+ * @author: Guos
+ * @time: 2025/10/16 下午3:00
+ */
+public enum QwStatusEnum {
+
+    BOUND(1, "已绑定"),
+    UNBOUND(0, "未绑定");
+
+    private Integer code;
+
+    private String detail;
+
+    QwStatusEnum(Integer code, String detail) {
+        this.code = code;
+        this.detail = detail;
+    }
+
+    public int getCode(){
+        return this.code;
+    }
+
+    public String getDetail() {
+        return this.detail;
+    }
+}

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

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

+ 3 - 1
fs-company/src/main/java/com/fs/framework/service/UserDetailsServiceImpl.java

@@ -9,6 +9,7 @@ import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.ICompanyService;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.framework.security.LoginUser;
+import com.fs.framework.security.SecurityUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -20,7 +21,7 @@ import org.springframework.stereotype.Service;
 /**
  * 用户验证处理
  *
- 
+
  */
 @Service
 public class UserDetailsServiceImpl implements UserDetailsService
@@ -45,6 +46,7 @@ public class UserDetailsServiceImpl implements UserDetailsService
 
 
         CompanyUser user = userService.selectUserByUserName(username);
+
         if (StringUtils.isNull(user))
         {
             log.info("登录用户:{} 不存在.", username);

+ 23 - 7
fs-company/src/main/java/com/fs/hisStore/controller/FsStoreOrderScrmController.java

@@ -35,10 +35,7 @@ import com.fs.hisStore.param.FsStoreOrderCreateUserParam;
 import com.fs.hisStore.param.FsStoreOrderFinishParam;
 import com.fs.hisStore.param.FsStoreOrderParam;
 import com.fs.hisStore.service.*;
-import com.fs.hisStore.vo.FsStoreOrderAuditLogVO;
-import com.fs.hisStore.vo.FsStoreOrderExportVO;
-import com.fs.hisStore.vo.FsStoreOrderItemExportVO;
-import com.fs.hisStore.vo.FsStoreOrderVO;
+import com.fs.hisStore.vo.*;
 import com.fs.system.service.ISysConfigService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -47,6 +44,8 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
 import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -171,7 +170,7 @@ public class FsStoreOrderScrmController extends BaseController
         if(!StringUtils.isEmpty(param.getDeliveryImportTimeRange())){
             param.setDeliveryImportTimeList(param.getDeliveryImportTimeRange().split("--"));
         }
-        List<FsStoreOrderExportVO> list = fsStoreOrderService.selectFsStoreOrderListVOByExport(param);
+        List<FsStoreOrderErpExportVO> list = fsStoreOrderService.selectFsStoreOrderListVOByExport(param);
         //对手机号脱敏
         if(list!=null){
             for(FsStoreOrderExportVO vo:list){
@@ -187,8 +186,25 @@ public class FsStoreOrderScrmController extends BaseController
 
             }
         }
-        ExcelUtil<FsStoreOrderExportVO> util = new ExcelUtil<FsStoreOrderExportVO>(FsStoreOrderExportVO.class);
-        return util.exportExcel(list,"订单数据");
+
+        String filter = param.getFilter();
+        // 1. 处理filter参数:将逗号分隔的字符串拆分为ArrayList<String>
+        ArrayList<String> filterList = new ArrayList<>();
+        if (StringUtils.isNotBlank(filter)) {
+            // 按逗号拆分,同时去除可能的空格(如filter传"orderId, orderCode"时兼容)
+            String[] filterArr = filter.split("\\s*,\\s*");
+            filterList.addAll(Arrays.asList(filterArr));
+        }
+        // 动态导出:根据选中的字段生成Excel
+        ExcelUtil<FsStoreOrderErpExportVO> util = new ExcelUtil<FsStoreOrderErpExportVO>(FsStoreOrderErpExportVO.class);
+        AjaxResult result;
+        // 如果有选中的字段,只导出这些字段
+        if (filter != null && !filter.isEmpty()) {
+            return util.exportExcelSelectedColumns(list, "订单数据", filterList);
+        } else {
+            // 导出所有字段
+            return util.exportExcel(list, "订单数据");
+        }
     }
 
 

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

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

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

@@ -3,12 +3,13 @@ server:
 # Spring配置
 spring:
   profiles:
-#    active: druid-fcky-test
-    active: druid-jnmy-test
+    active: druid-jnsyj-test
+#    active: druid-jnmy-test
 #    active: druid-jzzx-test
 #    active: druid-hdt
 #    active: druid-sxjz
 #    active: druid-yzt
 #    active: druid-myhk
 #    active: druid-sft
+#    active: dev-jnlzjk
 #    active: dev-yjb

+ 1 - 1
fs-company/src/main/resources/logback.xml

@@ -72,7 +72,7 @@
     </appender>
 
 	<!-- 系统模块日志级别控制  -->
-	<logger name="com.fs" level="info" />
+	<logger name="com.fs" level="debug" />
 	<!-- Spring日志级别控制  -->
 	<logger name="org.springframework" level="warn" />
 

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

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

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

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

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

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

+ 24 - 6
fs-doctor-app/src/main/java/com/fs/app/controller/DrugReportController.java

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

+ 50 - 11
fs-doctor-app/src/main/java/com/fs/app/controller/InquiryOrderController.java

@@ -3,11 +3,15 @@ package com.fs.app.controller;
 
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fs.app.annotation.Login;
 import com.fs.common.BeanCopyUtils;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.domain.R;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.enums.ImTypeEnum;
+import com.fs.common.utils.SecurityUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.service.ICompanyService;
 import com.fs.core.config.WxPayProperties;
@@ -17,19 +21,27 @@ import com.fs.his.dto.FsInquiryOrderPatientDTO;
 import com.fs.his.param.*;
 import com.fs.his.service.*;
 import com.fs.his.vo.*;
+import com.fs.im.config.ImTypeConfig;
 import com.fs.im.dto.MsgCustomDTO;
 import com.fs.im.dto.MsgDTO;
 import com.fs.im.dto.MsgDataDTO;
 import com.fs.im.dto.MsgDataFormatDTO;
 import com.fs.im.service.IImService;
+import com.fs.im.service.OpenIMService;
+import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
+import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
+import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.github.binarywang.wxpay.exception.WxPayException;
 import com.github.binarywang.wxpay.service.WxPayService;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
+import io.reactivex.internal.operators.parallel.ParallelRunOn;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
@@ -71,7 +83,8 @@ public class InquiryOrderController extends  AppBaseController {
     private IFsInquiryOrderReportService orderReportService;
     @Autowired
     private IImService imService;
-
+    @Autowired
+    private OpenIMService openIMService;
     @Login
     @GetMapping("/getInquiryOrderList")
     public R getInquiryOrderList(FsInquiryOrderListPDParam param)
@@ -79,11 +92,7 @@ public class InquiryOrderController extends  AppBaseController {
         FsDoctor doctor=doctorService.selectFsDoctorByDoctorId(Long.parseLong(getDoctorId()));
         PageHelper.startPage(param.getPageNum(), param.getPageSize());
 
-        if (Objects.nonNull(param.getUserId())) {
-            param.setDoctorId(null);
-        } else if (Objects.nonNull(param.getDoctorId())) {
-            param.setDoctorId(Long.parseLong(getDoctorId()));
-        }
+        param.setDoctorId(Long.parseLong(getDoctorId()));
 
         param.setIsAccept(doctor.getIsAccept());
         param.setIsSelf(doctor.getIsSelf());
@@ -164,7 +173,7 @@ public class InquiryOrderController extends  AppBaseController {
     @Login
     @ApiOperation("抢单")
     @PostMapping("/acceptOrder")
-    public R acceptOrder(@Validated @RequestBody FsInquiryOrderAcceptParam param, HttpServletRequest request){
+    public R acceptOrder(@Validated @RequestBody FsInquiryOrderAcceptParam param, HttpServletRequest request) throws JsonProcessingException {
         param.setDoctorId(Long.parseLong(getDoctorId()));
         return inquiryOrderService.acceptOrder(param);
     }
@@ -172,7 +181,7 @@ public class InquiryOrderController extends  AppBaseController {
     @Login
     @ApiOperation("接单")
     @PostMapping("/receiveOrder")
-    public R receiveOrder(@Validated @RequestBody FsInquiryOrderReceiveParam param, HttpServletRequest request){
+    public R receiveOrder(@Validated @RequestBody FsInquiryOrderReceiveParam param, HttpServletRequest request) throws JsonProcessingException {
         param.setDoctorId(Long.parseLong(getDoctorId()));
         return inquiryOrderService.receiveOrder(param);
     }
@@ -188,7 +197,7 @@ public class InquiryOrderController extends  AppBaseController {
     @Login
     @ApiOperation("完成订单")
     @PostMapping("/finishOrder")
-    public R finishOrder(@Validated @RequestBody FsInquiryOrderFinishParam param, HttpServletRequest request){
+    public R finishOrder(@Validated @RequestBody FsInquiryOrderFinishParam param, HttpServletRequest request) throws JsonProcessingException {
         param.setDoctorId(Long.parseLong(getDoctorId()));
         return inquiryOrderService.finishOrder(param);
     }
@@ -241,7 +250,7 @@ public class InquiryOrderController extends  AppBaseController {
     @ApiOperation("提交诊断报告")
     @PostMapping("/submitInquiryOrderReport")
     @Transactional
-    public R submitInquiryOrderReport(@Validated @RequestBody FsInquiryOrderReportSubmitDParam param, HttpServletRequest request){
+    public R submitInquiryOrderReport(@Validated @RequestBody FsInquiryOrderReportSubmitDParam param, HttpServletRequest request) throws JsonProcessingException {
         FsInquiryOrderReport report=null;
         if(param.getReportId()!=null&&param.getReportId()>0){
             report=orderReportService.selectFsInquiryOrderReportByReportId(param.getReportId());
@@ -299,7 +308,30 @@ public class InquiryOrderController extends  AppBaseController {
         msg.setMsgType("TIMCustomElem");//TIMCustomElem
         msgs.add(msg);
         msgDTO.setMsgBody(msgs);
-        imService.sendMsg(msgDTO);
+        if (ImTypeConfig.IMTYPE== ImTypeEnum.OPENIM){
+            ObjectMapper objectMapper = new ObjectMapper();
+            String ex = objectMapper.writeValueAsString(customDTO);
+            openIMService.sendUtil("D"+report.getDoctorId(),"U"+report.getUserId(),110,"report","","","",report.getOrderId().toString(),ex);
+        }else if (ImTypeConfig.IMTYPE== ImTypeEnum.TENCENT){
+            imService.sendMsg(msgDTO);
+        }
+//        JSONObject jsonObject = new JSONObject();
+//        OpenImMsgDTO openImMsgDTO = new OpenImMsgDTO();
+//        openImMsgDTO.setSendID("D"+report.getDoctorId().toString());
+//        openImMsgDTO.setRecvID("U"+report.getUserId().toString());
+//        openImMsgDTO.setContentType(110);
+//        openImMsgDTO.setSenderPlatformID(5);
+//        openImMsgDTO.setSessionType(1);
+//
+//        OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
+//        PayloadDTO payloadDTO = new PayloadDTO();
+//        payloadDTO.setData("startInquiry");
+//        PayloadDTO.Extension extension = new PayloadDTO.Extension();
+//        extension.setTitle();
+//        //content.setContent(ext);
+//        openImMsgDTO.setContent(content);
+//        openImMsgDTO.setEx(customDTO);
+//        openIMService.openIMSendMsg(openImMsgDTO);
         return R.ok("操作成功");
     }
 
@@ -330,4 +362,11 @@ public class InquiryOrderController extends  AppBaseController {
         }
         return R.ok().put("data","");
     }
+
+    @PostMapping("/closeOrder")
+    public R closeOrder(@RequestBody Long orderId){
+        inquiryOrderService.closeOrder(orderId);
+        logger.info("closeOrder: {}", orderId);
+        return R.ok();
+    }
 }

+ 108 - 6
fs-doctor-app/src/main/java/com/fs/app/controller/PrescribeController.java

@@ -2,23 +2,37 @@ package com.fs.app.controller;
 
 
 import cn.hutool.core.util.IdUtil;
+import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fs.app.annotation.Login;
 import com.fs.common.core.domain.R;
+import com.fs.common.enums.ImTypeEnum;
+import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.core.utils.OrderCodeUtils;
 import com.fs.his.domain.*;
 import com.fs.his.dto.FsInquiryOrderPatientDTO;
+import com.fs.his.dto.PayloadDTO;
 import com.fs.his.param.*;
 import com.fs.his.service.*;
 import com.fs.his.vo.FsDoctorPrescribeListDVO;
 import com.fs.his.vo.FsPrescribeListDVO;
+import com.fs.im.config.IMConfig;
+import com.fs.im.config.ImTypeConfig;
+import com.fs.im.dto.MsgCustomDTO;
+import com.fs.im.dto.OpenImMsgDTO;
+import com.fs.im.dto.OpenImResponseDTO;
 import com.fs.im.service.IImService;
+import com.fs.im.service.OpenIMService;
+import com.fs.qw.domain.QwExternalContact;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.Synchronized;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
@@ -26,12 +40,10 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 
+@Slf4j
 @Api("处方接口")
 @RestController
 @RequestMapping(value="/app/prescribe")
@@ -55,7 +67,8 @@ public class PrescribeController extends  AppBaseController {
     private IFsStoreOrderService storeOrderService;
     @Autowired
     private IImService imService;
-
+    @Autowired
+    private OpenIMService openIMService;
     @Login
     @GetMapping("/getDoctorPrescribeList")
     public R getDoctorPrescribeList(FsDoctorPrescribeListDParam param)
@@ -186,7 +199,7 @@ public class PrescribeController extends  AppBaseController {
     @ApiOperation("创建处方")
     @Transactional
     @PostMapping("/createPrescribe")
-    public R createPrescribe(@Validated @RequestBody FsPrescribeCreateParam param, HttpServletRequest request){
+    public R createPrescribe(@Validated @RequestBody FsPrescribeCreateParam param, HttpServletRequest request) throws JsonProcessingException {
 
         //获取问诊单
         FsInquiryOrder inquiryOrder=inquiryOrderService.selectFsInquiryOrderByOrderId(param.getOrderId());
@@ -253,6 +266,44 @@ public class PrescribeController extends  AppBaseController {
                     prescribeDrug.setPrescribeId(prescribe.getPrescribeId());
                     prescribeDrugService.insertFsPrescribeDrug(prescribeDrug);
                 }
+                if(ImTypeConfig.IMTYPE== ImTypeEnum.OPENIM){
+                    log.info("拼接消息体");
+                    //部署到正式环境以后下面这段代码要注释,使用定时任务执行auditPrescribe审核处方以后发送消息
+                    ObjectMapper objectMapper = new ObjectMapper();
+                    OpenImMsgDTO openImMsgDTO = new OpenImMsgDTO();
+                    openImMsgDTO.setSendID("D"+inquiryOrder.getDoctorId());
+                    openImMsgDTO.setRecvID("U"+inquiryOrder.getUserId());
+                    openImMsgDTO.setContentType(110);
+                    openImMsgDTO.setSenderPlatformID(5);
+                    openImMsgDTO.setSessionType(1);
+                    OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
+                    //content.setContent(ext);
+                    PayloadDTO payload = new PayloadDTO();
+                    payload.setData("prescribe");
+                    PayloadDTO.Extension extension = new PayloadDTO.Extension();
+                    extension.setDiagnose(inquiryOrder.getTitle());
+                    extension.setPrescribeId(prescribe.getPrescribeId().toString());
+                    payload.setExtension(extension);
+                    extension.setStatus(prescribe.getStatus());
+                    OpenImMsgDTO.ImData imData = new OpenImMsgDTO.ImData();
+
+                    imData.setPayload(payload);
+
+                    String imJson = objectMapper.writeValueAsString(imData);
+                    content.setData(imJson);
+                    openImMsgDTO.setContent(content);
+
+                    JSONObject jsonObject = new JSONObject(openImMsgDTO);
+                    log.info("开始发送消息");
+                    OpenImMsgDTO.OfflinePushInfo offlinePushInfo = new OpenImMsgDTO.OfflinePushInfo();
+                    offlinePushInfo.setDesc("处方单");
+                    offlinePushInfo.setTitle(doctor.getDoctorName());
+                    offlinePushInfo.setIOSBadgeCount(true);
+                    offlinePushInfo.setIOSPushSound("");
+                    openImMsgDTO.setOfflinePushInfo(offlinePushInfo);
+                    OpenImResponseDTO openImResponseDTO = openIMService.openIMSendMsg(openImMsgDTO);
+                }
+
 
                 return R.ok("操作成功").put("prescribe",prescribe);
             }
@@ -275,4 +326,55 @@ public class PrescribeController extends  AppBaseController {
         String url=prescribeService.getPrescribeCodeUrl(prescribeId);
         return R.ok().put("url",url);
     }
+    @PostMapping("/test")
+    public R test(@RequestBody HashMap<String,String> map) throws JsonProcessingException {
+        ObjectMapper objectMapper = new ObjectMapper();
+        OpenImMsgDTO openImMsgDTO = new OpenImMsgDTO();
+        openImMsgDTO.setSendID("D"+79);
+        openImMsgDTO.setRecvID("U"+map.get("userId"));
+        openImMsgDTO.setContentType(110);
+        openImMsgDTO.setSenderPlatformID(5);
+        openImMsgDTO.setSessionType(1);
+        OpenImMsgDTO.Content content = new OpenImMsgDTO.Content();
+        //content.setContent(ext);
+        PayloadDTO payload = new PayloadDTO();
+        payload.setData("prescribe");
+        PayloadDTO.Extension extension = new PayloadDTO.Extension();
+        extension.setDiagnose("感冒发烧,胸闷");
+        payload.setExtension(extension);
+        //log.info("payload:{}",payload);
+        OpenImMsgDTO.ImData imData = new OpenImMsgDTO.ImData();
+
+        imData.setPayload(payload);
+
+        String imJson = objectMapper.writeValueAsString(imData);
+        content.setData(imJson);
+        openImMsgDTO.setContent(content);
+        //log.info("openImMsgDTO:{}",openImMsgDTO);
+        JSONObject jsonObject = new JSONObject(openImMsgDTO);
+        //log.info("jsonObject:{}",jsonObject);
+        MsgCustomDTO customDTO=new MsgCustomDTO();
+        //customDTO.setType("startInquiry");
+        customDTO.setType(map.get("payloadDAata").toString());
+        customDTO.setOrderType(2);
+        customDTO.setOrderId(map.get("orderId"));
+        String imtype = map.get("imtype").toString();
+
+        customDTO.setImType(Integer.parseInt(imtype));
+        //openImMsgDTO.setEx(payload);
+        String ex = objectMapper.writeValueAsString(customDTO);
+        QwExternalContact qwExternalContact = new QwExternalContact();
+        qwExternalContact.setId(1l);
+        qwExternalContact.setFsUserId(1l);
+        //WatchSleepData last = watchSleepDataMapper.getLast("861389060165680");
+        //watchAudioMsgLogMapper.insert(watchAudioMsgLog);
+        //qwExternalContactMapper.selectRemarkByCompanyUserAndFsUser(map.get("sendId"), map.get("userId"),"wwwwww");
+        //fsUserCouponService.updateFsUserCouponStatusByLimtType2();
+//        openIMService.checkAndImportFriendByDianBo(Long.parseLong(map.get("sendId")),map.get("userId"),qwExternalContact.getCorpId());
+        //OpenImResponseDTO openImResponseDTO = openIMService.sendCourse(Long.parseLong(map.get("userId")), Long.parseLong(map.get("sendId")), "/pages/courseAnswer/index?link=1932017457275338752", "《五仙传医2.0》","https://cos.his.cdwjyyh.com/fs/20241108/a8ed49ae9a264c7483cec5bdcbcf6060.png");
+        log.info("请求地址{}",IMConfig.URL);
+//        log.info("前缀{}",IMConfig.PREFIX);
+        //OpenImResponseDTO openImResponseDTO = openIMService.sendUtil("D" +map.get("sendId"), "U"+map.get("userId").toString(), 110, map.get("payloadDAata").toString(), "", map.get("title").toString(), "", "3135749",ex);
+        return R.ok().put("data",null);
+    }
 }

+ 18 - 2
fs-doctor-app/src/main/java/com/fs/framework/config/MyBatisConfig.java

@@ -28,7 +28,7 @@ import java.util.List;
 
 /**
  * Mybatis支持*匹配扫描包
- * 
+ *
 
  */
 @Configuration
@@ -115,6 +115,22 @@ public class MyBatisConfig
         return resources.toArray(new Resource[resources.size()]);
     }
 
+    //    @Bean
+//    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
+//    {
+//        String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage");
+//        String mapperLocations = env.getProperty("mybatis.mapperLocations");
+//        String configLocation = env.getProperty("mybatis.configLocation");
+//        typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
+//        VFS.addImplClass(SpringBootVFS.class);
+//
+//        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
+//        sessionFactory.setDataSource(dataSource);
+//        sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
+//        sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
+//        sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
+//        return sessionFactory.getObject();
+//    }
     @Bean
     public SqlSessionFactory sqlSessionFactorys(DataSource dataSource) throws Exception
     {
@@ -131,4 +147,4 @@ public class MyBatisConfig
         sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
         return sessionFactory.getObject();
     }
-}
+}

+ 1 - 1
fs-doctor-app/src/main/resources/application.yml

@@ -6,4 +6,4 @@ server:
 spring:
   profiles:
 #    active: dev
-    active: druid-jnmy
+    active: dev-yjb

+ 2 - 2
fs-doctor-app/src/main/resources/mybatis/mybatis-config.xml

@@ -3,7 +3,7 @@
 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-config.dtd">
 <configuration>
-	
+
 	<settings>
 		<setting name="cacheEnabled"             value="true" />  <!-- 全局映射器启用缓存 -->
 		<setting name="useGeneratedKeys"         value="true" />  <!-- 允许 JDBC 支持自动生成主键 -->
@@ -11,5 +11,5 @@ PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 		<setting name="logImpl"                  value="SLF4J" /> <!-- 指定 MyBatis 所用日志的具体实现 -->
 		 <setting name="mapUnderscoreToCamelCase" value="true"/>
 	</settings>
-	
+
 </configuration>

+ 0 - 120
fs-hospital/pom.xml

@@ -1,120 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>fs</artifactId>
-        <groupId>com.fs</groupId>
-        <version>1.1.0</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <groupId>com.fs</groupId>
-    <artifactId>fs-hospital</artifactId>
-    <description>
-        诊所接口
-    </description>
-
-    <dependencies>
-
-        <!-- spring-boot-devtools -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-devtools</artifactId>
-            <optional>true</optional> <!-- 表示依赖不会传递 -->
-        </dependency>
-        <!-- swagger2-->
-
-        <dependency>
-            <groupId>io.springfox</groupId>
-            <artifactId>springfox-swagger2</artifactId>
-        </dependency>
-
-        <!-- swagger2-UI-->
-
-        <dependency>
-            <groupId>com.github.xiaoymin</groupId>
-            <artifactId>swagger-bootstrap-ui</artifactId>
-            <version>1.9.3</version>
-        </dependency>
-
-
-        <!-- Mysql驱动包 -->
-        <dependency>
-            <groupId>mysql</groupId>
-            <artifactId>mysql-connector-java</artifactId>
-        </dependency>
-
-        <!-- SpringBoot Web容器 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
-        </dependency>
-
-        <!-- SpringBoot 拦截器 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-aop</artifactId>
-        </dependency>
-
-        <!-- 阿里数据库连接池 -->
-        <dependency>
-            <groupId>com.alibaba</groupId>
-            <artifactId>druid-spring-boot-starter</artifactId>
-        </dependency>
-
-        <!-- 验证码 -->
-        <dependency>
-            <groupId>com.github.penggle</groupId>
-            <artifactId>kaptcha</artifactId>
-            <exclusions>
-                <exclusion>
-                    <artifactId>javax.servlet-api</artifactId>
-                    <groupId>javax.servlet</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
-        <!-- 获取系统信息 -->
-        <dependency>
-            <groupId>com.github.oshi</groupId>
-            <artifactId>oshi-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.fs</groupId>
-            <artifactId>fs-service</artifactId>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <version>2.1.1.RELEASE</version>
-                <configuration>
-                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
-                </configuration>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>repackage</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-war-plugin</artifactId>
-                <version>3.1.0</version>
-                <configuration>
-                    <failOnMissingWebXml>false</failOnMissingWebXml>
-                    <warName>${project.artifactId}</warName>
-                </configuration>
-            </plugin>
-        </plugins>
-        <finalName>${project.artifactId}</finalName>
-    </build>
-
-
-</project>

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