Browse Source

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

# Conflicts:
#	fs-service-system/src/main/java/com/fs/qw/mapper/QwExternalContactMapper.java
#	fs-service-system/src/main/java/com/fs/qw/service/IQwExternalContactService.java
#	fs-service-system/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java
caoliqin 3 tuần trước cách đây
mục cha
commit
62b35b896d
100 tập tin đã thay đổi với 4099 bổ sung85 xóa
  1. 1 0
      fs-admin/src/main/java/com/fs/store/controller/FsStoreOrderController.java
  2. 13 3
      fs-admin/src/main/resources/application-dev.yml
  3. 1 2
      fs-admin/src/main/resources/application.yml
  4. 2 1
      fs-company/src/main/java/com/fs/FSCompanyApplication.java
  5. 131 2
      fs-company/src/main/java/com/fs/course/controller/FsCourseWatchLogController.java
  6. 3 3
      fs-company/src/main/java/com/fs/qw/QwMaterialController.java
  7. 7 3
      fs-company/src/main/java/com/fs/qw/QwSopController.java
  8. 1 6
      fs-company/src/main/java/com/fs/qw/QwSopLogsController.java
  9. 21 0
      fs-company/src/main/java/com/fs/qw/vo/AdUploadVo.java
  10. 24 0
      fs-company/src/main/java/com/fs/qw/vo/CompanyUserQwVO.java
  11. 37 0
      fs-company/src/main/java/com/fs/qw/vo/FsAppContactWayListVO.java
  12. 57 0
      fs-company/src/main/java/com/fs/qw/vo/QwAppContactWayLogsListVO.java
  13. 69 0
      fs-company/src/main/java/com/fs/qw/vo/QwAutoTagsLogsVO.java
  14. 62 0
      fs-company/src/main/java/com/fs/qw/vo/QwAutoTagsVO.java
  15. 76 0
      fs-company/src/main/java/com/fs/qw/vo/QwChatSopTempSetting.java
  16. 9 0
      fs-company/src/main/java/com/fs/qw/vo/QwCloudAPVO.java
  17. 42 0
      fs-company/src/main/java/com/fs/qw/vo/QwContactBatchListVO.java
  18. 18 0
      fs-company/src/main/java/com/fs/qw/vo/QwContactListVO.java
  19. 30 0
      fs-company/src/main/java/com/fs/qw/vo/QwCrmCourseStudyVO.java
  20. 17 0
      fs-company/src/main/java/com/fs/qw/vo/QwExtStatisticsVO.java
  21. 36 0
      fs-company/src/main/java/com/fs/qw/vo/QwExternalContactCrmVO.java
  22. 37 0
      fs-company/src/main/java/com/fs/qw/vo/QwExternalContactFsCrmVO.java
  23. 11 0
      fs-company/src/main/java/com/fs/qw/vo/QwExternalContactFsUserVO.java
  24. 57 0
      fs-company/src/main/java/com/fs/qw/vo/QwExternalContactTransferLogListVO.java
  25. 114 0
      fs-company/src/main/java/com/fs/qw/vo/QwExternalContactVO.java
  26. 21 0
      fs-company/src/main/java/com/fs/qw/vo/QwFriendWelcomeDayPart.java
  27. 65 0
      fs-company/src/main/java/com/fs/qw/vo/QwFriendWelcomeVO.java
  28. 12 0
      fs-company/src/main/java/com/fs/qw/vo/QwFromUserVO.java
  29. 19 0
      fs-company/src/main/java/com/fs/qw/vo/QwFsUserVO.java
  30. 9 0
      fs-company/src/main/java/com/fs/qw/vo/QwGroupChatOptionsVO.java
  31. 81 0
      fs-company/src/main/java/com/fs/qw/vo/QwGroupChatUserVO.java
  32. 70 0
      fs-company/src/main/java/com/fs/qw/vo/QwGroupChatVO.java
  33. 77 0
      fs-company/src/main/java/com/fs/qw/vo/QwGroupMsgDetailsVO.java
  34. 165 0
      fs-company/src/main/java/com/fs/qw/vo/QwGroupMsgVO.java
  35. 63 0
      fs-company/src/main/java/com/fs/qw/vo/QwGroupchatStatisticVO.java
  36. 12 0
      fs-company/src/main/java/com/fs/qw/vo/QwHookAuthVO.java
  37. 83 0
      fs-company/src/main/java/com/fs/qw/vo/QwMaterialVO.java
  38. 34 0
      fs-company/src/main/java/com/fs/qw/vo/QwMessageListVO.java
  39. 11 0
      fs-company/src/main/java/com/fs/qw/vo/QwOptionsVO.java
  40. 120 0
      fs-company/src/main/java/com/fs/qw/vo/QwSopCourseFinishTempSetting.java
  41. 92 0
      fs-company/src/main/java/com/fs/qw/vo/QwSopRuleTimeVO.java
  42. 159 0
      fs-company/src/main/java/com/fs/qw/vo/QwSopTempSetting.java
  43. 134 0
      fs-company/src/main/java/com/fs/qw/vo/QwSopTempSetting2.java
  44. 44 0
      fs-company/src/main/java/com/fs/qw/vo/QwTagGroupAddParam.java
  45. 50 0
      fs-company/src/main/java/com/fs/qw/vo/QwTagGroupListVO.java
  46. 48 0
      fs-company/src/main/java/com/fs/qw/vo/QwTagGroupVO.java
  47. 32 0
      fs-company/src/main/java/com/fs/qw/vo/QwTagVO.java
  48. 71 0
      fs-company/src/main/java/com/fs/qw/vo/QwUserVO.java
  49. 50 0
      fs-company/src/main/java/com/fs/qw/vo/QwUserVideoVO.java
  50. 61 0
      fs-company/src/main/java/com/fs/qw/vo/QwUserbehaviorDataVO.java
  51. 82 0
      fs-company/src/main/java/com/fs/qw/vo/QwWatchLogAllStatisticsListVO.java
  52. 33 0
      fs-company/src/main/java/com/fs/qw/vo/QwWatchLogStatisticsListVO.java
  53. 14 0
      fs-company/src/main/java/com/fs/qw/vo/QwWayStatisticsListVO.java
  54. 40 0
      fs-company/src/main/java/com/fs/qw/vo/QwWelcomeJsonFrom.java
  55. 46 0
      fs-company/src/main/java/com/fs/qw/vo/QwWorkTaskListVO.java
  56. 95 0
      fs-company/src/main/java/com/fs/qw/vo/SopRuleTimeSetting.java
  57. 11 0
      fs-company/src/main/java/com/fs/qw/vo/SortDayVo.java
  58. 92 0
      fs-company/src/main/java/com/fs/qw/vo/WxSopRuleTimeVO.java
  59. 104 0
      fs-company/src/main/java/com/fs/wxuser/CompanyWxUserController.java
  60. 59 0
      fs-company/src/main/resources/application-dev.yml
  61. 15 1
      fs-service-system/pom.xml
  62. 33 0
      fs-service-system/src/main/java/com/fs/company/cache/ICompanyUserCacheService.java
  63. 32 0
      fs-service-system/src/main/java/com/fs/company/cache/impl/CompanyUserCacheServiceImpl.java
  64. 1 0
      fs-service-system/src/main/java/com/fs/company/domain/CompanyUser.java
  65. 79 15
      fs-service-system/src/main/java/com/fs/company/mapper/CompanyUserMapper.java
  66. 11 0
      fs-service-system/src/main/java/com/fs/company/param/CompanyUserAreaParam.java
  67. 4 2
      fs-service-system/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java
  68. 87 0
      fs-service-system/src/main/java/com/fs/course/domain/FsCourseSopAppLink.java
  69. 1 1
      fs-service-system/src/main/java/com/fs/course/domain/FsUserCourseVideo.java
  70. 6 1
      fs-service-system/src/main/java/com/fs/course/mapper/FsCourseLinkMapper.java
  71. 98 0
      fs-service-system/src/main/java/com/fs/course/mapper/FsCourseSopAppLinkMapper.java
  72. 80 8
      fs-service-system/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java
  73. 8 0
      fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseMapper.java
  74. 5 1
      fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java
  75. 0 1
      fs-service-system/src/main/java/com/fs/course/param/FsCourseLinkCreateParam.java
  76. 17 0
      fs-service-system/src/main/java/com/fs/course/param/FsCourseOverParam.java
  77. 1 0
      fs-service-system/src/main/java/com/fs/course/param/FsCourseSendRewardUParam.java
  78. 12 0
      fs-service-system/src/main/java/com/fs/course/param/FsCourseSopLinkParam.java
  79. 18 0
      fs-service-system/src/main/java/com/fs/course/param/FsCourseUserStatisticsListParam.java
  80. 1 0
      fs-service-system/src/main/java/com/fs/course/param/FsCourseWatchLogListParam.java
  81. 0 1
      fs-service-system/src/main/java/com/fs/course/param/FsUserCourseGetIntegralParam.java
  82. 0 1
      fs-service-system/src/main/java/com/fs/course/param/FsUserCourseListUParam.java
  83. 0 1
      fs-service-system/src/main/java/com/fs/course/param/FsUserCourseOrderCreateParam.java
  84. 6 0
      fs-service-system/src/main/java/com/fs/course/param/FsUserCourseVideoParam.java
  85. 0 1
      fs-service-system/src/main/java/com/fs/course/param/FsUserVipOrderCreateUParam.java
  86. 27 0
      fs-service-system/src/main/java/com/fs/course/param/SopRoomCourseParam.java
  87. 7 0
      fs-service-system/src/main/java/com/fs/course/service/IFsCourseLinkService.java
  88. 13 3
      fs-service-system/src/main/java/com/fs/course/service/IFsCourseWatchLogService.java
  89. 132 2
      fs-service-system/src/main/java/com/fs/course/service/impl/FsCourseLinkServiceImpl.java
  90. 161 16
      fs-service-system/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java
  91. 11 7
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java
  92. 4 2
      fs-service-system/src/main/java/com/fs/course/vo/FsCourseFinishTempListVO.java
  93. 26 0
      fs-service-system/src/main/java/com/fs/course/vo/FsCourseOverVO.java
  94. 7 0
      fs-service-system/src/main/java/com/fs/course/vo/FsCourseUserStatisticsListVO.java
  95. 12 1
      fs-service-system/src/main/java/com/fs/course/vo/FsCourseWatchLogListVO.java
  96. 20 0
      fs-service-system/src/main/java/com/fs/course/vo/FsCourseWatchLogTaskVO.java
  97. 83 0
      fs-service-system/src/main/java/com/fs/course/vo/FsQwCourseWatchLogVO.java
  98. 42 0
      fs-service-system/src/main/java/com/fs/course/vo/FsSopMyCourseLinkVO.java
  99. 3 0
      fs-service-system/src/main/java/com/fs/course/vo/FsUserCourseListPVO.java
  100. 1 0
      fs-service-system/src/main/java/com/fs/course/vo/FsUserCourseVideoQVO.java

+ 1 - 0
fs-admin/src/main/java/com/fs/store/controller/FsStoreOrderController.java

@@ -532,6 +532,7 @@ public class FsStoreOrderController extends BaseController {
     @GetMapping("/createErpOrder")
     public R createErpOrder(@RequestParam("orderCode") String orderCode) throws Exception
     {
+        logger.info("手动推管易订单号:{}",orderCode);
         FsStoreOrder order=fsStoreOrderService.selectFsStoreOrderByOrderCode(orderCode);
         fsStoreOrderService.createOmsOrder(order.getId());
         return R.ok();

+ 13 - 3
fs-admin/src/main/resources/application-dev.yml

@@ -83,9 +83,9 @@ spring:
             druid:
                 # 主库数据源
                 master:
-                    url: jdbc:mysql://139.186.77.83/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: Rtroot
-                    password: Rtroot
+                    url: jdbc:mysql://localhost/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: 123456
                 # 初始连接数
                 initialSize: 5
                 # 最小连接池数量
@@ -125,3 +125,13 @@ spring:
                     wall:
                         config:
                             multi-statement-allow: true
+rocketmq:
+    name-server: rmq-1243b25nj.rocketmq.gz.public.tencenttdmq.com:8080 # RocketMQ NameServer 地址
+    producer:
+        group: my-producer-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+    consumer:
+        group: test-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey

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

@@ -34,9 +34,8 @@ server:
 # 日志配置
 logging:
   level:
-    com.fs: info
+    com.fs: debug
     org.springframework: warn
-
 # Spring配置
 spring:
   mvc:

+ 2 - 1
fs-company/src/main/java/com/fs/FSCompanyApplication.java

@@ -1,5 +1,6 @@
 package com.fs;
 
+import com.fs.core.security.SecurityUtils;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@@ -20,6 +21,6 @@ public class FSCompanyApplication
     {
         // System.setProperty("spring.devtools.restart.enabled", "false");
         SpringApplication.run(FSCompanyApplication.class, args);
-        System.out.println("销售公司PC端启动成功 \n" );
+        System.out.println("销售公司PC端启动成功 \n");
     }
 }

+ 131 - 2
fs-company/src/main/java/com/fs/course/controller/FsCourseWatchLogController.java

@@ -8,15 +8,29 @@ import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.core.security.LoginUser;
+import com.fs.core.web.service.TokenService;
 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.service.IFsCourseWatchLogService;
+import com.fs.course.vo.FsCourseOverVO;
+import com.fs.course.vo.FsCourseUserStatisticsListVO;
 import com.fs.course.vo.FsCourseWatchLogListVO;
+import com.fs.course.vo.FsCourseWatchLogStatisticsListVO;
+import com.fs.qw.domain.QwWatchLog;
+import com.fs.qw.param.QwWatchLogStatisticsListParam;
+import com.fs.qw.param.SopUserLogsVO;
+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;
 import org.springframework.web.bind.annotation.*;
-import com.fs.common.annotation.Log;
-import com.fs.core.web.service.TokenService;
+
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -33,6 +47,10 @@ public class FsCourseWatchLogController extends BaseController
     private IFsCourseWatchLogService fsCourseWatchLogService;
     @Autowired
     private TokenService tokenService;
+    @Autowired
+    private SopUserLogsMapper sopUserLogsMapper;
+    @Autowired
+    private IQwWatchLogService qwWatchLogService;
     /**
      * 查询短链课程看课记录列表
      */
@@ -41,9 +59,120 @@ public class FsCourseWatchLogController extends BaseController
     public TableDataInfo list(FsCourseWatchLogListParam param)
     {
         startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId( loginUser.getCompany().getCompanyId());
         List<FsCourseWatchLogListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogListVO(param);
         return getDataTable(list);
     }
+
+    @PreAuthorize("@ss.hasPermi('course:courseWatchLog:statisticsList')")
+    @GetMapping("/statisticsList")
+    public TableDataInfo statisticsList(FsCourseWatchLogStatisticsListParam param)
+    {
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId( loginUser.getCompany().getCompanyId());
+        if (param.getSTime()==null||param.getETime()==null){
+            return getDataTable(new ArrayList<>());
+        }
+        List<FsCourseWatchLogStatisticsListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogStatisticsListVO(param);
+        return getDataTable(list);
+    }
+
+    @GetMapping("/qwWatchLogStatisticsList")
+    public TableDataInfo qwWatchLogStatisticsList(QwWatchLogStatisticsListParam param)
+    {
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId( loginUser.getCompany().getCompanyId());
+        if (param.getSTime()==null||param.getETime()==null){
+            return getDataTable(new ArrayList<>());
+        }
+        List<QwWatchLogStatisticsListVO> list = qwWatchLogService.selectQwWatchLogStatisticsListVO(param);
+        return getDataTable(list);
+    }
+    @GetMapping("/myQwWatchLogStatisticsList")
+    public TableDataInfo myQwWatchLogStatisticsList(QwWatchLogStatisticsListParam param)
+    {
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId( loginUser.getCompany().getCompanyId());
+        param.setCompanyUserId(loginUser.getUser().getUserId());
+        if (param.getSTime()==null||param.getETime()==null){
+            return getDataTable(new ArrayList<>());
+        }
+        List<QwWatchLogStatisticsListVO> list = qwWatchLogService.selectQwWatchLogStatisticsListVO(param);
+        return getDataTable(list);
+    }
+
+
+    @GetMapping("/qwWatchLogAllStatisticsList")
+    public TableDataInfo qwWatchLogAllStatisticsList(QwWatchLogStatisticsListParam param)
+    {
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId( loginUser.getCompany().getCompanyId());
+        if (param.getSTime()==null||param.getETime()==null){
+            return getDataTable(new ArrayList<>());
+        }
+        List<QwWatchLogAllStatisticsListVO> list = qwWatchLogService.selectQwWatchLogAllStatisticsListVO(param);
+        return getDataTable(list);
+    }
+    @GetMapping("/myQwWatchLogAllStatisticsList")
+    public TableDataInfo myQwWatchLogAllStatisticsList(QwWatchLogStatisticsListParam param)
+    {
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId( loginUser.getCompany().getCompanyId());
+        param.setCompanyUserId(loginUser.getUser().getUserId());
+        if (param.getSTime()==null||param.getETime()==null){
+            return getDataTable(new ArrayList<>());
+        }
+        List<QwWatchLogAllStatisticsListVO> list = qwWatchLogService.selectQwWatchLogAllStatisticsListVO(param);
+        return getDataTable(list);
+    }
+    @GetMapping("/watchLogStatistics")
+    public TableDataInfo watchLogStatistics(FsCourseOverParam param)
+    {
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId( loginUser.getCompany().getCompanyId());
+        if (param.getSTime()==null||param.getETime()==null){
+            return getDataTable(new ArrayList<>());
+        }
+        List<FsCourseOverVO> list = fsCourseWatchLogService.selectFsCourseWatchLogOverStatisticsListVO(param);
+        return getDataTable(list);
+    }
+    @GetMapping("/watchLogStatisticsExport")
+    public AjaxResult watchLogStatisticsExport(FsCourseOverParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId( loginUser.getCompany().getCompanyId());
+        if (param.getSTime()==null||param.getETime()==null){
+            return AjaxResult.error("请选择时间");
+        }
+        List<FsCourseOverVO> list = fsCourseWatchLogService.selectFsCourseWatchLogOverStatisticsListVO(param);
+        ExcelUtil<FsCourseOverVO> util = new ExcelUtil<FsCourseOverVO>(FsCourseOverVO.class);
+        return util.exportExcel(list, "完课数据");
+    }
+
+
+    @PreAuthorize("@ss.hasPermi('course:courseWatchLog:userStatisticsList')")
+    @GetMapping("/userStatisticsList")
+    public TableDataInfo userStatisticsList(FsCourseUserStatisticsListParam param)
+    {
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId( loginUser.getCompany().getCompanyId());
+        if (param.getSTime()==null||param.getETime()==null){
+            return getDataTable(new ArrayList<>());
+        }
+        List<FsCourseUserStatisticsListVO> list = fsCourseWatchLogService.selectFsCourseUserStatisticsListVO(param);
+        return getDataTable(list);
+    }
+
+
+
     /**
      * 查询短链课程看课记录列表
      */

+ 3 - 3
fs-company/src/main/java/com/fs/qw/QwMaterialController.java

@@ -3,6 +3,7 @@ package com.fs.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.utils.ServletUtils;
@@ -96,12 +97,11 @@ public class QwMaterialController extends BaseController
     @PreAuthorize("@ss.hasPermi('qw:material:add')")
     @Log(title = "素材库", businessType = BusinessType.INSERT)
     @PostMapping
-    public AjaxResult add(@RequestBody QwMaterial qwMaterial)
-    {
+    public R add(@RequestBody QwMaterial qwMaterial) throws Exception {
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         qwMaterial.setCreateUserId(loginUser.getUser().getUserId());
         qwMaterial.setCompanyId(loginUser.getUser().getCompanyId());
-        return toAjax(qwMaterialService.insertQwMaterial(qwMaterial));
+        return qwMaterialService.insertQwMaterial(qwMaterial);
     }
 
     /**

+ 7 - 3
fs-company/src/main/java/com/fs/qw/QwSopController.java

@@ -9,13 +9,14 @@ import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.course.mapper.FsUserCourseMapper;
-import com.fs.course.mapper.FsUserCourseVideoMapper;
 import com.fs.core.security.LoginUser;
 import com.fs.core.web.service.TokenService;
+import com.fs.course.mapper.FsUserCourseMapper;
+import com.fs.course.mapper.FsUserCourseVideoMapper;
 import com.fs.his.vo.OptionsVO;
 import com.fs.qw.domain.QwSopUpdateStatus;
 import com.fs.qw.service.IQwUserService;
+import com.fs.qw.vo.QwOptionsVO;
 import com.fs.sop.domain.QwSop;
 import com.fs.sop.params.QwSopAutoTime;
 import com.fs.sop.params.QwSopEditQwUserParam;
@@ -27,6 +28,7 @@ import org.springframework.web.bind.annotation.*;
 
 import java.io.IOException;
 import java.text.SimpleDateFormat;
+import java.util.Calendar;
 import java.util.Date;
 import java.util.List;
 
@@ -157,7 +159,7 @@ public class QwSopController extends BaseController
      * 修改企微sop
      */
     @PreAuthorize("@ss.hasPermi('qw:sop:edit')")
-    @Log(title = "企微sop", businessType = BusinessType.UPDATE)
+    @Log(title = "修改企微sop", businessType = BusinessType.UPDATE)
     @PutMapping
     public R edit(@RequestBody QwSop qwSop)
     {
@@ -170,6 +172,7 @@ public class QwSopController extends BaseController
      */
     @Log(title = "暂停企微sop", businessType = BusinessType.UPDATE)
     @PostMapping("/updateSopStatus")
+    @RepeatSubmit
     public R  updateSopStatus(@RequestBody QwSopUpdateStatus param)
     {
         return qwSopService.updateSopStatus(param);
@@ -211,6 +214,7 @@ public class QwSopController extends BaseController
      * 修改sop员工
      */
     @PostMapping( "/updateSopQwUser")
+    @Log(title = "修改sop员工", businessType = BusinessType.UPDATE)
     @PreAuthorize("@ss.hasPermi('qw:sop:updateSopQwUser')")
     public R updateSopQwUser(@RequestBody QwSopEditQwUserParam param)
     {

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

@@ -117,12 +117,7 @@ public class QwSopLogsController extends BaseController
     @PutMapping
     public AjaxResult edit(@RequestBody QwSopLogs QwSopLogs)
     {
-        boolean b = iQwSopLogsService.updateQwSopLogs(QwSopLogs);
-        if (b){
-            return  AjaxResult.success();
-        }else {
-            return    AjaxResult.error("修改失败");
-        }
+        return toAjax(iQwSopLogsService.updateQwSopLogs(QwSopLogs));
     }
 
     /**

+ 21 - 0
fs-company/src/main/java/com/fs/qw/vo/AdUploadVo.java

@@ -0,0 +1,21 @@
+package com.fs.qw.vo;
+
+import com.alibaba.fastjson.JSON;
+import com.fs.ad.enums.AdUploadType;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class AdUploadVo {
+    private String state;
+    private AdUploadType type;
+
+    public String json(){
+        return JSON.toJSONString(type);
+    }
+}

+ 24 - 0
fs-company/src/main/java/com/fs/qw/vo/CompanyUserQwVO.java

@@ -0,0 +1,24 @@
+package com.fs.qw.vo;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class CompanyUserQwVO {
+
+    private String qwUserId;
+
+    private Long userId;
+
+    private Long CompanyId;
+
+    @Excel(name = "用户账号")
+    private String userName;
+
+    /** 用户昵称 */
+    @Excel(name = "用户昵称")
+    private String nickName;
+
+    @Excel(name = "企微id")
+    private String qwId;
+}

+ 37 - 0
fs-company/src/main/java/com/fs/qw/vo/FsAppContactWayListVO.java

@@ -0,0 +1,37 @@
+package com.fs.qw.vo;
+
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+/**
+ * app客服活码上架对象 fs_app_contact_way
+ *
+ * @author fs
+ * @date 2024-12-02
+ */
+@Data
+public class FsAppContactWayListVO extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 主键Id */
+    private Long id;
+
+    /** 活码图片 */
+    private String corpName;
+
+    private String corpId;
+
+    private String qwUserIds;
+
+    /** 公司id */
+    private Long companyId;
+
+    private Long status;
+
+    private String name; //活码名称
+
+
+    private String companyName; //公司名称
+
+}

+ 57 - 0
fs-company/src/main/java/com/fs/qw/vo/QwAppContactWayLogsListVO.java

@@ -0,0 +1,57 @@
+package com.fs.qw.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class QwAppContactWayLogsListVO {
+    /** id */
+    private Long id;
+
+    /** app联系我id */
+
+    private Long appWayId;
+
+    /** 渠道 */
+    @Excel(name = "渠道")
+    private String source;
+
+    /** 用户id */
+    @Excel(name = "用户id")
+    private Long userId;
+
+    /** 公司id */
+
+    private Long companyId;
+
+    /** 公司用户id */
+
+    private Long companyUserId;
+
+    /** 企业CorpID */
+
+    private String corpId;
+
+    /** 外部联系人id */
+
+    private Long externalUserId;
+
+    private Long qwUserId;
+
+    @Excel(name = "公司")
+    private String companyName;
+    @Excel(name = "销售")
+    private String nickName;
+    @Excel(name = "企微主体")
+    private String corpName;
+    @Excel(name = "企微员工")
+    private String qwUserName;
+
+    @Excel(name = "添加时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+}

+ 69 - 0
fs-company/src/main/java/com/fs/qw/vo/QwAutoTagsLogsVO.java

@@ -0,0 +1,69 @@
+package com.fs.qw.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class QwAutoTagsLogsVO {
+
+    private static final long serialVersionUID = 1L;
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 自动添加标签主表id */
+    @Excel(name = "自动添加标签主表id")
+    private Long autoTagId;
+
+    /** 组别 1关键词打标签 2客户入群行为打标签 3分时段打标签 */
+    @Excel(name = "组别 1关键词打标签 2客户入群行为打标签 3分时段打标签")
+    private Long type;
+
+    /** 所属员工id */
+    @Excel(name = "所属员工id")
+    private String qwUserid;
+
+    private String qwUsername;
+
+    private String companyName;
+
+    /** 客户id */
+    @Excel(name = "客户id")
+    private String externalUserId;
+
+    private String externalUserName;
+
+    private String customerId;
+
+    /** 生效规则 */
+    @Excel(name = "生效规则")
+    private String effectiveRules;
+
+    /** 添加好友时间/加入群聊时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "添加好友时间/加入群聊时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date addTime;
+
+    /** 群聊id(2时有值) */
+    @Excel(name = "群聊id(2时有值)")
+    private String chatId;
+
+    private String chatName;
+
+
+
+    /** 入群方式。
+     0/1 - 由群成员邀请入群(直接邀请入群)
+     0/2 - 由群成员邀请入群(通过邀请链接入群)
+     3 - 通过扫描群二维码入群 */
+    @Excel(name = "入群方式")
+    private String joinScene;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+}

+ 62 - 0
fs-company/src/main/java/com/fs/qw/vo/QwAutoTagsVO.java

@@ -0,0 +1,62 @@
+package com.fs.qw.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.qw.domain.QwAutoTagsLogs;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class QwAutoTagsVO {
+    private static final long serialVersionUID = 1L;
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 组别 1关键词打标签 2客户入群行为打标签 3分时段打标签 */
+    @Excel(name = "组别 1关键词打标签 2客户入群行为打标签 3分时段打标签")
+    private Long type;
+
+    /** 创建人 */
+    @Excel(name = "创建人")
+    private String createName;
+
+    /** 生效成员1.3生效 */
+    @Excel(name = "生效成员1.3生效")
+    private String applyUsers;
+
+    /** 规则名称 */
+    @Excel(name = "规则名称")
+    private String ruleName;
+
+    /** 选择的规则及标签 */
+    @Excel(name = "选择的规则及标签")
+    private String rulesTags;
+
+    /** 打标签总数 */
+    @Excel(name = "打标签总数")
+    private Long totalNumTags;
+
+    private Long totalNumTagsCount;
+
+    /** 今日打标签数 */
+    @Excel(name = "今日打标签数")
+    private Long numTagsTaday;
+
+    private Long numTagsTadayCount;
+
+    /** 是否运用规则状态 1启用 2停用 */
+    @Excel(name = "是否运用规则状态 1启用 2停用")
+    private String isApply;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    private List<QwAutoTagsLogs> qwAutoTagsLogsList;
+}

+ 76 - 0
fs-company/src/main/java/com/fs/qw/vo/QwChatSopTempSetting.java

@@ -0,0 +1,76 @@
+package com.fs.qw.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+@Data
+public class QwChatSopTempSetting {
+    // 模板名称
+    private String name;
+    private List<Content> content;
+
+    @Data
+    public static class Content implements Cloneable {
+        // 普通/课程/订单
+        private int type;
+        private String contentType;
+        private List<Setting> setting;
+        private String time;
+        @Override
+        public Content clone() {
+            try {
+                Content clone = (Content) super.clone();
+                // 深克隆 setting 列表
+                if (this.setting != null) {
+                    clone.setting = new ArrayList<>();
+                    for (Setting originalSetting : this.setting) {
+                        clone.setting.add(originalSetting.clone());
+                    }
+                } else {
+                    clone.setting = new ArrayList<>(); // 初始化为空列表
+                }
+                return clone;
+            } catch (CloneNotSupportedException e) {
+                throw new AssertionError();
+            }
+        }
+
+        @Data
+        public static class Setting implements Serializable, Cloneable {
+            /**
+             * QwSopLog的主键(用于发送)
+             */
+            private Long sopLogId;
+
+            private Integer intervalTime;
+            /**
+             * 员工的id(用于发送)
+             */
+            private String qwUserid;
+            /**
+             * 客户的id(用于发送)
+             */
+            private String externalUserId;
+            // 文本-图片-链接-文件-视频-语音
+            private String contentType;
+            // 文本
+            private String value;
+
+            private String talkType;
+
+            @Override
+            public Setting clone() {
+                try {
+                    Setting clone = (Setting) super.clone();
+                    clone.setValue(this.getValue());
+                    return clone;
+                } catch (CloneNotSupportedException e) {
+                    throw new AssertionError();
+                }
+            }
+        }
+    }
+}
+

+ 9 - 0
fs-company/src/main/java/com/fs/qw/vo/QwCloudAPVO.java

@@ -0,0 +1,9 @@
+package com.fs.qw.vo;
+
+import lombok.Data;
+
+@Data
+public class QwCloudAPVO {
+    private String apAdmin;
+    private String apPassword;
+}

+ 42 - 0
fs-company/src/main/java/com/fs/qw/vo/QwContactBatchListVO.java

@@ -0,0 +1,42 @@
+package com.fs.qw.vo;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+@Data
+public class QwContactBatchListVO extends BaseEntity {
+
+    /** id */
+    private Long id;
+
+    /** 电话 */
+    @Excel(name = "电话")
+    private String phone;
+
+    /** 标签 */
+    @Excel(name = "标签")
+    private String tagIds;
+    private String nickName;
+    /** 状态 */
+    @Excel(name = "状态")
+    private Integer status;
+
+    /** 企微用户id */
+    @Excel(name = "企微用户id")
+    private Long userId;
+
+    /** 分配次数 */
+    @Excel(name = "分配次数")
+    private Integer num;
+
+    /** 员工id */
+    @Excel(name = "员工id")
+    private Long companyUserId;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    private Long qwUserId;
+}

+ 18 - 0
fs-company/src/main/java/com/fs/qw/vo/QwContactListVO.java

@@ -0,0 +1,18 @@
+package com.fs.qw.vo;
+
+import lombok.Data;
+
+@Data
+public class QwContactListVO {
+    private Long id;
+    private String conversationId;
+    private String displayName;
+    private String avatar;
+    private String index;
+    private Boolean isGroup;
+    private Integer unread;
+    private Long roomId;
+    private Long lastSendTime;
+    private String lastContent;
+
+}

+ 30 - 0
fs-company/src/main/java/com/fs/qw/vo/QwCrmCourseStudyVO.java

@@ -0,0 +1,30 @@
+package com.fs.qw.vo;
+
+import lombok.Data;
+
+@Data
+public class QwCrmCourseStudyVO {
+    private String externalUserId; //    外部用户id
+    private String externalUserName;//    外部用户姓名
+    private Long contactCrmId;//    qw_external_contact_crm表id
+    private String avatar; //    头像
+    private Long customerId;//CrmId
+    private String mobile; //    手机号
+    private Long studyId;//小程序用户学习课程的id
+    private Long courseId;//小程序用户课程id
+    private Long userId;//小程序用户id
+    private Integer periodTotal;  //总课时数
+    private Integer periodStudy; //已学课时数
+    private Integer status; //学习状态(1待学习,2正在学习 、3已结课)
+    private String studyCreateTime; //课程学习开始时间
+    private String courseName; //课程名称
+    private Long logId; //学习课程小节id
+    private Long videoId; //学习课程小节视频id
+    private Long courseSort; //学习课程第几小节
+    private String videoName; //课节名称
+    private String currentTimes; //学习课程小节当前观看时间点 秒
+    private String logCreateTime; //学习课程小节视频开始时间
+    private String times; //学习课程小节总学时秒
+    private Double rate; //学习课程小节视频进度条百分比
+
+}

+ 17 - 0
fs-company/src/main/java/com/fs/qw/vo/QwExtStatisticsVO.java

@@ -0,0 +1,17 @@
+package com.fs.qw.vo;
+
+import lombok.Data;
+
+@Data
+public class QwExtStatisticsVO {
+    private Long count;          // 总记录数
+    private Long interact;       // is_interact = 1 的数量
+    private Long a;              // level = 1 的数量
+    private Long b;              // level = 2 的数量
+    private Long c;              // level = 3 的数量
+    private Long d;              // level = 4 的数量
+    private Long sign;           // fs_user_id 不为 null 的数量
+    private Long los;            // status = 3 的数量
+    private Long del;            // status in (4, 5) 的数量
+
+}

+ 36 - 0
fs-company/src/main/java/com/fs/qw/vo/QwExternalContactCrmVO.java

@@ -0,0 +1,36 @@
+package com.fs.qw.vo;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class QwExternalContactCrmVO {
+
+    private static final long serialVersionUID = 1L;
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 外部联系人id */
+    @Excel(name = "外部联系人id")
+    private String externalUserId;
+
+    private String openid;
+
+    /** 外部联系人名称 */
+    @Excel(name = "外部联系人名称")
+    private String externalUserName;
+
+    @Excel(name = "头像")
+    private String avatar;
+
+    /** crm_customer主键 */
+    @Excel(name = "crm_customer主键")
+    private Long customerId;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    private Long companyUserId;
+}

+ 37 - 0
fs-company/src/main/java/com/fs/qw/vo/QwExternalContactFsCrmVO.java

@@ -0,0 +1,37 @@
+package com.fs.qw.vo;
+
+import lombok.Data;
+
+@Data
+public class QwExternalContactFsCrmVO {
+
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long id;
+
+    /** 属于用户id */
+    private String userId;
+
+    private Long companyUserId;
+
+    /** 外部联系人id */
+    private String externalUserId;
+
+    /**
+    * 客户名字
+    */
+    private String name;
+
+    /** 公司id */
+    private Long companyId;
+
+    /** 客户id */
+    private Long customerId;
+
+    /**
+    * crm绑定的小程序id
+    */
+    private Long miniUserId;
+
+}

+ 11 - 0
fs-company/src/main/java/com/fs/qw/vo/QwExternalContactFsUserVO.java

@@ -0,0 +1,11 @@
+package com.fs.qw.vo;
+
+import lombok.Data;
+
+@Data
+public class QwExternalContactFsUserVO {
+    private String stageStatus;
+    private Long fsUserId;
+    private String jpushId;
+    private String loginDevice;
+}

+ 57 - 0
fs-company/src/main/java/com/fs/qw/vo/QwExternalContactTransferLogListVO.java

@@ -0,0 +1,57 @@
+package com.fs.qw.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class QwExternalContactTransferLogListVO {
+    private Long id;
+
+    /** 企业id */
+    @Excel(name = "企业id")
+    private String corpId;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 员工id */
+    @Excel(name = "员工id")
+    private Long companyUserId;
+    /**
+    * 员工部门
+    */
+    private String deptName;
+
+    /** 企微外部联系人id */
+    @Excel(name = "企微外部联系人id")
+    private String externalUserId;
+
+    /** 客户id */
+    @Excel(name = "客户id")
+    private Long customerId;
+
+    /** 外部联系人id */
+    @Excel(name = "外部联系人id")
+    private Long externalContactId;
+
+    /** 状态 */
+    @Excel(name = "状态")
+    private Integer status;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    @Excel(name = "接替员工昵称")
+    private String companyUserNickName;
+
+    @Excel(name = "原员工昵称")
+    private String handoverQwUserName;
+
+    @Excel(name = "名称")
+    private String name;
+
+
+}

+ 114 - 0
fs-company/src/main/java/com/fs/qw/vo/QwExternalContactVO.java

@@ -0,0 +1,114 @@
+package com.fs.qw.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class QwExternalContactVO {
+    private Long id;
+
+    /** 属于用户id */
+    @Excel(name = "属于用户id")
+    private String userId;
+
+    /**
+    *  属于用户名称
+    */
+    private String qwUserName;
+
+    /**
+    * 员工所属部门
+    */
+    private String departmentName;
+
+
+    /** 外部联系人id */
+    @Excel(name = "外部联系人id")
+    private String externalUserId;
+
+    private Long companyUserId;
+
+    /**
+    * 是否绑定企业微信
+    */
+    private Long customerId;
+
+    /**
+    * CRM 绑定的小程序id
+    */
+    private Long miniUserId;
+
+    /** 名称 */
+    @Excel(name = "名称")
+    private String name;
+
+    /** 头像 */
+    @Excel(name = "头像")
+    private String avatar;
+
+    /** 外部联系人的类型1微信用户,2企业微信用户 */
+    @Excel(name = "外部联系人的类型1微信用户,2企业微信用户")
+    private Long type;
+
+    /** 0-未知 1-男性 2-女性 */
+    @Excel(name = "0-未知 1-男性 2-女性")
+    private Long gender;
+
+    /** 描述信息 */
+    @Excel(name = "描述信息")
+    private String description;
+
+    /** 标签id */
+    @Excel(name = "标签id")
+    private String tagIds;
+
+    /** 备注电话号码 */
+    @Excel(name = "备注电话号码")
+    private String remarkMobiles;
+
+    private String remark;
+
+    /** 备注企业名称 */
+    @Excel(name = "备注企业名称")
+    private String remarkCorpName;
+    @Excel(name = "来源")
+    private Long addWay;
+
+    /** oper用户id */
+    @Excel(name = "oper用户id")
+    private String operUserid;
+
+    /** 企业id */
+    @Excel(name = "企业id")
+    private String corpId;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    private Integer transferStatus;
+    private Integer status;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date lossTime;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date delTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date transferTime;
+    private Integer transferNum;
+
+    private String state;
+    private Long wayId;
+    private String stageStatus;
+    private String customerName;
+    private Long fsUserId;
+    @Excel(name = "客户等级")
+    private Long level;
+    @Excel(name = "等级升降")
+    private Long levelType;
+}

+ 21 - 0
fs-company/src/main/java/com/fs/qw/vo/QwFriendWelcomeDayPart.java

@@ -0,0 +1,21 @@
+package com.fs.qw.vo;
+
+import com.fs.qwApi.param.SendWelcomeMsgParam;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class QwFriendWelcomeDayPart {
+    private List<Schedule> schedules;
+
+    @Data
+    public static class Schedule {
+        private List<Integer> week;
+        private String endTime;
+        private String startTime;
+        private List<SendWelcomeMsgParam.Attachment> attachments;
+        private String welcomeText;
+    }
+
+}

+ 65 - 0
fs-company/src/main/java/com/fs/qw/vo/QwFriendWelcomeVO.java

@@ -0,0 +1,65 @@
+package com.fs.qw.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 好友欢迎语对象 qw_friend_welcome
+ * 
+ * @author fs
+ * @date 2024-07-20
+ */
+@Data
+public class QwFriendWelcomeVO extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 用这条欢迎语的企微员工ids */
+    @Excel(name = "用这条欢迎语的企微员工ids")
+    private String qwUserIds;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+    private String corpId;
+
+    /** 	消息文本内容,最长为4000字节 */
+    @Excel(name = "	消息文本内容,最长为4000字节")
+    private String welcomeText;
+
+    /** 附件 最多可添加9个 */
+    @Excel(name = "附件 最多可添加9个")
+    private String attachments;
+
+    /** 是否开启分时段欢迎语 1是 2否 */
+    @Excel(name = "是否开启分时段欢迎语 1是 2否")
+    private String isDayparting;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date createTime;
+
+    /** 更新时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "更新时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date updateTieme;
+
+    /** 是否发送欢迎语 1允许发送 2 不允许发送 */
+    @Excel(name = "是否发送欢迎语 1允许发送 2 不允许发送")
+    private String isSendMsg;
+
+    /** 分时段欢迎语 */
+    private String daypartingItemlist;
+
+    public List<QwUserVO> userSelectList;
+
+}

+ 12 - 0
fs-company/src/main/java/com/fs/qw/vo/QwFromUserVO.java

@@ -0,0 +1,12 @@
+package com.fs.qw.vo;
+
+import lombok.Data;
+
+@Data
+public class QwFromUserVO {
+    private Long id;
+    //头像
+    private String avatar;
+    //昵称
+    private String displayName;
+}

+ 19 - 0
fs-company/src/main/java/com/fs/qw/vo/QwFsUserVO.java

@@ -0,0 +1,19 @@
+package com.fs.qw.vo;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class QwFsUserVO {
+
+    /** 用户id */
+    private Long userId;
+    /** 用户昵称 */
+    @Excel(name = "用户昵称")
+    private String nickName;
+
+    /** 手机号码 */
+    @Excel(name = "手机号码")
+    private String phone;
+
+}

+ 9 - 0
fs-company/src/main/java/com/fs/qw/vo/QwGroupChatOptionsVO.java

@@ -0,0 +1,9 @@
+package com.fs.qw.vo;
+
+import lombok.Data;
+
+@Data
+public class QwGroupChatOptionsVO {
+    private String chatId;
+    private String name;
+}

+ 81 - 0
fs-company/src/main/java/com/fs/qw/vo/QwGroupChatUserVO.java

@@ -0,0 +1,81 @@
+package com.fs.qw.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class QwGroupChatUserVO {
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long id;
+
+    /** 客户群ID */
+    @Excel(name = "客户群ID")
+    private String chatId;
+
+    /** 群成员id */
+    @Excel(name = "群成员id")
+    private String userId;
+
+    /** 成员类型。
+     1 - 企业成员
+     2 - 外部联系人 */
+    @Excel(name = "成员类型")
+    private String type;
+
+    /** 外部联系人在微信开放平台的唯一身份标识(微信unionid) */
+    @Excel(name = "外部联系人在微信开放平台的唯一身份标识")
+    private String unionid;
+
+    /** 入群时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "入群时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private String joinTime;
+
+    /** 入群方式。
+     1 - 由群成员邀请入群(直接邀请入群)
+     2 - 由群成员邀请入群(通过邀请链接入群)
+     3 - 通过扫描群二维码入群 */
+    @Excel(name = "入群方式")
+    private String joinScene;
+
+    /** 邀请者。目前仅当是由本企业内部成员邀请入群时会返回该值 */
+    @Excel(name = "邀请者。目前仅当是由本企业内部成员邀请入群时会返回该值")
+    private String invitor;
+
+    private String invitorName;
+
+    /** 客户在群里的昵称 */
+    @Excel(name = "客户在群里的昵称")
+    private String groupNickname;
+
+    /** 名字。仅当 need_name = 1 时返回
+     如果是微信用户,则返回其在微信中设置的名字
+     如果是企业微信联系人,则返回其设置对外展示的别名或实名 */
+    @Excel(name = "名字")
+    private String name;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 是否退群 */
+    @Excel(name = "是否退群")
+    private Long isOut;
+
+    /** 企业微信的企业id */
+    @Excel(name = "企业微信的企业id")
+    private String corpId;
+
+    /** 退群时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "退群时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private String outTime;
+
+    /**
+     *  退群方式
+     */
+    private Integer quitScene;
+}

+ 70 - 0
fs-company/src/main/java/com/fs/qw/vo/QwGroupChatVO.java

@@ -0,0 +1,70 @@
+package com.fs.qw.vo;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+@Data
+public class QwGroupChatVO extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /** 客户群ID */
+    @Excel(name = "客户群ID")
+    private String chatId;
+
+    /** 群名 */
+    @Excel(name = "群名")
+    private String name;
+
+    /** 群主ID */
+    @Excel(name = "群主")
+    private String owner;
+
+    private String ownerName;
+
+    private String qwName;
+
+    /** 群公告 */
+    @Excel(name = "群公告")
+    private String notice;
+
+    /** 当前群成员版本号 */
+    @Excel(name = "当前群成员版本号")
+    private String memberVersion;
+
+    /** 客户群跟进状态。
+     0 - 跟进人正常
+     1 - 跟进人离职
+     2 - 离职继承中
+     3 - 离职继承完成 */
+    @Excel(name = "客户群跟进状态")
+    private String status;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 企业微信的企业id */
+    @Excel(name = "企业微信的企业id")
+    private String corpId;
+
+    /** 群的创建时间的时间戳 */
+    @Excel(name = "群的创建时间的时间戳")
+    private String createAt;
+
+    /** 群人数 */
+    @Excel(name = "群人数")
+    private Long groupSizeByChartUser;
+
+    /** 当日入群数 */
+    @Excel(name = "当日入群数")
+    private Long todayJoinByChartUser;
+
+    /** 当日退群数 */
+    @Excel(name = "当日退群数")
+    private Long todayOutByChartUser;
+
+    /** 累计退群人数 */
+    @Excel(name = "累计退群人数")
+    private Long allOutGroup;
+}

+ 77 - 0
fs-company/src/main/java/com/fs/qw/vo/QwGroupMsgDetailsVO.java

@@ -0,0 +1,77 @@
+package com.fs.qw.vo;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class QwGroupMsgDetailsVO {
+
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long id;
+
+    /** 企业服务人员的userid */
+    @Excel(name = "企业服务人员的userid")
+    private String userId;
+
+    /** 企业群发消息的id,可用于获取群发消息发送结果 */
+    @Excel(name = "企业群发消息的id,可用于获取群发消息发送结果")
+        private String msgId;
+
+    /** 发送状态:0-未发送 2-已发送 */
+    @Excel(name = "发送状态:0-未发送 2-已发送")
+    private Integer status;
+
+    /** 发送时间,未发送时不返回 */
+    private Long sendTime;
+
+    /** 外部联系人userid,群发消息到企业的客户群不返回该字段 */
+    @Excel(name = "外部联系人userid,群发消息到企业的客户群不返回该字段")
+    private String externalUserid;
+
+    /** 外部客户群id,群发消息到客户不返回该字段 */
+    @Excel(name = "外部客户群id,群发消息到客户不返回该字段")
+    private String chatId;
+
+    /** 群发任务类型 single表示发送给客户,group表示发送给客户群 */
+    @Excel(name = "群发任务类型 single表示发送给客户,group表示发送给客户群")
+    private String chatType;
+
+    /** 企微的企业id */
+    @Excel(name = "企微的企业id")
+    private String corpId;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 发送(接收)状态:0-未发送 1-已发送 2-因客户不是好友导致发送失败 3-因客户已经收到其他群发消息导致发送失败 */
+    @Excel(name = "发送", readConverterExp = "接=收")
+    private Integer sendStatus;
+
+    /** 群发记录主表id */
+    @Excel(name = "群发记录主表id")
+    private Long groupMsgId;
+
+    /**
+     *  成员姓名
+     */
+    private String nickName;
+
+    /** 客户姓名 */
+    private String name;
+
+    /**
+     *  客户头像
+     */
+    private String avatar;
+
+    /**
+     *  群名
+     */
+    private String chatName;
+
+    /** 单用于区分定时任务时,同步定时任务结果的 */
+    private Integer timerResultType;
+}

+ 165 - 0
fs-company/src/main/java/com/fs/qw/vo/QwGroupMsgVO.java

@@ -0,0 +1,165 @@
+package com.fs.qw.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class QwGroupMsgVO {
+    private static final long serialVersionUID = 1L;
+
+    /** 群发记录主表ID */
+    private Long id;
+
+    /** 企业群发消息的id,可用于获取群发消息发送结果 */
+    @Excel(name = "企业群发消息的id,可用于获取群发消息发送结果")
+    private String msgId;
+
+    /** 群发任务的类型,默认为single,表示发送给客户,group表示发送给客户群 */
+    @Excel(name = "群发任务的类型,默认为single,表示发送给客户,group表示发送给客户群")
+    private String chatType;
+
+    private Integer selectType;
+
+    private String filterCustomers;
+
+    /** 定时发送 1定时发送 2立即发送  */
+    private Integer isTimerSend;
+
+    /** 定时发送时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date timerSend;
+
+
+    /** 发送企业群发消息的成员userid,当类型为发送给客户群时必填 */
+    @Excel(name = "发送企业群发消息的成员userid,当类型为发送给客户群时必填")
+    private String sender;
+
+    /** 是否允许成员在待发送客户列表中重新进行选择,默认为true,仅支持客户群发场景 */
+    @Excel(name = "是否允许成员在待发送客户列表中重新进行选择,默认为true,仅支持客户群发场景")
+    private Integer allowSelect;
+
+    /** 消息文本内容,最多4000个字节 */
+    @Excel(name = "消息文本内容,最多4000个字节")
+    private String textContent;
+
+    /** 企微的企业id */
+    @Excel(name = "企微的企业id")
+    private String corpId;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 要进行群发的客户标签列表,同组标签之间按或关系进行筛选,不同组标签按且关系筛选,每组最多指定100个标签,支持规则组标签 */
+    @Excel(name = "要进行群发的客户标签列表,同组标签之间按或关系进行筛选,不同组标签按且关系筛选,每组最多指定100个标签,支持规则组标签")
+    private String tagNames;
+
+    /** 客户群名 */
+    @Excel(name = "客户群名")
+    private String groupChatNames;
+
+    /** 已发送成员 */
+    @Excel(name = "已发送成员")
+    private Integer fromUserCount;
+
+    /** 送达客户 */
+    @Excel(name = "送达客户")
+    private Integer toUserCount;
+
+    /** 发送成员总数 */
+    @Excel(name = "发送成员总数")
+    private Integer fromUserNum;
+
+    /** 发送客户总数 */
+    @Excel(name = "发送客户总数")
+    private Integer toUserNum;
+
+    /** 创建人 */
+    @Excel(name = "创建人")
+    private String createName;
+
+    /** 是否发送 0 发送失败  1发送成功 2发送成功待录入详细信息 */
+    @Excel(name = "是否发送 0 发送失败  1发送成功 2发送成功待录入详细信息")
+    private Integer isSend;
+
+    /** 群发记录主表id */
+    @Excel(name = "群发记录主表id")
+    private Long groupMsgId;
+
+    private Long itemId;
+
+    /** 附件类型 */
+    @Excel(name = "附件类型")
+    private Integer msgType;
+
+    /** 图片的media_id */
+    @Excel(name = "图片的media_id")
+    private String mediaId;
+
+    /** 图片的链接 */
+    @Excel(name = "图片的链接")
+    private String mediaPicUrl;
+
+    /** 图文消息标题 */
+    @Excel(name = "图文消息标题")
+    private String title;
+
+    /** 图文消息封面的url */
+    @Excel(name = "图文消息封面的url")
+    private String picurl;
+
+    /** 图文消息的描述 */
+    @Excel(name = "图文消息的描述")
+    private String description;
+
+    /** 图文消息的链接 */
+    @Excel(name = "图文消息的链接")
+    private String url;
+
+    /** 小程序消息封面的mediaid */
+    @Excel(name = "小程序消息封面的mediaid")
+    private String miniprogramPicMediaId;
+
+    /** 小程序封面地址 */
+    @Excel(name = "小程序封面地址")
+    private String miniprogramPicUrl;
+
+    /** 小程序appid */
+    @Excel(name = "小程序appid")
+    private String miniprogramAppid;
+
+    /** 小程序消息标题 */
+    @Excel(name = "小程序消息标题")
+    private String miniprogramTitle;
+
+    /** 小程序page路径 */
+    @Excel(name = "小程序page路径")
+    private String miniprogramPage;
+
+    /** 视频的media_id */
+    @Excel(name = "视频的media_id")
+    private String videoMediaId;
+
+    /** 视频地址 */
+    @Excel(name = "视频地址")
+    private String videoUrl;
+
+    /** 文件的media_id */
+    @Excel(name = "文件的media_id")
+    private String fileMediaId;
+
+    /** 文件地址 */
+    @Excel(name = "文件地址")
+    private String fileUrl;
+
+    /**
+     *  文件上传时间
+     */
+    private String createdAt;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+}

+ 63 - 0
fs-company/src/main/java/com/fs/qw/vo/QwGroupchatStatisticVO.java

@@ -0,0 +1,63 @@
+package com.fs.qw.vo;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class QwGroupchatStatisticVO {
+    private static final long serialVersionUID = 1L;
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 群主ID */
+    @Excel(name = "群主ID")
+    private String owner;
+
+    @Excel(name = "群主名称")
+    private String ownerName;
+
+    /** 日期,秒时间戳 */
+    @Excel(name = "日期,秒时间戳")
+    private Long dayTime;
+
+    /** 新增客户群数量 */
+    @Excel(name = "新增客户群数量")
+    private Long newChatCnt;
+
+    /** 截至当天客户群总数量 */
+    @Excel(name = "截至当天客户群总数量")
+    private Long chatTotal;
+
+    /** 截至当天有发过消息的客户群数量 */
+    @Excel(name = "截至当天有发过消息的客户群数量")
+    private Long chatHasMsg;
+
+    /** 客户群新增群人数 */
+    @Excel(name = "客户群新增群人数")
+    private Long newMemberCnt;
+
+    /** 截至当天客户群总人数 */
+    @Excel(name = "截至当天客户群总人数")
+    private Long memberTotal;
+
+    /** 截至当天有发过消息的群成员数 */
+    @Excel(name = "截至当天有发过消息的群成员数")
+    private Long memberHasMsg;
+
+    /** 截至当天客户群消息总数 */
+    @Excel(name = "截至当天客户群消息总数")
+    private Long msgTotal;
+
+    /** 截至当天新增迁移群数(仅教培行业返回) */
+    @Excel(name = "截至当天新增迁移群数(仅教培行业返回)")
+    private Long migrateTraineeChatCnt;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyid;
+
+    @Excel(name = "日期")
+    private String convertedDate;
+
+}

+ 12 - 0
fs-company/src/main/java/com/fs/qw/vo/QwHookAuthVO.java

@@ -0,0 +1,12 @@
+package com.fs.qw.vo;
+
+import lombok.Data;
+
+@Data
+public class QwHookAuthVO {
+
+    private String qwUserId;
+
+    private  String corpId;
+    private  String corpName;
+}

+ 83 - 0
fs-company/src/main/java/com/fs/qw/vo/QwMaterialVO.java

@@ -0,0 +1,83 @@
+package com.fs.qw.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 素材库对象 qw_material
+ *
+ * @author fs
+ * @date 2024-06-20
+ */
+@Data
+public class QwMaterialVO extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 素材库id */
+    private Long materialId;
+
+    /** 媒体文件类型,分别有图片(image),语音(voice),视频(video),普通文件(file) */
+    @Excel(name = "媒体文件类型,分别有图片(image),语音(voice),视频(video),普通文件(file)")
+    private String materialType;
+
+    /** 媒体文件上传后获取的唯一标识,3天内有效 */
+    @Excel(name = "媒体文件上传后获取的唯一标识,3天内有效")
+    private String materialMediaId;
+
+    /** 媒体文件上传时间戳 */
+    @Excel(name = "媒体文件上传时间戳")
+    private String createdAt;
+
+    /** 文件地址,图片可以上传永久的,其他类型的3天有效 */
+    @Excel(name = "文件地址,图片可以上传永久的,其他类型的3天有效")
+    private String materialUrl;
+
+    /** 素材分组id */
+    @Excel(name = "素材分组id")
+    private Long materialGroupId;
+
+    private String materialGroupName;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 文本消息 */
+    @Excel(name = "文本消息")
+    private String textContent;
+
+    /** 标题 */
+    @Excel(name = "标题")
+    private String title;
+
+    private String titleUrl;
+
+    /** 创建人id */
+    @Excel(name = "创建人id")
+    private Long createUserId;
+
+    private String createName;
+
+    /** 发送次数 */
+    @Excel(name = "发送次数")
+    private String sendCount;
+
+    private String cropId;
+
+    /**
+     *  创建时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+
+    /**
+     *  素材分类 1 普通素材组 2 朋友圈素材组
+     */
+    private Integer groupType;
+}

+ 34 - 0
fs-company/src/main/java/com/fs/qw/vo/QwMessageListVO.java

@@ -0,0 +1,34 @@
+package com.fs.qw.vo;
+
+import com.fs.qw.domain.QWFromUser;
+import com.fs.qw.domain.QwMsg;
+import lombok.Data;
+
+@Data
+public class QwMessageListVO {
+    private String id;
+    private String status;
+    private String type;
+    private Long sendTime;
+    private String content;
+    private String url;
+    private Long fileSize;
+    private String fileName;
+    private Integer fileShowType;
+    private String imageUrl;
+    private Integer duration; //时长
+    private String toContactId;
+    private QWFromUser fromUser;
+
+    //获取fromUser
+    public  QWFromUser getQwFromUser(Long senderId,QwMsg qwMsg){
+        QWFromUser fromUser=new QWFromUser();
+        fromUser.setId(senderId);
+        if(qwMsg!=null){
+            fromUser.setAvatar(qwMsg.getAvatar());
+            fromUser.setDisplayName(qwMsg.getAvatar());
+        }
+        return fromUser;
+    }
+
+}

+ 11 - 0
fs-company/src/main/java/com/fs/qw/vo/QwOptionsVO.java

@@ -0,0 +1,11 @@
+package com.fs.qw.vo;
+
+import lombok.Data;
+
+@Data
+public class QwOptionsVO {
+    String dictValue;
+    String dictLabel;
+    String CorpId;
+    String corpName;
+}

+ 120 - 0
fs-company/src/main/java/com/fs/qw/vo/QwSopCourseFinishTempSetting.java

@@ -0,0 +1,120 @@
+package com.fs.qw.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* 企微sop附件的消息内容
+*/
+@Data
+public class QwSopCourseFinishTempSetting implements Serializable,Cloneable{
+
+    //普通/课程/订单/ai
+    private int type;
+
+    //消息类型
+    private Integer courseType;
+
+    //课程
+    private Integer courseId;
+    //课节
+    private Integer videoId;
+
+    private List<Setting> setting;
+
+    @Override
+    public QwSopCourseFinishTempSetting clone() {
+        try {
+            QwSopCourseFinishTempSetting clone = (QwSopCourseFinishTempSetting) super.clone();
+            // 深克隆 setting 列表
+            if (this.setting != null) {
+                clone.setting = new ArrayList<>();
+                for (Setting originalSetting : this.setting) {
+                    clone.setting.add(originalSetting.clone());
+                }
+            } else {
+                clone.setting = new ArrayList<>();
+            }
+            return clone;
+        } catch (CloneNotSupportedException e) {
+            throw new AssertionError();
+        }
+    }
+
+    @Data
+    public static class Setting implements Cloneable {
+        /**
+         * QwSopLog的主键(用于发送)
+         */
+        private Long sopLogId;
+        /**
+         * 员工的id(用于发送)
+         */
+        private String qwUserid;
+        /**
+         * 客户的id(用于发送)
+         */
+        private String externalUserId;
+        //文本-图片-链接-小程序-文件-视频-语音-视频号-app
+        private String contentType;
+        //文本
+        private String value;
+        //图片
+        private String imgUrl;
+
+        /** 小程序appid */
+        private String miniprogramAppid;
+
+        /** 小程序消息标题 */
+        private String miniprogramTitle;
+
+        /** 小程序封面地址 */
+        private String miniprogramPicUrl;
+
+
+        /** 小程序page路径 */
+        private String miniprogramPage;
+
+        //链接标题
+        private String linkTitle;
+        //链接描述
+        private String linkDescribe;
+        //链接封面
+        private String linkImageUrl;
+        //链接地址
+        private String linkUrl;
+        //发送app消息的链接
+        private String appLinkUrl;
+        //文件地址
+        private String fileUrl;
+        //视频地址
+        private String videoUrl;
+        //语音地址
+        private String voiceUrl;
+        //时长
+        private String voiceDuration;
+        //是否绑定课程链接
+        private String isBindUrl;
+        //链接过期时间
+        private Integer expiresDays;
+
+        @Override
+        public Setting clone() {
+            try {
+                Setting clone = (Setting) super.clone();
+                clone.setValue(this.getValue());
+                clone.setLinkUrl(this.getLinkUrl());
+                clone.setAppLinkUrl(this.getAppLinkUrl());
+                return clone;
+            } catch (CloneNotSupportedException e) {
+                throw new AssertionError();
+            }
+        }
+    }
+
+}
+
+

+ 92 - 0
fs-company/src/main/java/com/fs/qw/vo/QwSopRuleTimeVO.java

@@ -0,0 +1,92 @@
+package com.fs.qw.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+import java.util.Date;
+
+//查出要执行的SOP
+@Data
+public class QwSopRuleTimeVO extends BaseEntity {
+
+    /** id */
+    private String id;
+
+    private String corpId;
+
+    /** 规则名称 */
+    @Excel(name = "规则名称")
+    private String name;
+
+    /** 状态 */
+    @Excel(name = "状态")
+    private Long status;
+
+    /** 类别 1个人 2企业微信 */
+    @Excel(name = "类别 1个人 2企业微信")
+    private Integer type;
+
+    /** qw_user主表的主键 */
+    @Excel(name = "qw_user主表的主键")
+    private String qwUserIds;
+
+    @Excel(name = "公司编号")
+    private Long companyId;
+
+    /**
+     发送类型 1定时接口发送 2 Ai接口发送  3完课  4AI对话 5一键群发 6一键群发app
+     **/
+    private Integer sendType;
+
+    /**
+    * 筛选的标签
+    */
+    private String tags;
+
+    /**
+    * 排除的标签
+    */
+    private String excludeTags;
+
+    /**
+    * 开始时间
+    */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date startTime;
+    /**
+     *  是否开启新客户添加自动创建sop 1 否 2 是
+     */
+    private Integer isAutoSop;
+    /**
+     *   自动添加SOP的时间段
+     */
+    private String autoSopTime;
+
+    /**
+    * 模板id
+    */
+    private String tempId;
+
+    /**
+     * 过滤类别 1 包含全部 2 包含任意
+     */
+    private Integer filterType;
+
+    /**
+    * 模板内容
+    */
+//    private String tempSetting;
+
+    /**
+    * 模板状态 正常  停用
+    */
+    private String tempStatus;
+
+    /**
+    * 间隔天数
+    */
+    private Integer tempGap;
+
+}

+ 159 - 0
fs-company/src/main/java/com/fs/qw/vo/QwSopTempSetting.java

@@ -0,0 +1,159 @@
+package com.fs.qw.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* 企微sop附件的消息内容
+*/
+@Data
+public class QwSopTempSetting implements Serializable{
+    //模板名称
+    private String name;
+    private List<Content> content;
+
+    @Data
+    public static class Content implements Cloneable {
+
+        //普通/课程/订单/ai
+        private Long id;
+        private int type;
+
+        private String contentType;
+
+        private List<Setting> setting;
+
+        //时间
+        private String time;
+
+        private String isOfficial;//是否企微官方接口
+        //课程
+        private Long courseId;
+        //课节
+        private Long videoId;
+
+        //消息类型 -普通0/待看课1/看课中断2/已完课3/待看和中断4
+        private Integer courseType;
+
+        private String aiTouch;
+
+        private String addTag;
+
+        private String delTag;
+
+        @Override
+        public Content clone() {
+            try {
+                Content clone = (Content) super.clone();
+                // 深克隆 setting 列表
+                if (this.setting != null) {
+                    clone.setting = new ArrayList<>();
+                    for (Setting originalSetting : this.setting) {
+                        clone.setting.add(originalSetting.clone());
+                    }
+                } else {
+                    clone.setting = new ArrayList<>(); // 初始化为空列表
+                }
+                return clone;
+            } catch (CloneNotSupportedException e) {
+                throw new AssertionError();
+            }
+        }
+
+        @Data
+        public static class Setting  implements Serializable,Cloneable {
+            /**
+             * QwSopLog的主键(用于发送)
+             */
+            private Long id;
+            private Long sopLogId;
+            private Integer intervalTime;
+            private String talkType;
+            /**
+             * 员工的id(用于发送)
+             */
+            private String qwUserid;
+            /**
+             * 客户的id(用于发送)
+             */
+            private String externalUserId;
+            //文本-图片-链接-小程序-文件-视频-语音-视频号-app
+            private String contentType;
+            //文本
+            private String value;
+            //图片
+            private String imgUrl;
+            //链接标题
+            private String linkTitle;
+            //链接描述
+            private String linkDescribe;
+            //链接封面
+            private String linkImageUrl;
+            //链接地址
+            private String linkUrl;
+            //发送app消息的链接
+            private String appLinkUrl;
+
+            /** 小程序appid */
+            private String miniprogramAppid;
+
+            /** 小程序消息标题 */
+            private String miniprogramTitle;
+
+            /** 小程序封面地址 */
+            private String miniprogramPicUrl;
+
+
+            /** 小程序page路径 */
+            private String miniprogramPage;
+
+            //文件地址
+            private String fileUrl;
+            //视频地址
+            private String videoUrl;
+            //语音地址
+            private String voiceUrl;
+            // 封面标题
+            private String nickname;
+            //头像
+            private String avatar;
+            //封面图片地址
+            private String coverUrl;
+            //封面图片地址
+            private String thumbUrl;
+            //简介
+            private String desc;
+            //视频地址
+            private String url;
+            //标识
+            private String extras;
+            //时长
+            private String voiceDuration;
+            //是否绑定课程链接
+            private String isBindUrl;
+            //链接过期时间
+            private Integer expiresDays;
+
+            @Override
+            public Setting clone() {
+                try {
+                    Setting clone = (Setting) super.clone();
+                    clone.setValue(this.getValue());
+                    clone.setLinkUrl(this.getLinkUrl());
+                    clone.setAppLinkUrl(this.getAppLinkUrl());
+                    return clone;
+                } catch (CloneNotSupportedException e) {
+                    throw new AssertionError();
+                }
+            }
+
+        }
+
+    }
+
+}
+
+

+ 134 - 0
fs-company/src/main/java/com/fs/qw/vo/QwSopTempSetting2.java

@@ -0,0 +1,134 @@
+package com.fs.qw.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* 企微sop附件的消息内容
+*/
+@Data
+public class QwSopTempSetting2 implements Serializable{
+    //模板名称
+    private String name;
+    private List<Content> content;
+
+    @Data
+    public static class Content implements Cloneable {
+
+        //普通/课程/订单/ai
+        private int type;
+
+        private String contentType;
+
+        private List<Setting> setting;
+
+        //时间
+        private String time;
+        //课程
+        private Long courseId;
+        //课节
+        private Long videoId;
+
+        //消息类型 -普通0/待看课1/看课中断2/已完课3/待看和中断4
+        private Integer courseType;
+
+        private String aiTouch;
+
+        @Override
+        public Content clone() {
+            try {
+                Content clone = (Content) super.clone();
+                // 深克隆 setting 列表
+                if (this.setting != null) {
+                    clone.setting = new ArrayList<>();
+                    for (Setting originalSetting : this.setting) {
+                        clone.setting.add(originalSetting.clone());
+                    }
+                } else {
+                    clone.setting = new ArrayList<>(); // 初始化为空列表
+                }
+                return clone;
+            } catch (CloneNotSupportedException e) {
+                throw new AssertionError();
+            }
+        }
+
+        @Data
+        public static class Setting  implements Serializable,Cloneable {
+            /**
+             * QwSopLog的主键(用于发送)
+             */
+            private Long sopLogId;
+            private Integer intervalTime;
+            private String talkType;
+            /**
+             * 员工的id(用于发送)
+             */
+            private String qwUserid;
+            /**
+             * 客户的id(用于发送)
+             */
+            private String externalUserId;
+            //文本-图片-链接-文件-视频-语音
+            private String contentType;
+            //文本
+            private String value;
+            //图片
+            private String imgUrl;
+            //链接标题
+            private String linkTitle;
+            //链接描述
+            private String linkDescribe;
+            //链接封面
+            private String linkImageUrl;
+            //链接地址
+            private String linkUrl;
+            //文件地址
+            private String fileUrl;
+            //视频地址
+            private String videoUrl;
+            //语音地址
+            private String voiceUrl;
+            // 封面标题
+            private String nickname;
+            //头像
+            private String avatar;
+            //封面图片地址
+            private String coverUrl;
+            //封面图片地址
+            private String thumbUrl;
+            //简介
+            private String desc;
+            //视频地址
+            private String url;
+            //标识
+            private String extras;
+            //时长
+            private String voiceDuration;
+            //是否绑定课程链接
+            private Integer isBindUrl;
+            //链接过期时间
+            private String expiresDays;
+
+            @Override
+            public Setting clone() {
+                try {
+                    Setting clone = (Setting) super.clone();
+                    clone.setValue(this.getValue());
+                    clone.setLinkUrl(this.getLinkUrl());
+                    return clone;
+                } catch (CloneNotSupportedException e) {
+                    throw new AssertionError();
+                }
+            }
+
+        }
+
+    }
+
+}
+
+

+ 44 - 0
fs-company/src/main/java/com/fs/qw/vo/QwTagGroupAddParam.java

@@ -0,0 +1,44 @@
+package com.fs.qw.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.qw.domain.QwTag;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class QwTagGroupAddParam {
+    private Long id;
+
+    /** 标签id */
+    @Excel(name = "标签id")
+    private String groupId;
+
+    /** 名称 */
+    @Excel(name = "名称")
+    private String name;
+
+    /** 排序 */
+    @Excel(name = "排序")
+    private Integer order;
+
+    /** 企业id */
+    @Excel(name = "企业id")
+    private String corpId;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+
+    /** 更新时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    List<QwTag> tag;
+}

+ 50 - 0
fs-company/src/main/java/com/fs/qw/vo/QwTagGroupListVO.java

@@ -0,0 +1,50 @@
+package com.fs.qw.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class QwTagGroupListVO {
+    private Long id;
+
+    /** 标签id */
+    @Excel(name = "标签id")
+    private String groupId;
+
+    /** 名称 */
+    @Excel(name = "名称")
+    private String name;
+
+    /** 排序 */
+    @Excel(name = "排序")
+    private Integer order;
+
+    /** 企业id */
+    @Excel(name = "企业id")
+    private String corpId;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+
+    /** 更新时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    /**
+    * 标签来源 0/null:其他应用 1:当前应用
+    */
+    private Integer groupFrom;
+
+    List<QwTagVO> tag;
+
+    private String tagName;
+}

+ 48 - 0
fs-company/src/main/java/com/fs/qw/vo/QwTagGroupVO.java

@@ -0,0 +1,48 @@
+package com.fs.qw.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.qw.domain.QwTag;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class QwTagGroupVO {
+    private Long id;
+
+    /** 标签id */
+    @Excel(name = "标签id")
+    private String groupId;
+
+    /** 名称 */
+    @Excel(name = "名称")
+    private String name;
+
+    /** 排序 */
+    @Excel(name = "排序")
+    private Integer order;
+
+    /** 企业id */
+    @Excel(name = "企业id")
+    private String corpId;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    /** 更新时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    /**
+     * 标签来源 0/null:其他应用 1:当前应用
+     */
+    private Integer groupFrom;
+
+    List<QwTag> tag;
+}

+ 32 - 0
fs-company/src/main/java/com/fs/qw/vo/QwTagVO.java

@@ -0,0 +1,32 @@
+package com.fs.qw.vo;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class QwTagVO {
+    private Long id;
+
+    /** 标签id */
+    @Excel(name = "标签id")
+    private String tagId;
+
+    /** 名称 */
+    @Excel(name = "名称")
+    private String name;
+
+    /** 标签组id */
+    @Excel(name = "标签组id")
+    private String groupId;
+
+    /** 排序 */
+    @Excel(name = "排序")
+    private Integer order;
+
+    /**
+     * 标签来源 0/null:其他应用 1:当前应用
+     */
+    private Integer tagFrom;
+
+
+}

+ 71 - 0
fs-company/src/main/java/com/fs/qw/vo/QwUserVO.java

@@ -0,0 +1,71 @@
+package com.fs.qw.vo;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class QwUserVO {
+    private Long id;
+
+    /** 企微用户id */
+    @Excel(name = "企微用户id")
+    private String qwUserId;
+
+    private String qwUserName;
+
+    private String department;
+
+    private String departmentName;
+
+    private String corpName;
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 公司员工id */
+    @Excel(name = "公司员工id")
+    private Long companyUserId;
+
+    /** 企微id */
+    @Excel(name = "企微id")
+    private String corpId;
+    private String appKey;
+
+    @Excel(name = "企微")
+    private Integer status;
+
+    @Excel(name = "企微")
+    private Integer isDel;
+
+    private String nickName;
+    private String userName;
+    private String welcomeText;
+    /**
+    * 活码id
+    */
+    private String configId;
+    /**
+    * 联系我
+    */
+    private String contactWay;
+    /**
+    * AI客服角色名
+    */
+    private String fastGptRoleName;
+
+    /**
+    * 登录状态
+    */
+    private Integer loginStatus;
+    private Integer toolStatus;
+    /**
+    * 云主机地址
+    */
+    private String loginCodeUrl;
+    /**
+     * 插件版本号
+     */
+    private String version;
+
+
+}

+ 50 - 0
fs-company/src/main/java/com/fs/qw/vo/QwUserVideoVO.java

@@ -0,0 +1,50 @@
+package com.fs.qw.vo;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class QwUserVideoVO {
+    /** $column.columnComment */
+    private Long id;
+
+    /** 授权码 */
+    @Excel(name = "授权码")
+    private String appKey;
+
+    /** 发送人名称 */
+    @Excel(name = "发送人名称")
+    private String senderName;
+
+    /** 视频号id */
+    @Excel(name = "视频号id")
+    private String objectId;
+
+    /** 封面图片 */
+    @Excel(name = "封面图片")
+    private String coverUrl;
+
+    /** 封面 */
+    @Excel(name = "封面")
+    private String thumbUrl;
+
+    /** 头像 */
+    @Excel(name = "头像")
+    private String avatar;
+
+    /** 封面标题 */
+    @Excel(name = "封面标题")
+    private String nickname;
+
+    /** 简介 */
+    @Excel(name = "简介")
+    private String desc;
+
+    /** 视频地址 */
+    @Excel(name = "视频地址")
+    private String url;
+
+    /** 标识 */
+    @Excel(name = "标识")
+    private String extras;
+}

+ 61 - 0
fs-company/src/main/java/com/fs/qw/vo/QwUserbehaviorDataVO.java

@@ -0,0 +1,61 @@
+package com.fs.qw.vo;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class QwUserbehaviorDataVO {
+
+    private static final long serialVersionUID = 1L;
+
+    /** $column.columnComment */
+    private Long id;
+
+    /** 企微成员ID */
+    @Excel(name = "企微成员ID")
+    private String userid;
+
+    /**
+    * 成员昵称
+    */
+    private String nickName;
+
+    /** 数据日期 秒时间戳 */
+    @Excel(name = "数据日期 秒时间戳")
+    private Long statTime;
+
+    /** 聊天总数 */
+    @Excel(name = "聊天总数")
+    private Long chatCnt;
+
+    /** 发送消息数 */
+    @Excel(name = "发送消息数")
+    private Long messageCnt;
+
+    /** 已回复聊天占比 */
+    @Excel(name = "已回复聊天占比")
+    private Long replyPercentage;
+
+    /** 平均首次回复时长,单位为分钟 */
+    @Excel(name = "平均首次回复时长,单位为分钟")
+    private Long avgReplyTime;
+
+    /** 删除/拉黑成员的客户数 */
+    @Excel(name = "删除/拉黑成员的客户数")
+    private Long negativeFeedbackCnt;
+
+    /** 主动向客户发起的好友申请数量 */
+    @Excel(name = "主动向客户发起的好友申请数量")
+    private Long newApplyCnt;
+
+    /** 成员新添加的客户数量 */
+    @Excel(name = "成员新添加的客户数量")
+    private Long newContactCnt;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyid;
+
+    @Excel(name = "日期")
+    private String convertedDate;
+}

+ 82 - 0
fs-company/src/main/java/com/fs/qw/vo/QwWatchLogAllStatisticsListVO.java

@@ -0,0 +1,82 @@
+package com.fs.qw.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class QwWatchLogAllStatisticsListVO {
+    Long id;
+    String qwUserName;
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    Date createTime;
+
+    Long line;//进线数
+
+    Long firstOnline;//先导课上线
+
+    Long firstOver;//先导课完课
+
+    Long d1Online;
+    Long d1Over;
+    Long d2Online;
+    Long d2Over;
+    Long d3Online;
+    Long d3Over;
+    Long d4Online;
+    Long d4Over;
+    Long d5Online;
+    Long d5Over;
+    Long d6Online;
+    Long d6Over;
+    Long d7Online;
+    Long d7Over;
+    Long d8Online;
+    Long d8Over;
+    Long d9Online;
+    Long d9Over;
+    Long d10Online;
+    Long d10Over;
+    Long d11Online;
+    Long d11Over;
+    Long d12Online;
+    Long d12Over;
+    Long d13Online;
+    Long d13Over;
+    Long d14Online;
+    Long d14Over;
+    Long d15Online;
+    Long d15Over;
+    Long d16Online;
+    Long d16Over;
+    Long d17Online;
+    Long d17Over;
+    Long d18Online;
+    Long d18Over;
+    Long d19Online;
+    Long d19Over;
+    Long d20Online;
+    Long d20Over;
+    Long d21Online;
+    Long d21Over;
+    Long d22Online;
+    Long d22Over;
+    Long d23Online;
+    Long d23Over;
+    Long d24Online;
+    Long d24Over;
+    Long d25Online;
+    Long d25Over;
+    Long d26Online;
+    Long d26Over;
+    Long d27Online;
+    Long d27Over;
+    Long d28Online;
+    Long d28Over;
+    Long d29Online;
+    Long d29Over;
+    Long d30Online;
+    Long d30Over;
+
+}

+ 33 - 0
fs-company/src/main/java/com/fs/qw/vo/QwWatchLogStatisticsListVO.java

@@ -0,0 +1,33 @@
+package com.fs.qw.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class QwWatchLogStatisticsListVO {
+    Long id;
+    String qwUserName;
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    Date createTime;
+
+    Long line;//进线数
+
+    Long firstOnline;//先导课上线
+
+    Long firstOver;//先导课完课
+
+    Long d1Online;//首日上线
+
+    Long d1Over;//首日完课
+
+    Long sign;//综合报名数
+    Long interact;//互动数
+    Long a;
+    Long b;
+    Long c;
+    Long d;
+    Long los;//流失数
+    Long del;//删除数
+}

+ 14 - 0
fs-company/src/main/java/com/fs/qw/vo/QwWayStatisticsListVO.java

@@ -0,0 +1,14 @@
+package com.fs.qw.vo;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class QwWayStatisticsListVO {
+    @Excel(name = "成交客户数")
+    Long addNum;
+    @Excel(name = "成交周期")
+    Long deleteNum;
+    @Excel(name = "成交周期")
+    Long num;
+}

+ 40 - 0
fs-company/src/main/java/com/fs/qw/vo/QwWelcomeJsonFrom.java

@@ -0,0 +1,40 @@
+package com.fs.qw.vo;
+
+import com.fs.qwApi.domain.inner.TextMessage;
+import lombok.Data;
+
+import java.util.List;
+@Data
+public class QwWelcomeJsonFrom {
+    /** 附件 最多可添加9个 */
+    private List<Attachment> attachments;
+    private List<Integer> week;
+    /** 开始时间 */
+    private String startTime;
+    /** 结束时间 */
+    private String endTime;
+    private TextMessage text; // 文本消息内容
+
+    @Data
+    // 用于附件
+    public static class Attachment {
+        private String msgtype; // 附件类型:image(图片),link(链接),miniprogram(小程序),video(视频),file(文件)
+        private ImageAttachment image; // 图片附件详情
+        private LinkAttachment link; // 链接附件详情
+        // 获取器和设置器
+        @Data
+        public static class ImageAttachment {
+            private String pic_url; // 图片的URL
+        }
+        @Data
+        public static class LinkAttachment {
+            private String title; // 链接标题
+            private String picurl; // 缩略图的URL
+            private String desc; // 链接描述
+            private String url; // 链接的URL
+            private String courseId; // 链接的课程id
+            private String videoId; // 链接的课节id
+            private Integer expiresDays; // 链接的过期时间
+        }
+    }
+}

+ 46 - 0
fs-company/src/main/java/com/fs/qw/vo/QwWorkTaskListVO.java

@@ -0,0 +1,46 @@
+package com.fs.qw.vo;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class QwWorkTaskListVO {
+    private Long id;
+
+    /** 外部联系人id */
+    @Excel(name = "外部联系人id")
+    private Long extId;
+
+    private String name;
+    private String qwUserName;
+    private String remark;
+    /** 企微用户id */
+    @Excel(name = "企微用户id")
+    private Long qwUserId;
+
+    /** 类别 1先导 2 课程 3 大小转 4 转人工 */
+    @Excel(name = "类别 1先导 2 课程 3 大小转 4 转人工")
+    private Integer type;
+
+    /** 状态 0 待处理 1 已处理 3 过期 */
+    @Excel(name = "状态 0 待处理 1 已处理 3 过期")
+    private Integer status;
+
+    /** 分值 */
+    @Excel(name = "分值")
+    private Integer score;
+
+    /** sopid */
+    @Excel(name = "sopid")
+    private String sopId;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 用户id */
+    @Excel(name = "用户id")
+    private Long companyUserId;
+
+    private String title;
+}

+ 95 - 0
fs-company/src/main/java/com/fs/qw/vo/SopRuleTimeSetting.java

@@ -0,0 +1,95 @@
+package com.fs.qw.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+//暂时废弃
+@Data
+public class SopRuleTimeSetting {
+
+    /**
+    * 内容名称
+    */
+    private String name;
+    /**
+    * 状态 正常 停用
+    */
+    private int type;
+    /**
+    * 内容
+    */
+    private List<ContentDetail> content;
+
+    private String day;
+    private String hour;
+    private String minute;
+    private String time;
+
+    @Data
+    public static class ContentDetail {
+        /**
+        * 类型 普通 课程 订单
+        */
+        private int type;
+        /**
+        * 内容类型 文字 图片 链接
+        */
+        private int contentType;
+        /**
+        * 是否添加url
+        */
+        private String isBindUrl;
+
+
+        private Integer expiresDays;
+
+        /**
+        * 时间
+        */
+        private String time;
+        /**
+        * 课程id
+        */
+        private int courseId;
+        /**
+        * 小节id
+        */
+        private Long videoId;
+        /**
+        *  0普通 1待看课 2看课中 3已完课
+        */
+        private int courseType;
+        /**
+        * 消息内容
+        */
+        private String value;
+
+        /**
+        *  内容类型是图片时的 图片url
+        */
+        private String imgUrl;
+
+        /**
+         * 链接标题
+         */
+        private String linkTitle;
+
+        /**
+         * 链接描述
+         */
+        private String linkDescribe;
+
+        /**
+         * 链接封面
+         */
+        private String linkImageUrl;
+
+        /**
+         * 链接url
+         */
+        private String linkUrl;
+        private String fileUrl;
+        private String videoUrl;
+    }
+}

+ 11 - 0
fs-company/src/main/java/com/fs/qw/vo/SortDayVo.java

@@ -0,0 +1,11 @@
+package com.fs.qw.vo;
+
+import lombok.Data;
+
+@Data
+public class SortDayVo {
+
+    private Long id;
+    private Integer dayNum;
+
+}

+ 92 - 0
fs-company/src/main/java/com/fs/qw/vo/WxSopRuleTimeVO.java

@@ -0,0 +1,92 @@
+package com.fs.qw.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+import java.time.LocalDate;
+
+//查出要执行的SOP
+@Data
+public class WxSopRuleTimeVO extends BaseEntity {
+
+    /** id */
+    private String id;
+
+    private String corpId;
+
+    /** 规则名称 */
+    @Excel(name = "规则名称")
+    private String name;
+
+    /** 状态 */
+    @Excel(name = "状态")
+    private Long status;
+
+    /** 类别 1个人 2企业微信 */
+    @Excel(name = "类别 1个人 2企业微信")
+    private Integer type;
+
+    /** qw_user主表的主键 */
+    @Excel(name = "qw_user主表的主键")
+    private String qwUserIds;
+
+    @Excel(name = "公司编号")
+    private Long companyId;
+
+    /**
+     发送类型 1定时接口发送 2 Ai接口发送  3wanke  4AIduihua
+     **/
+    private Integer sendType;
+
+    /**
+    * 筛选的标签
+    */
+    private String tags;
+
+    /**
+    * 排除的标签
+    */
+    private String excludeTags;
+
+    /**
+    * 开始时间
+    */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate startTime;
+    /**
+     *  是否开启新客户添加自动创建sop 1 否 2 是
+     */
+    private Integer isAutoSop;
+    /**
+     *   自动添加SOP的时间段
+     */
+    private String autoSopTime;
+
+    /**
+    * 模板id
+    */
+    private String tempId;
+
+    /**
+     * 过滤类别 1 包含全部 2 包含任意
+     */
+    private Integer filterType;
+
+    /**
+    * 模板内容
+    */
+//    private String tempSetting;
+
+    /**
+    * 模板状态 正常  停用
+    */
+    private String tempStatus;
+
+    /**
+    * 间隔天数
+    */
+    private Integer tempGap;
+
+}

+ 104 - 0
fs-company/src/main/java/com/fs/wxuser/CompanyWxUserController.java

@@ -0,0 +1,104 @@
+package com.fs.wxuser;
+
+import java.util.List;
+
+import com.fs.wxUser.domain.CompanyWxUser;
+import com.fs.wxUser.service.ICompanyWxUserService;
+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.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 【个微管理】Controller
+ *
+ * @author fs
+ * @date 2025-03-28
+ */
+@RestController
+@RequestMapping("/company/wxuser")
+public class CompanyWxUserController extends BaseController
+{
+    @Autowired
+    private ICompanyWxUserService companyWxUserService;
+
+    /**
+     * 查询【个微管理】列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyWxUser companyWxUser)
+    {
+        startPage();
+        List<CompanyWxUser> list = companyWxUserService.selectCompanyWxUserList(companyWxUser);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出【个微管理】列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:export')")
+    @Log(title = "【个微管理】", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(CompanyWxUser companyWxUser)
+    {
+        List<CompanyWxUser> list = companyWxUserService.selectCompanyWxUserList(companyWxUser);
+        ExcelUtil<CompanyWxUser> util = new ExcelUtil<CompanyWxUser>(CompanyWxUser.class);
+        return util.exportExcel(list, "user");
+    }
+
+    /**
+     * 获取【个微管理】详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:query')")
+    @GetMapping(value = "/{userId}")
+    public AjaxResult getInfo(@PathVariable("userId") Long userId)
+    {
+        return AjaxResult.success(companyWxUserService.selectCompanyWxUserByUserId(userId));
+    }
+
+    /**
+     * 新增【个微管理】
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:add')")
+    @Log(title = "【个微管理】", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyWxUser companyWxUser)
+    {
+        return toAjax(companyWxUserService.insertCompanyWxUser(companyWxUser));
+    }
+
+    /**
+     * 修改【个微管理】
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:edit')")
+    @Log(title = "【个微管理】", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody CompanyWxUser companyWxUser)
+    {
+        return toAjax(companyWxUserService.updateCompanyWxUser(companyWxUser));
+    }
+
+    /**
+     * 删除【个微管理】
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:remove')")
+    @Log(title = "【个微管理】", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{userIds}")
+    public AjaxResult remove(@PathVariable Long[] userIds)
+    {
+        return toAjax(companyWxUserService.deleteCompanyWxUserByUserIds(userIds));
+    }
+}

+ 59 - 0
fs-company/src/main/resources/application-dev.yml

@@ -76,3 +76,62 @@ spring:
                     wall:
                         config:
                             multi-statement-allow: true
+        sop:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://42.194.245.189:3306/test_his_sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: YJF_2024
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+
+rocketmq:
+    name-server: rmq-1243b25nj.rocketmq.gz.public.tencenttdmq.com:8080 # RocketMQ NameServer 地址
+    producer:
+        group: my-producer-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+    consumer:
+        group: test-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey

+ 15 - 1
fs-service-system/pom.xml

@@ -208,6 +208,20 @@
             <groupId>com.github.ben-manes.caffeine</groupId>
             <artifactId>caffeine</artifactId>
         </dependency>
-
+        <dependency>
+            <groupId>org.mapstruct</groupId>
+            <artifactId>mapstruct</artifactId>
+            <version>${org.mapstruct.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.mapstruct</groupId>
+            <artifactId>mapstruct-processor</artifactId>
+            <version>${org.mapstruct.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.rocketmq</groupId>
+            <artifactId>rocketmq-spring-boot-starter</artifactId>
+            <version>2.2.3</version>
+        </dependency>
     </dependencies>
 </project>

+ 33 - 0
fs-service-system/src/main/java/com/fs/company/cache/ICompanyUserCacheService.java

@@ -0,0 +1,33 @@
+package com.fs.company.cache;
+
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.param.CompanyUserQwParam;
+import com.fs.company.vo.CompanyQwUserByIdsVo;
+import com.fs.company.vo.CompanyUserQwListVO;
+import com.fs.company.vo.CompanyUserVO;
+import com.fs.company.vo.DocCompanyUserVO;
+import com.fs.his.vo.OptionsVO;
+import com.fs.qw.vo.CompanyUserQwVO;
+import com.fs.qw.vo.QwUserVO;
+
+import java.util.List;
+import java.util.Map;
+
+;
+
+/**
+ * 物业公司管理员信息Service接口
+ *
+ * @author fs
+ * @date 2021-05-25
+ */
+public interface ICompanyUserCacheService {
+    /**
+     * 查询物业公司管理员信息
+     *
+     * @param userId 物业公司管理员信息ID
+     * @return 物业公司管理员信息
+     */
+    public CompanyUser selectCompanyUserById(Long userId);
+
+}

+ 32 - 0
fs-service-system/src/main/java/com/fs/company/cache/impl/CompanyUserCacheServiceImpl.java

@@ -0,0 +1,32 @@
+package com.fs.company.cache.impl;
+
+import com.fs.company.cache.ICompanyCacheService;
+import com.fs.company.cache.ICompanyUserCacheService;
+import com.fs.company.domain.Company;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.service.ICompanyUserService;
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Service;
+
+import java.util.concurrent.TimeUnit;
+
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class CompanyUserCacheServiceImpl implements ICompanyUserCacheService {
+
+    private final ICompanyUserService companyUserService;
+
+    private static final Cache<Long, CompanyUser> USER_CACHE = Caffeine.newBuilder()
+            .maximumSize(1000)
+            .expireAfterWrite(10, TimeUnit.SECONDS)
+            .build();
+    @Override
+    public CompanyUser selectCompanyUserById(Long userId) {
+        return USER_CACHE.get(userId,e-> companyUserService.selectCompanyUserById(userId));
+    }
+}

+ 1 - 0
fs-service-system/src/main/java/com/fs/company/domain/CompanyUser.java

@@ -64,6 +64,7 @@ public class CompanyUser extends BaseEntity
     /** 帐号状态(0正常 1停用) */
     @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用")
     private String status;
+    private String statusText;
 
     /** 删除标志(0代表存在 2代表删除) */
     private String delFlag;

+ 79 - 15
fs-service-system/src/main/java/com/fs/company/mapper/CompanyUserMapper.java

@@ -1,6 +1,7 @@
 package com.fs.company.mapper;
 
 import com.fs.company.domain.CompanyUser;
+import com.fs.company.param.CompanyUserAreaParam;
 import com.fs.company.param.CompanyUserQwParam;
 import com.fs.company.vo.CompanyQwUserByIdsVo;
 import com.fs.company.vo.CompanyUserQwListVO;
@@ -8,7 +9,7 @@ import com.fs.company.vo.CompanyUserVO;
 import com.fs.company.vo.DocCompanyUserVO;
 import com.fs.qw.vo.CompanyUserQwVO;
 import com.fs.qw.vo.QwUserVO;
-import com.fs.his.vo.OptionsVO;;
+import com.fs.wxUser.domain.CompanyWxUser;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
@@ -55,6 +56,9 @@ public interface CompanyUserMapper
      */
     public int updateCompanyUser(CompanyUser companyUser);
 
+    @Update("UPDATE company_user SET qw_user_id = NULL,qw_status=0 where user_id=#{userId}")
+    public int updateCompanyUserByNullQwUserID(@Param("userId") Long companyUserId);
+
     public int updateAllCompanyUser(CompanyUser companyUser);
 
     /**
@@ -75,9 +79,6 @@ public interface CompanyUserMapper
 
     int updateUserAvatar(@Param("userName")String username, @Param("avatar") String avatar);
 
-    @Update("UPDATE company_user SET qw_user_id = NULL,qw_status=0 where user_id=#{userId}")
-    public int updateCompanyUserByNullQwUserID(@Param("userId") Long companyUserId);
-
     int resetUserPwd(@Param("userName")String userName,  @Param("password")String encryptPassword);
 
 
@@ -88,14 +89,29 @@ public interface CompanyUserMapper
     int resetUserPwdByUserId( @Param("userId")Long userId, @Param("password") String encryptPassword);
 
     List<CompanyUser> selectAllUsersList(CompanyUser user);
-
-
-    @Select("select * from  qw_user  where corp_id=#{corpId} and company_id=#{companyId}")
-    List<QwUserVO> selectCompanyQwUserList(@Param("corpId") String corpId, @Param("companyId")Long companyId);
-
-    @Select("select * from company_user  where company_id=#{companyId} and del_flag = 0 and  qw_user_id is  null")
-    List<CompanyUser> selectCompanyNoQwUserList(Long companyId);
-
+    @Select({"<script> " +
+            "select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,u.open_id,u.id_card, d.dept_name, d.leader from company_user u\n" +
+            "        left join company_dept d on u.dept_id = d.dept_id\n" +
+            "        where u.del_flag = '0' and u.status=0\n" +
+            "        <if test=\"companyId != null  \">\n" +
+            "            AND u.company_id = #{companyId}\n" +
+            "        </if>\n" +
+            "        <if test=\"nickName != null and nickName != ''\">\n" +
+            "            AND u.nick_name like concat(#{nickName}, '%')\n" +
+            "        </if>\n" +
+            "        <if test=\"phonenumber != null and phonenumber != ''\">\n" +
+            "            AND u.phonenumber like concat('%', #{phonenumber}, '%')\n" +
+            "        </if>\n" +
+            "        <if test=\"beginTime != null and beginTime != ''\"><!-- 开始时间检索 -->\n" +
+            "            AND date_format(u.create_time,'%y%m%d') &gt;= date_format(#{beginTime},'%y%m%d')\n" +
+            "        </if>\n" +
+            "        <if test=\"endTime != null and endTime != ''\"><!-- 结束时间检索 -->\n" +
+            "            AND date_format(u.create_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')\n" +
+            "        </if>\n" +
+            "        <if test=\"deptId != null and deptId != 0\">\n" +
+            "            AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM company_dept t WHERE find_in_set(#{deptId}, ancestors) ))\n" +
+            "        </if>"+
+            "</script>"})
     List<CompanyUserVO> selectMyUserList(CompanyUser user);
 
     @Select("select u.* from company_user u where u.dept_id in ( SELECT dept_id FROM company_dept WHERE dept_id = #{maps.deptId} or find_in_set( #{maps.deptId} , ancestors ) ) ${maps.params.dataScope}")
@@ -116,6 +132,32 @@ public interface CompanyUserMapper
     @Select("select u.* from company_user u   where u.company_id=#{companyId} and u.nick_name=#{nickName} limit 1 ")
     CompanyUser selectCompanyUserByCompanyIdAndNickName(@Param("companyId")long companyId,@Param("nickName") String nickName);
 
+    @Select({"<script> " +
+            "select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,u.open_id,u.id_card, d.dept_name, d.leader ,\n" +
+            "        (select count(1) from crm_customer cc where u.user_id= cc.receive_user_id and date_format(cc.receive_time,'%y%m%d') = date_format(now(),'%y%m%d')  ) as now_day_customer_count\n" +
+            "        from company_user u\n" +
+            "        left join company_dept d on u.dept_id = d.dept_id\n" +
+            "\n" +
+            "        where u.del_flag = '0' and u.status=0\n" +
+            "        <if test=\"companyId != null  \">\n" +
+            "            AND u.company_id = #{companyId}\n" +
+            "        </if>\n" +
+            "        <if test=\"nickName != null and nickName != ''\">\n" +
+            "            AND u.nick_name like concat( #{nickName}, '%')\n" +
+            "        </if>\n" +
+            "        <if test=\"phonenumber != null and phonenumber != ''\">\n" +
+            "            AND u.phonenumber like concat('%', #{phonenumber}, '%')\n" +
+            "        </if>\n" +
+            "        <if test=\"beginTime != null and beginTime != ''\"><!-- 开始时间检索 -->\n" +
+            "            AND date_format(u.create_time,'%y%m%d') &gt;= date_format(#{beginTime},'%y%m%d')\n" +
+            "        </if>\n" +
+            "        <if test=\"endTime != null and endTime != ''\"><!-- 结束时间检索 -->\n" +
+            "            AND date_format(u.create_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')\n" +
+            "        </if>\n" +
+            "        <if test=\"deptId != null and deptId != 0\">\n" +
+            "            AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM company_dept t WHERE find_in_set(#{deptId}, ancestors) ))\n" +
+            "        </if>"+
+            "</script>"})
     List<CompanyUserVO> selecCompanyAllUsersList(CompanyUser map);
 
     @Select("select user_id from company_user where company_id=#{companyId} and user_type = '00'")
@@ -137,6 +179,8 @@ public interface CompanyUserMapper
             "    OR FIND_IN_SET(#{maps.deptId}, cd.ancestors))")
     List<CompanyUserQwVO> getUserListByDeptIdToQwUserid(@Param("maps") CompanyUser user);
 
+    @Select("select * from  qw_user  where corp_id=#{corpId} and company_id=#{companyId}")
+    List<QwUserVO> selectCompanyQwUserList(@Param("corpId") String corpId,@Param("companyId")Long companyId);
 
     @Select({"<script> " +
             "select u.*, d.dept_name, d.leader from company_user u\n" +
@@ -147,7 +191,7 @@ public interface CompanyUserMapper
             "        </if>\n" +
             "\n" +
             "        <if test=\"nickName != null and nickName != ''\">\n" +
-            "            AND u.nick_name like concat('%', #{nickName}, '%')\n" +
+            "            AND u.nick_name like concat( #{nickName}, '%')\n" +
             "        </if>\n" +
             "        <if test=\"companyId != null and companyId != ''\">\n" +
             "            AND u.company_id = #{companyId}\n" +
@@ -155,6 +199,9 @@ public interface CompanyUserMapper
             "        <if test=\"status != null and status != ''\">\n" +
             "            AND u.status = #{status}\n" +
             "        </if>\n" +
+            "        <if test=\"qwStatus != null \">\n" +
+            "            AND u.qw_status = #{qwStatus} \n" +
+            "        </if>\n" +
             "        <if test=\"phonenumber != null and phonenumber != ''\">\n" +
             "            AND u.phonenumber like concat('%', #{phonenumber}, '%')\n" +
             "        </if>\n" +
@@ -172,8 +219,25 @@ public interface CompanyUserMapper
             "</script>"})
     List<CompanyUserQwListVO> selectCompanyUserQwListVO(CompanyUserQwParam user);
 
-    @Select("select user_id as dictValue,nick_name as dictLabel from company_user where status = 0 and user_type = '02' ")
-    List<OptionsVO> selectCompanyUserBySalesman();
+
+    @Update({
+            "<script>",
+            "  UPDATE company_user",
+            "  SET address_id = #{data.addressId}",
+            "  WHERE user_id IN",
+            "  <foreach collection='data.userIds' item='userId' open='(' separator=',' close=')'>",
+            "    #{userId}",
+            "  </foreach>",
+            "</script>"
+    })
+    public int updateCompanyUserAreaList(@Param("data") CompanyUserAreaParam param);
+
+    @Select("select * from  company_wx_user  where company_user_id=#{companyUserId} and nick_name=#{nickName}")
+    CompanyWxUser selectCompanyUserByNickName(@Param("companyUserId") Long companyUserId, @Param("nickName") String nickName);
 
     List<CompanyQwUserByIdsVo> selectCompanyQwUserByIds(@Param("ids") List<Long> ids);
+    @Select("select qw_user_id FROM company_user where user_id=#{companyUserId}")
+    String selectQwUserIdsByCompany(Long companyUserId);
+
+    List<String> selectCompanyUserNameByIds(@Param("companyUserIds")String companyUserIds);
 }

+ 11 - 0
fs-service-system/src/main/java/com/fs/company/param/CompanyUserAreaParam.java

@@ -0,0 +1,11 @@
+package com.fs.company.param;
+
+import lombok.Data;
+
+import java.util.ArrayList;
+
+@Data
+public class CompanyUserAreaParam {
+    public ArrayList<String> userIds;
+    public String addressId;
+}

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

@@ -261,7 +261,8 @@ public class CompanyUserServiceImpl implements ICompanyUserService
 
     @Override
     public List<CompanyUser> selectCompanyNoQwUserList(Long companyId) {
-        return companyUserMapper.selectCompanyNoQwUserList(companyId);
+//        return companyUserMapper.selectCompanyNoQwUserList(companyId);
+        return Collections.emptyList();
     }
 
     @Override
@@ -371,7 +372,8 @@ public class CompanyUserServiceImpl implements ICompanyUserService
 
     @Override
     public List<OptionsVO> selectCompanyUserBySalesman() {
-        return companyUserMapper.selectCompanyUserBySalesman();
+//        return companyUserMapper.selectCompanyUserBySalesman();
+        return Collections.emptyList();
     }
 
     @Override

+ 87 - 0
fs-service-system/src/main/java/com/fs/course/domain/FsCourseSopAppLink.java

@@ -0,0 +1,87 @@
+package com.fs.course.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * sop发送app消息的记录对象 fs_course_sop_app_link
+ *
+ * @author fs
+ * @date 2025-03-20
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FsCourseSopAppLink extends BaseEntity{
+
+    /** $column.columnComment */
+    @TableId
+    private Long id;
+
+    /** 链接后缀 */
+    @Excel(name = "链接后缀")
+    private String link;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 销售id */
+    @Excel(name = "销售id")
+    private Long companyUserId;
+
+    /** 企微userId */
+    @Excel(name = "企微userId")
+    private Long qwUserId;
+
+    /** 企微员工昵称 */
+    @Excel(name = "企微员工昵称")
+    private String qwUserName;
+
+    /** 企微主体id */
+    @Excel(name = "企微主体id")
+    private String corpId;
+
+    /** 课程Id */
+    @Excel(name = "课程Id")
+    private Long courseId;
+
+    /** 课程标题 */
+    @Excel(name = "课程标题")
+    private String courseTitle;
+
+    /** 课程封面 */
+    @Excel(name = "课程封面")
+    private String courseUrl;
+
+    /** 课节id */
+    @Excel(name = "课节id")
+    private Long videoId;
+
+    /** 课节描述 */
+    @Excel(name = "课节描述")
+    private String videoTitle;
+
+    /** 跳转链接 */
+    @Excel(name = "跳转链接")
+    private String appRealLink;
+
+    /** 企微外部联系人userId */
+    @Excel(name = "企微外部联系人userId")
+    private Long qwExternalId;
+
+    private Integer isRead;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+
+}

+ 1 - 1
fs-service-system/src/main/java/com/fs/course/domain/FsUserCourseVideo.java

@@ -80,7 +80,7 @@ public class FsUserCourseVideo extends BaseEntity
 
 
     private String packageJson;//绑定疗法
-
+    private Integer isFirst;
     private Integer isTranscode;//是否转码
 
     private String transcodeFileKey;//转码的文件key

+ 6 - 1
fs-service-system/src/main/java/com/fs/course/mapper/FsCourseLinkMapper.java

@@ -62,11 +62,16 @@ public interface FsCourseLinkMapper
      */
     public int deleteFsCourseLinkByLinkIds(Long[] linkIds);
 
-    @Select("select link, real_link, update_time from fs_course_link where link = #{suffix}")
+    @Select("select link, real_link, update_time from fs_course_link where link = #{suffix} order by link_id desc limit 1 ")
     FsCourseLink selectFsCourseLinkByLink(@Param("suffix") String suffix);
 
     void insertFsCourseLinkBatch(@Param("courseLinks")List<FsCourseLink> courseLinkToInsert);
 
     @Select("select link_id from fs_course_link where update_time < NOW() ")
     List<Long> selectExpireLink();
+
+    @Select("select link_id,real_link from fs_course_link where create_time > '2025-03-07 12:00:00' and create_time < '2025-03-07 17:00:00'")
+    List<FsCourseLink> selectFsCourseLinkListUpdate();
+
+
 }

+ 98 - 0
fs-service-system/src/main/java/com/fs/course/mapper/FsCourseSopAppLinkMapper.java

@@ -0,0 +1,98 @@
+package com.fs.course.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.course.domain.FsCourseSopAppLink;
+import com.fs.course.vo.FsSopMyCourseLinkVO;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+/**
+ * sop发送app消息的记录Mapper接口
+ *
+ * @author fs
+ * @date 2025-03-20
+ */
+public interface FsCourseSopAppLinkMapper extends BaseMapper<FsCourseSopAppLink> {
+    /**
+     * 查询sop发送app消息的记录
+     *
+     * @param id sop发送app消息的记录主键
+     * @return sop发送app消息的记录
+     */
+    FsCourseSopAppLink selectFsCourseSopAppLinkById(Long id);
+
+    /**
+     * 查询sop发送app消息的记录列表
+     *
+     * @param fsCourseSopAppLink sop发送app消息的记录
+     * @return sop发送app消息的记录集合
+     */
+    List<FsCourseSopAppLink> selectFsCourseSopAppLinkList(FsCourseSopAppLink fsCourseSopAppLink);
+
+    /**
+     * 新增sop发送app消息的记录
+     *
+     * @param fsCourseSopAppLink sop发送app消息的记录
+     * @return 结果
+     */
+    int insertFsCourseSopAppLink(FsCourseSopAppLink fsCourseSopAppLink);
+
+    void insertFsCourseSopAppLinkBatch(@Param("courseAppSopLinks")List<FsCourseSopAppLink> courseSopAppLinkToInsert);
+
+    /**
+     * 修改sop发送app消息的记录
+     *
+     * @param fsCourseSopAppLink sop发送app消息的记录
+     * @return 结果
+     */
+    int updateFsCourseSopAppLink(FsCourseSopAppLink fsCourseSopAppLink);
+
+    /**
+     * 删除sop发送app消息的记录
+     *
+     * @param id sop发送app消息的记录主键
+     * @return 结果
+     */
+    int deleteFsCourseSopAppLinkById(Long id);
+
+    /**
+     * 批量删除sop发送app消息的记录
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsCourseSopAppLinkByIds(Long[] ids);
+
+    @Select("SELECT\n" +
+            "al.id," +
+            "\tal.create_time," +
+            "\tal.update_time,\n" +
+            "\tal.qw_user_name,\n" +
+            "\tal.course_title AS courseName,\n" +
+            "\tal.course_url,\n" +
+            "\tal.video_title AS title,\n" +
+            "\tal.app_real_Link, \n" +
+            "\tal.is_read \n" +
+            "FROM\n" +
+            "\t`fs_course_sop_app_link` al\n" +
+            "\tLEFT JOIN qw_external_contact ec ON al.qw_external_id = ec.id \n" +
+            "WHERE\n" +
+            "\tec.fs_user_id = #{userId} \n" +
+            "\tAND al.update_time >= NOW() " +
+            "ORDER BY al.is_read desc,al.update_time desc ")
+    List<FsSopMyCourseLinkVO> getSopCourseStudyList(@Param("userId") Long userId);
+
+    @Select("SELECT\n" +
+            "\tcount(1) as isNotRead\n" +
+            "FROM\n" +
+            "\tfs_course_sop_app_link al\n" +
+            "\tLEFT JOIN qw_external_contact ec ON al.qw_external_id = ec.id \n" +
+            "WHERE\n" +
+            "\tec.fs_user_id = #{userId} \n" +
+            "\tAND al.is_read = 0 \n" +
+            "\tAND al.update_time >= NOW() ")
+    Integer selectSopCountIsNotRead(@Param("userId") Long userId);
+}

+ 80 - 8
fs-service-system/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java

@@ -2,15 +2,13 @@ package com.fs.course.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.course.domain.FsCourseWatchLog;
-import com.fs.course.param.FsCourseWatchLogByFinishTimeParam;
-import com.fs.course.param.FsCourseWatchLogListParam;
-import com.fs.course.param.FsCourseWatchLogParam;
-import com.fs.course.param.FsCourseWatchLogStatisticsListParam;
-import com.fs.course.vo.FsCourseWatchLogListVO;
-import com.fs.course.vo.FsCourseWatchLogStatisticsListVO;
-import com.fs.course.vo.FsCourseWatchLogVO;
+import com.fs.course.domain.FsUserCourseVideo;
+import com.fs.course.param.*;
+import com.fs.course.vo.*;
+import com.fs.sop.vo.QwRatingVO;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -73,6 +71,9 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
      */
     public int updateFsCourseWatchLog(FsCourseWatchLog fsCourseWatchLog);
 
+    @Update("UPDATE fs_course_watch_log SET user_id = #{userId} WHERE qw_external_contact_id = #{externalUserId}")
+    public int updateFsCourseWatchLogByQwExternalId(@Param("externalUserId") Long externalUserId,@Param("userId") Long userId);
+
     /**
      * 删除短链课程看课记录
      *
@@ -126,6 +127,42 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
 
     @Select("select l.*,v.title,c.course_name from fs_course_watch_log l LEFT JOIN fs_user_course_video v ON v.video_id = l.video_id LEFT JOIN fs_user_course c ON c.course_id = l.course_id WHERE l.qw_external_contact_id =#{id} ORDER BY l.create_time  desc LIMIT 1  ")
     FsCourseWatchLogVO selectFsCourseWatchLogByExtId(Long id);
+
+    @Select("select l.qw_external_contact_id,l.company_id,l.company_user_id,l.log_type,ext.`level`,l.qw_user_id FROM fs_course_watch_log l LEFT JOIN qw_external_contact ext ON ext.id =l.qw_external_contact_id  where l.sop_id=#{SopId} and  date(l.create_time)= CURDATE() and l.log_type =3 and l.video_id not in (select video_id from fs_user_course_video WHERE is_first=1 ) ")
+    List<FsCourseWatchLogTaskVO> selectFsCourseWatchLogByDaySopId3(@Param("SopId")String SopId);
+
+    @Select("select l.qw_external_contact_id,l.company_id,l.company_user_id,l.log_type,ext.`level`,l.qw_user_id,ext.last_watch_time FROM fs_course_watch_log l LEFT JOIN qw_external_contact ext ON ext.id =l.qw_external_contact_id  where l.sop_id=#{SopId} and  date(l.create_time)= CURDATE() and l.log_type =3 and l.video_id not in (select video_id from fs_user_course_video WHERE is_first=1 ) and ext.last_watch_time < #{lastTime} and ext.last_watch_time !=0  ")
+    List<FsCourseWatchLogTaskVO> selectFsCourseWatchLogByDaySopId3LastTime(@Param("SopId")String SopId,@Param("lastTime")Integer lastTime);
+
+    @Select("select l.qw_external_contact_id,l.company_id,l.company_user_id,l.log_type,ext.`level`,l.qw_user_id FROM fs_course_watch_log l LEFT JOIN qw_external_contact ext ON ext.id =l.qw_external_contact_id  where l.sop_id=#{SopId} and  date(l.create_time)= CURDATE() and l.log_type =4 and l.video_id not in (select video_id from fs_user_course_video WHERE is_first=1 ) ")
+    List<FsCourseWatchLogTaskVO> selectFsCourseWatchLogByDaySopId4(@Param("SopId")String SopId);
+//    @Select("   SELECT\n" +
+//            "            wl.log_type,\n" +
+//            "            ec.level\n" +
+//            "        FROM\n" +
+//            "            fs_course_watch_log wl LEFT JOIN qw_external_contact ec on wl.qw_external_contact_id=ec.id\n" +
+//            "        WHERE\n" +
+//            "            wl.send_type = 2\n" +
+//            "        and wl.qw_external_contact_id= #{externalId}\n" +
+//            "        AND wl.create_time &gt;= DATE_SUB(CURDATE(), INTERVAL #{dayNum} DAY)\n" +
+//            "        AND wl.create_time &lt; CURDATE()\n")
+
+    @Select("SELECT\n" +
+            "\twl.duration AS watchDuration,\n" +
+            "\tcv.duration AS allDuration,\n" +
+            "\tec.`level` AS levelType,\n" +
+            "\twl.finish_time " +
+            "FROM\n" +
+            "\tfs_course_watch_log wl\n" +
+            "\tLEFT JOIN qw_external_contact ec ON wl.qw_external_contact_id = ec.id\n" +
+            "\tLEFT JOIN fs_user_course_video cv ON wl.video_id = cv.video_id \n" +
+            "WHERE\n" +
+            "\twl.send_type = 2 \n" +
+            "\tAND wl.qw_external_contact_id = #{externalId} \n" +
+            "\tAND wl.create_time >= DATE_SUB( CURDATE(), INTERVAL #{dayNum} DAY ) \n" +
+            "\tAND wl.create_time < CURDATE() ")
+    List<QwRatingVO> selectFsCourseWatchLogByExtIdRating(@Param("externalId") Long externalId, @Param("dayNum") Integer dayNum);
+
     @Select("select l.*,v.title,c.course_name from fs_course_watch_log l LEFT JOIN fs_user_course_video v ON v.video_id = l.video_id LEFT JOIN fs_user_course c ON c.course_id = l.course_id WHERE l.qw_external_contact_id =#{ExtId} and l.qw_user_id=#{QwUserId} and DATE(l.create_time) =CURDATE() ORDER BY l.create_time  desc LIMIT 1  ")
     FsCourseWatchLogVO selectFsCourseWatchLogByExtIdAndQwUserId(@Param("ExtId")String ExtId,@Param("QwUserId")Long QwUserId);
 
@@ -169,7 +206,7 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
             "      and DATE(o.create_time) &lt;= DATE(#{eTime})\n" +
             "</if>" +
             "<if test ='nickName !=null and nickName!=\"\"'>\n" +
-            "   and qu.qw_user_name like concat('%', #{nickName}, '%')\n" +
+            "   and qu.qw_user_name like concat( #{nickName}, '%')\n" +
             "</if>" +
             "<if test ='courseId !=null'> " +
             "     and o.course_id = #{courseId} " +
@@ -187,6 +224,41 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
 
     void batchUpdateWatchLog(@Param("list") List<FsCourseWatchLog> logs);
 
+    List<FsCourseUserStatisticsListVO> selectFsCourseUserStatisticsListVO(FsCourseUserStatisticsListParam param);
+
+    @Select({"<script> " +
+            "select MIN(o.create_time) createTime,ANY_VALUE(qu.qw_user_name) qwUserName ,ext.name externalUserName,ext.create_time userCreateTime from fs_course_watch_log o LEFT JOIN qw_user qu on qu.id=o.qw_user_id LEFT JOIN qw_external_contact ext ON ext.id =  o.qw_external_contact_id where log_type=2 and o.company_id=#{companyId} " +
+            "<if test= 'sTime != null '> " +
+            "       and DATE(o.create_time) &gt;= DATE(#{sTime})\n" +
+            "</if>\n" +
+            "<if test='eTime != null '> " +
+            "      and DATE(o.create_time) &lt;= DATE(#{eTime})\n" +
+            "</if>" +
+            "<if test ='nickName !=null and nickName!=\"\"'>\n" +
+            "   and qu.qw_user_name like concat( #{nickName}, '%')\n" +
+            "</if>"+
+            " GROUP BY o.qw_external_contact_id"+
+            "</script>"})
+    List<FsCourseOverVO> selectFsCourseWatchLogOverStatisticsListVO(FsCourseOverParam param);
+
 
     void batchUpdateWatchLogSendMsg(@Param("list") List<FsCourseWatchLog> logs);
+
+    @Select("SELECT l.qw_external_contact_id,l.log_type,l.qw_user_id,l.create_time ,u.first_time,u.create_time lineTime FROM fs_course_watch_log  l " +
+            "LEFT JOIN qw_external_contact u ON u.id=l.qw_external_contact_id  " +
+            " WHERE  DATE(l.create_time) = DATE_SUB(CURDATE(), INTERVAL 1 DAY) and l.video_id =#{videoId}")
+    List<FsQwCourseWatchLogVO> selectFsCourseWatchLogByNoDayAndVoidId(Long videoId);
+    @Select("SELECT l.qw_external_contact_id,l.log_type,l.qw_user_id,l.create_time ,u.first_time,u.create_time lineTime FROM fs_course_watch_log  l " +
+            "LEFT JOIN qw_external_contact u ON u.id=l.qw_external_contact_id  " +
+            " WHERE  DATE(l.create_time) = DATE_SUB(CURDATE(), INTERVAL 2 DAY) and l.video_id =#{videoId}")
+    List<FsQwCourseWatchLogVO> selectFsCourseWatchLogByNoDayAndVoidId2(Long videoId);
+    @Select("SELECT l.qw_external_contact_id,l.log_type,l.qw_user_id,l.create_time ,u.first_time,u.create_time lineTime FROM fs_course_watch_log  l " +
+            "LEFT JOIN qw_external_contact u ON u.id=l.qw_external_contact_id  " +
+            " WHERE  DATE(l.create_time) = DATE_SUB(CURDATE(), INTERVAL 1 DAY) and l.sop_id =#{videoId}")
+    List<FsQwCourseWatchLogVO> selectFsCourseWatchLogBySopId(String id);
+    @Select("SELECT * FROM fs_course_watch_log  WHERE  DATE(create_time) = CURDATE() and video_id in (select video_id from fs_user_course_video WHERE is_first=1 ) ")
+    List<FsQwCourseWatchLogVO> selectFsCourseWatchLogByVideoId();
+    @Select("SELECT qw_external_contact_id FROM fs_course_watch_log  WHERE log_type=2 and DATE(create_time) = CURDATE() ")
+    List<Long> selectFsCourseWatchLogByFinish();
+
 }

+ 8 - 0
fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseMapper.java

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

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

@@ -144,7 +144,8 @@ public interface FsUserCourseVideoMapper
     List<FsUserCourseVideo> selectVideoIsPrivate();
     @Select("select * from fs_user_course_video WHERE video_id=#{videoId}")
     FsUserCourseVideo selectFsUserCourseVideoByVideoStringId(String videoId);
-
+    @Select("select * from fs_user_course_video WHERE course_id=#{courseId}")
+    List<FsUserCourseVideo> selectVideoByCourseId(Long courseId);
     @Select("select v.* from fs_user_course_video v " +
             "left join fs_user_course c on c.course_id = v.course_id " +
             "where c.is_private = 1 and v.is_del = 0 and v.is_transcode = #{isTranscode}")
@@ -156,4 +157,7 @@ public interface FsUserCourseVideoMapper
             "where c.is_private = 1 and v.is_del = 0 and v.is_transcode = 1 and transcode_file_key is null ")
     List<FsUserCourseVideo> selectVideoIsTranscode();
 
+    @Select("select video_id from fs_user_course_video WHERE is_first=1")
+    List<Long> selectVideoByFirst();
+
 }

+ 0 - 1
fs-service-system/src/main/java/com/fs/course/param/FsCourseLinkCreateParam.java

@@ -1,6 +1,5 @@
 package com.fs.course.param;
 
-import com.fs.his.param.BaseParam;
 import lombok.Data;
 
 import java.util.Date;

+ 17 - 0
fs-service-system/src/main/java/com/fs/course/param/FsCourseOverParam.java

@@ -0,0 +1,17 @@
+package com.fs.course.param;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class FsCourseOverParam {
+    private Long companyId;
+    private String nickName;
+    private String qwUserName;
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date eTime;
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date sTime;
+}

+ 1 - 0
fs-service-system/src/main/java/com/fs/course/param/FsCourseSendRewardUParam.java

@@ -23,5 +23,6 @@ public class FsCourseSendRewardUParam implements Serializable
     private Integer rewardType; //奖励类型
     private Integer linkType;
     private Long qwExternalId;
+    private Integer source=1;//来源 1:h5  2:彩虹汇医小程序
 
 }

+ 12 - 0
fs-service-system/src/main/java/com/fs/course/param/FsCourseSopLinkParam.java

@@ -0,0 +1,12 @@
+package com.fs.course.param;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class FsCourseSopLinkParam {
+
+    @ApiModelProperty(value = "页码,默认为1")
+    private Integer pageNum =1;
+    @ApiModelProperty(value = "页大小,默认为10")
+    private Integer pageSize = 10;
+}

+ 18 - 0
fs-service-system/src/main/java/com/fs/course/param/FsCourseUserStatisticsListParam.java

@@ -0,0 +1,18 @@
+package com.fs.course.param;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class FsCourseUserStatisticsListParam {
+    private Long companyId;
+
+    private String nickName;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date eTime;
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date sTime;
+}

+ 1 - 0
fs-service-system/src/main/java/com/fs/course/param/FsCourseWatchLogListParam.java

@@ -47,5 +47,6 @@ public class FsCourseWatchLogListParam implements Serializable {
     private String scheduleStartTime;
     @JsonFormat(pattern = "yyyy-MM-dd")
     private String scheduleEndTime;
+
     private List<String> sopIds;
 }

+ 0 - 1
fs-service-system/src/main/java/com/fs/course/param/FsUserCourseGetIntegralParam.java

@@ -1,6 +1,5 @@
 package com.fs.course.param;
 
-import com.fs.his.param.BaseParam;
 import lombok.Data;
 
 import java.io.Serializable;

+ 0 - 1
fs-service-system/src/main/java/com/fs/course/param/FsUserCourseListUParam.java

@@ -1,6 +1,5 @@
 package com.fs.course.param;
 
-import com.fs.his.param.BaseParam;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 

+ 0 - 1
fs-service-system/src/main/java/com/fs/course/param/FsUserCourseOrderCreateParam.java

@@ -1,6 +1,5 @@
 package com.fs.course.param;
 
-import com.fs.his.param.BaseParam;
 import lombok.Data;
 
 import java.io.Serializable;

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

@@ -1,6 +1,7 @@
 package com.fs.course.param;
 
 import com.fs.common.annotation.Excel;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 @Data
@@ -16,4 +17,9 @@ public class FsUserCourseVideoParam {
     private String redPacketMoney;
     private Long companyId;
 
+    @ApiModelProperty(value = "页码,默认为1")
+    private Integer pageNum =1;
+    @ApiModelProperty(value = "页大小,默认为10")
+    private Integer pageSize = 10;
+
 }

+ 0 - 1
fs-service-system/src/main/java/com/fs/course/param/FsUserVipOrderCreateUParam.java

@@ -1,6 +1,5 @@
 package com.fs.course.param;
 
-import com.fs.his.param.BaseParam;
 import lombok.Data;
 
 import javax.validation.constraints.NotNull;

+ 27 - 0
fs-service-system/src/main/java/com/fs/course/param/SopRoomCourseParam.java

@@ -0,0 +1,27 @@
+package com.fs.course.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class SopRoomCourseParam {
+
+    private String corpId;
+    /** qw_user_id */
+
+    private String qwUserid;
+
+    /** 企微外部联系人id */
+
+    private String externalUserId;
+
+    /** 0发送失败 1发送成功 3待发送 4未发送(未确定) 5已作废 */
+    private Long sendStatus;
+
+    @ApiModelProperty(value = "页码,默认为1")
+    private Integer pageNum =1;
+    @ApiModelProperty(value = "页大小,默认为10")
+    private Integer pageSize = 10;
+
+    private Long courseId;
+}

+ 7 - 0
fs-service-system/src/main/java/com/fs/course/service/IFsCourseLinkService.java

@@ -65,8 +65,15 @@ public interface IFsCourseLinkService
     R createLinkUrl(FsCourseLinkCreateParam param);
 
     R createLinkUrlWc(FsCourseLinkCreateParam param);
+    String createLinkUrlWcmini(FsCourseLinkCreateParam param);
 
     R getRealLink(String link);
 
+
     void delCourseExpireLink();
+
+    void updateLinks();
+
+    R createLinkByMiniApp(FsCourseLinkCreateParam param);
+
 }

+ 13 - 3
fs-service-system/src/main/java/com/fs/course/service/IFsCourseWatchLogService.java

@@ -2,9 +2,9 @@ package com.fs.course.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.course.domain.FsCourseWatchLog;
-import com.fs.course.param.FsCourseWatchLogListParam;
-import com.fs.course.param.FsCourseWatchLogParam;
-import com.fs.course.param.FsCourseWatchLogStatisticsListParam;
+import com.fs.course.param.*;
+import com.fs.course.vo.FsCourseOverVO;
+import com.fs.course.vo.FsCourseUserStatisticsListVO;
 import com.fs.course.vo.FsCourseWatchLogListVO;
 import com.fs.course.vo.FsCourseWatchLogStatisticsListVO;
 
@@ -91,4 +91,14 @@ public interface IFsCourseWatchLogService extends IService<FsCourseWatchLog> {
     void scheduleBatchUpdateToDatabase();
 
     void checkWatchStatus();
+
+    List<FsCourseUserStatisticsListVO> selectFsCourseUserStatisticsListVO(FsCourseUserStatisticsListParam param);
+
+    List<FsCourseOverVO> selectFsCourseWatchLogOverStatisticsListVO(FsCourseOverParam param);
+
+    void addCourseWatchLogDay();
+
+    void addCourseWatchLogDay2();
+
+    FsCourseWatchLog getWatchCourseVideoH5(Long videoId,String qwUserId,Long externalId);
 }

+ 132 - 2
fs-service-system/src/main/java/com/fs/course/service/impl/FsCourseLinkServiceImpl.java

@@ -1,5 +1,6 @@
 package com.fs.course.service.impl;
 
+import cn.hutool.core.util.IdUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.fs.common.core.domain.R;
@@ -8,27 +9,36 @@ import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsCourseDomainName;
 import com.fs.course.domain.FsCourseLink;
 import com.fs.course.domain.FsCourseRealLink;
+import com.fs.course.domain.FsUserCourseVideo;
 import com.fs.course.mapper.FsCourseDomainNameMapper;
 import com.fs.course.mapper.FsCourseLinkMapper;
+import com.fs.course.mapper.FsCourseSopAppLinkMapper;
 import com.fs.course.mapper.FsUserCourseVideoMapper;
 import com.fs.course.param.FsCourseLinkCreateParam;
+import com.fs.course.service.IFsCourseDomainNameService;
 import com.fs.course.service.IFsCourseLinkService;
+import com.fs.qw.domain.QwUser;
 import com.fs.qw.mapper.QwUserMapper;
+import com.fs.qw.vo.QwSopCourseFinishTempSetting;
 import com.fs.system.service.ISysConfigService;
 import lombok.Synchronized;
 import lombok.extern.slf4j.Slf4j;
+import org.checkerframework.checker.units.qual.A;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.io.UnsupportedEncodingException;
+import java.net.URI;
 import java.net.URLDecoder;
 import java.security.SecureRandom;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.util.*;
 
+import static com.fs.course.utils.LinkUtil.generateRandomStringWithLock;
+
 /**
  * 短链Service业务层处理
  *
@@ -41,6 +51,10 @@ public class FsCourseLinkServiceImpl implements IFsCourseLinkService
 {
     @Autowired
     private FsCourseLinkMapper fsCourseLinkMapper;
+
+    @Autowired
+    private  FsCourseSopAppLinkMapper fsCourseSopAppLinkMapper;
+
     @Autowired
     private ISysConfigService configService;
 
@@ -125,7 +139,9 @@ public class FsCourseLinkServiceImpl implements IFsCourseLinkService
         return fsCourseLinkMapper.deleteFsCourseLinkByLinkId(linkId);
     }
 
-    private static final String realLink = "https://h5.cdwjyyh.com/courseh5/pages/course/learning?course=";
+    private static final String realLink = "/courseh5/pages/course/learning?course=";
+    private static final String miniappRealLink = "/pages_course/video?course=";
+    private static final String appRealLink = "/pages/courseAnswer/index?link=";
 
 
     /**
@@ -236,6 +252,65 @@ public class FsCourseLinkServiceImpl implements IFsCourseLinkService
         return R.error("短链生成失败!");
     }
 
+    @Override
+    public String createLinkUrlWcmini(FsCourseLinkCreateParam param) {
+
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+
+
+        FsCourseLink link = createFsCourseLink(param.getCorpId(), param.getSendTime(), param.getCourseId(), param.getVideoId(), param.getQwUserId(),
+                param.getCompanyUserId(), param.getCompanyId(), param.getQwExternalId(),3);
+
+        FsCourseRealLink courseMap = new FsCourseRealLink();
+        BeanUtils.copyProperties(link,courseMap);
+
+        String courseJson = JSON.toJSONString(courseMap);
+        String realLinkFull = miniappRealLink + courseJson;
+        link.setRealLink(realLinkFull);
+
+        Date updateTime = createUpdateTime(param.getDays(), param.getSendTime(), config);
+
+        link.setUpdateTime(updateTime);
+        //存短链-
+        fsCourseLinkMapper.insertFsCourseLink(link);
+
+        return link.getRealLink();
+    }
+
+    public FsCourseLink createFsCourseLink(String corpId, Date sendTime,Long courseId,Long videoId, String qwUserId,
+                                           Long companyUserId, Long companyId,Long externalId,Integer type){
+        // 手动创建 FsCourseLink 对象,避免使用 BeanUtils.copyProperties
+        FsCourseLink link = new FsCourseLink();
+        link.setCompanyId(companyId);
+        link.setQwUserId(qwUserId);
+        link.setCompanyUserId(companyUserId);
+        link.setVideoId(videoId);
+        link.setCorpId(corpId);
+        link.setCourseId(courseId);
+        link.setQwExternalId(externalId);
+        link.setLinkType(type); //小程序
+        String randomString = generateRandomStringWithLock();
+        link.setLink(randomString);
+        link.setCreateTime(sendTime);
+
+        return link;
+    }
+
+    private Date createUpdateTime(Integer expiresDays, Date sendTime, CourseConfig config){
+
+        Integer expireDays = (expiresDays == null || expiresDays == 0)
+                ? config.getVideoLinkExpireDate()
+                : expiresDays;
+
+//         使用 Java 8 时间 API 计算过期时间
+        LocalDateTime sendDateTime = sendTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+        LocalDateTime expireDateTime = sendDateTime.plusDays(expireDays-1);
+        expireDateTime = expireDateTime.toLocalDate().atTime(23, 59, 59);
+        Date updateTime = Date.from(expireDateTime.atZone(ZoneId.systemDefault()).toInstant());
+
+        return updateTime;
+    }
 
     // 生成随机的八位数字字母大小写的字符串(改为生成随机不重复的雪花id)
     public static String generateRandomString() {
@@ -279,7 +354,10 @@ public class FsCourseLinkServiceImpl implements IFsCourseLinkService
                         return R.error("真实链接不存在").put("realLink", sLink);
                     }
                     log.info("链接仍然有效: {}", sLink);
-                    return R.ok().put("realLink", courseLink.getRealLink());
+                    String json = configService.selectConfigByKey("course.config");
+                    CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+                    String realLink = config.getRealLinkDomainName()+courseLink.getRealLink();
+                    return R.ok().put("realLink",realLink );
                 }
             } else {
                 // 链接不存在或解析失败
@@ -326,4 +404,56 @@ public class FsCourseLinkServiceImpl implements IFsCourseLinkService
             }
         }
     }
+
+    @Override
+    public void updateLinks() {
+        List<FsCourseLink> links = fsCourseLinkMapper.selectFsCourseLinkListUpdate();
+        for (FsCourseLink link : links){
+            String newUrl = link.getRealLink().replace("https://h5.cdwjyyh.com","");
+            link.setRealLink(newUrl);
+            fsCourseLinkMapper.updateFsCourseLink(link);
+        }
+    }
+
+    @Override
+    public R createLinkByMiniApp(FsCourseLinkCreateParam param) {
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+
+        FsCourseLink link = new FsCourseLink();
+        link.setCompanyId(param.getCompanyId());
+        link.setQwUserId(param.getQwUserId());
+        link.setCompanyUserId(param.getCompanyUserId());
+        link.setVideoId(param.getVideoId());
+        link.setCorpId(param.getCorpId());
+        link.setCourseId(param.getCourseId());
+        link.setQwExternalId(param.getQwExternalId());
+        link.setLinkType(3);
+        String randomString = generateRandomString();
+        link.setLink(randomString);
+
+        //组装参数json
+        FsCourseRealLink courseMap = new FsCourseRealLink();
+        BeanUtils.copyProperties(link,courseMap);
+        // 将实体类对象转换为 JSON 字符串
+        String course = JSON.toJSONString(courseMap);
+        link.setRealLink(miniappRealLink+course );
+
+        link.setCreateTime(param.getSendTime());
+        Integer expireDays = 0;
+        if (param.getDays() == null || param.getDays() == 0){
+            expireDays = config.getVideoLinkExpireDate();
+        }else {
+            expireDays = param.getDays();
+        }
+        // 设置过期时间
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(param.getSendTime());
+        calendar.add(Calendar.DAY_OF_MONTH, expireDays);
+        link.setUpdateTime(calendar.getTime());
+        if (fsCourseLinkMapper.insertFsCourseLink(link)>0){
+            return R.ok("短链生成").put("url",link.getRealLink());
+        }
+        return R.error("短链生成失败!");
+    }
 }

+ 161 - 16
fs-service-system/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java

@@ -11,29 +11,29 @@ import com.fs.common.utils.DateUtils;
 import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsCourseFinishTemp;
 import com.fs.course.domain.FsCourseWatchLog;
+import com.fs.course.domain.FsUserCourse;
 import com.fs.course.domain.FsUserCourseVideo;
 import com.fs.course.mapper.FsCourseFinishTempMapper;
 import com.fs.course.mapper.FsCourseWatchLogMapper;
+import com.fs.course.mapper.FsUserCourseMapper;
 import com.fs.course.mapper.FsUserCourseVideoMapper;
-import com.fs.course.param.FsCourseWatchLogListParam;
-import com.fs.course.param.FsCourseWatchLogParam;
-import com.fs.course.param.FsCourseWatchLogStatisticsListParam;
+import com.fs.course.param.*;
 import com.fs.course.service.IFsCourseWatchLogService;
-import com.fs.course.vo.FsCourseWatchLogListVO;
-import com.fs.course.vo.FsCourseWatchLogStatisticsListVO;
+import com.fs.course.vo.*;
+import com.fs.his.config.FsSysConfig;
+import com.fs.his.utils.ConfigUtil;
 import com.fs.qw.Bean.MsgBean;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.domain.QwUser;
+import com.fs.qw.domain.QwWatchLog;
 import com.fs.qw.mapper.QwExternalContactMapper;
 import com.fs.qw.mapper.QwUserMapper;
+import com.fs.qw.mapper.QwWatchLogMapper;
 import com.fs.qw.param.SendSopParamDetails;
-import com.fs.qw.param.SopUserLogsVO;
 import com.fs.qw.vo.QwSopCourseFinishTempSetting;
 import com.fs.qw.vo.QwSopTempSetting;
 import com.fs.sop.domain.QwSopLogs;
-import com.fs.sop.mapper.QwSopLogsMapper;
 import com.fs.sop.mapper.SopUserLogsMapper;
-import com.fs.sop.service.IQwSopLogsService;
 import com.fs.system.service.ISysConfigService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -41,9 +41,15 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.time.Duration;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
-import java.util.*;
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
 
 /**
  * 短链课程看课记录Service业务层处理
@@ -59,20 +65,23 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
     private FsCourseWatchLogMapper fsCourseWatchLogMapper;
     @Autowired
     private SopUserLogsMapper sopUserLogsMapper;
-    @Autowired
-    private QwSopLogsMapper sopLogsMapper;
 
     @Autowired
-    private IQwSopLogsService qwSopLogsService;
+    private FsUserCourseVideoMapper fsUserCourseVideoMapper;
+    @Autowired
+    private FsUserCourseMapper fsUserCourseMapper;
     @Autowired
     private FsCourseFinishTempMapper fsCourseFinishTempMapper;
     @Autowired
     private QwExternalContactMapper qwExternalContactMapper;
     @Autowired
     RedisCache redisCache;
-
+    @Autowired
+    private QwWatchLogMapper qwWatchLogMapper;
     @Autowired
     private FsUserCourseVideoMapper courseVideoMapper;
+    @Autowired
+    private ConfigUtil configUtil;
 
     /**
      * 查询短链课程看课记录
@@ -164,6 +173,10 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
         return fsCourseWatchLogMapper.getWatchCourseVideo(userId,videoId,qwUserId,externalId);
     }
 
+    @Override
+    public FsCourseWatchLog getWatchCourseVideoH5(Long videoId, String qwUserId, Long externalId) {
+        return fsCourseWatchLogMapper.getWatchCourseLogVideoBySop(videoId,qwUserId,externalId);
+    }
 
     @Override
     public FsCourseWatchLog getWatchCourseLogVideoBySop(Long videoId,String qwUserId,Long externalId )
@@ -256,8 +269,6 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
         return fsCourseWatchLogMapper.selectFsCourseWatchLogStatisticsListVO(param);
     }
 
-    private static final String hookUrl = "https://qwtool.ylrzcloud.com/app/";
-
 
     public void sendSocket(String cmd,String message,String appKey){
         MsgBean msgBean=new MsgBean();
@@ -267,7 +278,9 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
         JSONObject params=new JSONObject();
         params.put("id",appKey);
         params.put("message",JSONObject.toJSONString(msgBean));
-        HttpRequest.post(hookUrl+"qwmsg/receiveMsg")
+        FsSysConfig config = configUtil.getSysConfig();
+        String domainName = config.getHookUrl();
+        HttpRequest.post(domainName+"/app/qwmsg/receiveMsg")
                 .body(JSONObject.toJSONString(params),"application/json;charset=UTF-8")
                 .execute().body();
     }
@@ -362,6 +375,138 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
         batchUpdateFsCourseWatchLog(logs,100);
     }
 
+    @Override
+    public List<FsCourseUserStatisticsListVO> selectFsCourseUserStatisticsListVO(FsCourseUserStatisticsListParam param) {
+        return fsCourseWatchLogMapper.selectFsCourseUserStatisticsListVO(param);
+    }
+
+    @Override
+    public List<FsCourseOverVO> selectFsCourseWatchLogOverStatisticsListVO(FsCourseOverParam param) {
+        return fsCourseWatchLogMapper.selectFsCourseWatchLogOverStatisticsListVO(param);
+    }
+
+    @Override
+    public void addCourseWatchLogDay() {
+
+        List<FsUserCourse> courses = fsUserCourseMapper.selectFsUserCourseAllCourse();
+        for (FsUserCourse course : courses) {
+            Long project = course.getProject();
+            List<FsUserCourseVideo> fsUserCourseVideos = fsUserCourseVideoMapper.selectVideoByCourseId(course.getCourseId());
+            for (FsUserCourseVideo fsUserCourseVideo : fsUserCourseVideos) {
+                try {
+                    ArrayList<QwWatchLog> QwWatchLogs = new ArrayList<>();
+                    List<FsQwCourseWatchLogVO> watchLogs = fsCourseWatchLogMapper.selectFsCourseWatchLogByNoDayAndVoidId(fsUserCourseVideo.getVideoId());
+                    for (FsQwCourseWatchLogVO fsCourseWatchLog : watchLogs) {
+                        Date firstTime = fsCourseWatchLog.getFirstTime();
+                        Long day=1L;
+                        if (fsCourseWatchLog.getLineTime()==null){
+                            continue;
+                        }
+                        //不是第一次 看课程
+                        if (firstTime!=null){
+                            LocalDate firstLocalDate = firstTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+                            LocalDate currentDate = LocalDate.now();
+                            day = ChronoUnit.DAYS.between(firstLocalDate, currentDate);
+                        }else {
+                            //是先导课
+                            if (fsUserCourseVideo.getIsFirst()!=null&&fsUserCourseVideo.getIsFirst()==1){
+                                int count = qwWatchLogMapper.selectQwWatchLogIsFirst(fsCourseWatchLog.getQwExternalContactId());
+                                if (count>0){
+                                    continue;
+                                }
+                                day=0L;
+                                //不是先导课
+                            }else {
+                                day=1L;
+                                QwExternalContact qwExternalContact = new QwExternalContact();
+                                qwExternalContact.setId(fsCourseWatchLog.getQwExternalContactId());
+                                qwExternalContact.setFirstTime(fsCourseWatchLog.getCreateTime());
+                                qwExternalContactMapper.updateQwExternalContact(qwExternalContact);
+                            }
+                        }
+                        QwWatchLog qwWatchLog = new QwWatchLog();
+                        qwWatchLog.setExtId(fsCourseWatchLog.getQwExternalContactId());
+                        qwWatchLog.setLineTime(fsCourseWatchLog.getLineTime());
+                        qwWatchLog.setQwUserId(Long.parseLong(fsCourseWatchLog.getQwUserId()));
+                        qwWatchLog.setDay(day);
+                        qwWatchLog.setStatus(fsCourseWatchLog.getLogType()==3?0:fsCourseWatchLog.getLogType()==2?2:1);
+                        qwWatchLog.setProject(project);
+                        qwWatchLog.setCreateTime(fsCourseWatchLog.getCreateTime());
+                        QwWatchLogs.add(qwWatchLog);
+                    }
+                    if (!QwWatchLogs.isEmpty()){
+                        qwWatchLogMapper.insertQwWatchLogBatch(QwWatchLogs);
+                    }
+                }catch (Exception e){
+                    log.error("看课记录add异常:{}",course.getCourseId(),e);
+                }
+
+
+            }
+        }
+
+
+    }
+    @Override
+    public void addCourseWatchLogDay2() {
+
+        List<FsUserCourse> courses = fsUserCourseMapper.selectFsUserCourseAllCourse();
+        for (FsUserCourse course : courses) {
+            Long project = course.getProject();
+            List<FsUserCourseVideo> fsUserCourseVideos = fsUserCourseVideoMapper.selectVideoByCourseId(course.getCourseId());
+            for (FsUserCourseVideo fsUserCourseVideo : fsUserCourseVideos) {
+                ArrayList<QwWatchLog> QwWatchLogs = new ArrayList<>();
+                List<FsQwCourseWatchLogVO> watchLogs = fsCourseWatchLogMapper.selectFsCourseWatchLogByNoDayAndVoidId2(fsUserCourseVideo.getVideoId());
+                for (FsQwCourseWatchLogVO fsCourseWatchLog : watchLogs) {
+                    Date firstTime = fsCourseWatchLog.getFirstTime();
+                    Long day=1L;
+                    if (fsCourseWatchLog.getLineTime()==null){
+                        continue;
+                    }
+                    //不是第一次 看课程
+                    if (firstTime!=null){
+                        LocalDate firstLocalDate = firstTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+                        LocalDate currentDate = LocalDate.now();
+                        day = ChronoUnit.DAYS.between(firstLocalDate, currentDate);
+                        day=day-1;
+                    }else {
+                        //是先导课
+                        if (fsUserCourseVideo.getIsFirst()!=null&&fsUserCourseVideo.getIsFirst()==1){
+                            int count = qwWatchLogMapper.selectQwWatchLogIsFirst(fsCourseWatchLog.getQwExternalContactId());
+                            if (count>0){
+                                continue;
+                            }
+                            day=0L;
+                            //不是先导课
+                        }else {
+                            day=1L;
+                            QwExternalContact qwExternalContact = new QwExternalContact();
+                            qwExternalContact.setId(fsCourseWatchLog.getQwExternalContactId());
+                            qwExternalContact.setFirstTime(fsCourseWatchLog.getCreateTime());
+                            qwExternalContactMapper.updateQwExternalContact(qwExternalContact);
+                        }
+                    }
+                    QwWatchLog qwWatchLog = new QwWatchLog();
+                    qwWatchLog.setExtId(fsCourseWatchLog.getQwExternalContactId());
+                    qwWatchLog.setLineTime(fsCourseWatchLog.getLineTime());
+                    qwWatchLog.setQwUserId(Long.parseLong(fsCourseWatchLog.getQwUserId()));
+                    qwWatchLog.setDay(day);
+                    qwWatchLog.setStatus(fsCourseWatchLog.getLogType()==3?0:fsCourseWatchLog.getLogType()==2?2:1);
+                    qwWatchLog.setProject(project);
+                    qwWatchLog.setCreateTime(fsCourseWatchLog.getCreateTime());
+                    QwWatchLogs.add(qwWatchLog);
+                }
+                if (!QwWatchLogs.isEmpty()){
+                    qwWatchLogMapper.insertQwWatchLogBatch(QwWatchLogs);
+                }
+
+            }
+        }
+
+
+    }
+
+
     public Long getVideoDuration(Long videoId){
         //将视频时长也存到redis
         String videoRedisKey = "h5user:video:duration:" + videoId;

+ 11 - 7
fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java

@@ -1,8 +1,10 @@
 package com.fs.course.service.impl;
 
 import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
+import com.fs.common.utils.DictUtils;
 import com.fs.course.domain.FsUserCourse;
 import com.fs.course.domain.FsUserCourseStudy;
 import com.fs.course.domain.FsUserCourseStudyLog;
@@ -49,12 +51,7 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
     private FsUserCourseStudyMapper fsUserCourseStudyMapper;
     @Autowired
     private FsUserCourseStudyLogMapper fsUserCourseStudyLogMapper;
-    @Autowired
-    private FsUserIntegralLogsMapper fsUserIntegralLogsMapper;
-    @Autowired
-    private FsUserMapper fsUserMapper;
-    @Autowired
-    private ISysConfigService configService;
+
     /**
      * 查询课程
      *
@@ -199,7 +196,14 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
 
     @Override
     public List<FsUserCourseListPVO> selectFsUserCourseListPVO(FsUserCourse param) {
-        return fsUserCourseMapper.selectFsUserCourseListPVO(param);
+        List<FsUserCourseListPVO> fsUserCourseListPVOS = fsUserCourseMapper.selectFsUserCourseListPVO(param);
+        for (FsUserCourseListPVO fsUserCourseListPVO : fsUserCourseListPVOS){
+            if(ObjectUtils.isNotNull(fsUserCourseListPVO.getProject())){
+                String sysCourseProject = DictUtils.getDictLabel("sys_course_project", String.valueOf(fsUserCourseListPVO.getProject()));
+                fsUserCourseListPVO.setProjectName(sysCourseProject);
+            }
+        }
+        return fsUserCourseListPVOS;
     }
 
     @Override

+ 4 - 2
fs-service-system/src/main/java/com/fs/course/vo/FsCourseFinishTempListVO.java

@@ -1,7 +1,5 @@
 package com.fs.course.vo;
 
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import lombok.Data;
@@ -54,6 +52,10 @@ public class FsCourseFinishTempListVO implements Serializable
     @Excel(name = "删除标志")
     private Long isDel;
 
+    /** 是否全选销售 */
+    @Excel(name = "是否全选销售")
+    private Integer isAllCompanyUser;
+
 
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date createTime;

+ 26 - 0
fs-service-system/src/main/java/com/fs/course/vo/FsCourseOverVO.java

@@ -0,0 +1,26 @@
+package com.fs.course.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class FsCourseOverVO {
+
+
+    @Excel(name = "企微客户")
+    private String qwUserName;
+    @Excel(name = "企业微信员工名称")
+    private String externalUserName;
+
+    @Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date createTime;
+
+    @Excel(name = "进线时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date userCreateTime;
+
+}

+ 7 - 0
fs-service-system/src/main/java/com/fs/course/vo/FsCourseUserStatisticsListVO.java

@@ -0,0 +1,7 @@
+package com.fs.course.vo;
+
+import lombok.Data;
+
+@Data
+public class FsCourseUserStatisticsListVO {
+}

+ 12 - 1
fs-service-system/src/main/java/com/fs/course/vo/FsCourseWatchLogListVO.java

@@ -24,7 +24,10 @@ public class FsCourseWatchLogListVO extends BaseEntity
     @Excel(name = "会员id")
     private Long userId;
 
+    @Excel(name = "小程序昵称")
     private String fsNickName;
+
+    @Excel(name = "小程序头像")
     private String fsAvatar;
 
     @Excel(name = "课程名称")
@@ -58,28 +61,36 @@ public class FsCourseWatchLogListVO extends BaseEntity
     @Excel(name = "所属团队")
     private String companyName;
 
+    @Excel(name = "所属团队编号")
+    private String companyId;
+
 
     @Excel(name = "发送方式")
     private Integer sendType; //归属发送方式:1 个微  2 企微
 
 
     /** 创建时间 */
-    @Excel(name = "创建时间")
+    @Excel(name = "创建时间",dateFormat = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date createTime;
 
+    @Excel(name = "更新时间",dateFormat = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date updateTime;
 
+    @Excel(name = "最后心跳时间",dateFormat = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date lastHeartbeatTime;
 
+    @Excel(name = "完课时间",dateFormat = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date finishTime;
 
+    @Excel(name = "营期时间",dateFormat = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd")
     private Date campPeriodTime;
 
+    @Excel(name = "外部联系人名称")
     private String externalUserName; //外部联系人名称
 
 }

+ 20 - 0
fs-service-system/src/main/java/com/fs/course/vo/FsCourseWatchLogTaskVO.java

@@ -0,0 +1,20 @@
+package com.fs.course.vo;
+
+import lombok.Data;
+
+@Data
+public class FsCourseWatchLogTaskVO {
+
+
+    private Integer logType;
+
+    private Long qwExternalContactId;
+
+    private Long companyUserId;
+
+    private Long companyId;
+
+    private Integer level;
+
+    private Long qwUserId;
+}

+ 83 - 0
fs-service-system/src/main/java/com/fs/course/vo/FsQwCourseWatchLogVO.java

@@ -0,0 +1,83 @@
+package com.fs.course.vo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+
+@Data
+public class FsQwCourseWatchLogVO {
+    /** 日志Id */
+    @TableId(type = IdType.AUTO)
+    private Long logId;
+
+    /** 用户id */
+    @Excel(name = "用户id")
+    private Long userId;
+
+    /** 小节id */
+    @Excel(name = "小节id")
+    private Long videoId;
+
+    /** 记录类型 1看课中 2完课 3待看课 4看课中断 */
+    @Excel(name = "记录类型 1看课中 2完课 3待看课 4看课中断")
+    private Integer logType;
+
+    /** 企微外部联系人id */
+    @Excel(name = "企微外部联系人id")
+    private Long qwExternalContactId;
+
+    /** 播放时长 */
+    @Excel(name = "播放时长")
+    private Long duration;
+
+    /** 分享人企微userId */
+    @Excel(name = "分享人企微userId")
+    private String qwUserId;
+
+    /** 销售id */
+    @Excel(name = "销售id")
+    private Long companyUserId;
+
+    /** 公司id */
+    @Excel(name = "公司id")
+    private Long companyId;
+
+    /** 课程id */
+    @Excel(name = "课程id")
+    private Long courseId;
+
+    private Integer sendType; //归属发送方式:1 个微  2 企微
+
+    private Integer rewardType;//发放奖励类型
+
+
+    private LocalDateTime lastHeartbeatTime;//心跳时间
+
+
+    private String sopId; //sop任务id
+
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date finishTime; //完课时间
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date campPeriodTime; //sop任务中营期
+
+    private Integer sendFinishMsg;//是否发送完课消息
+
+    private Long project;
+    private Long day;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date firstTime; //完课时间
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime; //完课时间
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date lineTime; //完课时间
+
+}

+ 42 - 0
fs-service-system/src/main/java/com/fs/course/vo/FsSopMyCourseLinkVO.java

@@ -0,0 +1,42 @@
+package com.fs.course.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+
+@Data
+public class FsSopMyCourseLinkVO  {
+
+    private static final long serialVersionUID = 1L;
+
+    /** 主键Id */
+    private Long id;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private String createTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private String updateTime;
+
+
+    /** 企微员工昵称 */
+    private String qwUserName;
+
+    /** 课程标题 */
+    @Excel(name = "课程标题")
+    private String courseName;
+
+    /** 课程封面 */
+    private String courseUrl;
+
+    /** 课节描述 */
+    private String title;
+
+
+    /** 课节跳转地址 */
+    private String appRealLink;
+
+    private Integer isRead;
+
+}

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

@@ -43,6 +43,9 @@ public class FsUserCourseListPVO extends BaseEntity
     private Integer isShow;
 
     private Integer isPrivate;
+    private Integer project;
+
+    private String projectName;
 
 
 }

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

@@ -81,4 +81,5 @@ public class FsUserCourseVideoQVO extends BaseEntity {
     private List<FsCourseQuestionBank> questionBankList;
 
     private String packageJson;
+    private Integer isFirst;
 }

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác