Pārlūkot izejas kodu

Merge remote-tracking branch 'origin/master'

zx 4 dienas atpakaļ
vecāks
revīzija
7c1d800372
86 mainītis faili ar 1901 papildinājumiem un 142 dzēšanām
  1. 28 2
      fs-admin/src/main/java/com/fs/qw/controller/SopUserLogsController.java
  2. 3 1
      fs-company/src/main/java/com/fs/company/controller/baidu/Conversion.java
  3. 30 12
      fs-company/src/main/java/com/fs/company/controller/qw/SopUserLogsController.java
  4. 0 6
      fs-qw-api-msg/src/main/java/com/fs/app/controller/imgTest.java
  5. 1 1
      fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java
  6. 161 0
      fs-qwhook-sop/src/main/java/com/fs/app/controller/ApisFsUserCourseVideoController.java
  7. 41 0
      fs-qwhook-sop/src/main/java/com/fs/app/controller/ApisQwStatisticsController.java
  8. 101 0
      fs-qwhook-sop/src/main/java/com/fs/app/controller/ApisQwUserController.java
  9. 75 0
      fs-qwhook-sop/src/main/java/com/fs/app/controller/ApisQwWorkTaskController.java
  10. 100 4
      fs-qwhook-sop/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java
  11. 11 0
      fs-service/src/main/java/com/fs/course/dto/WatchLogDTO.java
  12. 2 2
      fs-service/src/main/java/com/fs/course/mapper/FsCourseFinishTempMapper.java
  13. 6 0
      fs-service/src/main/java/com/fs/course/mapper/FsCourseWatchCommentMapper.java
  14. 58 0
      fs-service/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java
  15. 11 0
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseMapper.java
  16. 13 0
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java
  17. 7 0
      fs-service/src/main/java/com/fs/course/mapper/FsVideoResourceMapper.java
  18. 28 0
      fs-service/src/main/java/com/fs/course/param/FsCourseLinkMiniParam.java
  19. 38 0
      fs-service/src/main/java/com/fs/course/param/FsCourseListBySidebarParam.java
  20. 5 2
      fs-service/src/main/java/com/fs/course/param/FsCourseWatchCommentListParam.java
  21. 2 2
      fs-service/src/main/java/com/fs/course/service/IFsCourseWatchCommentService.java
  22. 3 4
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseService.java
  23. 6 0
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseVideoService.java
  24. 8 8
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseFinishTempParentServiceImpl.java
  25. 5 1
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseWatchCommentServiceImpl.java
  26. 6 4
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java
  27. 195 1
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  28. 17 12
      fs-service/src/main/java/com/fs/course/service/impl/TencentCloudCosService.java
  29. 26 0
      fs-service/src/main/java/com/fs/course/vo/FsCourseListBySidebarVO.java
  30. 37 0
      fs-service/src/main/java/com/fs/course/vo/FsCourseVideoListBySidebarVO.java
  31. 9 5
      fs-service/src/main/java/com/fs/event/WeixinTemplateService.java
  32. 19 0
      fs-service/src/main/java/com/fs/his/config/WxMiniappTempConfig.java
  33. 33 0
      fs-service/src/main/java/com/fs/his/dto/PackageOrderDTO.java
  34. 3 0
      fs-service/src/main/java/com/fs/his/mapper/FsPackageOrderMapper.java
  35. 3 0
      fs-service/src/main/java/com/fs/his/service/IFsPackageOrderService.java
  36. 1 1
      fs-service/src/main/java/com/fs/his/service/impl/FsDoctorServiceImpl.java
  37. 12 8
      fs-service/src/main/java/com/fs/his/service/impl/FsInquiryOrderServiceImpl.java
  38. 6 0
      fs-service/src/main/java/com/fs/his/service/impl/FsPackageOrderServiceImpl.java
  39. 4 4
      fs-service/src/main/java/com/fs/his/service/impl/FsPackageServiceImpl.java
  40. 26 3
      fs-service/src/main/java/com/fs/qw/domain/QwWorkTask.java
  41. 3 0
      fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactInfoMapper.java
  42. 9 9
      fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactMapper.java
  43. 17 8
      fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java
  44. 17 0
      fs-service/src/main/java/com/fs/qw/param/ExternalContactDetailsParam.java
  45. 3 0
      fs-service/src/main/java/com/fs/qw/param/QwExternalContactVOTime.java
  46. 33 0
      fs-service/src/main/java/com/fs/qw/param/SelectQwWorkTaskListParam.java
  47. 3 1
      fs-service/src/main/java/com/fs/qw/service/IQwExternalContactInfoService.java
  48. 17 0
      fs-service/src/main/java/com/fs/qw/service/IQwExternalContactService.java
  49. 3 0
      fs-service/src/main/java/com/fs/qw/service/IQwUserService.java
  50. 5 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactInfoServiceImpl.java
  51. 29 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java
  52. 54 4
      fs-service/src/main/java/com/fs/qw/service/impl/QwUserServiceImpl.java
  53. 34 0
      fs-service/src/main/java/com/fs/qw/vo/ExternalContactDetailsVO.java
  54. 24 0
      fs-service/src/main/java/com/fs/qw/vo/QwExternalListByHeavyVO.java
  55. 1 0
      fs-service/src/main/java/com/fs/sop/domain/SopUserLogsInfo.java
  56. 5 1
      fs-service/src/main/java/com/fs/sop/mapper/SopUserLogsInfoMapper.java
  57. 3 0
      fs-service/src/main/java/com/fs/sop/mapper/SopUserLogsMapper.java
  58. 2 0
      fs-service/src/main/java/com/fs/sop/service/ISopUserLogsService.java
  59. 20 8
      fs-service/src/main/java/com/fs/sop/service/impl/SopUserLogsServiceImpl.java
  60. 10 0
      fs-service/src/main/java/com/fs/statis/service/IStatisticsService.java
  61. 23 0
      fs-service/src/main/java/com/fs/statis/service/impl/StatisticsServiceImpl.java
  62. 25 0
      fs-service/src/main/java/com/fs/statistics/dto/WatchCourseStatisticsDTO.java
  63. 9 0
      fs-service/src/main/java/com/fs/statistics/mapper/StatisticsServiceMapper.java
  64. 30 0
      fs-service/src/main/java/com/fs/statistics/param/WatchCourseStatisticsParam.java
  65. 18 0
      fs-service/src/main/java/com/fs/statistics/service/IStatisticsService.java
  66. 40 0
      fs-service/src/main/java/com/fs/statistics/service/impl/StatisticsServiceImpl.java
  67. 6 1
      fs-service/src/main/resources/application-config-myhk.yml
  68. 4 4
      fs-service/src/main/resources/application-druid-myhk.yml
  69. 54 0
      fs-service/src/main/resources/db/20250530-初始化表结构.sql
  70. 1 1
      fs-service/src/main/resources/mapper/course/FsCourseQuestionBankMapper.xml
  71. 18 0
      fs-service/src/main/resources/mapper/course/FsCourseWatchCommentMapper.xml
  72. 1 1
      fs-service/src/main/resources/mapper/course/FsVideoResourceMapper.xml
  73. 8 0
      fs-service/src/main/resources/mapper/his/FsPackageOrderMapper.xml
  74. 43 0
      fs-service/src/main/resources/mapper/qw/QwExternalContactInfoMapper.xml
  75. 106 0
      fs-service/src/main/resources/mapper/qw/QwExternalContactMapper.xml
  76. 12 0
      fs-service/src/main/resources/mapper/qw/QwUserMapper.xml
  77. 1 1
      fs-service/src/main/resources/mapper/qw/QwWatchLogMapper.xml
  78. 5 1
      fs-service/src/main/resources/mapper/sop/QwSopMapper.xml
  79. 9 0
      fs-service/src/main/resources/mapper/sop/SopUserLogsInfoMapper.xml
  80. 7 0
      fs-service/src/main/resources/mapper/sop/SopUserLogsMapper.xml
  81. 0 2
      fs-user-app/src/main/java/com/fs/app/config/WebSocketConfig.java
  82. 6 15
      fs-user-app/src/main/java/com/fs/app/controller/CourseController.java
  83. 3 1
      fs-user-app/src/main/java/com/fs/app/controller/PackageController.java
  84. 36 0
      fs-user-app/src/main/java/com/fs/app/controller/PackageOrderController.java
  85. 1 1
      fs-user-app/src/main/java/com/fs/app/utils/JwtUtils.java
  86. 3 0
      fs-user-app/src/main/java/com/fs/websocket/bean/SendMsgVO.java

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

@@ -4,7 +4,10 @@ package com.fs.qw.controller;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.page.TableDataInfo;
+import com.fs.qw.mapper.QwUserMapper;
 import com.fs.qw.param.SopUserLogsVO;
+import com.fs.sop.domain.QwSop;
+import com.fs.sop.mapper.QwSopMapper;
 import com.fs.sop.params.SopUserLogsParam;
 import com.fs.sop.service.ISopUserLogsService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -29,14 +32,37 @@ public class SopUserLogsController extends BaseController
     @Autowired
     private ISopUserLogsService sopUserLogsService;
 
+    @Autowired
+    private QwSopMapper sopMapper;
+
+    @Autowired
+    private QwUserMapper qwUserMapper;
+
+
     /**
      * 查询sopUserLogs列表
      */
     @GetMapping("/list")
     public TableDataInfo list(SopUserLogsParam sopUserLogs)
     {
-        startPage();
-        List<SopUserLogsVO> list = sopUserLogsService.selectSopUserLogsList(sopUserLogs);
+
+        QwSop qwSop = sopMapper.selectQwSopById(sopUserLogs.getSopId());
+        Integer filterMode = qwSop.getFilterMode();
+
+        List<SopUserLogsVO> list=null;
+        if(filterMode == null || filterMode == 1){
+            startPage();
+            list = sopUserLogsService.selectSopUserLogsList(sopUserLogs);
+        }else {
+            startPage();
+            list = sopUserLogsService.selectSopUserLogsGroupListByParam(sopUserLogs);
+        }
+
+
+        list.forEach(item->{
+            item.setQwUserName(qwUserMapper.selectQwUserByQwUserIdAndCorpId(item.getQwUserId(), item.getCorpId()));
+        });
+
         return getDataTable(list);
     }
 

+ 3 - 1
fs-company/src/main/java/com/fs/company/controller/baidu/Conversion.java

@@ -17,7 +17,9 @@ import java.util.List;
 public class Conversion {
     @Autowired
     private BaiduApiService conversionDataService;
-    @Value("${baidu.token}")
+
+//    @Value("${baidu.token}")
+    @Value("12345649")
     private String token;
     /**
      * 发送单个转换数据

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

@@ -11,13 +11,16 @@ import com.fs.framework.service.TokenService;
 import com.fs.qw.mapper.QwUserMapper;
 import com.fs.qw.param.SopUserLogsVO;
 import com.fs.qw.service.IQwUserService;
+import com.fs.sop.domain.QwSop;
 import com.fs.sop.domain.SopUserLogs;
+import com.fs.sop.mapper.QwSopMapper;
 import com.fs.sop.params.SopUserLogsParam;
 import com.fs.sop.service.ISopUserLogsService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -38,6 +41,9 @@ public class SopUserLogsController extends BaseController
     @Autowired
     private QwUserMapper qwUserMapper;
 
+    @Autowired
+    private QwSopMapper sopMapper;
+
     /**
      * 查询sopUserLogs列表
      */
@@ -45,12 +51,24 @@ public class SopUserLogsController extends BaseController
     @GetMapping("/list")
     public TableDataInfo list(SopUserLogsParam sopUserLogs)
     {
-        startPage();
         sopUserLogs.setStatus(1);
-        List<SopUserLogsVO> list = sopUserLogsService.selectSopUserLogsList(sopUserLogs);
+
+        QwSop qwSop = sopMapper.selectQwSopById(sopUserLogs.getSopId());
+        Integer filterMode = qwSop.getFilterMode();
+
+        List<SopUserLogsVO> list=null;
+        if(filterMode == null || filterMode == 1){
+            startPage();
+             list = sopUserLogsService.selectSopUserLogsList(sopUserLogs);
+        }else {
+            startPage();
+            list = sopUserLogsService.selectSopUserLogsGroupListByParam(sopUserLogs);
+        }
+
         list.forEach(item->{
             item.setQwUserName(qwUserMapper.selectQwUserByQwUserIdAndCorpId(item.getQwUserId(), item.getCorpId()));
         });
+
         return getDataTable(list);
     }
 
@@ -89,14 +107,14 @@ public class SopUserLogsController extends BaseController
     }
 
 
-//    /**
-//     * 删除sopUserLogs
-//     */
-//    @PreAuthorize("@ss.hasPermi('qwSop:sopUserLogs:remove')")
-//    @Log(title = "sopUserLogs", businessType = BusinessType.DELETE)
-//	@DeleteMapping("/{ids}")
-//    public AjaxResult remove(@PathVariable Long[] ids)
-//    {
-//        return toAjax(sopUserLogsService.deleteSopUserLogsByIds(ids));
-//    }
+    /**
+     * 删除sopUserLogs
+     */
+    @PreAuthorize("@ss.hasPermi('qwSop:sopUserLogs:remove')")
+    @Log(title = "删除sopUserLogs", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable String[] ids)
+    {
+        return toAjax(sopUserLogsService.deleteSopUserLogsByIds(ids));
+    }
 }

+ 0 - 6
fs-qw-api-msg/src/main/java/com/fs/app/controller/imgTest.java

@@ -1,11 +1,5 @@
 package com.fs.app.controller;
 
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
-import com.fs.app.config.ConfigProperties;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;

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

@@ -1733,7 +1733,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
         sopLogs.setSendType(3);
         sopLogs.setSendStatus(3L);
         sopLogs.setReceivingStatus(0L);
-        sopLogs.setSort(4);
+        sopLogs.setSort(40000000);
         sopLogs.setCompanyId(finishLog.getCompanyId());
         sopLogs.setSopId(finishLog.getSopId());
         sopLogs.setExternalUserId(externalContact.getExternalUserId());

+ 161 - 0
fs-qwhook-sop/src/main/java/com/fs/app/controller/ApisFsUserCourseVideoController.java

@@ -0,0 +1,161 @@
+package com.fs.app.controller;
+
+import com.fs.common.annotation.RepeatSubmit;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.course.param.FsCourseLinkMiniParam;
+import com.fs.course.param.newfs.UserCourseVideoPageParam;
+import com.fs.course.service.IFsUserCoursePeriodService;
+import com.fs.course.service.IFsUserCourseService;
+import com.fs.course.service.IFsUserCourseVideoService;
+import com.fs.course.param.FsCourseListBySidebarParam;
+import com.fs.course.vo.FsCourseListBySidebarVO;
+import com.fs.course.vo.FsCourseVideoListBySidebarVO;
+import com.fs.course.vo.newfs.FsUserCourseVideoPageListVO;
+import com.fs.qw.domain.QwUser;
+import com.fs.qw.service.IQwExternalContactService;
+import com.fs.voice.utils.StringUtil;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+
+@Api("课程库相关接口")
+@RestController
+@RequestMapping("/apis/app/fs/course")
+@Slf4j
+public class ApisFsUserCourseVideoController extends BaseController {
+
+    @Autowired
+    private IFsUserCourseVideoService fsUserCourseVideoService;
+
+    @Autowired
+    private IFsUserCourseService fsUserCourseService;
+
+    @Autowired
+    private IFsUserCoursePeriodService fsUserCoursePeriodService;
+
+    @Autowired
+    private IQwExternalContactService qwExternalContactService;
+
+
+
+    @PostMapping("/pageList")
+    @ApiOperation("课程分页列表")
+    public R list(@RequestBody UserCourseVideoPageParam param) {
+
+        QwUser qwUser = qwExternalContactService.getQwUserByRedis(param.getCorpId().trim(), param.getQwUserId().trim());
+
+        if (qwUser == null || qwUser.getCompanyId() == null) {
+            return R.error("员工未绑定 销售公司 或 未获取到员工信息,请重试!");
+        }
+        param.setCompanyId(qwUser.getCompanyId());
+
+
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        List<FsUserCourseVideoPageListVO> list = fsUserCourseVideoService.pageListCourseVideo(param);
+        PageInfo<FsUserCourseVideoPageListVO> pageInfo = new PageInfo<>(list);
+        return R.ok().put("data",pageInfo);
+    }
+
+
+    @ApiOperation("课程视频详情")
+    @GetMapping(value = "/videoDetails")
+    public R getVideoDetails(Long videoId) {
+        return R.ok().put("data",fsUserCourseVideoService.getVideoDetails(videoId));
+    }
+
+
+    @PostMapping("/getFsCourseListBySidebar")
+    @ApiOperation("获取视频课程下拉列表 侧边栏")
+    public R getFsCourseListBySidebar(@RequestBody FsCourseListBySidebarParam param) {
+
+        QwUser qwUser = qwExternalContactService.getQwUserByRedis(param.getCorpId().trim(),param.getQwUserId().trim());
+
+        if (qwUser == null || qwUser.getCompanyId() == null) {
+            return R.error("员工未绑定 销售公司 或 未获取到员工信息,请重试!");
+        }
+        param.setCompanyId(qwUser.getCompanyId());
+
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        List<FsCourseListBySidebarVO> fsCourseListBySidebar = fsUserCourseService.getFsCourseListBySidebar(param);
+        PageInfo<FsCourseListBySidebarVO> result = new PageInfo<>(fsCourseListBySidebar);
+        return R.ok().put("data", result);
+    }
+
+    @PostMapping("/getFsCourseVideoListBySidebar")
+    @ApiOperation("获取视频课程的课节下拉列表 侧边栏")
+    public R getFsCourseVideoListBySidebar(@RequestBody FsCourseListBySidebarParam param) {
+
+        if (param.getCourseId()==null){
+            return R.error("课程id不能为空");
+        }
+
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        List<FsCourseVideoListBySidebarVO> videoListBySidebar = fsUserCourseVideoService.getFsCourseVideoListBySidebar(param);
+        PageInfo<FsCourseVideoListBySidebarVO> result = new PageInfo<>(videoListBySidebar);
+        return R.ok().put("data", result);
+    }
+
+    /**
+    * 创建 发客户小程序
+    */
+
+    @RepeatSubmit
+    @PostMapping("/createMiniLink")
+    public R createMiniLink(@RequestBody FsCourseLinkMiniParam param) {
+
+        if (param.getCourseId()==null){
+            return R.error("课程id不能为空");
+        }
+        if (param.getVideoId()==null){
+            return R.error("视频id不能为空");
+        }
+        if (StringUtil.strIsNullOrEmpty(param.getQwUserId())){
+            return R.error("用户id不能为空");
+        }
+        if (StringUtil.strIsNullOrEmpty(param.getCorpId())){
+            return R.error("企业id不能为空");
+        }
+
+        if (param.getExternalUserId()==null){
+            return R.error("客户id不能为空");
+        }
+
+        return fsUserCourseVideoService.createMiniLink(param);
+    }
+
+    /**
+    * 创建发卡片
+    */
+    @RepeatSubmit
+    @PostMapping("/createCartLink")
+    public R createCartLink(@RequestBody  FsCourseLinkMiniParam param) {
+
+        if (param.getCourseId()==null){
+            return R.error("课程id不能为空");
+        }
+        if (param.getVideoId()==null){
+            return R.error("视频id不能为空");
+        }
+        if (StringUtil.strIsNullOrEmpty(param.getQwUserId())){
+            return R.error("用户id不能为空");
+        }
+        if (StringUtil.strIsNullOrEmpty(param.getCorpId())){
+            return R.error("企业id不能为空");
+        }
+
+        if (param.getExternalUserId()==null){
+            return R.error("客户id不能为空");
+        }
+
+        return fsUserCourseVideoService.createCartLink(param);
+    }
+
+}

+ 41 - 0
fs-qwhook-sop/src/main/java/com/fs/app/controller/ApisQwStatisticsController.java

@@ -0,0 +1,41 @@
+package com.fs.app.controller;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.common.exception.CustomException;
+
+import com.fs.statis.service.IStatisticsService;
+import com.fs.statistics.dto.WatchCourseStatisticsDTO;
+import com.fs.statistics.param.WatchCourseStatisticsParam;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 企微统计数据
+ */
+@RestController
+@RequestMapping("/apis/app/qw/statistics")
+public class ApisQwStatisticsController extends BaseController {
+
+    @Autowired
+    private IStatisticsService statisticsService;
+
+
+//    @Login
+    @PostMapping("/course/watch")
+    @ApiOperation("会员看课详情")
+    public R queryCourseWatchStatistics(@RequestBody WatchCourseStatisticsParam param) {
+        if(param.getQwExternalContactId() == null) {
+            throw new CustomException("外部联系人id为空!");
+        }
+
+        WatchCourseStatisticsDTO watchCourseStatisticsDTO = statisticsService.queryWatchCourse(param);
+
+        return R.ok().put("data",watchCourseStatisticsDTO);
+    }
+
+}

+ 101 - 0
fs-qwhook-sop/src/main/java/com/fs/app/controller/ApisQwUserController.java

@@ -0,0 +1,101 @@
+package com.fs.app.controller;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.common.exception.CustomException;
+import com.fs.course.param.FsCourseListBySidebarParam;
+import com.fs.qw.domain.QwExternalContactInfo;
+import com.fs.qw.domain.QwUser;
+import com.fs.qw.param.ExternalContactDetailsParam;
+import com.fs.qw.service.IQwExternalContactInfoService;
+import com.fs.qw.service.IQwExternalContactService;
+import com.fs.qw.vo.ExternalContactDetailsVO;
+import com.fs.qw.vo.QwExternalListByHeavyVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@Api(tags = "企微会员相关接口")
+@RestController
+@RequestMapping("/apis/app/qw/user")
+public class ApisQwUserController extends BaseController {
+
+    @Autowired
+    private IQwExternalContactService qwExternalContactService;
+
+    @Autowired
+    private IQwExternalContactInfoService qwExternalContactInfoService;
+
+    @GetMapping("/details")
+    @ApiOperation("会员看课详情")
+    public R getUserDetails(@ApiParam(value = "外部联系人id", required = true) @RequestParam Long contactId,
+                            @ApiParam(value = "时间tab,不传表示查询全部,分别是:今天、昨天、前天、近七天", required = true) String dateTag) {
+        ExternalContactDetailsParam param = new ExternalContactDetailsParam();
+        param.setUserId(getUserId());
+        param.setContactId(contactId);
+        param.setDateTag(dateTag);
+        ExternalContactDetailsVO userDetails = qwExternalContactService.getUserDetails(param);
+        Map<String, Object> map = new HashMap<>();
+        map.put("userDetails", userDetails);
+        return R.ok(map);
+    }
+
+
+    @GetMapping("/getQwUserInfo")
+    @ApiOperation("获取企微用户信息")
+    public R getQwUserInfo(@RequestParam(value = "qwExternalContactId",required = false) Long qwExternalContactId){
+        if(qwExternalContactId == null) {
+            throw new CustomException("企微外部联系人id不能为空!");
+        }
+//        QwExternalContact qwExternalContact = qwExternalContactService.selectQwExternalContactById(qwExternalContactId);
+        QwExternalContactInfo contactInfo = qwExternalContactInfoService.selectQwExternalContactInfoByExternalContactId(qwExternalContactId);
+        if (contactInfo==null){
+
+            contactInfo = new QwExternalContactInfo();
+            contactInfo.setExternalContactId(qwExternalContactId);
+            qwExternalContactInfoService.insertQwExternalContactInfo(contactInfo);
+
+        }
+
+//        return R.ok().put("data",qwExternalContact).put("moreInfo",contactInfo);
+        return R.ok().put("moreInfo",contactInfo);
+    }
+
+    @PostMapping("/updateQwUserInfo")
+    @ApiOperation("更新企微用户信息")
+    public R updateQwUserInfo(@RequestBody QwExternalContactInfo qwExternalContactInfo){
+        if(qwExternalContactInfo.getExternalContactId() == null) {
+            throw new CustomException("企微外部联系人id不能为空!");
+        }
+        qwExternalContactInfoService.updateQwExternalContactInfoByExternalContactId(qwExternalContactInfo);
+        return R.ok();
+    }
+
+    /**
+    * 获取客户是否加了其他的销售(重粉)
+    */
+    @PostMapping("/getQwExternalListByHeavy")
+    @ApiOperation("获取客户是否加了其他的销售")
+    public R getQwExternalListByHeavy(@RequestBody FsCourseListBySidebarParam param){
+        QwUser qwUser = qwExternalContactService.getQwUserByRedis(param.getCorpId().trim(),param.getQwUserId().trim());
+
+        if (qwUser == null) {
+            return R.error("未查询到企业微信账号信息!请重试");
+        }
+
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        List<QwExternalListByHeavyVO> qwExternalListByHeavy = qwExternalContactService.getQwExternalListByHeavy(param);
+        PageInfo<QwExternalListByHeavyVO> result = new PageInfo<>(qwExternalListByHeavy);
+        return R.ok().put("data", result);
+    }
+}

+ 75 - 0
fs-qwhook-sop/src/main/java/com/fs/app/controller/ApisQwWorkTaskController.java

@@ -0,0 +1,75 @@
+package com.fs.app.controller;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.company.service.ICompanyUserService;
+import com.fs.course.mapper.FsCourseWatchLogMapper;
+import com.fs.qw.domain.QwUser;
+import com.fs.qw.domain.QwWorkTask;
+import com.fs.qw.param.SelectQwWorkTaskListParam;
+import com.fs.qw.service.IQwExternalContactService;
+import com.fs.qw.service.IQwUserService;
+import com.fs.qw.service.IQwWorkTaskService;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@Slf4j
+@Api(tags = "企微任务看板接口")
+@RestController
+@RequestMapping("/apis/app/qw/workTask")
+@AllArgsConstructor
+public class ApisQwWorkTaskController extends BaseController {
+
+    private final IQwWorkTaskService qwWorkTaskService;
+    private final IQwUserService qwUserService;
+
+    @Autowired
+    ICompanyUserService companyUserService;
+
+    @Autowired
+    private FsCourseWatchLogMapper fsCourseWatchLogMapper;
+
+    @Autowired
+    private IQwExternalContactService qwExternalContactService;
+
+//    @Login
+    @PostMapping("/list")
+    @ApiOperation("企微任务看板列表")
+    public R selectQwWorkTaskList(@RequestBody SelectQwWorkTaskListParam param) {
+
+        log.info("企微任务看板列表: {}",param);
+
+
+        QwUser qwUser = qwExternalContactService.getQwUserByRedis(param.getCorpId().trim(), param.getQwUserId().trim());
+
+        if (qwUser == null || qwUser.getCompanyId() == null) {
+            return R.error("员工未绑定 销售公司 或 未获取到员工信息,请重试!");
+        }
+
+        param.setUserId(qwUser.getId());
+
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        List<QwWorkTask> list = qwUserService.selectQwWorkTaskList(param);
+        for (QwWorkTask qwWorkTask : list) {
+            List<Integer> logs = fsCourseWatchLogMapper.selectFsCourseWatchLog7DayByExtId(qwWorkTask.getExtId());
+            qwWorkTask.setLogs(logs);
+        }
+
+        PageInfo<QwWorkTask> pageInfo = new PageInfo<>(list);
+        return R.ok().put("data",pageInfo);
+    }
+
+
+
+}

+ 100 - 4
fs-qwhook-sop/src/main/java/com/fs/app/controller/FsUserCourseVideoController.java

@@ -1,31 +1,36 @@
 package com.fs.app.controller;
 
 import com.alibaba.fastjson.JSONObject;
+import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.course.domain.FsUserCourse;
 import com.fs.course.param.FsCourseLinkCreateParam;
+import com.fs.course.param.FsCourseLinkMiniParam;
 import com.fs.course.param.FsCourseLinkRoomParam;
 import com.fs.course.param.newfs.FsUserCourseListParam;
 import com.fs.course.param.newfs.UserCourseVideoPageParam;
 import com.fs.course.service.IFsCourseLinkService;
 import com.fs.course.service.IFsUserCourseService;
 import com.fs.course.service.IFsUserCourseVideoService;
+import com.fs.course.param.FsCourseListBySidebarParam;
+import com.fs.course.vo.FsCourseListBySidebarVO;
+import com.fs.course.vo.FsCourseVideoListBySidebarVO;
 import com.fs.course.vo.newfs.FsUserCourseListVO;
 import com.fs.course.vo.newfs.FsUserCourseVideoDetailsVO;
 import com.fs.course.vo.newfs.FsUserCourseVideoPageListVO;
 import com.fs.course.vo.newfs.FsUserVideoListVO;
 import com.fs.qw.domain.QwUser;
+import com.fs.qw.service.IQwExternalContactService;
 import com.fs.qw.service.IQwUserService;
+import com.fs.voice.utils.StringUtil;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
 
@@ -45,10 +50,15 @@ public class FsUserCourseVideoController {
     @Autowired
     private IQwUserService qwUserService;
 
+    @Autowired
+    private IQwExternalContactService qwExternalContactService;
+
     @GetMapping("/pageList")
     @ApiOperation("课程分页列表")
     public ResponseResult<PageInfo<FsUserCourseVideoPageListVO>> list(UserCourseVideoPageParam param) {
-        QwUser qwUser = qwUserService.getByQwUserIdAndCorId(param.getQwUserId(), param.getCorpId());
+
+        QwUser qwUser = qwExternalContactService.getQwUserByRedis(param.getCorpId().trim(), param.getQwUserId().trim());
+
         if (qwUser==null||qwUser.getCompanyId()==null){
             return ResponseResult.fail(500,"无权限");
         }
@@ -93,6 +103,38 @@ public class FsUserCourseVideoController {
         return ResponseResult.ok(result);
     }
 
+
+    @PostMapping("/getFsCourseListBySidebar")
+    @ApiOperation("获取视频课程下拉列表 侧边栏")
+    public R getFsCourseListBySidebar(@RequestBody FsCourseListBySidebarParam param) {
+
+        QwUser qwUser = qwExternalContactService.getQwUserByRedis(param.getCorpId().trim(),param.getQwUserId().trim());
+
+        if (qwUser == null || qwUser.getCompanyId() == null) {
+            return R.error("员工未绑定 销售公司 或 未获取到员工信息,请重试!");
+        }
+        param.setCompanyId(qwUser.getCompanyId());
+
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        List<FsCourseListBySidebarVO> fsCourseListBySidebar = fsUserCourseService.getFsCourseListBySidebar(param);
+        PageInfo<FsCourseListBySidebarVO> result = new PageInfo<>(fsCourseListBySidebar);
+        return R.ok().put("data", result);
+    }
+
+    @PostMapping("/getFsCourseVideoListBySidebar")
+    @ApiOperation("获取视频课程的课节下拉列表 侧边栏")
+    public R getFsCourseVideoListBySidebar(@RequestBody FsCourseListBySidebarParam param) {
+
+        if (param.getCourseId()==null){
+            return R.error("课程id不能为空");
+        }
+
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        List<FsCourseVideoListBySidebarVO> videoListBySidebar = fsUserCourseVideoService.getFsCourseVideoListBySidebar(param);
+        PageInfo<FsCourseVideoListBySidebarVO> result = new PageInfo<>(videoListBySidebar);
+        return R.ok().put("data", result);
+    }
+
     @Autowired
     private IFsCourseLinkService courseLinkService;
 
@@ -127,4 +169,58 @@ public class FsUserCourseVideoController {
         return R.ok().put("news",news);
     }
 
+    /**
+     * 创建 发客户小程序
+     */
+
+    @RepeatSubmit
+    @PostMapping("/createMiniLink")
+    public R createMiniLink(@RequestBody FsCourseLinkMiniParam param) {
+
+        if (param.getCourseId()==null){
+            return R.error("课程id不能为空");
+        }
+        if (param.getVideoId()==null){
+            return R.error("视频id不能为空");
+        }
+        if (StringUtil.strIsNullOrEmpty(param.getQwUserId())){
+            return R.error("用户id不能为空");
+        }
+        if (StringUtil.strIsNullOrEmpty(param.getCorpId())){
+            return R.error("企业id不能为空");
+        }
+
+        if (param.getExternalUserId()==null){
+            return R.error("客户id不能为空");
+        }
+
+        return fsUserCourseVideoService.createMiniLink(param);
+    }
+
+    /**
+     * 创建发卡片
+     */
+    @RepeatSubmit
+    @PostMapping("/createCartLink")
+    public R createCartLink(@RequestBody  FsCourseLinkMiniParam param) {
+
+        if (param.getCourseId()==null){
+            return R.error("课程id不能为空");
+        }
+        if (param.getVideoId()==null){
+            return R.error("视频id不能为空");
+        }
+        if (StringUtil.strIsNullOrEmpty(param.getQwUserId())){
+            return R.error("用户id不能为空");
+        }
+        if (StringUtil.strIsNullOrEmpty(param.getCorpId())){
+            return R.error("企业id不能为空");
+        }
+
+        if (param.getExternalUserId()==null){
+            return R.error("客户id不能为空");
+        }
+
+        return fsUserCourseVideoService.createCartLink(param);
+    }
 }

+ 11 - 0
fs-service/src/main/java/com/fs/course/dto/WatchLogDTO.java

@@ -0,0 +1,11 @@
+package com.fs.course.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class WatchLogDTO implements Serializable {
+    private String date;
+    private Integer logType;
+}

+ 2 - 2
fs-service/src/main/java/com/fs/course/mapper/FsCourseFinishTempMapper.java

@@ -91,13 +91,13 @@ public interface FsCourseFinishTempMapper
     List<FsCourseFinishTempListVO> selectFsCourseFinishTempListVO(@Param("maps") FsCourseFinishTemp fsCourseFinishTemp);
 
     @Select("select * from fs_course_finish_temp where video_id = #{videoId} " +
-            "and find_in_set(#{userId},company_user_ids) and is_del= 0 order by create_time desc  limit 1 ")
+            "and find_in_set(#{userId},company_user_ids) and is_del= 0 AND status= 1 order by create_time desc  limit 1 ")
     FsCourseFinishTemp selectFsCourseFinishTempByCompanyUserId(@Param("userId") Long companyUserId, @Param("videoId")Long videoId);
 
     @Select("    SELECT *\n" +
             "    FROM fs_course_finish_temp\n" +
             "    WHERE video_id = #{videoId}\n" +
-            "    AND is_del = 0\n" +
+            "    AND is_del = 0 AND status= 1 \n" +
             "    AND (\n" +
             "        (is_all_company_user = 1 AND company_id = #{companyId})\n" +
             "        OR\n" +

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

@@ -77,4 +77,10 @@ public interface FsCourseWatchCommentMapper extends BaseMapper<FsCourseWatchComm
      */
     List<FsCourseWatchCommentVO> selectH5CourseWatchComments(FsCourseWatchCommentListParam param);
 
+    /**
+     * 随机获取200条弹幕
+     * @param param 入参
+     * @return list
+     */
+    List<FsCourseWatchCommentVO> selectH5CourseWatchCommentsRound(FsCourseWatchCommentListParam param);
 }

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

@@ -3,6 +3,7 @@ package com.fs.course.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.course.domain.FsCourseWatchLog;
 import com.fs.course.domain.FsUserCourseVideo;
+import com.fs.course.dto.WatchLogDTO;
 import com.fs.course.param.*;
 import com.fs.course.vo.*;
 import com.fs.sop.vo.QwRatingVO;
@@ -319,4 +320,61 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
     FsCourseWatchLog selectFsCourseWatchLogByCourseSopIdAndVideoId(@Param("userId") Long userId,
                                                                    @Param("videoId") Long videoId,
                                                                    @Param("qwUserId") String qwUserId);
+
+    @Select("WITH date_series AS (\n" +
+            "  SELECT DATE_SUB(CURRENT_DATE(), INTERVAL 6-n DAY) AS report_date\n" +
+            "  FROM (\n" +
+            "    SELECT 0 AS n UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 \n" +
+            "    UNION SELECT 4 UNION SELECT 5 UNION SELECT 6\n" +
+            "  ) days\n" +
+            "  ORDER BY n\n" +
+            "),\n" +
+            "daily_data AS (\n" +
+            "  SELECT \n" +
+            "    DATE(create_time) AS log_date,\n" +
+            "    log_type,\n" +
+            "    ROW_NUMBER() OVER (PARTITION BY DATE(create_time) ORDER BY create_time DESC) AS rn\n" +
+            "  FROM fs_course_watch_log\n" +
+            "  WHERE qw_external_contact_id = #{extId}\n" +
+            "    AND create_time >= DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY)\n" +
+            ")\n" +
+            "SELECT \n" +
+            "ds.report_date AS date,"+
+            "  IFNULL(dd.log_type, 0) AS log_type\n" +
+            "FROM date_series ds\n" +
+            "LEFT JOIN (\n" +
+            "  SELECT log_date, log_type FROM daily_data WHERE rn = 1\n" +
+            ") dd ON ds.report_date = dd.log_date\n" +
+            "ORDER BY ds.report_date ASC  ")
+    List<WatchLogDTO> selectFsCourseWatchLog7Day(@Param("extId") Long extId);
+
+    @Select("WITH date_series AS (\n" +
+            "  SELECT DATE_SUB(CURRENT_DATE(), INTERVAL 29-n DAY) AS report_date\n" +
+            "  FROM (\n" +
+            "    SELECT 0 AS n UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 \n" +
+            "    UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 \n" +
+            "    UNION SELECT 12 UNION SELECT 13 UNION SELECT 14 UNION SELECT 15 UNION SELECT 16 UNION SELECT 17 \n" +
+            "    UNION SELECT 18 UNION SELECT 19 UNION SELECT 20 UNION SELECT 21 UNION SELECT 22 UNION SELECT 23 \n" +
+            "    UNION SELECT 24 UNION SELECT 25 UNION SELECT 26 UNION SELECT 27 UNION SELECT 28 UNION SELECT 29\n" +
+            "  ) days\n" +
+            "  ORDER BY n\n" +
+            "),\n" +
+            "daily_data AS (\n" +
+            "  SELECT \n" +
+            "    DATE(create_time) AS log_date,\n" +
+            "    log_type,\n" +
+            "    ROW_NUMBER() OVER (PARTITION BY DATE(create_time) ORDER BY create_time DESC) AS rn\n" +
+            "  FROM fs_course_watch_log\n" +
+            "  WHERE qw_external_contact_id = #{extId}\n" +
+            "    AND create_time >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)\n" +
+            ")\n" +
+            "SELECT \n" +
+            "  ds.report_date AS date,\n" +
+            "  IFNULL(dd.log_type, 0) AS log_type\n" +
+            "FROM date_series ds\n" +
+            "LEFT JOIN (\n" +
+            "  SELECT log_date, log_type FROM daily_data WHERE rn = 1\n" +
+            ") dd ON ds.report_date = dd.log_date\n" +
+            "ORDER BY ds.report_date ASC")
+    List<WatchLogDTO> selectFsCourseWatchLog30DayByExtId(@Param("extId") Long extId);
 }

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

@@ -2,6 +2,7 @@ package com.fs.course.mapper;
 
 import java.util.List;
 import com.fs.course.domain.FsUserCourse;
+import com.fs.course.param.FsCourseListBySidebarParam;
 import com.fs.course.param.FsUserCourseAddStudyCourseParam;
 import com.fs.course.param.FsUserCourseListUParam;
 import com.fs.course.param.FsUserCourseParam;
@@ -247,4 +248,14 @@ public interface FsUserCourseMapper
 
     @Select("select course_id ,img_url   from fs_user_course where is_del = 0 and is_private = 1")
     List<FsUserCourse> selectFsUserCourseAllCourseByQw();
+
+    @Select("<script> " +
+            "select course_id,course_name,title,img_url from fs_user_course where is_del=0  and is_private = 1 " +
+            "and find_in_set(#{data.companyId},company_ids)" +
+            "        <if test=\"data.keyword != null and data.keyword !='' \">\n" +
+            "            AND course_name LIKE concat('%',#{data.keyword},'%')\n" +
+            "        </if>" +
+            "order by course_id asc" +
+            "</script> ")
+    List<FsCourseListBySidebarVO> getFsCourseListBySidebar(@Param("data") FsCourseListBySidebarParam param);
 }

+ 13 - 0
fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java

@@ -2,9 +2,11 @@ package com.fs.course.mapper;
 
 import com.fs.course.domain.FsUserCourseVideo;
 import com.fs.course.param.CourseVideoUpdates;
+import com.fs.course.param.FsCourseListBySidebarParam;
 import com.fs.course.param.FsUserCourseVideoListUParam;
 import com.fs.course.param.FsUserCourseVideoParam;
 import com.fs.course.param.newfs.UserCourseVideoPageParam;
+import com.fs.course.vo.FsCourseVideoListBySidebarVO;
 import com.fs.course.vo.FsUserCourseVideoListUVO;
 import com.fs.course.vo.FsUserCourseVideoVO;
 import com.fs.course.vo.newfs.FsUserCourseVideoPageListVO;
@@ -180,4 +182,15 @@ public interface FsUserCourseVideoMapper
      * @return  list
      */
     List<OptionsVO> selectVideoListByMap(@Param("params") Map<String, Object> params);
+
+    @Select("<script> " +
+            "select v.video_id,v.course_id,v.title,v.video_url,v.thumbnail,v.duration,v.create_time 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.course_id=#{data.courseId} " +
+            "        <if test=\"data.keyword != null and data.keyword !='' \">\n" +
+            "            AND v.title LIKE concat('%',#{data.keyword},'%')\n" +
+            "        </if>" +
+            "order by v.video_id asc " +
+            "</script>")
+    List<FsCourseVideoListBySidebarVO> getFsCourseVideoListBySidebar(@Param("data") FsCourseListBySidebarParam param);
 }

+ 7 - 0
fs-service/src/main/java/com/fs/course/mapper/FsVideoResourceMapper.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.course.domain.FsVideoResource;
 import com.fs.course.vo.FsVideoResourceVO;
 import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
 
 import java.util.List;
 import java.util.Map;
@@ -17,4 +18,10 @@ public interface FsVideoResourceMapper extends BaseMapper<FsVideoResource> {
      * @return  list
      */
     List<FsVideoResourceVO> selectVideoResourceListByMap(@Param("params") Map<String, Object> params);
+
+    @Select("select * from fs_video_resource where line1 is not null and is_transcode = 0 and is_del = 0")
+    List<FsVideoResource> selectVideoNotTranscode();
+
+    @Select("select * from fs_video_resource where is_transcode = 1 and is_del = 0 and transcode_file_key is null")
+    List<FsVideoResource> selectVideoIsTranscode();
 }

+ 28 - 0
fs-service/src/main/java/com/fs/course/param/FsCourseLinkMiniParam.java

@@ -0,0 +1,28 @@
+package com.fs.course.param;
+
+import lombok.Data;
+
+@Data
+public class FsCourseLinkMiniParam {
+
+    private Long videoId;
+
+    private String qwUserId;
+
+    private String corpId;
+
+    private Long courseId;
+
+    private String title;//视频标题
+
+    /**
+    * 客户表的主键
+    */
+    private Long externalUserId;
+
+    /**
+    * 客户的小程序id
+    */
+    private Long fsUserId;
+
+}

+ 38 - 0
fs-service/src/main/java/com/fs/course/param/FsCourseListBySidebarParam.java

@@ -0,0 +1,38 @@
+package com.fs.course.param;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+@ApiModel
+public class FsCourseListBySidebarParam implements Serializable {
+
+    @ApiModelProperty(value = "页码,默认为1", required = true)
+    private Integer pageNum = 1;
+
+    @ApiModelProperty(value = "页大小,默认为10", required = true)
+    private Integer pageSize = 10;
+
+    @ApiModelProperty(value = "模糊搜索,通过视频名称来匹配")
+    private String keyword;
+
+    @ApiModelProperty(value = "公司id")
+    private Long companyId;
+
+    /**
+    * 课程id
+    */
+    private Long courseId;
+
+    private String corpId;
+
+    private String qwUserId;
+
+    /**
+    * 客户信息的长字符串id
+    */
+    private String externalUserId;
+}

+ 5 - 2
fs-service/src/main/java/com/fs/course/param/FsCourseWatchCommentListParam.java

@@ -14,8 +14,8 @@ public class FsCourseWatchCommentListParam{
     @ApiModelProperty(value = "页大小,默认为10", required = true)
     private Integer pageSize = 10;
 
-//    @ApiModelProperty(value = "不传,通过配置获取")
-//    private Integer listNum;
+    @ApiModelProperty(value = "不传,通过配置获取")
+    private Integer listNum;
 
     @ApiModelProperty(value = "课程id")
     private Long courseId;
@@ -23,4 +23,7 @@ public class FsCourseWatchCommentListParam{
     @ApiModelProperty(value = "视频id")
     private Long videoId;
 
+    @ApiModelProperty(value = "1-评论/2-弹幕")
+    private Integer openCommentStatus;
+
 }

+ 2 - 2
fs-service/src/main/java/com/fs/course/service/IFsCourseWatchCommentService.java

@@ -64,7 +64,7 @@ public interface IFsCourseWatchCommentService extends IService<FsCourseWatchComm
     int deleteFsCourseWatchCommentByCommentId(Long commentId);
 
     /**
-     * 保存h5的评论数据
+     * 保存评论/弹幕数据
      * @param param 入参
      * @return
      */
@@ -78,7 +78,7 @@ public interface IFsCourseWatchCommentService extends IService<FsCourseWatchComm
     R revokeH5CourseWatchComment(Long commentId);
 
     /**
-     * h5查询评论列表
+     * 查询评论列表
      * @param param 入参
      * @return list
      */

+ 3 - 4
fs-service/src/main/java/com/fs/course/service/IFsUserCourseService.java

@@ -4,10 +4,7 @@ import java.util.List;
 
 import com.fs.common.core.domain.R;
 import com.fs.course.domain.FsUserCourse;
-import com.fs.course.param.FsUserCourseAddStudyCourseParam;
-import com.fs.course.param.FsUserCourseGetIntegralParam;
-import com.fs.course.param.FsUserCourseListUParam;
-import com.fs.course.param.FsUserCourseParam;
+import com.fs.course.param.*;
 import com.fs.course.param.newfs.FsUserCourseListParam;
 import com.fs.course.vo.*;
 import com.fs.course.vo.newfs.FsUserCourseListVO;
@@ -108,4 +105,6 @@ public interface IFsUserCourseService
     List<FsUserCourseListVO> getFsUserCourseList(FsUserCourseListParam param);
 
     void  processQwSopCourseMaterialTimer();
+
+    List<FsCourseListBySidebarVO> getFsCourseListBySidebar(FsCourseListBySidebarParam param);
 }

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

@@ -8,6 +8,7 @@ import com.fs.course.param.newfs.FsUserCourseAddCompanyUserParam;
 import com.fs.course.param.newfs.FsUserCourseVideoLinkParam;
 import com.fs.course.param.newfs.FsUserCourseVideoUParam;
 import com.fs.course.param.newfs.UserCourseVideoPageParam;
+import com.fs.course.vo.FsCourseVideoListBySidebarVO;
 import com.fs.course.vo.FsUserCourseVideoListUVO;
 import com.fs.course.vo.FsUserCourseVideoQVO;
 import com.fs.course.vo.FsUserCourseVideoVO;
@@ -157,4 +158,9 @@ public interface IFsUserCourseVideoService
      * @return  list
      */
     List<OptionsVO> selectVideoListByMap(Map<String, Object> params);
+
+    List<FsCourseVideoListBySidebarVO> getFsCourseVideoListBySidebar(FsCourseListBySidebarParam param);
+
+    R createMiniLink(FsCourseLinkMiniParam param);
+    R createCartLink(FsCourseLinkMiniParam param);
 }

+ 8 - 8
fs-service/src/main/java/com/fs/course/service/impl/FsCourseFinishTempParentServiceImpl.java

@@ -20,7 +20,7 @@ import com.fs.course.service.IFsCourseFinishTempParentService;
 
 /**
  * 完课模板Service业务层处理
- * 
+ *
  * @author 吴树波
  * @date 2025-05-22
  */
@@ -34,7 +34,7 @@ public class FsCourseFinishTempParentServiceImpl extends ServiceImpl<FsCourseFin
 
     /**
      * 查询完课模板
-     * 
+     *
      * @param id 完课模板主键
      * @return 完课模板
      */
@@ -46,7 +46,7 @@ public class FsCourseFinishTempParentServiceImpl extends ServiceImpl<FsCourseFin
 
     /**
      * 查询完课模板列表
-     * 
+     *
      * @param fsCourseFinishTempParent 完课模板
      * @return 完课模板
      */
@@ -58,7 +58,7 @@ public class FsCourseFinishTempParentServiceImpl extends ServiceImpl<FsCourseFin
 
     /**
      * 新增完课模板
-     * 
+     *
      * @param fsCourseFinishTempParent 完课模板
      * @return 结果
      */
@@ -73,7 +73,7 @@ public class FsCourseFinishTempParentServiceImpl extends ServiceImpl<FsCourseFin
         videoList.forEach(e -> {
             FsCourseFinishTemp temp = new FsCourseFinishTemp();
             temp.setName(e.getFileName());
-            temp.setStatus(fsCourseFinishTempParent.getStatus());
+            temp.setStatus(0L);
             temp.setSetting(fsCourseFinishTempParent.getSetting());
             temp.setChatSetting(fsCourseFinishTempParent.getChatSetting());
             temp.setCompanyId(fsCourseFinishTempParent.getCompanyId());
@@ -89,7 +89,7 @@ public class FsCourseFinishTempParentServiceImpl extends ServiceImpl<FsCourseFin
 
     /**
      * 修改完课模板
-     * 
+     *
      * @param fsCourseFinishTempParent 完课模板
      * @return 结果
      */
@@ -102,7 +102,7 @@ public class FsCourseFinishTempParentServiceImpl extends ServiceImpl<FsCourseFin
 
     /**
      * 批量删除完课模板
-     * 
+     *
      * @param ids 需要删除的完课模板主键
      * @return 结果
      */
@@ -115,7 +115,7 @@ public class FsCourseFinishTempParentServiceImpl extends ServiceImpl<FsCourseFin
 
     /**
      * 删除完课模板信息
-     * 
+     *
      * @param id 完课模板主键
      * @return 结果
      */

+ 5 - 1
fs-service/src/main/java/com/fs/course/service/impl/FsCourseWatchCommentServiceImpl.java

@@ -161,7 +161,11 @@ public class FsCourseWatchCommentServiceImpl extends ServiceImpl<FsCourseWatchCo
 
     @Override
     public List<FsCourseWatchCommentVO> selectH5CourseWatchComments(FsCourseWatchCommentListParam param) {
-        return baseMapper.selectH5CourseWatchComments(param);
+        if(param.getOpenCommentStatus() != null && 2 == param.getOpenCommentStatus()){
+            return baseMapper.selectH5CourseWatchCommentsRound(param);
+        } else {
+            return baseMapper.selectH5CourseWatchComments(param);
+        }
     }
 
 }

+ 6 - 4
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java

@@ -18,10 +18,7 @@ import com.fs.course.domain.FsUserCourseStudy;
 import com.fs.course.domain.FsUserCourseStudyLog;
 import com.fs.course.domain.FsUserCourseVideo;
 import com.fs.course.mapper.*;
-import com.fs.course.param.FsUserCourseAddStudyCourseParam;
-import com.fs.course.param.FsUserCourseGetIntegralParam;
-import com.fs.course.param.FsUserCourseListUParam;
-import com.fs.course.param.FsUserCourseParam;
+import com.fs.course.param.*;
 import com.fs.course.param.newfs.FsUserCourseListParam;
 import com.fs.course.vo.*;
 import com.fs.course.vo.newfs.FsUserCourseListVO;
@@ -432,6 +429,11 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
         }
     }
 
+    @Override
+    public List<FsCourseListBySidebarVO> getFsCourseListBySidebar(FsCourseListBySidebarParam param) {
+        return  fsUserCourseMapper.getFsCourseListBySidebar(param);
+    }
+
     /**
      * 上传课程图片到企业微信并缓存
      *

+ 195 - 1
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -3,6 +3,7 @@ package com.fs.course.service.impl;
 import cn.hutool.core.util.NumberUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.fs.common.BeanCopyUtils;
 import com.fs.common.core.domain.R;
@@ -21,6 +22,7 @@ import com.fs.course.param.*;
 import com.fs.course.param.newfs.*;
 import com.fs.course.service.IFsUserCourseVideoService;
 import com.fs.course.service.IFsVideoResourceService;
+import com.fs.course.vo.FsCourseVideoListBySidebarVO;
 import com.fs.course.vo.FsUserCourseVideoListUVO;
 import com.fs.course.vo.FsUserCourseVideoQVO;
 import com.fs.course.vo.FsUserCourseVideoVO;
@@ -33,10 +35,13 @@ import com.fs.his.param.WxSendRedPacketParam;
 import com.fs.his.service.IFsStorePaymentService;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.vo.OptionsVO;
+import com.fs.qw.domain.QwCompany;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.domain.QwUser;
 import com.fs.qw.mapper.QwExternalContactMapper;
 import com.fs.qw.mapper.QwUserMapper;
+import com.fs.qw.service.IQwCompanyService;
+import com.fs.qw.service.IQwExternalContactService;
 import com.fs.qwApi.Result.QwAddContactWayResult;
 import com.fs.qwApi.param.QwAddContactWayParam;
 import com.fs.qwApi.service.QwApiService;
@@ -44,6 +49,7 @@ import com.fs.sop.mapper.QwSopLogsMapper;
 import com.fs.sop.mapper.SopUserLogsInfoMapper;
 import com.fs.sop.service.ISopUserLogsInfoService;
 import com.fs.system.service.ISysConfigService;
+import com.fs.voice.utils.StringUtil;
 import com.github.binarywang.wxpay.bean.transfer.TransferBillsResult;
 import lombok.extern.slf4j.Slf4j;
 import org.slf4j.Logger;
@@ -57,11 +63,14 @@ import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
+import java.time.ZoneId;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.stream.Collectors;
 
+import static com.fs.course.utils.LinkUtil.generateRandomStringWithLock;
+
 /**
  * 课堂视频Service业务层处理
  *
@@ -73,6 +82,12 @@ import java.util.stream.Collectors;
 public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 {
     private static final Logger logger = LoggerFactory.getLogger(FsUserCourseVideoServiceImpl.class);
+
+
+    private static final String miniappRealLink = "/pages_course/video.html?course=";
+    private static final String REAL_LINK_PREFIX = "/courseH5/pages/course/learning?course=";
+    private static final String SHORT_LINK_PREFIX = "/courseH5/pages/course/learning?s=";
+
     @Autowired
     private FsUserCourseVideoMapper fsUserCourseVideoMapper;
     @Autowired
@@ -149,6 +164,12 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     @Autowired
     private FsUserCompanyUserMapper fsUserCompanyUserMapper;
 
+    @Autowired
+    private IQwExternalContactService qwExternalContactService;
+    @Autowired
+    private IQwCompanyService iQwCompanyService;
+
+
     /**
      * 查询课堂视频
      *
@@ -410,7 +431,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         if (log==null){
             createWatchLog(param);
         }
-        return R.ok();
+        return R.ok().put("qwExternalId",matchedContact.getId());
     }
 
     private void createWatchLog(FsUserCourseVideoAddKfUParam param) {
@@ -1207,6 +1228,179 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         return fsUserCourseVideoMapper.selectVideoListByMap(params);
     }
 
+    @Override
+    public List<FsCourseVideoListBySidebarVO> getFsCourseVideoListBySidebar(FsCourseListBySidebarParam param) {
+        return fsUserCourseVideoMapper.getFsCourseVideoListBySidebar(param);
+    }
+
+    @Override
+    public R createMiniLink(FsCourseLinkMiniParam param) {
+
+        QwUser qwUser = qwExternalContactService.getQwUserByRedis(param.getCorpId().trim(), param.getQwUserId().trim());
+
+        if (qwUser==null||qwUser.getCompanyId()==null||qwUser.getCompanyUserId()==null){
+            return R.error("员工未绑定 销售公司 或 销售 请先绑定");
+        }
+
+        QwCompany qwCompany = iQwCompanyService.getQwCompanyByRedis(param.getCorpId());
+
+        if (qwCompany == null ) {
+            return  R.error().put("msg","企业不存在,请联系管理员");
+        }
+
+        //看课记录
+        addWatchLogIfNeeded(param.getVideoId(), param.getCourseId(),param.getFsUserId(),qwUser , param.getExternalUserId());
+
+        //生成小程序链接
+        String linkByMiniApp = createLinkByMiniApp(new Date(), param.getCourseId(), param.getVideoId(), qwUser, param.getExternalUserId(),2,null);
+
+        JSONObject news = new JSONObject(true);
+        news.put("miniprogramAppid", qwCompany.getMiniAppId());
+        news.put("miniprogramTitle", param.getTitle());
+        news.put("miniprogramPicUrl", "https://cos.his.cdwjyyh.com/fs/20250523/9c8af5735d784847818cada7fa776a7b.jpg");
+        news.put("miniprogramPage", linkByMiniApp);
+
+        return R.ok().put("data",news);
+    }
+
+    @Override
+    public R createCartLink(FsCourseLinkMiniParam param) {
+
+        QwUser qwUser = qwExternalContactService.getQwUserByRedis(param.getCorpId().trim(), param.getQwUserId().trim());
+
+        if (qwUser==null||qwUser.getCompanyId()==null||qwUser.getCompanyUserId()==null){
+            return R.error("员工未绑定 销售公司 或 销售 请先绑定");
+        }
+
+        QwCompany qwCompany = iQwCompanyService.getQwCompanyByRedis(param.getCorpId());
+
+        if (qwCompany == null ) {
+            return  R.error().put("msg","企业不存在,请联系管理员");
+        }
+
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSON.parseObject(json, CourseConfig.class);
+
+        if (config == null) {
+            return R.error().put("msg","课程默认配置为空,请联系管理员");
+        }
+
+        //域名
+        String domainName = companyUserMapper.selectDomainByUserId(qwUser.getCompanyUserId());
+        if (StringUtils.isEmpty(domainName)){
+            domainName = config.getRealLinkDomainName();
+        }
+
+        addWatchLogIfNeeded(param.getVideoId(), param.getCourseId(),param.getFsUserId(),qwUser , param.getExternalUserId());
+
+        String linkByCartLink = createLinkByMiniApp(new Date(), param.getCourseId(), param.getVideoId(), qwUser, param.getExternalUserId(),1,domainName);
+
+
+        //生成卡片链接
+        JSONObject news = new JSONObject(true); // true 表示保持字段顺序
+        news.put("linkTitle", param.getTitle());
+        news.put("linkDescribe", param.getTitle());
+        news.put("linkImageUrl", "https://cos.his.cdwjyyh.com/fs/20250523/9c8af5735d784847818cada7fa776a7b.jpg");
+        news.put("linkUrl", linkByCartLink);
+
+        return R.ok().put("data",news);
+
+    }
+
+    //插入观看记录
+    private void addWatchLogIfNeeded(Long videoId, Long courseId,
+                                     Long fsUserId, QwUser qwUser,Long externalId) {
+
+        try {
+
+            FsCourseWatchLog watchLog = new FsCourseWatchLog();
+            watchLog.setVideoId(videoId);
+            watchLog.setQwExternalContactId(externalId);
+            watchLog.setSendType(2);
+            watchLog.setQwUserId(String.valueOf(qwUser.getId()));
+            watchLog.setDuration(0L);
+            watchLog.setCourseId(courseId);
+            watchLog.setCompanyUserId(qwUser.getCompanyUserId());
+            watchLog.setCompanyId(qwUser.getCompanyId());
+            watchLog.setCreateTime(new Date());
+            watchLog.setUpdateTime(new Date());
+            watchLog.setLogType(3);
+
+            if (fsUserId == null) {
+                fsUserId=0L;
+            }
+
+            watchLog.setUserId(fsUserId);
+
+            //存看课记录
+            courseWatchLogMapper.insertOrUpdateFsCourseWatchLog(watchLog);
+        }catch (Exception e){
+            logger.error("一键群发失败-插入观看记录失败:"+e.getMessage());
+        }
+
+
+    }
+
+    private String createLinkByMiniApp(Date sendTime, Long courseId, Long videoId,
+                                       QwUser qwUser, Long externalId,int type,String domainName) {
+
+        FsCourseLink link = new FsCourseLink();
+        link.setCompanyId(qwUser.getCompanyId());
+        link.setQwUserId(String.valueOf(qwUser.getId()));
+        link.setCompanyUserId(qwUser.getCompanyUserId());
+        link.setVideoId(videoId);
+        link.setCorpId(qwUser.getCorpId());
+        link.setCourseId(courseId);
+        link.setQwExternalId(externalId);
+
+        if (type == 1) {
+            link.setLinkType(0);
+        }else {
+            link.setLinkType(3);
+        }
+
+        String randomString = generateRandomStringWithLock();
+        if (StringUtil.strIsNullOrEmpty(randomString)){
+            link.setLink(UUID.randomUUID().toString().replace("-", ""));
+        }else {
+            link.setLink(randomString);
+        }
+
+        link.setCreateTime(sendTime);
+
+        FsCourseRealLink courseMap = new FsCourseRealLink();
+        BeanUtils.copyProperties(link,courseMap);
+
+        String courseJson = JSON.toJSONString(courseMap);
+
+        String realLinkFull = null;
+
+        if (type == 1) {
+            realLinkFull = REAL_LINK_PREFIX + courseJson;
+        }else {
+            realLinkFull = miniappRealLink + courseJson;
+        }
+
+        link.setRealLink(realLinkFull);
+
+
+        // 使用 Java 8 时间 API 计算过期时间
+        LocalDateTime sendDateTime = sendTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+        LocalDateTime expireDateTime = sendDateTime.plusDays(0);
+        expireDateTime = expireDateTime.toLocalDate().atTime(23, 59, 59);
+        Date updateTime = Date.from(expireDateTime.atZone(ZoneId.systemDefault()).toInstant());
+        link.setUpdateTime(updateTime);
+
+        //存短链-
+        fsCourseLinkMapper.insertFsCourseLink(link);
+
+        if (type==1){
+            return domainName + SHORT_LINK_PREFIX + link.getLink();
+        }else {
+            return link.getRealLink();
+        }
+
+    }
     //会员-更新心跳时间
     public void updateHeartbeatWx(FsUserCourseVideoUParam param) {
         String redisKey = "h5wxuser:watch:heartbeat:" + param.getUserId() + ":" + param.getVideoId() + ":" + param.getCompanyUserId();

+ 17 - 12
fs-service/src/main/java/com/fs/course/service/impl/TencentCloudCosService.java

@@ -3,7 +3,9 @@ package com.fs.course.service.impl;
 import com.fs.common.core.domain.R;
 import com.fs.config.tencent.TencentProperties;
 import com.fs.course.domain.FsUserCourseVideo;
+import com.fs.course.domain.FsVideoResource;
 import com.fs.course.mapper.FsUserCourseVideoMapper;
+import com.fs.course.mapper.FsVideoResourceMapper;
 import com.fs.course.service.ITencentCloudCosService;
 import com.qcloud.cos.COSClient;
 import com.qcloud.cos.exception.CosClientException;
@@ -162,14 +164,14 @@ public class TencentCloudCosService implements ITencentCloudCosService {
     public R updateUrl() {
         try {
             //查出已转码的视频并且没有文件key的
-            List<FsUserCourseVideo> videos =  courseVideoMapper.selectVideoIsTranscode();
-            for (FsUserCourseVideo video : videos ){
-                String newUrl = replaceCourse(video.getLineOne());
-                FsUserCourseVideo videoMap = new FsUserCourseVideo();
-                videoMap.setVideoId(video.getVideoId());
-                videoMap.setLineOne(newUrl);
+            List<FsVideoResource> videos =  videoResourceMapper.selectVideoIsTranscode();
+            for (FsVideoResource video : videos ){
+                String newUrl = replaceCourse(video.getLine1());
+                FsVideoResource videoMap = new FsVideoResource();
+                videoMap.setId(video.getId());
+                videoMap.setLine1(newUrl);
                 videoMap.setTranscodeFileKey(replaceCourse(video.getFileKey()));
-                courseVideoMapper.updateFsUserCourseVideo(videoMap);
+                videoResourceMapper.updateById(videoMap);
             }
             return R.ok();
         }catch (Exception e){
@@ -209,6 +211,9 @@ public class TencentCloudCosService implements ITencentCloudCosService {
     @Autowired
     private FsUserCourseVideoMapper courseVideoMapper;
 
+    @Autowired
+    private FsVideoResourceMapper videoResourceMapper;
+
     /**
      * 批量转码
      * @return
@@ -216,15 +221,15 @@ public class TencentCloudCosService implements ITencentCloudCosService {
     @Override
     public R videoTranscode() {
         //查出未转码的视频
-        List<FsUserCourseVideo> videos =  courseVideoMapper.selectVideoTranscode(0);
-        for (FsUserCourseVideo video : videos ){
+        List<FsVideoResource> videos =  videoResourceMapper.selectVideoNotTranscode();
+        for (FsVideoResource video : videos ){
             String inputPath = "/"+video.getFileKey();
             String outputPath = "/"+replaceCourse(video.getFileKey());
             submitTranscodeJob(inputPath,outputPath);
-            FsUserCourseVideo videoMap = new FsUserCourseVideo();
-            videoMap.setVideoId(video.getVideoId());
+            FsVideoResource videoMap = new FsVideoResource();
+            videoMap.setId(video.getId());
             videoMap.setIsTranscode(1);
-            courseVideoMapper.updateFsUserCourseVideo(videoMap);
+            videoResourceMapper.updateById(videoMap);
         }
 
         return R.ok();

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

@@ -0,0 +1,26 @@
+package com.fs.course.vo;
+
+import lombok.Data;
+
+@Data
+public class FsCourseListBySidebarVO {
+    /**
+    * 课程id
+    */
+    private Long courseId;
+    /**
+    * 课程名称
+    */
+    private String courseName;
+
+    /**
+    * 标题
+    */
+    private String title;
+
+    /**
+    * 课程封面
+    */
+    private String imgUrl;
+
+}

+ 37 - 0
fs-service/src/main/java/com/fs/course/vo/FsCourseVideoListBySidebarVO.java

@@ -0,0 +1,37 @@
+package com.fs.course.vo;
+
+import lombok.Data;
+
+@Data
+public class FsCourseVideoListBySidebarVO {
+
+    private Long videoId;
+
+    private Long courseId;
+
+    /**
+    * 视频标题
+    */
+    private String title;
+
+    /**
+    * 视频地址
+    */
+    private String videoUrl;
+
+    /**
+    * 时长
+    */
+    private Integer duration;
+
+    /**
+    * 视频缩略图
+    */
+    private String thumbnail;
+
+    /**
+    * 视频创建时间
+    */
+    private String createTime;
+
+}

+ 9 - 5
fs-service/src/main/java/com/fs/event/WeixinTemplateService.java

@@ -5,6 +5,7 @@ import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
 import cn.hutool.core.util.StrUtil;
 import com.fs.core.config.WxMaConfiguration;
+import com.fs.his.config.WxMiniappTempConfig;
 import com.fs.his.domain.FsUser;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.utils.ConfigUtil;
@@ -30,6 +31,9 @@ public class WeixinTemplateService {
     @Autowired
     private IFsUserService userService;
 
+    @Autowired
+    WxMiniappTempConfig wxMiniappTempConfig;
+
 
     public void cancelOrderNotice(String orderId,String title,String remark,Long uid){
         String openId = this.getUserOpenid(uid);
@@ -40,7 +44,7 @@ public class WeixinTemplateService {
         //订单号
         map.put("thing1",title);
         map.put("thing4",remark);
-        String tempId = "YyaBF62vH1GPKY0tume8C2C5UETxcKrVsaTKdBW5eok";
+        String tempId = wxMiniappTempConfig.getInquiryTempID();
         if(StrUtil.isNotBlank(tempId)) {
             this.sendWxMpTemplateMessage(openId, tempId, "pages_order/inquiryOrderDetails?orderId=" + orderId, map);
         }
@@ -54,7 +58,7 @@ public class WeixinTemplateService {
         //订单号
         map.put("thing1",title);
         map.put("thing4",remark);
-        String tempId = "YyaBF62vH1GPKY0tume8C2C5UETxcKrVsaTKdBW5eok";
+        String tempId = wxMiniappTempConfig.getInquiryTempID();;
         if(StrUtil.isNotBlank(tempId)) {
             this.sendWxMpTemplateMessage(openId, tempId, "pages_order/inquiryOrderDetails?orderId=" + orderId, map);
         }
@@ -71,7 +75,7 @@ public class WeixinTemplateService {
         map.put("time7",df.format(createTime));
         map.put("character_string9",orderCode);
         map.put("thing4",remark);
-        String tempId = "jARl4BpoBkRu-2MxPMkQVhIfGMG0V9qW-X3V_7NtEOU";
+        String tempId = wxMiniappTempConfig.getPayOrderTempID();
         if(StrUtil.isNotBlank(tempId)) {
             this.sendWxMpTemplateMessage(openId, tempId, "pages_order/packageOrderDetails?orderId=" + orderId, map);
         }
@@ -85,7 +89,7 @@ public class WeixinTemplateService {
         Map<String,String> map = new HashMap<>();
         map.put("thing1",title);
         map.put("thing4",remark);
-        String tempId = "YyaBF62vH1GPKY0tume8C2C5UETxcKrVsaTKdBW5eok";
+        String tempId = wxMiniappTempConfig.getInquiryTempID();
         if(StrUtil.isNotBlank(tempId)) {
             this.sendWxMpTemplateMessage(openId, tempId, "pages_user/followList", map);
         }
@@ -99,7 +103,7 @@ public class WeixinTemplateService {
         Map<String,String> map = new HashMap<>();
         map.put("thing1",title);
         map.put("thing4",remark);
-        String tempId = "YyaBF62vH1GPKY0tume8C2C5UETxcKrVsaTKdBW5eok";
+        String tempId = wxMiniappTempConfig.getInquiryTempID();
         if(StrUtil.isNotBlank(tempId)) {
             this.sendWxMpTemplateMessage(openId, tempId, "pages/TUIKit/TUIPages/TUIConversation/index" , map);
         }

+ 19 - 0
fs-service/src/main/java/com/fs/his/config/WxMiniappTempConfig.java

@@ -0,0 +1,19 @@
+package com.fs.his.config;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.io.Serializable;
+
+@Data
+@Component
+public class WxMiniappTempConfig implements Serializable {
+
+
+    @Value("${wx_miniapp_temp.pay_order_temp_id}")
+    private String payOrderTempID;
+
+    @Value("${wx_miniapp_temp.inquiry_temp_id}")
+    private String inquiryTempID;
+}

+ 33 - 0
fs-service/src/main/java/com/fs/his/dto/PackageOrderDTO.java

@@ -0,0 +1,33 @@
+package com.fs.his.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class PackageOrderDTO {
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "支付时间")
+    private Date payTime;
+
+    private Date createTime;
+
+    /** 套餐名称 */
+    @Excel(name = "套餐名称")
+    private String packageName;
+
+    /** 用户ID */
+    @Excel(name = "用户ID")
+    private Long userId;
+
+    /** 订单号 */
+    @Excel(name = "订单号")
+    private String orderSn;
+
+    private String fsUserName;
+
+
+}

+ 3 - 0
fs-service/src/main/java/com/fs/his/mapper/FsPackageOrderMapper.java

@@ -5,6 +5,7 @@ import java.util.List;
 import com.fs.his.domain.FsPackage;
 import com.fs.his.domain.FsPackageOrder;
 import com.fs.his.domain.FsStorePayment;
+import com.fs.his.dto.PackageOrderDTO;
 import com.fs.his.param.FsPackageOrderListUParam;
 import com.fs.his.param.FsPackageOrderParam;
 import com.fs.his.vo.FsPackageOrderExcelVO;
@@ -219,4 +220,6 @@ public interface FsPackageOrderMapper
     Long selectFsPackageOrderExcelListVOCount(FsPackageOrderParam fsPackageOrder);
 
     FsPackage selectFsPackageByOrderId(Long packageOrderId);
+
+    List<PackageOrderDTO> getNewOrder();
 }

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

@@ -6,6 +6,7 @@ import com.fs.common.core.domain.R;
 import com.fs.his.domain.FsPackage;
 import com.fs.his.domain.FsPackageOrder;
 import com.fs.his.domain.FsStorePayment;
+import com.fs.his.dto.PackageOrderDTO;
 import com.fs.his.param.*;
 import com.fs.his.vo.FsPackageOrderExcelVO;
 import com.fs.his.vo.FsPackageOrderListUVO;
@@ -117,4 +118,6 @@ public interface IFsPackageOrderService
     void exportData(FsPackageOrderParam fsPackageOrder);
 
     FsPackage selectFsPackageByOrderId(Long packageOrderId);
+
+    List<PackageOrderDTO> getNewOrder();
 }

+ 1 - 1
fs-service/src/main/java/com/fs/his/service/impl/FsDoctorServiceImpl.java

@@ -111,7 +111,7 @@ public class FsDoctorServiceImpl implements IFsDoctorService
 
         fsDoctor.setCreateTime(DateUtils.getNowDate());
         int i = fsDoctorMapper.insertFsDoctor(fsDoctor);
-        if (fsDoctor.getIsPrescribeDoctor()==1){
+        if (fsDoctor.getIsPrescribeDoctor() != null && fsDoctor.getIsPrescribeDoctor()==1){
             fsDoctor.setPrescribeDoctorId(fsDoctor.getDoctorId());
             fsDoctorMapper.updateFsDoctor(fsDoctor);
         }

+ 12 - 8
fs-service/src/main/java/com/fs/his/service/impl/FsInquiryOrderServiceImpl.java

@@ -985,14 +985,18 @@ public class FsInquiryOrderServiceImpl implements IFsInquiryOrderService
         map.setStatus(3);
         map.setStartTime(new Date());
         fsInquiryOrderMapper.updateFsInquiryOrder(map);
-        TemplateBean templateBean = TemplateBean.builder()
-                .orderId(order.getOrderId().toString())
-                .title("问诊订单医生已接单")
-                .remark("您的问诊订单,订单号:"+order.getOrderSn()+"医生已接单")
-                .uid(order.getUserId())
-                .templateType(TemplateListenEnum.TYPE_2.getValue())
-                .build();
-        publisher.publishEvent(new TemplateEvent(this, templateBean));
+        try {
+            TemplateBean templateBean = TemplateBean.builder()
+                    .orderId(order.getOrderId().toString())
+                    .title("问诊订单医生已接单")
+                    .remark("您的问诊订单,订单号:"+order.getOrderSn()+"医生已接单")
+                    .uid(order.getUserId())
+                    .templateType(TemplateListenEnum.TYPE_2.getValue())
+                    .build();
+            publisher.publishEvent(new TemplateEvent(this, templateBean));
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
 
 
         if (order.getInquiryType()!=2){

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

@@ -37,6 +37,7 @@ import com.fs.event.TemplateListenEnum;
 import com.fs.his.config.FsSysConfig;
 import com.fs.his.domain.*;
 import com.fs.his.dto.PackageConfigDTO;
+import com.fs.his.dto.PackageOrderDTO;
 import com.fs.his.dto.PayConfigDTO;
 import com.fs.his.dto.StoreOrderProductDTO;
 import com.fs.his.enums.FsPackageOrderStatusEnum;
@@ -1397,6 +1398,11 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
         return fsPackageOrderMapper.selectFsPackageByOrderId(packageOrderId);
     }
 
+    @Override
+    public List<PackageOrderDTO> getNewOrder() {
+        return fsPackageOrderMapper.getNewOrder();
+    }
+
     @Override
     public R addPackageOrder(FsPackageOrderAddParam param) {
         FsPatient patient=null;

+ 4 - 4
fs-service/src/main/java/com/fs/his/service/impl/FsPackageServiceImpl.java

@@ -77,7 +77,7 @@ public class FsPackageServiceImpl implements IFsPackageService {
     public int insertFsPackage(FsPackage fsPackage) {
 
         fsPackage.setCreateTime(DateUtils.getNowDate());
-        if (fsPackage.getPackageSubType() != 1) {
+//        if (fsPackage.getPackageSubType() != 1) {
             if (fsPackage.getProductJson() != null) {
                 JSONArray objects = JSONUtil.parseArray(fsPackage.getProductJson());
                 List<FsPackagePruductDTO> products = JSONUtil.toList(objects, FsPackagePruductDTO.class);
@@ -93,7 +93,7 @@ public class FsPackageServiceImpl implements IFsPackageService {
                 fsPackage.setInquiryCostPrice(in);
                 fsPackage.setTotalCostPrice(toal.add(in));
             }
-        }
+//        }
         return fsPackageMapper.insertFsPackage(fsPackage);
     }
 
@@ -106,7 +106,7 @@ public class FsPackageServiceImpl implements IFsPackageService {
     @Override
     public int updateFsPackage(FsPackage fsPackage) {
         fsPackage.setUpdateTime(DateUtils.getNowDate());
-        if (fsPackage.getPackageSubType() != null && fsPackage.getPackageSubType() != 1) {
+//        if (fsPackage.getPackageSubType() != null && fsPackage.getPackageSubType() != 1) {
             if (fsPackage.getProductJson() != null) {
                 JSONArray objects = JSONUtil.parseArray(fsPackage.getProductJson());
                 List<FsPackagePruductDTO> products = JSONUtil.toList(objects, FsPackagePruductDTO.class);
@@ -119,7 +119,7 @@ public class FsPackageServiceImpl implements IFsPackageService {
                 fsPackage.setInquiryCostPrice(in);
                 fsPackage.setTotalCostPrice(toal.add(in));
             }
-        }
+//        }
         return fsPackageMapper.updateFsPackage(fsPackage);
     }
 

+ 26 - 3
fs-service/src/main/java/com/fs/qw/domain/QwWorkTask.java

@@ -1,10 +1,14 @@
 package com.fs.qw.domain;
 
+import com.baomidou.mybatisplus.annotation.TableId;
 import com.fs.common.annotation.Excel;
-import com.fs.common.core.domain.BaseEntity;
+import io.swagger.models.auth.In;
 import lombok.Data;
+import com.fs.common.core.domain.BaseEntity;
 import lombok.EqualsAndHashCode;
 
+import java.util.List;
+
 /**
  * 企微任务看板对象 qw_work_task
  *
@@ -22,6 +26,11 @@ public class QwWorkTask extends BaseEntity{
     @Excel(name = "外部联系人id")
     private Long extId;
 
+    @Excel(name = "外部联系人长字符串")
+    private String externalContactId;
+
+    private String description;
+
     /** 企微用户id */
     @Excel(name = "企微用户id")
     private Long qwUserId;
@@ -34,6 +43,11 @@ public class QwWorkTask extends BaseEntity{
     @Excel(name = "状态 0 待处理 1 已处理 3 过期")
     private Integer status;
 
+    /**
+     * 最晚看课时间
+     */
+    @Excel(name = "最晚看课时间")
+    private String lastWatchDate;
     /** 分值 */
     @Excel(name = "分值")
     private Integer score;
@@ -46,15 +60,24 @@ public class QwWorkTask extends BaseEntity{
     @Excel(name = "公司id")
     private Long companyId;
 
+    private Integer trackType;
     /** 用户id */
     @Excel(name = "用户id")
     private Long companyUserId;
 
     private String title;
-
     /** 通话时长 */
     @Excel(name = "通话时长")
     private Long duration;
 
-    private Integer trackType;
+    /** 名称 */
+    @Excel(name = "名称")
+    private String name;
+
+    /** 头像 */
+    @Excel(name = "头像")
+    private String avatar;
+
+    List<Integer> logs;
+
 }

+ 3 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactInfoMapper.java

@@ -61,6 +61,7 @@ public interface QwExternalContactInfoMapper
      * @return 结果
      */
     public int deleteQwExternalContactInfoByIds(Long[] ids);
+
     @Select("select * from qw_external_contact_info where external_contact_id =#{id}")
     QwExternalContactInfo selectQwExternalContactInfoByExternalContactId(Long id);
 
@@ -69,4 +70,6 @@ public interface QwExternalContactInfoMapper
             "ON DUPLICATE KEY UPDATE " +
             "talk = VALUES(talk);")
     int updateQwExternalContactInfoByExtId(Long id);
+
+    void updateQwExternalContactInfoByExternalContactId(QwExternalContactInfo qwExternalContactInfo);
 }

+ 9 - 9
fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactMapper.java

@@ -2,17 +2,11 @@ package com.fs.qw.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.qw.domain.QwExternalContact;
-import com.fs.qw.param.ConversionStatisticsParam;
-import com.fs.qw.param.QwCountCustomerParam;
-import com.fs.qw.param.QwExternalContactParam;
-import com.fs.qw.param.QwExternalContactVOTime;
+import com.fs.qw.param.*;
 import com.fs.qw.result.QwExternalContactByQwResult;
 import com.fs.qw.result.QwExternalContactLogVo;
 import com.fs.qw.result.QwExternalContactVo;
-import com.fs.qw.vo.GroupUserExternalVo;
-import com.fs.qw.vo.QwExternalContactFsCrmVO;
-import com.fs.qw.vo.QwExternalContactFsUserVO;
-import com.fs.qw.vo.QwExternalContactVO;
+import com.fs.qw.vo.*;
 import com.fs.qwApi.param.QwExternalContactHParam;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
@@ -301,7 +295,7 @@ public interface QwExternalContactMapper extends BaseMapper<QwExternalContact> {
     @Update("UPDATE qw_external_contact SET company_id = #{companyId},company_user_id=#{companyUserId} WHERE corp_id = #{corpId} and user_id =#{qwUserId}")
     void updateBindUserByQwUser(@Param("corpId")String corpId, @Param("qwUserId")String qwUserId, @Param("companyId")Long companyId, @Param("companyUserId")Long companyUserId);
 
-    @Select("SELECT * FROM  qw_external_contact " +
+    @Select("SELECT id,external_user_id,name,avatar,remark,description FROM  qw_external_contact " +
             " WHERE user_id = #{map.userId}   " +
             "AND external_user_id = #{map.externalUserId} " +
             "AND corp_id =#{map.corpId} " +
@@ -370,4 +364,10 @@ public interface QwExternalContactMapper extends BaseMapper<QwExternalContact> {
     @Update("update qw_external_contact set comment_status = #{commentStatus} where fs_user_id = #{fsUserId}")
     int updateQwExternalContactByFsUserId(@Param("commentStatus") Integer commentStatus, @Param("fsUserId")Long fsUserId);
 
+    ExternalContactDetailsVO getCountAnswer (@Param("param") ExternalContactDetailsParam param);
+
+    ExternalContactDetailsVO getCountRedPacket (@Param("param") ExternalContactDetailsParam param);
+
+    ExternalContactDetailsVO getCountCourseWatch(@Param("param") ExternalContactDetailsParam param);
+
 }

+ 17 - 8
fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java

@@ -1,17 +1,13 @@
 package com.fs.qw.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.course.param.FsCourseListBySidebarParam;
 import com.fs.qw.domain.QwUser;
+import com.fs.qw.domain.QwWorkTask;
 import com.fs.qw.dto.QwUserByToolDTO;
 import com.fs.qw.dto.QwUserKeyDTO;
-import com.fs.qw.param.QwFsServerBindParam;
-import com.fs.qw.param.QwUserListParam;
-import com.fs.qw.param.QwUserParam;
-import com.fs.qw.param.QwWatchLogStatisticsListParam;
-import com.fs.qw.vo.QwHookAuthVO;
-import com.fs.qw.vo.QwOptionsVO;
-import com.fs.qw.vo.QwUserVO;
-import com.fs.qw.vo.QwWatchLogStatisticsListVO;
+import com.fs.qw.param.*;
+import com.fs.qw.vo.*;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.ibatis.annotations.MapKey;
 import org.apache.ibatis.annotations.Param;
@@ -367,4 +363,17 @@ public interface QwUserMapper extends BaseMapper<QwUser>
             "</foreach> " +
             "</script>")
     public List<QwUserVO> getQwUserByIdsNoCropId(@Param("qwUserIds") List<String> qwUserIds);
+
+    @Select("<script> " +
+            "select qu.qw_user_id,qu.qw_user_name,qe.create_time from qw_external_contact qe " +
+            "left join  qw_user qu " +
+            "on qe.user_id=qu.qw_user_id and qe.corp_id=qu.corp_id" +
+            "where qe.external_user_id=#{data.externalUserId} " +
+            "   and qe.corp_id=#{data.corpId} " +
+            "   and qe.status=0 " +
+            "   and qe.user_id != #{data.qwUserId} " +
+            "</script>")
+    List<QwExternalListByHeavyVO> getQwExternalListByHeavy(@Param("data") FsCourseListBySidebarParam param);
+
+    List<QwWorkTask> selectQwWorkTaskList(SelectQwWorkTaskListParam param);
 }

+ 17 - 0
fs-service/src/main/java/com/fs/qw/param/ExternalContactDetailsParam.java

@@ -0,0 +1,17 @@
+package com.fs.qw.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class ExternalContactDetailsParam {
+
+    @ApiModelProperty(value = "登录用户id,不用传")
+    private Long userId;
+
+    @ApiModelProperty(value = "外部联系人id")
+    private Long contactId;
+
+    @ApiModelProperty(value = "时间tab,不传表示查询全部,分别是:今天、昨天、前天、近七天")
+    private String dateTag;
+}

+ 3 - 0
fs-service/src/main/java/com/fs/qw/param/QwExternalContactVOTime.java

@@ -11,6 +11,7 @@ public class QwExternalContactVOTime {
     private Long id;
 
     private String tagIds;
+
     private List<String> tagIdsName;
 
     private String remark;
@@ -22,4 +23,6 @@ public class QwExternalContactVOTime {
 
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private String createTime;
+
+    private String name;
 }

+ 33 - 0
fs-service/src/main/java/com/fs/qw/param/SelectQwWorkTaskListParam.java

@@ -0,0 +1,33 @@
+package com.fs.qw.param;
+
+import com.fs.watch.param.BaseQueryParam;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+@Data
+public class SelectQwWorkTaskListParam extends BaseQueryParam {
+    /**
+     * 企微用户ID
+     */
+    @NotBlank(message = "ID不能为空")
+    private String qwUserId;
+    /**
+     * 时间 (yyyy-MM-dd)
+     */
+    @NotBlank(message = "时间不能为空")
+    private String date;
+
+
+    /**
+     * 企微用户corpId
+     */
+    @NotBlank(message = "corpId不能为空")
+    private String corpId;
+
+    /**
+    * 企业微信员工Qw_User的主键
+    */
+    private Long userId;
+
+}

+ 3 - 1
fs-service/src/main/java/com/fs/qw/service/IQwExternalContactInfoService.java

@@ -60,11 +60,13 @@ public interface IQwExternalContactInfoService
      */
     public int deleteQwExternalContactInfoById(Long id);
 
-    Object selectQwExternalContactInfoByExternalContactId(Long id);
+    QwExternalContactInfo selectQwExternalContactInfoByExternalContactId(Long id);
 
     int updateQwExternalContactInfoByIds(Long[] ids);
 
     void updateQwExternalContactInfoBytalk(String talkType, Long externalId);
 
     int updateQwExternalContactInfoByQwUserId(Long id);
+
+    void updateQwExternalContactInfoByExternalContactId(QwExternalContactInfo qwExternalContactInfo);
 }

+ 17 - 0
fs-service/src/main/java/com/fs/qw/service/IQwExternalContactService.java

@@ -3,11 +3,15 @@ package com.fs.qw.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.common.core.domain.R;
+import com.fs.course.param.FsCourseListBySidebarParam;
 import com.fs.qw.domain.QwExternalContact;
+import com.fs.qw.domain.QwUser;
 import com.fs.qw.param.*;
 import com.fs.qw.result.QwExternalContactLogVo;
 import com.fs.qw.result.QwExternalContactVo;
+import com.fs.qw.vo.ExternalContactDetailsVO;
 import com.fs.qw.vo.QwExternalContactVO;
+import com.fs.qw.vo.QwExternalListByHeavyVO;
 import com.fs.qw.vo.QwSopRuleTimeVO;
 import com.fs.qwApi.param.QwExternalContactHParam;
 import org.codehaus.jettison.json.JSONException;
@@ -103,6 +107,9 @@ public interface IQwExternalContactService extends IService<QwExternalContact> {
 
     R delUserTag(QwExternalContactAddTagParam param);
 
+    QwUser getQwUserByRedis(String corpId, String userID);
+
+
     void insertQwExternalContactByExternalUserId(String externalUserID, String userID, Long companyId, String corpId, String state, String welcomeCode) throws ParseException;
 
     void insertQwExternalContactByExternalUserId2(String externalUserID, String userID, Long companyId, String corpId, String state, String welcomeCode) throws ParseException;
@@ -164,7 +171,17 @@ public interface IQwExternalContactService extends IService<QwExternalContact> {
 
     void synchronizeQwExternalContactTask();
 
+    /**
+     * 获取会员答题和看课情况
+     * @param param 参数
+     * @return
+     */
+    ExternalContactDetailsVO getUserDetails(ExternalContactDetailsParam param);
+
     List<QwExternalContactVOTime> selectQwExternalContactListVOByUserIds(List<String> externalIdList);
 
     Integer selectQwIsRepeat(Long id);
+
+
+    List<QwExternalListByHeavyVO> getQwExternalListByHeavy(FsCourseListBySidebarParam param);
 }

+ 3 - 0
fs-service/src/main/java/com/fs/qw/service/IQwUserService.java

@@ -2,6 +2,7 @@ package com.fs.qw.service;
 
 import com.fs.common.core.domain.R;
 import com.fs.qw.domain.QwUser;
+import com.fs.qw.domain.QwWorkTask;
 import com.fs.qw.dto.QwUserKeyDTO;
 import com.fs.qw.param.*;
 import com.fs.qw.vo.QwHookAuthVO;
@@ -161,4 +162,6 @@ public interface IQwUserService
     R getQwIpad(QwLoginHookParam loginParam);
 
     R delQwIpad(QwLoginHookParam loginParam);
+
+    List<QwWorkTask> selectQwWorkTaskList(SelectQwWorkTaskListParam param);
 }

+ 5 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactInfoServiceImpl.java

@@ -136,4 +136,9 @@ public class QwExternalContactInfoServiceImpl implements IQwExternalContactInfoS
 
         return 1;
     }
+
+    @Override
+    public void updateQwExternalContactInfoByExternalContactId(QwExternalContactInfo qwExternalContactInfo) {
+        qwExternalContactInfoMapper.updateQwExternalContactInfoByExternalContactId(qwExternalContactInfo);
+    }
 }

+ 29 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java

@@ -20,6 +20,7 @@ import com.fs.course.mapper.FsCourseSopLogsMapper;
 import com.fs.course.mapper.FsCourseSopMapper;
 import com.fs.course.mapper.FsCourseWatchLogMapper;
 import com.fs.course.param.FsCourseLinkCreateParam;
+import com.fs.course.param.FsCourseListBySidebarParam;
 import com.fs.course.service.IFsCourseLinkService;
 import com.fs.crm.domain.CrmCustomer;
 import com.fs.crm.mapper.CrmCustomerMapper;
@@ -59,6 +60,7 @@ import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 
 import java.io.IOException;
+import java.math.BigDecimal;
 import java.text.ParseException;
 import java.time.*;
 import java.time.format.DateTimeFormatter;
@@ -292,6 +294,28 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
 
     }
 
+    @Override
+    public ExternalContactDetailsVO getUserDetails(ExternalContactDetailsParam param) {
+        ExternalContactDetailsVO countCourseWatch = qwExternalContactMapper.getCountCourseWatch(param);
+        ExternalContactDetailsVO countAnswer = qwExternalContactMapper.getCountAnswer(param);
+        ExternalContactDetailsVO countRedPacket = qwExternalContactMapper.getCountRedPacket(param);
+        ExternalContactDetailsVO vo = new ExternalContactDetailsVO();
+        if(countCourseWatch != null){
+            BeanUtils.copyProperties(countCourseWatch, vo);
+        }
+        if (countAnswer != null) {
+            vo.setAnswerTime(countAnswer.getAnswerTime());
+            vo.setAnswerRightTime(countAnswer.getAnswerRightTime());
+        }
+        if (countRedPacket != null) {
+            vo.setAnswerRedPacketTime(countRedPacket.getAnswerRedPacketTime());
+            vo.setAnswerRedPacketAmount(countRedPacket.getAnswerRedPacketAmount());
+        } else {
+            vo.setAnswerRedPacketAmount(BigDecimal.ZERO);
+        }
+        return vo;
+    }
+
     @Override
     public List<QwExternalContactVOTime> selectQwExternalContactListVOByUserIds(List<String> ids) {
         List<QwExternalContactVOTime> list = qwExternalContactMapper.selectQwExternalContactListVOByUserIds(ids);
@@ -313,6 +337,11 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
         return qwExternalContactMapper.selectQwIsRepeat(id);
     }
 
+    @Override
+    public List<QwExternalListByHeavyVO> getQwExternalListByHeavy(FsCourseListBySidebarParam param) {
+        return qwUserMapper.getQwExternalListByHeavy(param);
+    }
+
     /**
      * 处理一个分组(组内串行)
      */

+ 54 - 4
fs-service/src/main/java/com/fs/qw/service/impl/QwUserServiceImpl.java

@@ -12,10 +12,7 @@ import com.fs.config.ai.AiHostProper;
 import com.fs.config.cloud.CloudHostProper;
 import com.fs.his.config.FsSysConfig;
 import com.fs.his.utils.ConfigUtil;
-import com.fs.qw.domain.QwCompany;
-import com.fs.qw.domain.QwIpadServerLog;
-import com.fs.qw.domain.QwIpadServerUser;
-import com.fs.qw.domain.QwUser;
+import com.fs.qw.domain.*;
 import com.fs.qw.dto.QwUserByToolDTO;
 import com.fs.qw.dto.QwUserKeyDTO;
 import com.fs.qw.mapper.QwUserMapper;
@@ -52,6 +49,8 @@ import java.util.*;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 /**
  * 企微用户Service业务层处理
@@ -94,6 +93,9 @@ public class QwUserServiceImpl implements IQwUserService
     IQwIpadServerLogService qwIpadServerLogService;
     @Autowired
     IQwIpadServerUserService qwIpadServerUserService;
+    @Autowired
+    IQwExternalContactService externalContactService;
+
     @Override
     public R getQwIpad(QwLoginHookParam loginParam) {
         QwUser qwUser = qwUserMapper.selectQwUserById(loginParam.getQwUserId());
@@ -178,6 +180,54 @@ public class QwUserServiceImpl implements IQwUserService
         return R.ok();
     }
 
+    @Override
+    public List<QwWorkTask> selectQwWorkTaskList(SelectQwWorkTaskListParam param) {
+
+        List<QwWorkTask> qwWorkTasks = qwUserMapper.selectQwWorkTaskList(param);
+
+        // 提取非空的 extId 列表
+        List<Long> extIds = qwWorkTasks.stream()
+                .map(QwWorkTask::getExtId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+
+        if (!extIds.isEmpty()){
+
+            // 查询外部联系人数据,并转为 Map<extId, QwExternalContactVOTime>
+            Map<Long, QwExternalContactVOTime> contactMap =
+                    externalContactService.selectQwExternalContactListVOByIds(extIds)
+                            .stream()
+                            .collect(Collectors.toMap(
+                                    QwExternalContactVOTime::getId,
+                                    Function.identity()
+                            ));
+
+            // 遍历 qwWorkTasks,填充 name、avatar、externalContactId
+            qwWorkTasks.forEach(task -> {
+                Optional.ofNullable(task.getExtId())
+                        .map(contactMap::get)
+                        .ifPresent(contact -> {
+                            task.setName(contact.getName());
+                            task.setAvatar(contact.getAvatar());
+                            task.setExternalContactId(contact.getExternalUserId());
+                        });
+            });
+        }
+
+
+//        for (QwWorkTask qwWorkTask : qwWorkTasks) {
+//            if(qwWorkTask.getExtId() != null) {
+//                QwExternalContact qwExternalContact = externalContactService.selectQwExternalContactById(qwWorkTask.getExtId());
+//                if(qwExternalContact != null) {
+//                    qwWorkTask.setName(qwExternalContact.getName());
+//                    qwWorkTask.setAvatar(qwExternalContact.getAvatar());
+//                    qwWorkTask.setExternalContactId(qwExternalContact.getExternalUserId());
+//                }
+//            }
+//        }
+        return qwWorkTasks;
+    }
+
 
     /**
      * 查询企微用户

+ 34 - 0
fs-service/src/main/java/com/fs/qw/vo/ExternalContactDetailsVO.java

@@ -0,0 +1,34 @@
+package com.fs.qw.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 外部联系人/会员详情 输出参数
+ */
+@Data
+@ApiModel
+public class ExternalContactDetailsVO {
+
+    @ApiModelProperty(value = "答题次数")
+    private int answerTime;
+
+    @ApiModelProperty(value = "答题正确次数")
+    private int answerRightTime;
+
+    @ApiModelProperty(value = "答题红包数")
+    private int answerRedPacketTime;
+
+    @ApiModelProperty(value = "答题红包金额")
+    private BigDecimal answerRedPacketAmount;
+
+    @ApiModelProperty(value = "完播次数")
+    private int courseCompleteTime;
+
+    @ApiModelProperty(value = "观看次数")
+    private int courseWatchTime;
+
+}

+ 24 - 0
fs-service/src/main/java/com/fs/qw/vo/QwExternalListByHeavyVO.java

@@ -0,0 +1,24 @@
+package com.fs.qw.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+@Data
+public class QwExternalListByHeavyVO {
+
+    /**
+    * 员工账号
+    */
+    private String qwUserId;
+
+    /**
+    * 员工姓名
+    */
+    private String qwUserName;
+
+    /**
+    * 添加时间
+    */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private String createTime;
+}

+ 1 - 0
fs-service/src/main/java/com/fs/sop/domain/SopUserLogsInfo.java

@@ -46,6 +46,7 @@ public class SopUserLogsInfo implements Serializable {
 
     @TableField(exist = false)
     private Integer filterMode;
+
     @TableField(exist = false)
     private String chatId;
     @TableField(exist = false)

+ 5 - 1
fs-service/src/main/java/com/fs/sop/mapper/SopUserLogsInfoMapper.java

@@ -96,7 +96,11 @@ public interface SopUserLogsInfoMapper {
     @DataSource(DataSourceType.SOP)
     int deleteSopUserLogsInfoBySopIds(@Param("sopIds") String[] sopIds);
 
-
+    /**
+     * 批量删除
+     */
+    @DataSource(DataSourceType.SOP)
+    int deleteSopUserLogsInfoByUserLogsIds(@Param("userLogsIds") String[] userLogsIds);
     /**
      * 根据ID修改记录
      * @return 影响行数

+ 3 - 0
fs-service/src/main/java/com/fs/sop/mapper/SopUserLogsMapper.java

@@ -26,6 +26,9 @@ public interface SopUserLogsMapper {
     @DataSource(DataSourceType.SOP)
     public int deleteSopUserLogsById(String id);
 
+    @DataSource(DataSourceType.SOP)
+    public int deleteSopUserLogsByIds(String[] ids);
+
     @DataSource(DataSourceType.SOP)
     public int insertSopUserLogsByDate(@Param("data") SopUserLogsParamByDate logsParamByDate);
 

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

@@ -15,6 +15,7 @@ public interface ISopUserLogsService {
 
     public int insertSopUserLogsByDate(SopUserLogsParamByDate logsParamByDate);
 
+    public int deleteSopUserLogsByIds(String[] ids);
 //    public int updateSopUserLogsDistinct(SopUserLogs sopUserLogs);
 
 //    public int updateSopUserLogsDistinctByList(SopUserLogsArray userLogsArray);
@@ -28,6 +29,7 @@ public interface ISopUserLogsService {
     public List<SopUserLogs> selectSopUserLogsList(SopUserLogs sopUserLogs);
 
     public List<SopUserLogsVO> selectSopUserLogsList(SopUserLogsParam param);
+    public List<SopUserLogsVO> selectSopUserLogsGroupListByParam(SopUserLogsParam param);
 
     public String selectSopUserLogsByUpdate(SopUserLogs sopUserLogs);
 

+ 20 - 8
fs-service/src/main/java/com/fs/sop/service/impl/SopUserLogsServiceImpl.java

@@ -120,6 +120,14 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
         return sopUserLogsMapper.insertSopUserLogsByDate(logsParamByDate);
     }
 
+    @Override
+    public int deleteSopUserLogsByIds(String[] ids) {
+        //删除营期详情用户
+        sopUserLogsInfoMapper.deleteSopUserLogsInfoByUserLogsIds(ids);
+
+        return sopUserLogsMapper.deleteSopUserLogsByIds(ids);
+    }
+
 
 //    @Override
 //    public int updateSopUserLogsDistinct(SopUserLogs sopUserLogs) {
@@ -617,14 +625,17 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
 
     @Override
     public List<SopUserLogsVO> selectSopUserLogsList(SopUserLogsParam param) {
-        QwSop qwSop = sopMapper.selectQwSopById(param.getSopId());
-        Integer filterMode = qwSop.getFilterMode();
-        List<SopUserLogsVO> list;
-        if(filterMode == null || filterMode == 1){
-            list = sopUserLogsMapper.selectSopUserLogsListByParam(param);
-        }else{
-            list = sopUserLogsMapper.selectSopUserLogsGroupListByParam(param);
-        }
+        List<SopUserLogsVO> list = sopUserLogsMapper.selectSopUserLogsListByParam(param);
+        return resultSopUserLogsList(list);
+    }
+
+    @Override
+    public List<SopUserLogsVO> selectSopUserLogsGroupListByParam(SopUserLogsParam param) {
+        List<SopUserLogsVO> list = sopUserLogsMapper.selectSopUserLogsGroupListByParam(param);
+        return resultSopUserLogsList(list);
+    }
+
+    private List<SopUserLogsVO> resultSopUserLogsList( List<SopUserLogsVO> list){
         List<String> chatIdList = PubFun.listToNewList(list, SopUserLogsVO::getChatId);
         if(!chatIdList.isEmpty()){
             List<QwGroupChat> qwGroupChatList = qwGroupChatService.selectQwGroupChatByChatIds(chatIdList.toArray(new String[0]));
@@ -633,6 +644,7 @@ public class SopUserLogsServiceImpl  implements ISopUserLogsService {
                 e.setChatName(groupChatMap.get(e.getChatId()).getName());
             });
         }
+
         return list;
     }
 

+ 10 - 0
fs-service/src/main/java/com/fs/statis/service/IStatisticsService.java

@@ -1,6 +1,8 @@
 package com.fs.statis.service;
 
 import com.fs.statis.dto.*;
+import com.fs.statistics.dto.WatchCourseStatisticsDTO;
+import com.fs.statistics.param.WatchCourseStatisticsParam;
 
 import java.util.List;
 
@@ -109,4 +111,12 @@ public interface IStatisticsService {
      * 本月收款数
      */
     void thisMonthRecvCount();
+
+    /**
+     * 查询看课统计
+     *
+     * @param param
+     * @return
+     */
+    public WatchCourseStatisticsDTO queryWatchCourse(WatchCourseStatisticsParam param);
 }

+ 23 - 0
fs-service/src/main/java/com/fs/statis/service/impl/StatisticsServiceImpl.java

@@ -5,7 +5,9 @@ import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.utils.TimeUtils;
 import com.fs.company.cache.ICompanyCacheService;
+import com.fs.course.dto.WatchLogDTO;
 import com.fs.course.mapper.FsCourseTrafficLogMapper;
+import com.fs.course.mapper.FsCourseWatchLogMapper;
 import com.fs.his.service.IFsStoreOrderService;
 import com.fs.his.service.IFsStorePaymentService;
 import com.fs.his.service.IFsStoreProductService;
@@ -15,6 +17,8 @@ import com.fs.statis.dto.*;
 import com.fs.statis.mapper.ConsumptionBalanceMapper;
 import com.fs.statis.service.IStatisticsService;
 import com.fs.statis.service.utils.TrendDataFiller;
+import com.fs.statistics.dto.WatchCourseStatisticsDTO;
+import com.fs.statistics.param.WatchCourseStatisticsParam;
 import com.fs.store.service.cache.IFsUserCourseCacheService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.service.ISysConfigService;
@@ -65,6 +69,9 @@ public class StatisticsServiceImpl implements IStatisticsService {
     @Autowired
     private IFsStoreProductService productService;
 
+    @Autowired
+    private com.fs.course.mapper.FsCourseWatchLogMapper FsCourseWatchLogMapper;
+
     @Autowired
     private ISysConfigService configService;
 
@@ -965,4 +972,20 @@ public class StatisticsServiceImpl implements IStatisticsService {
         R result = R.ok().put("dates", dates).put("orderCount", orderCount).put("payMoney", payMoney);
         redisCache.setCacheObject(THIS_MONTH_RECV_COUNT,result);
     }
+
+    @Override
+    public WatchCourseStatisticsDTO queryWatchCourse(WatchCourseStatisticsParam param) {
+        List<WatchLogDTO> data = null;
+        // 七天
+        if(org.apache.commons.lang3.ObjectUtils.equals(param.getType(),0)) {
+            data = FsCourseWatchLogMapper.selectFsCourseWatchLog7Day(param.getQwExternalContactId());
+        } else if(org.apache.commons.lang3.ObjectUtils.equals(param.getType(),1)){
+            data = FsCourseWatchLogMapper.selectFsCourseWatchLog30DayByExtId(param.getQwExternalContactId());
+        }
+
+        WatchCourseStatisticsDTO watchCourseStatisticsDTO = new WatchCourseStatisticsDTO();
+        watchCourseStatisticsDTO.setData(data);
+
+        return watchCourseStatisticsDTO;
+    }
 }

+ 25 - 0
fs-service/src/main/java/com/fs/statistics/dto/WatchCourseStatisticsDTO.java

@@ -0,0 +1,25 @@
+package com.fs.statistics.dto;
+
+
+import com.fs.course.dto.WatchLogDTO;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 看课统计
+ */
+@Data
+public class WatchCourseStatisticsDTO implements Serializable {
+//    /**
+//     * 观看次数
+//     */
+//    private Long watchCount;
+//    /**
+//     * 完播次数
+//     */
+//    private Long finishCount;
+
+    private List<WatchLogDTO> data;
+}

+ 9 - 0
fs-service/src/main/java/com/fs/statistics/mapper/StatisticsServiceMapper.java

@@ -0,0 +1,9 @@
+package com.fs.statistics.mapper;
+
+import com.fs.statistics.param.WatchCourseStatisticsParam;
+
+public interface StatisticsServiceMapper {
+    public Long queryWatchUserCount(WatchCourseStatisticsParam param);
+
+    public Long queryCompletedCount(WatchCourseStatisticsParam param);
+}

+ 30 - 0
fs-service/src/main/java/com/fs/statistics/param/WatchCourseStatisticsParam.java

@@ -0,0 +1,30 @@
+ package com.fs.statistics.param;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 看课统计参数
+ */
+@Data
+public class WatchCourseStatisticsParam implements Serializable {
+//    /**
+//     * 开始时间
+//     */
+//    private String startTime;
+//    /**
+//     * 结束时间
+//     */
+//    private String endTime;
+
+    /**
+     * 0 七天
+     * 1 30天
+     */
+    private Integer type;
+    /**
+     * 企微外部联系人id
+     */
+    private Long qwExternalContactId;
+}

+ 18 - 0
fs-service/src/main/java/com/fs/statistics/service/IStatisticsService.java

@@ -0,0 +1,18 @@
+package com.fs.statistics.service;
+
+import com.fs.statistics.dto.WatchCourseStatisticsDTO;
+import com.fs.statistics.param.WatchCourseStatisticsParam;
+
+
+public interface IStatisticsService {
+    /**
+     * 查询看课统计
+     *
+     * @param param
+     * @return
+     */
+    public WatchCourseStatisticsDTO queryWatchCourse(WatchCourseStatisticsParam param);
+
+
+
+}

+ 40 - 0
fs-service/src/main/java/com/fs/statistics/service/impl/StatisticsServiceImpl.java

@@ -0,0 +1,40 @@
+package com.fs.statistics.service.impl;
+
+import com.fs.course.dto.WatchLogDTO;
+import com.fs.course.mapper.FsCourseWatchLogMapper;
+import com.fs.statistics.dto.WatchCourseStatisticsDTO;
+import com.fs.statistics.mapper.StatisticsServiceMapper;
+import com.fs.statistics.param.WatchCourseStatisticsParam;
+import com.fs.statistics.service.IStatisticsService;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class StatisticsServiceImpl implements IStatisticsService {
+    @Autowired
+    private StatisticsServiceMapper statisticsServiceMapper;
+
+    @Autowired
+    private FsCourseWatchLogMapper FsCourseWatchLogMapper;
+
+
+    @Override
+    public WatchCourseStatisticsDTO queryWatchCourse(WatchCourseStatisticsParam param) {
+
+        List<WatchLogDTO> data = null;
+        // 七天
+        if(ObjectUtils.equals(param.getType(),0)) {
+            data = FsCourseWatchLogMapper.selectFsCourseWatchLog7Day(param.getQwExternalContactId());
+        } else if(ObjectUtils.equals(param.getType(),1)){
+            data = FsCourseWatchLogMapper.selectFsCourseWatchLog30DayByExtId(param.getQwExternalContactId());
+        }
+
+        WatchCourseStatisticsDTO watchCourseStatisticsDTO = new WatchCourseStatisticsDTO();
+        watchCourseStatisticsDTO.setData(data);
+
+        return watchCourseStatisticsDTO;
+    }
+}

+ 6 - 1
fs-service/src/main/resources/application-config-myhk.yml

@@ -47,7 +47,8 @@ watch:
   password3: v9xsKuqn_$d2y
 
 fs :
-  commonApi: http://172.16.0.16:8010
+#  commonApi: http://172.16.0.16:8010
+  commonApi: http://127.0.0.1:8010
   h5CommonApi: http://119.29.195.254:8010
 nuonuo:
   key: 10924508
@@ -70,5 +71,9 @@ headerImg:
 ipad:
   ipadUrl: http://ipad.cdwjyyh.com
 
+wx_miniapp_temp:
+  pay_order_temp_id: VXEvKaGNPFuJmhWK9O_QPrTZxe9umDCukq-maI8Vdek
+  inquiry_temp_id: 9POPYeqhI48LOPvq-Rfoklze7H-9SlunJKh10Qt4_2I
+
 
 

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

@@ -2,14 +2,14 @@
 spring:
     # redis 配置
     redis:
-#        host: 172.27.0.6
-        host: 127.0.0.1
+        host: 172.27.0.6
+#        host: 127.0.0.1
         port: 6379
         # 数据库索引
         database: 0
         # 密码
-#        password: myhk888777666.
-        password:
+        password: myhk888777666.
+#        password:
         # 连接超时时间
         timeout: 10s
         lettuce:

+ 54 - 0
fs-service/src/main/resources/db/20250530-初始化表结构.sql

@@ -0,0 +1,54 @@
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for sys_keyword
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_keyword`;
+CREATE TABLE `sys_keyword`  (
+                                `keyword_id` bigint NOT NULL AUTO_INCREMENT COMMENT '关键字id',
+                                `keyword` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '关键字',
+                                `company_id` bigint NULL DEFAULT NULL COMMENT '所属公司',
+                                `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+                                `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+                                PRIMARY KEY (`keyword_id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '系统关键字表' ROW_FORMAT = Dynamic;
+
+SET FOREIGN_KEY_CHECKS = 1;
+
+
+    
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for fs_course_watch_comment
+-- ----------------------------
+DROP TABLE IF EXISTS `fs_course_watch_comment`;
+CREATE TABLE `fs_course_watch_comment`  (
+                                            `comment_id` bigint NOT NULL AUTO_INCREMENT COMMENT '评论id',
+                                            `user_id` bigint NULL DEFAULT NULL COMMENT '用户id',
+                                            `user_type` tinyint NULL DEFAULT 2 COMMENT '用户类型,1-管理员,2-用户',
+                                            `course_id` bigint NULL DEFAULT NULL COMMENT '课程id',
+                                            `video_id` bigint NULL DEFAULT NULL COMMENT '视频id',
+                                            `type` tinyint NULL DEFAULT 1 COMMENT '评论类型 1:评论,2:回复',
+                                            `parent_id` bigint NULL DEFAULT NULL COMMENT '父评论id',
+                                            `content` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '评论内容',
+                                            `create_time` datetime NULL DEFAULT NULL COMMENT '评论时间',
+                                            `update_time` datetime NULL DEFAULT NULL,
+                                            `is_revoke` tinyint NULL DEFAULT 0 COMMENT '是否是撤回的消息,1-是,0-否',
+                                            `time` int NULL DEFAULT NULL COMMENT '时间点,记录发送消息的视频播放时间点',
+                                            `font_size` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '字体大小',
+                                            `mode` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '展示模式',
+                                            `color` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '字体颜色',
+                                            PRIMARY KEY (`comment_id`) USING BTREE,
+                                            INDEX `user_id_index`(`user_id` ASC) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 128 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '看课评论表' ROW_FORMAT = Dynamic;
+
+SET FOREIGN_KEY_CHECKS = 1;
+
+
+
+

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

@@ -33,7 +33,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="question != null  and question != ''"> and question = #{question}</if>
             <if test="answer != null  and answer != ''"> and answer = #{answer}</if>
         </where>
-        order by create_time desc
+        order by sort,id
     </select>
 
     <select id="selectFsCourseQuestionBankById" parameterType="Long" resultMap="FsCourseQuestionBankResult">

+ 18 - 0
fs-service/src/main/resources/mapper/course/FsCourseWatchCommentMapper.xml

@@ -130,4 +130,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         order by cwc.create_time desc
     </select>
 
+    <select id="selectH5CourseWatchCommentsRound" resultType="com.fs.course.vo.FsCourseWatchCommentVO">
+        select * from (
+        select cwc.comment_id, cwc.user_id, cwc.user_type, cwc.course_id, cwc.video_id, cwc.type, cwc.content,
+        cwc.create_time,
+        fs_user.nick_name,cwc.time,cwc.font_size, cwc.mode, cwc.color from fs_course_watch_comment cwc
+        left join fs_user on fs_user.user_id = cwc.user_id
+        <where>
+            and cwc.is_revoke = 0
+            <if test="courseId != null">
+                and cwc.course_id = #{courseId}
+            </if>
+            <if test="videoId != null">
+                and cwc.video_id = #{videoId}
+            </if>
+        </where>
+        ORDER BY RAND() LIMIT #{listNum}
+        ) a
+    </select>
 </mapper>

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

@@ -21,6 +21,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <if test="params.typeSubId != null">
             and rr.type_sub_id = #{params.typeSubId}
         </if>
-        order by rr.create_time desc
+        order by rr.id
     </select>
 </mapper>

+ 8 - 0
fs-service/src/main/resources/mapper/his/FsPackageOrderMapper.xml

@@ -309,4 +309,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="selectFsPackageByOrderId" resultType="com.fs.his.domain.FsPackage">
         SELECT fp.* FROM fs_package_order fpo LEFT JOIN fs_package fp ON fpo.package_id = fp.package_id WHERE fpo.order_id = #{packageOrderId}
     </select>
+    <select id="getNewOrder" resultType="com.fs.his.dto.PackageOrderDTO">
+        SELECT O.pay_time AS payTime, O.create_time AS createTime , O.order_sn AS orderSn , O.user_id AS userId ,
+               U.nick_name AS fsUserName , P.package_name AS packageName
+        FROM fs_barrage_package_order O
+            LEFT JOIN fs_user U ON O.user_id = U.user_id
+            LEFT JOIN fs_package P ON O.package_id = P.package_id
+        where O.is_pay = 1 ORDER BY RAND() desc LIMIT 20
+    </select>
 </mapper>

+ 43 - 0
fs-service/src/main/resources/mapper/qw/QwExternalContactInfoMapper.xml

@@ -211,6 +211,49 @@
         where id = #{id}
     </update>
 
+    <update id="updateQwExternalContactInfoByExternalContactId">
+        update qw_external_contact_info
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="externalContactId != null">external_contact_id = #{externalContactId},</if>
+            <if test="name != null">name = #{name},</if>
+            <if test="sex != null">sex = #{sex},</if>
+            <if test="age != null">age = #{age},</if>
+            <if test="address != null">address = #{address},</if>
+            <if test="habits != null">habits = #{habits},</if>
+            <if test="illnessTime != null">illness_time = #{illnessTime},</if>
+            <if test="body != null">body = #{body},</if>
+            <if test="study != null">study = #{study},</if>
+            <if test="courseStatus != null">course_status = #{courseStatus},</if>
+            <if test="family != null">family = #{family},</if>
+            <if test="familyDisease != null">family_disease = #{familyDisease},</if>
+            <if test="talk != null">talk = #{talk},</if>
+            <if test="userType != null">user_type = #{userType},</if>
+            <if test="isSelf != null">is_self = #{isSelf},</if>
+            <if test="intensify != null">intensify = #{intensify},</if>
+            <if test="isCold != null">is_cold = #{isCold},</if>
+            <if test="coldBody != null">cold_body = #{coldBody},</if>
+            <if test="sweat != null">sweat = #{sweat},</if>
+            <if test="other != null">other = #{other},</if>
+            <if test="toilet != null">toilet = #{toilet},</if>
+            <if test="eat != null">eat = #{eat},</if>
+            <if test="menses != null">menses = #{menses},</if>
+            <if test="medicine != null">medicine = #{medicine},</if>
+            <if test="constitution != null">constitution = #{constitution},</if>
+            <if test="recommendMedicine != null">recommend_medicine = #{recommendMedicine},</if>
+            <if test="consultProduct != null">consult_product = #{consultProduct},</if>
+            <if test="isBuy != null">is_buy = #{isBuy},</if>
+            <if test="buyProduct != null">buy_product = #{buyProduct},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="disease != null">disease = #{disease},</if>
+            <if test="isLine != null">is_line = #{isLine},</if>
+            <if test="course != null">course = #{course},</if>
+            <if test="productTalk != null">product_talk = #{productTalk},</if>
+            <if test="diseaseTalk != null">disease_talk = #{diseaseTalk},</if>
+        </trim>
+        where external_contact_id = #{externalContactId}
+    </update>
+
     <delete id="deleteQwExternalContactInfoById" parameterType="Long">
         delete from qw_external_contact_info where id = #{id}
     </delete>

+ 106 - 0
fs-service/src/main/resources/mapper/qw/QwExternalContactMapper.xml

@@ -322,4 +322,110 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <foreach collection="ids" open="(" separator="," close=")" item="item">#{item}</foreach>
         GROUP BY user_id,external_user_id
     </select>
+
+    <select id="getCountAnswer" resultType="com.fs.qw.vo.ExternalContactDetailsVO">
+        SELECT
+        count( DISTINCT fs_course_answer_logs.log_id ) AS answerTime,
+        count( DISTINCT CASE WHEN fs_course_answer_logs.is_right = 1 THEN fs_course_answer_logs.log_id END ) AS answerRightTime,
+        is_right,
+        qw_external_contact.id,
+        qw_external_contact.external_user_id,
+        qw_external_contact.qw_user_id
+        FROM
+        fs_course_answer_logs
+        LEFT JOIN qw_user ON qw_user.id = fs_course_answer_logs.qw_user_id
+        LEFT JOIN qw_external_contact ON qw_external_contact.user_id = qw_user.qw_user_id
+        <where>
+            <if test="param.dateTag != null and param.dateTag !='' ">
+                <choose>
+                    <when test = "param.dateTag == '今天'">
+                        and to_days(fs_course_answer_logs.create_time) = to_days(now())
+                    </when>
+                    <when test = "param.dateTag == ' 昨天'">
+                        and to_days(now()) - to_days(fs_course_answer_logs.create_time) &lt;= 1
+                    </when>
+                    <when test = "param.dateTag == '前天'">
+                        and to_days(now()) - to_days(fs_course_answer_logs.create_time) &lt;= 2
+                    </when>
+                    <when test = "param.dateTag == '近七天'">
+                        and DATE_SUB(CURDATE(), INTERVAL 7 DAY) &lt;= date(fs_course_answer_logs.create_time)
+                    </when>
+                </choose>
+            </if>
+        </where>
+        GROUP BY
+        qw_external_contact.id
+        HAVING
+        qw_external_contact.id = #{param.contactId}
+    </select>
+
+    <select id="getCountRedPacket" resultType="com.fs.qw.vo.ExternalContactDetailsVO">
+        SELECT
+        count( DISTINCT log_id ) AS answerRedPacketTime,
+        ifnull(sum( amount ), 0) AS answerRedPacketAmount,
+        amount,
+        qw_external_contact.id,
+        qw_external_contact.external_user_id,
+        qw_external_contact.qw_user_id
+        FROM
+        fs_course_red_packet_log
+        LEFT JOIN qw_user ON qw_user.id = fs_course_red_packet_log.qw_user_id
+        LEFT JOIN qw_external_contact ON qw_external_contact.user_id = qw_user.qw_user_id
+        <where>
+            <if test="param.dateTag != null and param.dateTag !='' ">
+                <choose>
+                    <when test = "param.dateTag == '今天'">
+                        and to_days(fs_course_red_packet_log.create_time) = to_days(now())
+                    </when>
+                    <when test = "param.dateTag == ' 昨天'">
+                        and to_days(now()) - to_days(fs_course_red_packet_log.create_time) &lt;= 1
+                    </when>
+                    <when test = "param.dateTag == '前天'">
+                        and to_days(now()) - to_days(fs_course_red_packet_log.create_time) &lt;= 2
+                    </when>
+                    <when test = "param.dateTag == '近七天'">
+                        and DATE_SUB(CURDATE(), INTERVAL 7 DAY) &lt;= date(fs_course_red_packet_log.create_time)
+                    </when>
+                </choose>
+            </if>
+        </where>
+        GROUP BY
+        qw_external_contact.id
+        HAVING
+        qw_external_contact.id = #{param.contactId}
+    </select>
+
+    <select id="getCountCourseWatch" resultType="com.fs.qw.vo.ExternalContactDetailsVO">
+        SELECT
+        count( CASE WHEN fwl.log_type != 3 THEN fwl.log_id END ) AS courseWatchTime,
+        count( CASE WHEN fwl.log_type = 2 THEN fwl.log_id END ) AS courseCompleteTime,
+        GROUP_CONCAT( fwl.video_id ),
+        fwl.qw_external_contact_id,
+        fwl.qw_user_id
+        FROM
+        fs_course_watch_log fwl
+        <where>
+            <if test="param.dateTag != null and param.dateTag !='' ">
+                <choose>
+                    <when test = "param.dateTag == '今天'">
+                        and to_days(fwl.update_time) = to_days(now())
+                    </when>
+                    <when test = "param.dateTag == ' 昨天'">
+                        and to_days(now()) - to_days(fwl.update_time) &lt;= 1
+                    </when>
+                    <when test = "param.dateTag == '前天'">
+                        and to_days(now()) - to_days(fwl.update_time) &lt;= 2
+                    </when>
+                    <when test = "param.dateTag == '近七天'">
+                        and DATE_SUB(CURDATE(), INTERVAL 7 DAY) &lt;= date(fwl.update_time)
+                    </when>
+                </choose>
+            </if>
+        </where>
+        GROUP BY
+        fwl.qw_external_contact_id
+        having fwl.qw_external_contact_id = #{param.contactId}
+
+    </select>
+
 </mapper>

+ 12 - 0
fs-service/src/main/resources/mapper/qw/QwUserMapper.xml

@@ -214,4 +214,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{userId}
         </foreach>
     </select>
+
+
+    <select id="selectQwWorkTaskList" resultType="com.fs.qw.domain.QwWorkTask">
+        select
+            qwt.id,qwt.ext_id, qwt.qw_user_id, qwt.status, qwt.track_type, qwt.type, qwt.title, qwt.remark, qwt.score, qwt.sop_id,
+            qwt.company_id, qwt.company_user_id, qwt.duration, qwt.create_time, qwt.update_time
+        from qw_work_task qwt
+        where qwt.qw_user_id = #{userId}
+          and date(qwt.create_time) = #{date}
+          and qwt.status = 0
+    </select>
+
 </mapper>

+ 1 - 1
fs-service/src/main/resources/mapper/qw/QwWatchLogMapper.xml

@@ -38,7 +38,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             resultType="com.fs.qw.vo.QwWatchLogAllStatisticsListVO">
         select
         any_value(company_id) as company_id,
-        company_user_id,line_time as create_time,
+        company_user_id,MIN(line_time) as create_time,
         COUNT(CASE WHEN day = 0 and status in (1,2) THEN 1 END) AS firstOnline,
         COUNT(CASE WHEN day = 0 and status=2 THEN 1 END) AS firstOver,
         COUNT(CASE WHEN day = 1 and status in (1,2) THEN 1 END) AS d1Online,

+ 5 - 1
fs-service/src/main/resources/mapper/sop/QwSopMapper.xml

@@ -17,6 +17,7 @@
         <result property="tags"    column="tags"    />
         <result property="excludeTags"    column="exclude_tags"    />
         <result property="startTime"    column="start_time"  />
+        <result property="filterMode"    column="filter_mode"  />
         <result property="filterType"    column="filter_type"    />
         <result property="tempId"    column="temp_id"    />
         <result property="corpId"    column="corp_id"    />
@@ -34,7 +35,10 @@
     </resultMap>
 
     <sql id="selectQwSopVo">
-        select *  from qw_sop
+        select id,name,status,type,qw_user_ids,create_by,create_time,company_id,send_type,tags,exclude_tags,start_time,
+               filter_mode,filter_type,temp_id,corp_id,expiry_time,is_auto_sop,auto_sop_time,min_conversion_day,
+               max_conversion_day,min_send,max_send,stop_time,is_rating,course_day,open_comment_status
+        from qw_sop
     </sql>
 
     <select id="selectQwSopAutoByTagsByForeach"  resultType="com.fs.qw.vo.QwSopRuleTimeVO">

+ 9 - 0
fs-service/src/main/resources/mapper/sop/SopUserLogsInfoMapper.xml

@@ -172,6 +172,15 @@
             and external_id = #{data.externalId}
     </delete>
 
+    <delete id="deleteSopUserLogsInfoByUserLogsIds" parameterType="map">
+        DELETE FROM sop_user_logs_info  WHERE user_logs_id IN
+        <foreach item="userLogsId" index="index" collection="userLogsIds"
+                 open="(" separator="," close=")">
+            #{userLogsId}
+        </foreach>
+    </delete>
+
+
 
     <!-- 根据ID查询单条记录 -->
     <select id="selectById" parameterType="String" resultMap="SopUserLogsInfoResult">

+ 7 - 0
fs-service/src/main/resources/mapper/sop/SopUserLogsMapper.xml

@@ -50,6 +50,13 @@
         DELETE FROM sop_user_logs  WHERE id = #{id}
     </delete>
 
+    <delete id="deleteSopUserLogsByIds" parameterType="String">
+        delete from sop_user_logs where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
     <insert id="insertSopUserLogsByDate" parameterType="com.fs.sop.params.SopUserLogsParamByDate" useGeneratedKeys="false" >
         insert into sop_user_logs
         <trim prefix="(" suffix=")" suffixOverrides=",">

+ 0 - 2
fs-user-app/src/main/java/com/fs/app/config/WebSocketConfig.java

@@ -12,7 +12,6 @@ public class WebSocketConfig {
      *
      * @return
      */
-
     @Bean
     public ServerEndpointExporter serverEndpointExporter() {
         return new ServerEndpointExporter();
@@ -24,7 +23,6 @@ public class WebSocketConfig {
      *
      * @return
      */
-
     @Bean
     public ServletServerContainerFactoryBean createWebSocketContainer() {
         ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();

+ 6 - 15
fs-user-app/src/main/java/com/fs/app/controller/CourseController.java

@@ -562,26 +562,17 @@ public class CourseController extends  AppBaseController{
 
     @ApiOperation("获取历史评论数据")
     @GetMapping("/getComments")
-    public ResponseResult<PageInfo<FsCourseWatchCommentVO>> getCourseWatchComments(@ApiParam(value = "页码", required = true) @RequestParam Integer pageNum,
-            @ApiParam(value = "每页大小", required = true) @RequestParam Integer pageSize,
-            @ApiParam(value = "课程id", required = true) @RequestParam Long courseId,
-            @ApiParam(value = "视频id", required = true) @RequestParam Long videoId)
+    public R getCourseWatchComments(FsCourseWatchCommentListParam param)
     {
         //获取配置信息中需要查询的数据条数
-//        String json = configService.selectConfigByKey("course.config");
-//        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-
-        FsCourseWatchCommentListParam param = new FsCourseWatchCommentListParam();
-        param.setPageNum(pageNum);
-        param.setPageSize(pageSize);
-        param.setCourseId(courseId);
-        param.setVideoId(videoId);
-//        param.setListNum(config.getViewCommentNum() != null &&  config.getViewCommentNum() != 0 ? config.getViewCommentNum() : 200);
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        param.setListNum(config.getViewCommentNum() != null &&  config.getViewCommentNum() != 0 ? config.getViewCommentNum() : 200);
 
-        PageHelper.startPage(pageNum, pageSize);
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
         List<FsCourseWatchCommentVO> list = courseWatchCommentService.selectH5CourseWatchComments(param);
         PageInfo<FsCourseWatchCommentVO> pageInfo = new PageInfo<>(list);
-        return ResponseResult.ok(pageInfo);
+        return R.ok().put("data", pageInfo);
     }
 
 }

+ 3 - 1
fs-user-app/src/main/java/com/fs/app/controller/PackageController.java

@@ -86,6 +86,7 @@ public class PackageController extends AppBaseController {
             }
         } else {
             log.info("zyp \n【套餐包不存在】:{}", packageId);
+            return R.error("套餐包不存在");
         }
 
         FsPackageDetailVO vo = new FsPackageDetailVO();
@@ -98,7 +99,8 @@ public class PackageController extends AppBaseController {
                     fsPackage.setImgUrl(s);
                 }
             } catch (Exception e) {
-                throw new RuntimeException(e);
+//                throw new RuntimeException(e);
+                log.error(e.getMessage());
             }
 
         }

+ 36 - 0
fs-user-app/src/main/java/com/fs/app/controller/PackageOrderController.java

@@ -11,6 +11,7 @@ import com.fs.common.utils.StringUtils;
 import com.fs.his.domain.*;
 import com.fs.his.dto.FsInquiryOrderPatientDTO;
 import com.fs.his.dto.FsStoreOrderAddressDTO;
+import com.fs.his.dto.PackageOrderDTO;
 import com.fs.his.param.*;
 import com.fs.his.service.*;
 import com.fs.his.vo.*;
@@ -25,6 +26,7 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
 import java.util.*;
+import java.util.concurrent.ThreadLocalRandom;
 
 
 @Api("套餐订单接口")
@@ -198,4 +200,38 @@ public class PackageOrderController extends  AppBaseController {
         return R.ok().put("count",count);
     }
 
+    @ApiOperation("/根据套餐id查询最新的20条订单")
+    @GetMapping("/getNewOrderByPackageId")
+    public R getNewOrderByPackageId(@RequestParam("packageId") Long packageId){
+        List<PackageOrderDTO> newOrderByPackageId = packageOrderService.getNewOrder();
+
+        // 当前时间 和 10分钟前
+        long nowMillis = System.currentTimeMillis();
+        long tenMinutesAgoMillis = nowMillis - 10 * 60 * 1000;
+
+        for (PackageOrderDTO dto : newOrderByPackageId) {
+            // 在10分钟内随机一个时间戳
+            long randomMillis = ThreadLocalRandom.current().nextLong(tenMinutesAgoMillis, nowMillis);
+            dto.setPayTime(new Date(randomMillis));
+            //用户名脱敏
+            // 脱敏 fsUserName 字段(保留首尾)
+            String fsUserName = dto.getFsUserName();
+            if (fsUserName != null && fsUserName.length() > 2) {
+                StringBuilder sb = new StringBuilder();
+                sb.append(fsUserName.charAt(0)); // 第一个字符
+                for (int i = 1; i < fsUserName.length() - 1; i++) {
+                    sb.append("*"); // 中间全部 *
+                }
+                sb.append(fsUserName.charAt(fsUserName.length() - 1)); // 最后一个字符
+                dto.setFsUserName(sb.toString());
+            }
+            // 如果只有 2 个字符,不需要加星
+            else if (fsUserName != null && fsUserName.length() == 2) {
+                dto.setFsUserName(fsUserName);
+            }
+        }
+
+        return R.ok().put("data", newOrderByPackageId);
+    }
+
 }

+ 1 - 1
fs-user-app/src/main/java/com/fs/app/utils/JwtUtils.java

@@ -32,7 +32,7 @@ public class JwtUtils {
         //过期时间
         Date expireDate = new Date(nowDate.getTime() + expire * 1000);
 //        System.out.println("==============================="+secret);
-        logger.info("secret:{}",secret);
+//        logger.info("secret:{}",secret);
         return Jwts.builder()
                 .setHeaderParam("typ", "JWT")
                 .setSubject(userId+"")

+ 3 - 0
fs-user-app/src/main/java/com/fs/websocket/bean/SendMsgVO.java

@@ -14,6 +14,9 @@ public class SendMsgVO {
     @ApiModelProperty("用户id")
     private Long userId;
 
+    @ApiModelProperty(value = "用户名称")
+    private String nickName;
+
     @ApiModelProperty("用户类型,1-管理员,2-用户")
     private Integer userType;