Browse Source

Merge remote-tracking branch 'origin/master' into ScrmStore

# Conflicts:
#	fs-service/src/main/resources/application-config-druid-yjb.yml
yjwang 3 weeks ago
parent
commit
112c59d688
75 changed files with 1601 additions and 519 deletions
  1. 8 0
      fs-admin/src/main/java/com/fs/api/controller/IndexStatisticsController.java
  2. 36 2
      fs-admin/src/main/java/com/fs/course/controller/FsCourseQuestionBankController.java
  3. 16 0
      fs-admin/src/main/java/com/fs/course/controller/FsCourseTrafficLogController.java
  4. 52 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseController.java
  5. 16 4
      fs-admin/src/main/java/com/fs/course/controller/FsUserCoursePeriodController.java
  6. 25 1
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseTrainingCampController.java
  7. 45 2
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseVideoController.java
  8. 34 2
      fs-admin/src/main/java/com/fs/course/controller/FsVideoResourceController.java
  9. 19 0
      fs-admin/src/main/java/com/fs/his/task/trafficlog/TrafficlogTask.java
  10. 2 0
      fs-company/src/main/java/com/fs/company/controller/company/IndexStatisticsController.java
  11. 1 1
      fs-company/src/main/java/com/fs/company/controller/course/FsUserCourseVideoController.java
  12. 6 0
      fs-company/src/main/java/com/fs/company/controller/qw/QwUserController.java
  13. 37 1
      fs-ipad-task/src/main/java/com/fs/app/service/IpadSendServer.java
  14. 24 2
      fs-ipad-task/src/main/java/com/fs/app/task/SendMsg.java
  15. 1 1
      fs-qw-task/src/main/java/com/fs/FsQwTaskApplication.java
  16. 9 7
      fs-qw-task/src/main/java/com/fs/app/controller/CommonController.java
  17. 1 228
      fs-service/src/main/java/com/fs/company/domain/Company.java
  18. 3 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyMiniappServiceImpl.java
  19. 2 2
      fs-service/src/main/java/com/fs/core/config/WxOpenProperties.java
  20. 5 0
      fs-service/src/main/java/com/fs/course/config/CourseConfig.java
  21. 2 0
      fs-service/src/main/java/com/fs/course/domain/FsVideoResource.java
  22. 67 0
      fs-service/src/main/java/com/fs/course/mapper/FsCourseTrafficLogMapper.java
  23. 22 0
      fs-service/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java
  24. 4 1
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseMapper.java
  25. 3 0
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java
  26. 23 0
      fs-service/src/main/java/com/fs/course/param/BatchCompanyRedPackageParam.java
  27. 9 0
      fs-service/src/main/java/com/fs/course/param/TrafficRecord.java
  28. 1 1
      fs-service/src/main/java/com/fs/course/service/IFsCourseQuestionBankService.java
  29. 10 0
      fs-service/src/main/java/com/fs/course/service/IFsCourseTrafficLogService.java
  30. 1 1
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseTrainingCampService.java
  31. 14 8
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseVideoRedPackageService.java
  32. 1 2
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseVideoService.java
  33. 2 1
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseQuestionBankServiceImpl.java
  34. 166 4
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseTrafficLogServiceImpl.java
  35. 8 0
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseServiceImpl.java
  36. 2 1
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseTrainingCampServiceImpl.java
  37. 50 8
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoRedPackageServiceImpl.java
  38. 46 69
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  39. 94 86
      fs-service/src/main/java/com/fs/course/service/impl/FsUserWatchCourseStatisticsServiceImpl.java
  40. 15 0
      fs-service/src/main/java/com/fs/course/vo/FsUserCourseParticipationRecordVO.java
  41. 63 9
      fs-service/src/main/java/com/fs/ipad/IpadSendUtils.java
  42. 12 0
      fs-service/src/main/java/com/fs/ipad/param/WxGetSessionRoomListParam.java
  43. 11 0
      fs-service/src/main/java/com/fs/ipad/param/WxRoomUserListParam.java
  44. 18 0
      fs-service/src/main/java/com/fs/ipad/param/WxSendAtMsgParam.java
  45. 23 0
      fs-service/src/main/java/com/fs/ipad/vo/WxGetSessionRoomListVo.java
  46. 44 0
      fs-service/src/main/java/com/fs/ipad/vo/WxRoomUserListVo.java
  47. 19 0
      fs-service/src/main/java/com/fs/ipad/vo/WxSendAtMsgVo.java
  48. 22 0
      fs-service/src/main/java/com/fs/ipad/vo/WxVideoVo.java
  49. 1 0
      fs-service/src/main/java/com/fs/qw/domain/QwUser.java
  50. 7 0
      fs-service/src/main/java/com/fs/qw/domain/QwUserVideo.java
  51. 2 0
      fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java
  52. 4 0
      fs-service/src/main/java/com/fs/qw/service/IQwUserService.java
  53. 71 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwUserServiceImpl.java
  54. 1 0
      fs-service/src/main/java/com/fs/qw/vo/QwSopCourseFinishTempSetting.java
  55. 4 0
      fs-service/src/main/java/com/fs/statis/dto/TrafficLogDTO.java
  56. 19 19
      fs-service/src/main/java/com/fs/task/trafficlog/TrafficlogTask.java
  57. 38 0
      fs-service/src/main/java/com/fs/wxwork/dto/WxwSendVideoNumberMsgDTO.java
  58. 45 16
      fs-service/src/main/java/com/fs/wxwork/service/WxWorkServiceNew.java
  59. 90 0
      fs-service/src/main/resources/application-config-druid-drk-test.yml
  60. 1 1
      fs-service/src/main/resources/application-config-druid-kyt.yml
  61. 1 1
      fs-service/src/main/resources/application-config-druid-sxjz.yml
  62. 2 4
      fs-service/src/main/resources/application-config-druid-yjb.yml
  63. 3 20
      fs-service/src/main/resources/application-config-zkzh.yml
  64. 143 0
      fs-service/src/main/resources/application-druid-drk-test.yml
  65. 9 4
      fs-service/src/main/resources/application-druid-kyt.yml
  66. 4 0
      fs-service/src/main/resources/mapper/company/CompanyMapper.xml
  67. 7 2
      fs-service/src/main/resources/mapper/course/FsCourseQuestionBankMapper.xml
  68. 1 1
      fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml
  69. 3 0
      fs-service/src/main/resources/mapper/course/FsUserCourseMapper.xml
  70. 3 1
      fs-service/src/main/resources/mapper/course/FsUserCourseTrainingCampMapper.xml
  71. 3 0
      fs-service/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml
  72. 3 0
      fs-service/src/main/resources/mapper/course/FsVideoResourceMapper.xml
  73. 1 0
      fs-service/src/main/resources/mapper/his/FsUserMapper.xml
  74. 9 1
      fs-service/src/main/resources/mapper/qw/QwUserMapper.xml
  75. 32 5
      fs-service/src/main/resources/mapper/qw/QwUserVideoMapper.xml

+ 8 - 0
fs-admin/src/main/java/com/fs/api/controller/IndexStatisticsController.java

@@ -4,6 +4,8 @@ import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.statis.StatisticsRedisConstant;
 import com.fs.statis.dto.*;
+import com.fs.system.domain.SysConfig;
+import com.fs.system.service.ISysConfigService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -20,6 +22,9 @@ import static com.fs.statis.StatisticsRedisConstant.*;
 public class IndexStatisticsController {
     @Autowired
     private RedisCache redisCache;
+
+    @Autowired
+    private ISysConfigService sysConfigService;
     /**
      * 分析概览
      */
@@ -59,6 +64,9 @@ public class IndexStatisticsController {
     @GetMapping("/trafficLog")
     public R getTrafficLog(){
         TrafficLogDTO trafficLogDTO = redisCache.getCacheObject(DATA_OVERVIEW_TRAFFIC_LOG);
+        SysConfig sysConfig = sysConfigService.selectConfigByConfigKey("redPacket.Traffic.config");
+        String configValue = sysConfig.getConfigValue();
+        trafficLogDTO.setTraffic(configValue);
         return R.ok().put("data",trafficLogDTO);
     }
 

+ 36 - 2
fs-admin/src/main/java/com/fs/course/controller/FsCourseQuestionBankController.java

@@ -1,5 +1,7 @@
 package com.fs.course.controller;
 
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONUtil;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
@@ -8,10 +10,12 @@ import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsCourseQuestionBank;
 import com.fs.course.dto.FsCourseQuestionBankImportDTO;
 import com.fs.course.service.IFsCourseQuestionBankService;
 import com.fs.framework.web.service.TokenService;
+import com.fs.system.service.ISysConfigService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
@@ -34,7 +38,8 @@ public class FsCourseQuestionBankController extends BaseController
 
     @Autowired
     private TokenService tokenService;
-
+    @Autowired
+    private ISysConfigService configService;
     /**
      * 查询题库列表
      */
@@ -43,6 +48,13 @@ public class FsCourseQuestionBankController extends BaseController
     public TableDataInfo list(FsCourseQuestionBank fsCourseQuestionBank)
     {
         startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsCourseQuestionBank.setUserId(userId);
+        }
         List<FsCourseQuestionBank> list = fsCourseQuestionBankService.selectFsCourseQuestionBankList(fsCourseQuestionBank);
         return getDataTable(list);
     }
@@ -55,6 +67,14 @@ public class FsCourseQuestionBankController extends BaseController
     @GetMapping("/export")
     public AjaxResult export(FsCourseQuestionBank fsCourseQuestionBank)
     {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsCourseQuestionBank.setUserId(userId);
+        }
+
         List<FsCourseQuestionBankImportDTO> list = fsCourseQuestionBankService.exportData(fsCourseQuestionBank);
         ExcelUtil<FsCourseQuestionBankImportDTO> util = new ExcelUtil<>(FsCourseQuestionBankImportDTO.class);
         return util.exportExcel(list, "题库数据");
@@ -81,6 +101,13 @@ public class FsCourseQuestionBankController extends BaseController
     {
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         fsCourseQuestionBank.setCreateBy(loginUser.getUser().getNickName());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsCourseQuestionBank.setUserId(userId);
+        }
+
         return toAjax(fsCourseQuestionBankService.insertFsCourseQuestionBank(fsCourseQuestionBank));
     }
 
@@ -121,7 +148,14 @@ public class FsCourseQuestionBankController extends BaseController
         List<FsCourseQuestionBankImportDTO> list = util.importExcel(file.getInputStream());
 
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        String message = fsCourseQuestionBankService.importData(list, loginUser.getUser().getNickName());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            String message = fsCourseQuestionBankService.importData(list, loginUser.getUser().getNickName(),userId);
+            return AjaxResult.success(message);
+        }
+        String message = fsCourseQuestionBankService.importData(list, loginUser.getUser().getNickName(),null);
         return AjaxResult.success(message);
     }
 

+ 16 - 0
fs-admin/src/main/java/com/fs/course/controller/FsCourseTrafficLogController.java

@@ -4,8 +4,10 @@ import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.List;
 
+import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
 import com.fs.course.param.FsCourseTrafficLogParam;
+import com.fs.course.param.InternetTrafficParam;
 import com.fs.course.vo.FsCourseTrafficLogListVO;
 import com.fs.qw.param.QwWatchLogStatisticsListParam;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -121,4 +123,18 @@ public class FsCourseTrafficLogController extends BaseController
     {
         return toAjax(fsCourseTrafficLogService.deleteFsCourseTrafficLogByLogIds(logIds));
     }
+
+    /**
+     * 充值流量
+     *
+     * @param internetTrafficParam
+     * @return
+     */
+    @PostMapping(value = "/rechargeTraffic")
+    public R rechargeTraffic(@RequestBody InternetTrafficParam internetTrafficParam) {
+
+        fsCourseTrafficLogService.updateTrafficStatus(internetTrafficParam);
+        return R.ok().put("data", null);  // 返回计算结果
+    }
+
 }

+ 52 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseController.java

@@ -2,13 +2,17 @@ package com.fs.course.controller;
 
 import java.util.List;
 
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONUtil;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.model.LoginUser;
 import com.fs.common.utils.ServletUtils;
+import com.fs.course.config.CourseConfig;
 import com.fs.course.vo.FsUserCourseListPVO;
 import com.fs.framework.web.service.TokenService;
 import com.fs.his.utils.RedisCacheUtil;
 import com.fs.his.vo.OptionsVO;
+import com.fs.system.service.ISysConfigService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -44,6 +48,12 @@ public class FsUserCourseController extends BaseController
     @Autowired
     private RedisCacheUtil redisCacheUtil;
 
+    @Autowired
+    private TokenService tokenService;
+
+    @Autowired
+    private ISysConfigService configService;
+
     /**
      * 查询课程列表
      */
@@ -52,6 +62,13 @@ public class FsUserCourseController extends BaseController
     public TableDataInfo list(FsUserCourse fsUserCourse)
     {
         startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsUserCourse.setUserId(userId);
+        }
         List<FsUserCourseListPVO> list = fsUserCourseService.selectFsUserCourseListPVO(fsUserCourse);
         return getDataTable(list);
     }
@@ -64,6 +81,13 @@ public class FsUserCourseController extends BaseController
     public TableDataInfo publicList(FsUserCourse fsUserCourse)
     {
         startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsUserCourse.setUserId(userId);
+        }
         List<FsUserCourseListPVO> list = fsUserCourseService.selectFsUserCourseListPVO(fsUserCourse);
         return getDataTable(list);
     }
@@ -76,6 +100,13 @@ public class FsUserCourseController extends BaseController
     @GetMapping("/export")
     public AjaxResult export(FsUserCourse fsUserCourse)
     {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsUserCourse.setUserId(userId);
+        }
         List<FsUserCourse> list = fsUserCourseService.selectFsUserCourseList(fsUserCourse);
         ExcelUtil<FsUserCourse> util = new ExcelUtil<FsUserCourse>(FsUserCourse.class);
         return util.exportExcel(list, "课程数据");
@@ -89,6 +120,13 @@ public class FsUserCourseController extends BaseController
     @GetMapping("/publicExport")
     public AjaxResult publicExport(FsUserCourse fsUserCourse)
     {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsUserCourse.setUserId(userId);
+        }
         List<FsUserCourse> list = fsUserCourseService.selectFsUserCourseList(fsUserCourse);
         ExcelUtil<FsUserCourse> util = new ExcelUtil<FsUserCourse>(FsUserCourse.class);
         return util.exportExcel(list, "课程数据");
@@ -122,6 +160,13 @@ public class FsUserCourseController extends BaseController
     @PostMapping
     public AjaxResult add(@RequestBody FsUserCourse fsUserCourse)
     {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsUserCourse.setUserId(userId);
+        }
         fsUserCourseService.insertFsUserCourse(fsUserCourse);
         redisCacheUtil.delRedisKey("getCourseList");
 
@@ -136,6 +181,13 @@ public class FsUserCourseController extends BaseController
     @PostMapping("/public")
     public AjaxResult publicAdd(@RequestBody FsUserCourse fsUserCourse)
     {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsUserCourse.setUserId(userId);
+        }
         fsUserCourseService.insertFsUserCourse(fsUserCourse);
         redisCacheUtil.delRedisKey("getCourseList");
 

+ 16 - 4
fs-admin/src/main/java/com/fs/course/controller/FsUserCoursePeriodController.java

@@ -10,10 +10,7 @@ import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.course.domain.FsUserCoursePeriod;
 import com.fs.course.domain.FsUserCoursePeriodDays;
 import com.fs.course.domain.FsUserCourseVideoRedPackage;
-import com.fs.course.param.CompanyRedPacketParam;
-import com.fs.course.param.FsBatchPeriodRedPackageParam;
-import com.fs.course.param.PeriodCountParam;
-import com.fs.course.param.PeriodStatisticCountParam;
+import com.fs.course.param.*;
 import com.fs.course.service.IFsUserCoursePeriodDaysService;
 import com.fs.course.service.IFsUserCoursePeriodService;
 import com.fs.course.service.IFsUserCourseVideoRedPackageService;
@@ -25,6 +22,7 @@ import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import java.math.BigDecimal;
@@ -273,4 +271,18 @@ public class FsUserCoursePeriodController extends BaseController {
         List<FsUserCoursePeriod> list = fsUserCoursePeriodService.selectFsPeriodlist(param);
         return R.ok().put("data", list);
     }
+
+    @PreAuthorize("@ss.hasPermi('course:period:setCompanyRedPacket')")
+    @ApiOperation("按公司批量保存设置红包金额")
+    @PostMapping("/batchRedPacket/byCompany")
+    public R batchRedPacketByCompany(@Validated @RequestBody BatchCompanyRedPackageParam param) {
+        try {
+            fsUserCourseVideoRedPackageService.batchRedPacketByCompany(param);
+        } catch (Exception e) {
+            logger.error("按恭送批量保存设置红包金额-失败!,入参:{}", param);
+            return R.error("保存失败!");
+        }
+        return R.ok();
+    }
+
 }

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

@@ -1,5 +1,7 @@
 package com.fs.course.controller;
 
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONUtil;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
@@ -7,12 +9,15 @@ import com.fs.common.core.domain.model.LoginUser;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.SortUtils;
+import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsUserCourseTrainingCamp;
 import com.fs.course.dto.FsUserCourseTrainingCampDTO;
 import com.fs.course.dto.FsUserCourseTrainingCampUpdateDTO;
 import com.fs.course.service.IFsUserCourseTrainingCampService;
 import com.fs.course.vo.FsUserCourseTrainingCampVO;
+import com.fs.framework.web.service.TokenService;
 import com.fs.his.vo.OptionsVO;
+import com.fs.system.service.ISysConfigService;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import lombok.AllArgsConstructor;
@@ -31,7 +36,9 @@ import java.util.Objects;
 public class FsUserCourseTrainingCampController {
 
     private final IFsUserCourseTrainingCampService fsUserCourseTrainingCampService;
+    private final TokenService tokenService;
 
+    private final ISysConfigService configService;
     /**
      * 查询训练营列表
      */
@@ -48,6 +55,14 @@ public class FsUserCourseTrainingCampController {
         params.put("scs", SortUtils.parseSort(scs));
         params.put("userId", userId);
 
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userIds = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            params.put("userIds", userIds);
+        }
+
         PageHelper.startPage(pageNum, pageSize);
         List<FsUserCourseTrainingCampVO> list = fsUserCourseTrainingCampService.selectFsUserCourseTrainingCampVOListByMap(params);
         return AjaxResult.success(new PageInfo<>(list));
@@ -62,7 +77,16 @@ public class FsUserCourseTrainingCampController {
     @Log(title = "训练营", businessType = BusinessType.INSERT)
     @PostMapping
     public AjaxResult add(@Valid @RequestBody FsUserCourseTrainingCampDTO params) {
-        fsUserCourseTrainingCampService.add(params);
+
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userIds = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsUserCourseTrainingCampService.add(params,userIds);
+            return AjaxResult.success();
+        }
+        fsUserCourseTrainingCampService.add(params,null);
         return AjaxResult.success();
     }
 

+ 45 - 2
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseVideoController.java

@@ -1,5 +1,7 @@
 package com.fs.course.controller;
 
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONUtil;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
@@ -9,6 +11,7 @@ import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsUserCourse;
 import com.fs.course.domain.FsUserCourseVideo;
 import com.fs.course.mapper.FsUserCourseVideoMapper;
@@ -19,6 +22,7 @@ import com.fs.course.service.IFsUserCourseService;
 import com.fs.course.service.IFsUserCourseVideoService;
 import com.fs.framework.web.service.TokenService;
 import com.fs.his.vo.OptionsVO;
+import com.fs.system.service.ISysConfigService;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -46,6 +50,11 @@ public class FsUserCourseVideoController extends BaseController
     private FsUserCourseVideoMapper fsUserCourseVideoMapper;
     @Autowired
     private IFsUserCourseService fsUserCourseService;
+    @Autowired
+    private TokenService tokenService;
+
+    @Autowired
+    private ISysConfigService configService;
 
     /**
      * 查询课堂视频列表
@@ -54,6 +63,13 @@ public class FsUserCourseVideoController extends BaseController
     @GetMapping("/list")
     public TableDataInfo list(FsUserCourseVideo fsUserCourseVideo)
     {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsUserCourseVideo.setUserId(userId);
+        }
         startPage();
         List<FsUserCourseVideo> list = fsUserCourseVideoService.selectFsUserCourseVideoList(fsUserCourseVideo);
         return getDataTable(list);
@@ -67,6 +83,13 @@ public class FsUserCourseVideoController extends BaseController
     @GetMapping("/export")
     public AjaxResult export(FsUserCourseVideo fsUserCourseVideo)
     {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsUserCourseVideo.setUserId(userId);
+        }
         List<FsUserCourseVideo> list = fsUserCourseVideoService.selectFsUserCourseVideoList(fsUserCourseVideo);
         ExcelUtil<FsUserCourseVideo> util = new ExcelUtil<FsUserCourseVideo>(FsUserCourseVideo.class);
         return util.exportExcel(list, "课堂视频数据");
@@ -79,7 +102,14 @@ public class FsUserCourseVideoController extends BaseController
     @GetMapping(value = "/{videoId}")
     public AjaxResult getInfo(@PathVariable("videoId") Long videoId)
     {
-        return AjaxResult.success(fsUserCourseVideoService.selectFsUserCourseVideoByVideoIdVO(videoId));
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            return AjaxResult.success(fsUserCourseVideoService.selectFsUserCourseVideoByVideoIdVO(videoId,userId));
+        }
+        return AjaxResult.success(fsUserCourseVideoService.selectFsUserCourseVideoByVideoIdVO(videoId,null));
     }
 
     /**
@@ -94,7 +124,13 @@ public class FsUserCourseVideoController extends BaseController
         if (count>0){
             return AjaxResult.error("课程排序重复");
         }
-
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsUserCourseVideo.setUserId(userId);
+        }
         // 设置项目ID
         FsUserCourse fsUserCourse = fsUserCourseService.selectFsUserCourseByCourseId(fsUserCourseVideo.getCourseId());
         fsUserCourseVideo.setProjectId(fsUserCourse.getProject());
@@ -128,6 +164,13 @@ public class FsUserCourseVideoController extends BaseController
     public TableDataInfo getVideoListByCourseId(FsUserCourseVideo fsUserCourseVideo)
     {
         startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsUserCourseVideo.setUserId(userId);
+        }
         List<FsUserCourseVideo> list = fsUserCourseVideoService.selectFsUserCourseVideoListByCourseId(fsUserCourseVideo);
         return getDataTable(list);
     }

+ 34 - 2
fs-admin/src/main/java/com/fs/course/controller/FsVideoResourceController.java

@@ -1,5 +1,7 @@
 package com.fs.course.controller;
 
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.annotation.Log;
@@ -9,10 +11,12 @@ import com.fs.common.core.domain.model.LoginUser;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
+import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsVideoResource;
 import com.fs.course.service.IFsVideoResourceService;
 import com.fs.course.vo.FsVideoResourceVO;
 import com.fs.framework.web.service.TokenService;
+import com.fs.system.service.ISysConfigService;
 import com.github.pagehelper.PageHelper;
 import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -33,6 +37,12 @@ public class FsVideoResourceController extends BaseController {
 
     private final IFsVideoResourceService fsVideoResourceService;
 
+    @Autowired
+    private TokenService tokenService;
+
+    @Autowired
+    private ISysConfigService configService;
+
     /**
      * 查询视频素材库列表
      */
@@ -50,7 +60,12 @@ public class FsVideoResourceController extends BaseController {
         params.put("fileName", fileName);
         params.put("typeId", typeId);
         params.put("typeSubId", typeSubId);
-
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            params.put("userId", loginUser.getUser().getUserId());
+        }
         PageHelper.startPage(pageNum, pageSize);
         List<FsVideoResourceVO> list = fsVideoResourceService.selectVideoResourceListByMap(params);
         return getDataTable(list);
@@ -75,6 +90,13 @@ public class FsVideoResourceController extends BaseController {
     @PostMapping
     public AjaxResult add(@RequestBody FsVideoResource fsVideoResource)
     {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsVideoResource.setUserId(userId);
+        }
         fsVideoResource.setCreateTime(LocalDateTime.now());
         fsVideoResourceService.save(fsVideoResource);
         return AjaxResult.success();
@@ -151,7 +173,17 @@ public class FsVideoResourceController extends BaseController {
         if (Objects.isNull(list) || list.isEmpty()) {
             return AjaxResult.error("数据不能为空");
         }
-        list.forEach(v -> v.setCreateTime(LocalDateTime.now()));
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+
+        list.forEach(v ->{
+            v.setCreateTime(LocalDateTime.now());
+            if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+                v.setUserId(userId);
+            }
+        } );
         fsVideoResourceService.saveBatch(list);
         return AjaxResult.success();
     }

+ 19 - 0
fs-admin/src/main/java/com/fs/his/task/trafficlog/TrafficlogTask.java

@@ -0,0 +1,19 @@
+package com.fs.his.task.trafficlog;
+
+import com.fs.course.service.IFsCourseTrafficLogService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service("trafficlogTask")
+@Slf4j
+public class TrafficlogTask {
+    @Autowired
+    private IFsCourseTrafficLogService fsCourseTrafficLogService;
+    /**
+     * 红包流量统计
+     */
+    public void sumTrafficlog(){
+        fsCourseTrafficLogService.sumTrafficlog();
+    }
+}

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

@@ -7,6 +7,8 @@ import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
 import com.fs.statis.StatisticsRedisConstant;
 import com.fs.statis.dto.*;
+import com.fs.system.domain.SysConfig;
+import com.fs.system.service.ISysConfigService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 

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

@@ -69,7 +69,7 @@ public class FsUserCourseVideoController extends BaseController
     @GetMapping(value = "/{videoId}")
     public AjaxResult getInfo(@PathVariable("videoId") Long videoId)
     {
-        return AjaxResult.success(fsUserCourseVideoService.selectFsUserCourseVideoByVideoIdVO(videoId));
+        return AjaxResult.success(fsUserCourseVideoService.selectFsUserCourseVideoByVideoIdVO(videoId,null));
     }
 
     /**

+ 6 - 0
fs-company/src/main/java/com/fs/company/controller/qw/QwUserController.java

@@ -837,4 +837,10 @@ public class QwUserController extends BaseController
         return qwUserService.updateSendType(vo);
     }
 
+    @GetMapping("/changeVideoStatus")
+    public R changeVideoStatus(Long id) {
+        qwUserService.changeVideoStatus(id);
+        return R.ok();
+    }
+
 }

+ 37 - 1
fs-ipad-task/src/main/java/com/fs/app/service/IpadSendServer.java

@@ -9,8 +9,12 @@ import com.fs.course.service.IFsCourseWatchLogService;
 import com.fs.ipad.IpadSendUtils;
 import com.fs.ipad.vo.*;
 import com.fs.qw.domain.QwUser;
+import com.fs.qw.domain.QwUserVideo;
 import com.fs.qw.mapper.QwExternalContactMapper;
 import com.fs.qw.mapper.QwUserMapper;
+import com.fs.qw.service.IQwUserService;
+import com.fs.qw.service.IQwUserVideoService;
+import com.fs.qw.service.impl.QwUserServiceImpl;
 import com.fs.qw.vo.QwSopCourseFinishTempSetting;
 import com.fs.qwApi.param.QwExternalContactHParam;
 import com.fs.sop.domain.QwSopLogs;
@@ -30,10 +34,12 @@ import java.util.Map;
 public class IpadSendServer {
 
     private final QwUserMapper qwUserMapper;
+    private final IQwUserService qwUserService;
     private final IpadSendUtils ipadSendUtils;
     private final IQwSopLogsService qwSopLogsService;
     private final QwExternalContactMapper qwExternalContactMapper;
     private final IFsCourseWatchLogService watchLogService;
+    private final IQwUserVideoService qwUserVideoService;
     private final RedisCache redisCache;
 
     private void sendMiniProgram(BaseVo vo, QwSopCourseFinishTempSetting.Setting content, Map<String, CourseMaConfig> miniMap) {
@@ -122,6 +128,28 @@ public class IpadSendServer {
         }
     }
 
+    public void sendWxVideo(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
+        QwUserVideo qwUserVideo = qwUserVideoService.selectQwUserVideoById(content.getVideoId());
+        WxVideoVo videoVo = WxVideoVo.builder()
+                .coverUrl(qwUserVideo.getCoverUrl())
+                .thumbUrl(qwUserVideo.getThumbUrl())
+                .avatar(qwUserVideo.getAvatar())
+                .nickname(qwUserVideo.getNickName())
+                .desc(qwUserVideo.getDesc())
+                .url(qwUserVideo.getUrl())
+                .extras(qwUserVideo.getExtras())
+                .objectId(qwUserVideo.getObjectId())
+                .objectNonceId(qwUserVideo.getObjectNonceId())
+                .build();
+        videoVo.setBase(vo);
+        WxWorkResponseDTO<WxwSendVideoNumberRespDTO> resp = ipadSendUtils.sendWxVideo(videoVo);
+        if (resp.getErrcode() != 0) {
+            log.debug("ID:{}-ipad接口请求返回异常:{}", vo.getId(), resp.getErrmsg());
+            content.setSendStatus(2);
+            content.setSendRemarks("发送失败:" + resp.getErrmsg());
+        }
+    }
+
     public void sendVoice(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
         if (StringUtils.isEmpty(content.getVoiceUrl()) || StringUtils.isEmpty(content.getVoiceDuration())) {
             log.debug("语音未生成无法发送,转文字发送:{}", vo);
@@ -172,6 +200,7 @@ public class IpadSendServer {
                 updateQwUser.setRemark("AI未初始化");
                 updateQwUser.setIpadStatus(0);
                 qwUserMapper.updateById(updateQwUser);
+                qwUserService.atMsg(qwUser, "掉线提醒(未初始化)");
                 return false;
             }
             if (login.getLoginType() == 1) {
@@ -179,6 +208,7 @@ public class IpadSendServer {
                 updateQwUser.setRemark("未登录");
                 updateQwUser.setIpadStatus(0);
                 qwUserMapper.updateById(updateQwUser);
+                qwUserService.atMsg(qwUser, "掉线提醒(未登录)");
                 return false;
             }
             if (!login.getUser_info().isLogin()) {
@@ -186,15 +216,17 @@ public class IpadSendServer {
                 updateQwUser.setRemark("登录状态异常");
                 updateQwUser.setIpadStatus(0);
                 qwUserMapper.updateById(updateQwUser);
+                qwUserService.atMsg(qwUser, "掉线提醒(登录异常)");
                 return false;
             }
             parentVo.setCorpId(login.getUser_info().getObject().getCorp_id());
             log.debug("QwUserID:{}, AI主机信息:{}", qwUser.getId(), login);
         } catch (Exception e) {
             updateQwUser.setId(qwUser.getId());
-            updateQwUser.setRemark("登录状态异常");
+            updateQwUser.setRemark("登录状态异常" + e.getMessage());
             updateQwUser.setIpadStatus(0);
             qwUserMapper.updateById(updateQwUser);
+            qwUserService.atMsg(qwUser, "掉线提醒(登录信息异常,请联系管理员:"+e.getMessage()+")");
             return false;
         }
 
@@ -318,6 +350,10 @@ public class IpadSendServer {
                     // 语音
                     sendVoice(vo, content);
                     break;
+                case "8":
+                    // 语音
+                    sendWxVideo(vo, content);
+                    break;
                 default:
                     // 未知类型,记录警告
                     log.error("SOP_LOG_ID:{}错误的发送类型: {}", qwSopLogs.getId(), content.getContentType());

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

@@ -15,6 +15,7 @@ import com.fs.qw.mapper.QwIpadServerMapper;
 import com.fs.qw.mapper.QwUserMapper;
 import com.fs.qw.service.impl.AsyncSopTestService;
 import com.fs.qw.vo.QwSopCourseFinishTempSetting;
+import com.fs.qw.vo.QwSopTempSetting;
 import com.fs.sop.domain.QwSopLogs;
 import com.fs.sop.mapper.QwSopLogsMapper;
 import com.fs.sop.service.IQwSopLogsService;
@@ -36,6 +37,7 @@ import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 @Component
 @Slf4j
@@ -100,6 +102,7 @@ public class SendMsg {
             log.error("corpId为空不执行");
             return;
         }
+        // 看课配置文件获取
         SysConfig courseConfig = sysConfigMapper.selectConfigByConfigKey("course.config");
         CourseConfig config = JSON.parseObject(courseConfig.getConfigValue(), CourseConfig.class);
         // 消息发送延迟
@@ -113,12 +116,17 @@ public class SendMsg {
             delayStart = config.getDelayStart();
             delayEnd = config.getDelayEnd();
         }
+        // 小程序配置获取
         Map<String, CourseMaConfig> miniMap = getMiniMap();
+        // 获取 pad 发送的企微
         getQwUserList().forEach(e -> {
+            // 如果没有值就执行后面的方法 并且入值
             qwMap.computeIfAbsent(e.getId(), k -> {
+                // 线程启动
                 CompletableFuture.runAsync(() -> {
                     try {
                         log.info("开始任务:{}", e.getQwUserName());
+                        // 开始任务
                         processUser(e, delayStart, delayEnd, miniMap);
                     } catch (Exception exception) {
                         log.error("发送错误:", exception);
@@ -133,21 +141,32 @@ public class SendMsg {
         });
     }
 
+    /**
+     * 发送任务执行
+     * @param qwUser     发送企微
+     * @param delayStart 随机延迟 最小值
+     * @param delayEnd   随机延迟 最大值
+     * @param miniMap    小程序配置
+     */
     private void processUser(QwUser qwUser, int delayStart, int delayEnd, Map<String, CourseMaConfig> miniMap) {
         long start1 = System.currentTimeMillis();
+        // 获取当前企微待发送记录
         List<QwSopLogs> qwSopLogList = qwSopLogsMapper.selectByQwUserId(qwUser.getId());
         if (qwSopLogList.isEmpty()) {
             return;
         }
+        // 获取企微用户
         QwUser user = qwUserMapper.selectById(qwUser.getId());
         BaseVo parentVo = new BaseVo();
         parentVo.setCorpCode(qwUser.getCorpId());
         long end1 = System.currentTimeMillis();
+        // 判断这个企微是否需要发送
         if (!sendServer.isSend(user, parentVo)) {
             return;
         }
         log.info("销售:{}, 消息:{}, 耗时: {}, 时间:{}", user.getQwUserName(), qwSopLogList.size(), end1 - start1, qwMap.get(qwUser.getId()));
         long start3 = System.currentTimeMillis();
+        // 循环代发送消息
         for (QwSopLogs qwSopLogs : qwSopLogList) {
             long start2 = System.currentTimeMillis();
             QwSopCourseFinishTempSetting setting = JSON.parseObject(qwSopLogs.getContentJson(), QwSopCourseFinishTempSetting.class);
@@ -159,17 +178,20 @@ public class SendMsg {
             log.info("进入发送消息状态:{}", qwSopLogs.getId());
             String key = "qw:logs:pad:send:id:" + qwSopLogs.getId();
             Long time = redisCache.getCacheObject(key);
+            // 判断这个消息有没有进入过发送,如果进了就不要再发了,防止重复发送,,,,, TODO 千万不能动!!!!!
             if (redisCache.getCacheObject(key) != null) {
                 log.error("{}已有发送:{}, :{}", qwUser.getQwUserName(), qwSopLogs.getId(), time);
                 continue;
             }
-            redisCache.setCacheObject(key, System.currentTimeMillis(), 10, TimeUnit.MINUTES);
+            redisCache.setCacheObject(key, System.currentTimeMillis(), 24, TimeUnit.HOURS);
+            // 循环发送消息里面的每一条消息
             for (QwSopCourseFinishTempSetting.Setting content : setting.getSetting()) {
                 long start4 = System.currentTimeMillis();
+                // 发送
                 sendServer.send(content, user, qwSopLogs, miniMap, parentVo);
                 long end4 = System.currentTimeMillis();
                 log.info("请求pad发送完成:{}, {}, 时长4:{}", user.getQwUserName(), qwSopLogs.getId(), end4 - start4);
-                if(content.getSendStatus() == 2 && "请求失败:消息发送过于频繁,请稍后再试".equals(content.getSendRemarks())){
+                if(content.getSendStatus() == 2 && ("请求失败:消息发送过于频繁,请稍后再试".equals(content.getSendRemarks()) || "请求失败:请求频率异常".equals(content.getSendRemarks()))){
                     QwUser update = new QwUser();
                     update.setRemark("请求频率异常,暂停发送,三小时后恢复继续发送");
                     update.setUpdateTime(new Date());

+ 1 - 1
fs-qw-task/src/main/java/com/fs/FsQwTaskApplication.java

@@ -13,7 +13,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
 @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
 @EnableTransactionManagement
 @EnableAsync
-@EnableScheduling
+//@EnableScheduling
 public class FsQwTaskApplication
 {
     public static void main(String[] args){

+ 9 - 7
fs-qw-task/src/main/java/com/fs/app/controller/CommonController.java

@@ -7,13 +7,11 @@ import com.fs.app.taskService.SopLogsChatTaskService;
 import com.fs.app.taskService.SopLogsTaskService;
 import com.fs.app.taskService.SopWxLogsService;
 import com.fs.common.core.domain.R;
+import com.fs.common.core.domain.ResponseResult;
 import com.fs.course.mapper.FsCourseWatchLogMapper;
-import com.fs.course.service.IFsCourseLinkService;
-import com.fs.course.service.IFsCourseWatchLogService;
-import com.fs.course.service.IFsUserVideoService;
-import com.fs.course.service.IHuaweiObsService;
+import com.fs.course.param.newfs.FsUserCourseAddCompanyUserParam;
+import com.fs.course.service.*;
 import com.fs.his.service.IFsInquiryOrderService;
-import com.fs.his.service.IFsPackageOrderService;
 import com.fs.qw.mapper.QwExternalContactMapper;
 import com.fs.qw.service.IQwExternalContactService;
 import com.fs.qw.service.IQwMaterialService;
@@ -22,7 +20,6 @@ import com.fs.sop.mapper.QwSopLogsMapper;
 import com.fs.sop.mapper.QwSopMapper;
 import com.fs.sop.mapper.SopUserLogsMapper;
 import com.fs.sop.service.*;
-import com.fs.sop.vo.ExtCourseSopWatchLogVO;
 import com.fs.sop.vo.QwSopLogsDoSendListTVO;
 import com.fs.store.service.IFsUserCourseCountService;
 import io.swagger.annotations.Api;
@@ -37,7 +34,6 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.Arrays;
-import java.util.Base64;
 import java.util.List;
 
 @Api("公共接口")
@@ -49,6 +45,8 @@ public class CommonController {
     @Autowired
     private SopLogsTaskService service;
     @Autowired
+    private IFsUserCourseVideoService courseVideoService;
+    @Autowired
     private SopLogsTaskService sopLogsTaskService;
     @Autowired
     private SopWxLogsService sopWxLogsService;
@@ -262,6 +260,10 @@ public class CommonController {
         userCourseCountService.insertFsUserCourseCountTask();
         return "s";
     }
+    @GetMapping("/isAddkf")
+    public ResponseResult<Boolean> isAddkf(FsUserCourseAddCompanyUserParam param) throws Exception {
+        return courseVideoService.isAddCompanyUser(param);
+    }
 
     @PostMapping("/updateUrl")
     public R updateUrl()

+ 1 - 228
fs-service/src/main/java/com/fs/company/domain/Company.java

@@ -115,6 +115,7 @@ public class Company extends BaseEntity
     private Integer repeat;
     private Integer sendIfType;
     private Integer ifNum;
+    private String groupName;
     @TableField(exist = false)
     private List<String> miniAppMaster;
     @TableField(exist = false)
@@ -123,232 +124,4 @@ public class Company extends BaseEntity
     /** 后台制单是否需要付款 默认1 0-否 1-是*/
     private Integer isPay;
 
-//    public String getDoctorIds() {
-//        return doctorIds;
-//    }
-//
-//    public void setDoctorIds(String doctorIds) {
-//        this.doctorIds = doctorIds;
-//    }
-//
-//    public String getFollowDoctorIds() {
-//        return followDoctorIds;
-//    }
-//
-//    public void setFollowDoctorIds(String followDoctorIds) {
-//        this.followDoctorIds = followDoctorIds;
-//    }
-//
-//    public String getManager() {
-//        return manager;
-//    }
-//
-//    public void setManager(String manager) {
-//        this.manager = manager;
-//    }
-//
-//    public String getOmsCode() {
-//        return omsCode;
-//    }
-//
-//    public void setOmsCode(String omsCode) {
-//        this.omsCode = omsCode;
-//    }
-//
-//    public Integer getVoiceCallerNumber() {
-//        return voiceCallerNumber;
-//    }
-//
-//    public void setVoiceCallerNumber(Integer voiceCallerNumber) {
-//        this.voiceCallerNumber = voiceCallerNumber;
-//    }
-//
-//    public Integer getIsDel() {
-//        return isDel;
-//    }
-//
-//    public void setIsDel(Integer isDel) {
-//        this.isDel = isDel;
-//    }
-//
-//    public BigDecimal getTuiMoney() {
-//        return tuiMoney;
-//    }
-//
-//    public void setTuiMoney(BigDecimal tuiMoney) {
-//        this.tuiMoney = tuiMoney;
-//    }
-//
-//    @Override
-//    public String getRemark() {
-//        return remark;
-//    }
-//
-//    @Override
-//    public void setRemark(String remark) {
-//        this.remark = remark;
-//    }
-//
-//    public String getLinkName() {
-//        return linkName;
-//    }
-//
-//    public void setLinkName(String linkName) {
-//        this.linkName = linkName;
-//    }
-//
-//    public Integer getLimitUserCount() {
-//        return limitUserCount;
-//    }
-//
-//    public void setLimitUserCount(Integer limitUserCount) {
-//        this.limitUserCount = limitUserCount;
-//    }
-//
-//    public Date getLimitTime() {
-//        return limitTime;
-//    }
-//
-//    public void setLimitTime(Date limitTime) {
-//        this.limitTime = limitTime;
-//    }
-//
-//    public String getAppId() {
-//        return appId;
-//    }
-//
-//    public void setAppId(String appId) {
-//        this.appId = appId;
-//    }
-//
-//    public String getAppKey() {
-//        return appKey;
-//    }
-//
-//    public void setAppKey(String appKey) {
-//        this.appKey = appKey;
-//    }
-//
-//    public Long getUserId() {
-//        return userId;
-//    }
-//
-//    public void setUserId(Long userId) {
-//        this.userId = userId;
-//    }
-//
-//    public String getAddressId() {
-//        return addressId;
-//    }
-//
-//    public void setAddressId(String addressId) {
-//        this.addressId = addressId;
-//    }
-//
-//    public Integer getCompanyType() {
-//        return companyType;
-//    }
-//
-//    public void setCompanyType(Integer companyType) {
-//        this.companyType = companyType;
-//    }
-//
-//    public static long getSerialVersionUID() {
-//        return serialVersionUID;
-//    }
-//
-//
-//
-//    public String getUserName() {
-//        return userName;
-//    }
-//
-//    public void setUserName(String userName) {
-//        this.userName = userName;
-//    }
-//
-//    public String getPassword() {
-//        return password;
-//    }
-//
-//    public void setPassword(String password) {
-//        this.password = password;
-//    }
-//
-//    public void setCompanyId(Long companyId)
-//    {
-//        this.companyId = companyId;
-//    }
-//
-//    public Long getCompanyId()
-//    {
-//        return companyId;
-//    }
-//    public void setCompanyName(String companyName)
-//    {
-//        this.companyName = companyName;
-//    }
-//
-//    public String getCompanyName()
-//    {
-//        return companyName;
-//    }
-//    public void setCompanyMobile(String companyMobile)
-//    {
-//        this.companyMobile = companyMobile;
-//    }
-//
-//    public String getCompanyMobile()
-//    {
-//        return companyMobile;
-//    }
-//    public void setCompanyAddress(String companyAddress)
-//    {
-//        this.companyAddress = companyAddress;
-//    }
-//
-//    public String getCompanyAddress()
-//    {
-//        return companyAddress;
-//    }
-//    public void setStatus(Integer status)
-//    {
-//        this.status = status;
-//    }
-//
-//    public Integer getStatus()
-//    {
-//        return status;
-//    }
-//    public void setStartTime(Date startTime)
-//    {
-//        this.startTime = startTime;
-//    }
-//
-//    public Date getStartTime()
-//    {
-//        return startTime;
-//    }
-//
-//    public void setMoney(BigDecimal money)
-//    {
-//        this.money = money;
-//    }
-//
-//    public BigDecimal getMoney()
-//    {
-//        return money;
-//    }
-//
-//    public void setVoiceApiId(Long voiceApiId)
-//    {
-//        this.voiceApiId = voiceApiId;
-//    }
-//
-//    public Long getVoiceApiId()
-//    {
-//        return voiceApiId;
-//    }
-
-
 }

+ 3 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanyMiniappServiceImpl.java

@@ -2,6 +2,8 @@ package com.fs.company.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.annotation.Log;
+import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.PubFun;
 import com.fs.company.domain.CompanyMiniapp;
@@ -119,6 +121,7 @@ public class CompanyMiniappServiceImpl extends ServiceImpl<CompanyMiniappMapper,
     }
 
     @Override
+    @Log(title = "删除企业绑定小程序", businessType = BusinessType.DELETE)
     public void removeByCompanyId(Long companyId) {
         remove(new QueryWrapper<CompanyMiniapp>().eq("company_id",companyId));
     }

+ 2 - 2
fs-service/src/main/java/com/fs/core/config/WxOpenProperties.java

@@ -9,7 +9,7 @@ import org.springframework.context.annotation.Configuration;
 @ConfigurationProperties("wx.open")
 public class WxOpenProperties {
 
-    private String appId = "wxcb1e78baf03c0662";
+    private String appId;
 
-    private String secret = "d041d3e2392a68a3e86dc22d976ed4a0";
+    private String secret;
 }

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

@@ -52,6 +52,11 @@ public class CourseConfig implements Serializable {
      */
     private String userCourseAuthDomain;
 
+    /**
+     * 是否绑定
+     */
+    private Boolean isBound;
+
 
     @Data
     public static class DisabledTimeVo{

+ 2 - 0
fs-service/src/main/java/com/fs/course/domain/FsVideoResource.java

@@ -97,4 +97,6 @@ public class FsVideoResource {
     private String transcodeFileKey;//转码的文件key
 
     private Integer sort;
+
+    private Long userId;
 }

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

@@ -1,14 +1,17 @@
 package com.fs.course.mapper;
 
+import java.util.Date;
 import java.util.List;
 
 import com.fs.common.annotation.DataSource;
 import com.fs.common.enums.DataSourceType;
 import com.fs.course.domain.FsCourseTrafficLog;
 import com.fs.course.param.FsCourseTrafficLogParam;
+import com.fs.course.param.TrafficRecord;
 import com.fs.course.vo.FsCourseTrafficLogListVO;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
 import org.springframework.stereotype.Repository;
 
 /**
@@ -110,4 +113,68 @@ public interface FsCourseTrafficLogMapper
     void insertCourseTrafficLogByTwoDaysLaterBatch(@Param("list") List<FsCourseTrafficLog> redPacketLogs);
 
     List<FsCourseTrafficLogListVO> selectTrafficNew(FsCourseTrafficLogParam param);
+
+    @Select("<script>" +
+            "SELECT COALESCE(sum(internet_traffic), 0) FROM fs_course_traffic_log " +
+            "WHERE status =0" +
+            "<if test='createTime != null'>AND create_time &lt;= #{createTime}</if> " +
+            "</script>")
+    Long findRecordsNumBYD( @Param("createTime") Date createTime);
+
+    @Select("<script>" +
+            "SELECT log_id FROM fs_course_traffic_log " +
+            "WHERE status =0" +
+            "<if test='createTime != null'>AND create_time &lt;= #{createTime}</if> " +
+            "</script>")
+    List<Long> findRecordsNumByIds( @Param("createTime") Date createTime);
+
+    @Update("<script>" +
+            "UPDATE fs_course_traffic_log SET status = #{status} WHERE log_id IN " +
+            "<foreach item='id' collection='ids' open='(' separator=',' close=')'>" +
+            "#{id}" +
+            "</foreach>" +
+            "</script>")
+    int updateStatusByIds(@Param("ids") List<Long> ids,@Param("status")Integer status);
+
+
+
+    // 按创建时间查询未使用的流量记录(用于分批更新)
+    @Select("<script>" +
+            "SELECT COALESCE(sum(internet_traffic), 0) FROM fs_course_traffic_log " +
+            "WHERE status = 0" +
+            "<if test='companyId != null'>AND company_id = #{companyId}</if> " +
+            "</script>")
+    Long findRecordsNum(@Param("companyId") Long companyId);
+
+//    // 批量更新状态
+//    @Update("<script>" +
+//            "UPDATE fs_course_traffic_log SET status = 1 WHERE log_id IN " +
+//            "<foreach item='id' collection='ids' open='(' separator=',' close=')'>" +
+//            "#{id}" +
+//            "</foreach>" +
+//            "</script>")
+//    int updateStatusByIds(@Param("ids") List<Long> ids);
+
+    @Select("<script>" +
+            "SELECT internet_traffic FROM fs_course_traffic_log WHERE log_id IN " +
+            "<foreach item='id' collection='ids' open='(' separator=',' close=')'>" +
+            "#{id}" +
+            "</foreach>" +
+            "</script>")
+    List<Long> getTrafficByIds(@Param("ids") List<Long> ids);
+
+    // 新增带流量字段的记录查询(按公司ID)
+    @Select("<script>" +
+            "SELECT log_id, internet_traffic FROM fs_course_traffic_log " +
+            "WHERE status = 0" +
+            "<if test='companyId != null'>AND company_id = #{companyId}</if> " +
+            "ORDER BY create_time ASC " +
+            "LIMIT #{offset}, #{pageSize}" +
+            "</script>")
+    List<TrafficRecord> findUnusedRecordsWithTraffic(
+            @Param("companyId") Long companyId,
+            @Param("offset") int offset,
+            @Param("pageSize") int pageSize);
+
+
 }

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

@@ -465,4 +465,26 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
     FsCourseWatchLog getWatchCourseVideoIsOpen(@Param("userId") Long userId,@Param("videoId") Long videoId);
 
     void batchUpdateWatchLogIsOpen(@Param("list") List<FsCourseWatchLog> batchList);
+
+    @Select("select count(*) from fs_course_watch_log where user_id =#{userId} and project =#{projectId} ")
+    Long selectByWatchLjDay(@Param("userId") Long userId,@Param("projectId")  Long projectId);
+    @Select("SELECT IFNULL(MAX(streak), 0) AS current_consecutive_days\n" +
+            "FROM (\n" +
+            "    SELECT \n" +
+            "        watch_date,\n" +
+            "        @streak := IF(\n" +
+            "            DATEDIFF(@prev_date, watch_date) = 1, \n" +
+            "            @streak + 1, \n" +
+            "            1\n" +
+            "        ) AS streak,\n" +
+            "        @prev_date := watch_date\n" +
+            "    FROM (\n" +
+            "        SELECT DISTINCT DATE(create_time) AS watch_date\n" +
+            "        FROM fs_course_watch_log\n" +
+            "        WHERE user_id = #{userId} AND project = #{projectId}\n" +
+            "        ORDER BY watch_date DESC\n" +
+            "    ) AS dates,\n" +
+            "    (SELECT @streak := 0, @prev_date := NULL) AS vars\n" +
+            ") AS streak_data;")
+    Long selectByWatchlxDay(@Param("userId") Long userId,@Param("projectId")  Long projectId);
 }

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

@@ -140,6 +140,9 @@ public interface FsUserCourseMapper
             "<if test = ' maps.subCateId !=null '> " +
             "and c.sub_cate_id =#{maps.subCateId}" +
             "</if>" +
+            "<if test = ' maps.userId !=null '> " +
+            "and c.user_id =#{maps.userId}" +
+            "</if>" +
             "<if test = ' maps.courseName!=null and maps.courseName != \"\" '> " +
             "and c.course_name like concat('%', #{maps.courseName}, '%') " +
             "</if>" +
@@ -284,7 +287,7 @@ public interface FsUserCourseMapper
 
     @Select("select video_id,title,course_id,video_url,SEC_TO_TIME(duration) as total_duration," +
             "thumbnail videoImgUrl,description videoDescription,video_url videoUrl,question_bank_id questionBankId " +
-            " from fs_user_course_video where course_id = #{courseId} and is_del = 0 order by course_sort,video_id")
+            " from fs_user_course_video where course_id = #{courseId} and is_del = 0 order by course_sort DESC,video_id")
     List<FsUserCourseVideoAppletVO.FsUserCourseVideo> selectFsUserCourseVideoAppletByCourseId(@Param("courseId") Long courseId);
 
 }

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

@@ -85,6 +85,9 @@ public interface FsUserCourseVideoMapper
             "<if test = ' maps.title!=null and maps.title != \"\" '> " +
             "and v.title = #{maps.title} " +
             "</if>" +
+            "<if test = ' maps.userId!=null and maps.userId != \"\" '> " +
+            "and v.user_id = #{maps.userId} " +
+            "</if>" +
             " order by v.course_sort  "+
             "</script>"})
     List<FsUserCourseVideo> selectFsUserCourseVideoListByCourseId(@Param("maps") FsUserCourseVideo fsUserCourseVideo);

+ 23 - 0
fs-service/src/main/java/com/fs/course/param/BatchCompanyRedPackageParam.java

@@ -0,0 +1,23 @@
+package com.fs.course.param;
+
+import lombok.Data;
+
+import javax.validation.constraints.DecimalMin;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+public class BatchCompanyRedPackageParam {
+
+    @NotNull(message = "营期ID不能为空")
+    private Long periodId;
+
+    @NotEmpty(message = "公司ID不能为空")
+    private List<Long> companyIds;
+
+    @NotNull(message = "红包金额不能为空")
+    @DecimalMin(value = "0.1", message = "红包金额必须大于0.1")
+    private BigDecimal redPacketMoney;
+}

+ 9 - 0
fs-service/src/main/java/com/fs/course/param/TrafficRecord.java

@@ -0,0 +1,9 @@
+package com.fs.course.param;
+
+import lombok.Data;
+
+@Data
+public class TrafficRecord {
+    private Long logId;
+    private Long internetTraffic; // 单位:KB
+}

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

@@ -73,7 +73,7 @@ public interface IFsCourseQuestionBankService
      * @param nickName 昵称
      * @return String
      */
-    String importData(List<FsCourseQuestionBankImportDTO> list, String nickName);
+    String importData(List<FsCourseQuestionBankImportDTO> list, String nickName,Long userId);
 
     /**
      * 根据ID查询题目

+ 10 - 0
fs-service/src/main/java/com/fs/course/service/IFsCourseTrafficLogService.java

@@ -3,6 +3,7 @@ package com.fs.course.service;
 import java.util.List;
 import com.fs.course.domain.FsCourseTrafficLog;
 import com.fs.course.param.FsCourseTrafficLogParam;
+import com.fs.course.param.InternetTrafficParam;
 import com.fs.course.vo.FsCourseTrafficLogListVO;
 
 /**
@@ -70,4 +71,13 @@ public interface IFsCourseTrafficLogService
     void saveCourseTrafficLog();
 
     List<FsCourseTrafficLogListVO> selectTrafficNew(FsCourseTrafficLogParam param);
+
+
+    void updateTrafficStatus(InternetTrafficParam internetTrafficParam);
+
+
+    /**
+     * 定时统计流量总数
+     */
+    void sumTrafficlog();
 }

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

@@ -30,7 +30,7 @@ public interface IFsUserCourseTrainingCampService extends IService<FsUserCourseT
      * 新增训练营
      * @param params    参数
      */
-    void add(FsUserCourseTrainingCampDTO params);
+    void add(FsUserCourseTrainingCampDTO params,Long userId);
     /**
      * 删除训练营
      * @param ids   ids

+ 14 - 8
fs-service/src/main/java/com/fs/course/service/IFsUserCourseVideoRedPackageService.java

@@ -2,19 +2,20 @@ package com.fs.course.service;
 
 import java.util.List;
 import com.fs.course.domain.FsUserCourseVideoRedPackage;
+import com.fs.course.param.BatchCompanyRedPackageParam;
 import com.fs.course.param.FsBatchPeriodRedPackageParam;
 
 /**
  * 课程公司红包Service接口
- * 
+ *
  * @author fs
  * @date 2024-10-25
  */
-public interface IFsUserCourseVideoRedPackageService 
+public interface IFsUserCourseVideoRedPackageService
 {
     /**
      * 查询课程公司红包
-     * 
+     *
      * @param id 课程公司红包主键
      * @return 课程公司红包
      */
@@ -22,7 +23,7 @@ public interface IFsUserCourseVideoRedPackageService
 
     /**
      * 查询课程公司红包列表
-     * 
+     *
      * @param fsUserCourseVideoRedPackage 课程公司红包
      * @return 课程公司红包集合
      */
@@ -30,7 +31,7 @@ public interface IFsUserCourseVideoRedPackageService
 
     /**
      * 新增课程公司红包
-     * 
+     *
      * @param fsUserCourseVideoRedPackage 课程公司红包
      * @return 结果
      */
@@ -38,7 +39,7 @@ public interface IFsUserCourseVideoRedPackageService
 
     /**
      * 修改课程公司红包
-     * 
+     *
      * @param fsUserCourseVideoRedPackage 课程公司红包
      * @return 结果
      */
@@ -46,7 +47,7 @@ public interface IFsUserCourseVideoRedPackageService
 
     /**
      * 批量删除课程公司红包
-     * 
+     *
      * @param ids 需要删除的课程公司红包主键集合
      * @return 结果
      */
@@ -54,7 +55,7 @@ public interface IFsUserCourseVideoRedPackageService
 
     /**
      * 删除课程公司红包信息
-     * 
+     *
      * @param id 课程公司红包主键
      * @return 结果
      */
@@ -78,4 +79,9 @@ public interface IFsUserCourseVideoRedPackageService
     List<FsUserCourseVideoRedPackage> selectByRuleIds(List<Long> ruleIds);
 
     void batchSaveFsUserCourseVideoRedPackage(List<FsUserCourseVideoRedPackage> redPackage);
+    /**
+     * 按照公司批量设置红包
+     * @param param 入参
+     */
+    void batchRedPacketByCompany(BatchCompanyRedPackageParam param);
 }

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

@@ -186,8 +186,7 @@ public interface IFsUserCourseVideoService
 
     R checkUserInfo(Long userId);
 
-    FsUserCourseVideoQVO selectFsUserCourseVideoByVideoIdVO(Long videoId);
-
+    public FsUserCourseVideoQVO selectFsUserCourseVideoByVideoIdVO(Long videoId,Long userId);
     R updateWatchDurationIsOpen(FsUserCourseVideoFinishUParam param);
 
     R isAddKfIsOpen(FsUserCourseVideoAddKfUParam param);

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

@@ -467,7 +467,7 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
      * @return String
      */
     @Override
-    public String importData(List<FsCourseQuestionBankImportDTO> list, String nickName) {
+    public String importData(List<FsCourseQuestionBankImportDTO> list, String nickName,Long userId) {
         if (Objects.isNull(list) || list.isEmpty()) {
             throw new ServiceException("导入数据不能为空");
         }
@@ -487,6 +487,7 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
 
                 // 构建题目对象
                 FsCourseQuestionBank questionBank = buildQuestionBank(importDTO, categoryData, nickName);
+                questionBank.setUserId(userId);
                 importData.add(questionBank);
                 result.addSuccess(importDTO.getTitle());
 

+ 166 - 4
fs-service/src/main/java/com/fs/course/service/impl/FsCourseTrafficLogServiceImpl.java

@@ -1,18 +1,21 @@
 package com.fs.course.service.impl;
 
 import java.text.SimpleDateFormat;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
 
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.DictUtils;
 import com.fs.company.cache.ICompanyCacheService;
 import com.fs.course.param.FsCourseTrafficLogParam;
+import com.fs.course.param.InternetTrafficParam;
+import com.fs.course.param.TrafficRecord;
 import com.fs.course.vo.FsCourseTrafficLogListVO;
 import com.fs.store.service.cache.IFsUserCourseCacheService;
+import com.fs.system.domain.SysConfig;
+import com.fs.system.service.ISysConfigService;
 import com.hc.openapi.tool.util.StringUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -33,7 +36,8 @@ public class FsCourseTrafficLogServiceImpl implements IFsCourseTrafficLogService
 {
     @Autowired
     private FsCourseTrafficLogMapper fsCourseTrafficLogMapper;
-
+    @Autowired
+    private ISysConfigService iSysConfigService;
     @Autowired
     private ICompanyCacheService companyCacheService;
 
@@ -202,6 +206,164 @@ public class FsCourseTrafficLogServiceImpl implements IFsCourseTrafficLogService
         return fsCourseTrafficLogListVOS;
     }
 
+    @Override
+    public void updateTrafficStatus(InternetTrafficParam internetTrafficParam) {
+        System.out.println("开始处理流量充值...");
+
+        // 计算充值对应的流量
+        double account = Double.parseDouble(internetTrafficParam.getAccount());
+
+        SysConfig config = iSysConfigService.selectConfigByConfigKey("statis.config");
+        JSONObject jsonObject = JSONObject.parseObject(config.getConfigValue());
+        float trafficPrice = jsonObject.getFloatValue("trafficPrice");
+
+        double trafficGB = account / trafficPrice;
+        long trafficKB = (long) (trafficGB * 1024 * 1024);
+
+        System.out.println("充值金额:" + account + " 元,对应可用流量:" + trafficKB + " KB");
+
+        long updatedTrafficKB = 0L;
+        int pageSize = 1000;  // 每次查询1000条
+        int pageNum = 0;      // 分页页码
+        int loopCount = 0;    // 查询次数
+        int maxLoop = 20;     // 最大循环次数
+
+        List<Long> idsToUpdate = new ArrayList<>();       // 用于更新状态为1的ID
+        Set<Long> processedIds = new HashSet<>();         // 用于去重
+        long remainingTrafficKB = trafficKB;              // 还需补充的流量
+        long totalInternetTrafficRemaining = 0L;          // 记录未处理的流量总和
+
+        // 第一阶段:处理需要用于充值的记录
+        while (updatedTrafficKB < trafficKB && loopCount < maxLoop) {
+            loopCount++;
+            int offset = pageNum * pageSize;
+
+            // 查询当前分页的数据
+            List<TrafficRecord> trafficRecords =
+                    fsCourseTrafficLogMapper.findUnusedRecordsWithTraffic(
+                            internetTrafficParam.getCompanyId(), offset, pageSize);
+
+            if (trafficRecords.isEmpty()) {
+                break;
+            }
+
+            // 处理当前批次的数据
+            for (TrafficRecord record : trafficRecords) {
+                Long logId = record.getLogId();
+
+                if (processedIds.contains(logId)) {
+                    continue;
+                }
+
+                if (updatedTrafficKB < trafficKB) {
+                    updatedTrafficKB += record.getInternetTraffic();
+                    idsToUpdate.add(logId);
+                    remainingTrafficKB = Math.max(0, trafficKB - updatedTrafficKB);
+                }
+
+                processedIds.add(logId);
+                totalInternetTrafficRemaining += record.getInternetTraffic();
+            }
+
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+                break;
+            }
+
+            pageNum++;
+        }
+
+        // 第二阶段:将所有未处理的记录状态改为3
+        List<Long> allUnprocessedIds = new ArrayList<>();
+        pageNum = 0;  // 重置分页
+        boolean hasMore = true;
+
+        while (hasMore && loopCount < maxLoop * 2) {  // 扩大循环次数限制
+            loopCount++;
+            int offset = pageNum * pageSize;
+
+            List<TrafficRecord> allRecords =
+                    fsCourseTrafficLogMapper.findUnusedRecordsWithTraffic(
+                            internetTrafficParam.getCompanyId(), offset, pageSize);
+
+            if (allRecords.isEmpty()) {
+                hasMore = false;
+                continue;
+            }
+
+            for (TrafficRecord record : allRecords) {
+                Long logId = record.getLogId();
+                if (!idsToUpdate.contains(logId)) {  // 不是已处理的记录
+                    allUnprocessedIds.add(logId);
+                }
+            }
+
+            pageNum++;
+        }
+
+        // 更新数据库状态
+        if (!idsToUpdate.isEmpty()) {
+            fsCourseTrafficLogMapper.updateStatusByIds(idsToUpdate, 1);
+            System.out.println("共更新状态为1的记录数:" + idsToUpdate.size());
+        }
+
+        if (!allUnprocessedIds.isEmpty()) {
+            fsCourseTrafficLogMapper.updateStatusByIds(allUnprocessedIds, 3);
+            System.out.println("共更新状态为3的记录数:" + allUnprocessedIds.size());
+        }
+
+        // 剩余的计算和输出逻辑保持不变...
+        Long count = fsCourseTrafficLogMapper.findRecordsNum(internetTrafficParam.getCompanyId());
+        long overflowTrafficKB = Math.max(0, updatedTrafficKB - trafficKB) + count;
+        if (overflowTrafficKB > 0) {
+            System.out.println("已使用流量超过充值流量,超出部分:" + overflowTrafficKB + " KB");
+        }
+
+        System.out.println("充值总流量:" + trafficKB + " KB");
+        System.out.println("已使用流量:" + updatedTrafficKB + " KB");
+        long finalRemainingTrafficKB = Math.max(0, trafficKB - updatedTrafficKB);
+        System.out.println("最终剩余流量:" + finalRemainingTrafficKB + " KB");
+
+        // 系统配置更新逻辑保持不变...
+        SysConfig sysConfig = iSysConfigService.selectConfigByConfigKey("redPacket.Traffic.config");
+        String trafficCount = finalRemainingTrafficKB == 0 ?
+                "-" + overflowTrafficKB : String.valueOf(finalRemainingTrafficKB);
+
+        if (ObjectUtils.isEmpty(sysConfig)) {
+            sysConfig = new SysConfig();
+            sysConfig.setConfigKey("redPacket.Traffic.config");
+            sysConfig.setConfigName("红包流量配置");
+            sysConfig.setConfigValue(trafficCount);
+            iSysConfigService.insertConfig(sysConfig);
+        } else {
+            sysConfig.setConfigValue(trafficCount);
+            iSysConfigService.updateConfig(sysConfig);
+        }
+    }
+    @Override
+    public void sumTrafficlog() {
+        SysConfig sysConfig = iSysConfigService.selectConfigByConfigKey("redPacket.Traffic.config");
+        Date date = new Date();
+        Long count = fsCourseTrafficLogMapper.findRecordsNumBYD(date);
+        List<Long> ids = fsCourseTrafficLogMapper.findRecordsNumByIds(date);
+        if (count<=0){
+            return;
+        }
+        if (ObjectUtils.isEmpty(sysConfig)){
+            sysConfig = new SysConfig();
+            sysConfig.setConfigKey("redPacket.Traffic.config");
+            sysConfig.setConfigName("红包流量配置");
+            sysConfig.setConfigValue("-"+count);
+            iSysConfigService.insertConfig(sysConfig);
+        }else {
+            sysConfig.setConfigValue(String.valueOf((Long.parseLong(sysConfig.getConfigValue())-count)));
+            iSysConfigService.updateConfig(sysConfig);
+        }
+        fsCourseTrafficLogMapper.updateStatusByIds(ids,2);
+    }
+
     private static String formatDuration(long millis) {
         long seconds = millis / 1000;
         long minutes = seconds / 60;

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

@@ -529,6 +529,14 @@ public class FsUserCourseServiceImpl implements IFsUserCourseService
             // 观看时长
             recordVO.setWatchTime((BigDecimal) sumMap.getOrDefault("watchTime", BigDecimal.ZERO));
 
+            Long ljDay = fsCourseWatchLogMapper.selectByWatchLjDay(recordVO.getUserId(),recordVO.getProjectId());
+            System.out.println("进入了统计累计观看天数:"+ljDay+"天");
+            recordVO.setWatchLjCount(ljDay);
+            //连续观看天数
+            Long lxDay = fsCourseWatchLogMapper.selectByWatchlxDay(recordVO.getUserId(),recordVO.getProjectId());
+            System.out.println("进入了连续观看天数:"+lxDay+"天");
+            recordVO.setWatchLxCount(lxDay);
+
             // 领取状态
             Long count = fsCourseAnswerLogsMapper.selectRedStatus(recordVO.getUserId(), recordVO.getVideoId());
             if (Objects.nonNull(count) && count > 0) {

+ 2 - 1
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseTrainingCampServiceImpl.java

@@ -62,11 +62,12 @@ public class FsUserCourseTrainingCampServiceImpl extends ServiceImpl<FsUserCours
      * @param params    参数
      */
     @Override
-    public void add(FsUserCourseTrainingCampDTO params) {
+    public void add(FsUserCourseTrainingCampDTO params,Long userId) {
         FsUserCourseTrainingCamp trainingCamp = new FsUserCourseTrainingCamp();
         trainingCamp.setTrainingCampName(params.getTrainingCampName());
         trainingCamp.setOrderNumber(baseMapper.getOrderNumber());
         trainingCamp.setCreateTime(LocalDateTime.now());
+        trainingCamp.setUserId(userId);
         baseMapper.insert(trainingCamp);
     }
 

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

@@ -4,10 +4,13 @@ import java.util.*;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
+import com.fs.common.exception.CustomException;
+import com.fs.common.utils.StringUtils;
 import com.fs.course.domain.FsUserCoursePeriod;
 import com.fs.course.domain.FsUserCoursePeriodDays;
 import com.fs.course.mapper.FsUserCoursePeriodDaysMapper;
 import com.fs.course.mapper.FsUserCoursePeriodMapper;
+import com.fs.course.param.BatchCompanyRedPackageParam;
 import com.fs.course.param.FsBatchPeriodRedPackageParam;
 import com.google.common.collect.Lists;
 import org.apache.ibatis.annotations.Param;
@@ -23,12 +26,12 @@ import org.springframework.transaction.annotation.Transactional;
 
 /**
  * 课程公司红包Service业务层处理
- * 
+ *
  * @author fs
  * @date 2024-10-25
  */
 @Service
-public class FsUserCourseVideoRedPackageServiceImpl implements IFsUserCourseVideoRedPackageService 
+public class FsUserCourseVideoRedPackageServiceImpl implements IFsUserCourseVideoRedPackageService
 {
     @Autowired
     private FsUserCourseVideoRedPackageMapper fsUserCourseVideoRedPackageMapper;
@@ -44,7 +47,7 @@ public class FsUserCourseVideoRedPackageServiceImpl implements IFsUserCourseVide
 
     /**
      * 查询课程公司红包
-     * 
+     *
      * @param id 课程公司红包主键
      * @return 课程公司红包
      */
@@ -56,7 +59,7 @@ public class FsUserCourseVideoRedPackageServiceImpl implements IFsUserCourseVide
 
     /**
      * 查询课程公司红包列表
-     * 
+     *
      * @param fsUserCourseVideoRedPackage 课程公司红包
      * @return 课程公司红包
      */
@@ -68,7 +71,7 @@ public class FsUserCourseVideoRedPackageServiceImpl implements IFsUserCourseVide
 
     /**
      * 新增课程公司红包
-     * 
+     *
      * @param fsUserCourseVideoRedPackage 课程公司红包
      * @return 结果
      */
@@ -80,7 +83,7 @@ public class FsUserCourseVideoRedPackageServiceImpl implements IFsUserCourseVide
 
     /**
      * 修改课程公司红包
-     * 
+     *
      * @param fsUserCourseVideoRedPackage 课程公司红包
      * @return 结果
      */
@@ -92,7 +95,7 @@ public class FsUserCourseVideoRedPackageServiceImpl implements IFsUserCourseVide
 
     /**
      * 批量删除课程公司红包
-     * 
+     *
      * @param ids 需要删除的课程公司红包主键
      * @return 结果
      */
@@ -104,7 +107,7 @@ public class FsUserCourseVideoRedPackageServiceImpl implements IFsUserCourseVide
 
     /**
      * 删除课程公司红包信息
-     * 
+     *
      * @param id 课程公司红包主键
      * @return 结果
      */
@@ -239,5 +242,44 @@ public class FsUserCourseVideoRedPackageServiceImpl implements IFsUserCourseVide
     public void batchSaveFsUserCourseVideoRedPackage(List<FsUserCourseVideoRedPackage> redPackage) {
         fsUserCourseVideoRedPackageMapper.batchSaveFsUserCourseVideoRedPackage(redPackage);
     }
+    /**
+     * 按照公司批量设置红包
+     * @param param 入参
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void batchRedPacketByCompany(BatchCompanyRedPackageParam param) {
+        FsUserCoursePeriod period = userCoursePeriodMapper.selectFsUserCoursePeriodById(param.getPeriodId());
+        if (Objects.isNull(period)) {
+            throw new CustomException("营期不存在");
+        }
+
+        Set<Long> targetCompanyIds = new HashSet<>(param.getCompanyIds());
+        Set<Long> companyIds = Arrays.stream(period.getCompanyId().split(","))
+                .filter(StringUtils::isNotBlank)
+                .map(Long::valueOf)
+                .filter(targetCompanyIds::contains)
+                .collect(Collectors.toSet());
+
+        if (companyIds.isEmpty()) {
+            throw new CustomException("当前营期不包含所选公司");
+        }
+
+        List<FsUserCoursePeriodDays> periodVideos = userCoursePeriodDaysMapper.selectCourseVideoList(Collections.singleton(period.getPeriodId()));
+
+        List<FsUserCourseVideoRedPackage> fsRedPackageList = companyIds.stream()
+                .flatMap(companyId -> periodVideos.stream().map(video -> {
+                    FsUserCourseVideoRedPackage redPkg = new FsUserCourseVideoRedPackage();
+                    redPkg.setCompanyId(companyId);
+                    redPkg.setVideoId(video.getVideoId());
+                    redPkg.setRedPacketMoney(param.getRedPacketMoney());
+                    redPkg.setPeriodId(period.getPeriodId());
+                    redPkg.setDataType(2);
+                    return redPkg;
+                }))
+                .collect(Collectors.toList());
+
+        this.batchSaveCompanyRedPackage(fsRedPackageList);
+    }
 
 }

+ 46 - 69
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -71,6 +71,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
@@ -97,6 +98,9 @@ import static com.fs.course.utils.LinkUtil.generateRandomStringWithLock;
 @Service
 public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 {
+    @Value("${cloud_host.company_name}")
+    private String signProjectName;
+
     private static final Logger logger = LoggerFactory.getLogger(FsUserCourseVideoServiceImpl.class);
 
 
@@ -1020,31 +1024,32 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         packetParam.setSource(param.getSource());
         packetParam.setRedPacketMode(config.getRedPacketMode());
         packetParam.setCompanyId(param.getCompanyId());
+        packetParam.setAppId(param.getAppId());
 
         System.out.println("红包金额"+amount);
         System.out.println("红包商户号"+packetParam);
         //2025.6.19 红包金额为0的时候
         if (amount.compareTo(BigDecimal.ZERO)>0){
 
-            Company company = companyMapper.selectCompanyByIdForUpdate(param.getCompanyId());
-            BigDecimal money = company.getMoney();
-            BigDecimal subtract = money.subtract(amount);
-            if (subtract.compareTo(BigDecimal.ZERO)<0){
-                FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
-                redPacketLog.setCourseId(param.getCourseId());
-                redPacketLog.setCompanyId(param.getCompanyId());
-                redPacketLog.setUserId(param.getUserId());
-                redPacketLog.setVideoId(param.getVideoId());
-                redPacketLog.setStatus(2);
-                redPacketLog.setQwUserId(param.getQwUserId() != null ? param.getQwUserId() : null);
-                redPacketLog.setCompanyUserId(param.getCompanyUserId());
-                redPacketLog.setCreateTime(new Date());
-                redPacketLog.setAmount(amount);
-                redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
-                redPacketLog.setPeriodId(param.getPeriodId());
-                redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
-                return R.error("销售公司余额不足");
-            }
+//            Company company = companyMapper.selectCompanyByIdForUpdate(param.getCompanyId());
+           // BigDecimal money = company.getMoney();
+         //   BigDecimal subtract = money.subtract(amount);
+//            if (subtract.compareTo(BigDecimal.ZERO)<0){
+//                FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
+//                redPacketLog.setCourseId(param.getCourseId());
+//                redPacketLog.setCompanyId(param.getCompanyId());
+//                redPacketLog.setUserId(param.getUserId());
+//                redPacketLog.setVideoId(param.getVideoId());
+//                redPacketLog.setStatus(2);
+//                redPacketLog.setQwUserId(param.getQwUserId() != null ? param.getQwUserId() : null);
+//                redPacketLog.setCompanyUserId(param.getCompanyUserId());
+//                redPacketLog.setCreateTime(new Date());
+//                redPacketLog.setAmount(amount);
+//                redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
+//                redPacketLog.setPeriodId(param.getPeriodId());
+//                redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
+//                return R.error("余额不足请稍等");
+//            }
             // 发送红包
             R sendRedPacket = paymentService.sendRedPacket(packetParam);
             if (sendRedPacket.get("code").equals(200)) {
@@ -1075,17 +1080,18 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
                 // 更新观看记录的奖励类型
                 log.setRewardType(config.getRewardType());
                 courseWatchLogMapper.updateFsCourseWatchLog(log);
-                company.setMoney(subtract);
-                companyMapper.updateCompany(company);
-
-                CompanyMoneyLogs logs=new CompanyMoneyLogs();
-                logs.setCompanyId(company.getCompanyId());
-                logs.setRemark("扣除红包金额");
-                logs.setMoney(amount.multiply(new BigDecimal(-1)));
-                logs.setLogsType(15);
-                logs.setBalance(company.getMoney());
-                logs.setCreateTime(new Date());
-                moneyLogsMapper.insertCompanyMoneyLogs(logs);
+//
+//                company.setMoney(subtract);
+//                companyMapper.updateCompany(company);
+//
+//                CompanyMoneyLogs logs=new CompanyMoneyLogs();
+//                logs.setCompanyId(company.getCompanyId());
+//                logs.setRemark("扣除红包金额");
+//                logs.setMoney(amount.multiply(new BigDecimal(-1)));
+//                logs.setLogsType(15);
+//                logs.setBalance(company.getMoney());
+//                logs.setCreateTime(new Date());
+//                moneyLogsMapper.insertCompanyMoneyLogs(logs);
 
                 return sendRedPacket;
             } else {
@@ -1209,26 +1215,6 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         //2025.6.19 红包金额为0的时候
         if (amount.compareTo(BigDecimal.ZERO)>0){
 
-            Company company = companyMapper.selectCompanyByIdForUpdate(param.getCompanyId());
-            BigDecimal money = company.getMoney();
-            BigDecimal subtract = money.subtract(amount);
-            if (subtract.compareTo(BigDecimal.ZERO)<0){
-                FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
-                redPacketLog.setCourseId(param.getCourseId());
-                redPacketLog.setCompanyId(param.getCompanyId());
-                redPacketLog.setUserId(param.getUserId());
-                redPacketLog.setVideoId(param.getVideoId());
-                redPacketLog.setStatus(0);
-                redPacketLog.setQwUserId(param.getQwUserId() != null ? param.getQwUserId() : null);
-                redPacketLog.setCompanyUserId(param.getCompanyUserId());
-                redPacketLog.setCreateTime(new Date());
-                redPacketLog.setAmount(amount);
-                redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
-                redPacketLog.setPeriodId(param.getPeriodId());
-                redPacketLog.setAppId(param.getAppId());
-                redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
-                return R.error("销售公司余额不足");
-            }
             // 发送红包
             R sendRedPacket = paymentService.sendRedPacket(packetParam);
             if (sendRedPacket.get("code").equals(200)) {
@@ -1260,17 +1246,6 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
                 // 更新观看记录的奖励类型
                 log.setRewardType(config.getRewardType());
                 courseWatchLogMapper.updateFsCourseWatchLog(log);
-                company.setMoney(subtract);
-                companyMapper.updateCompany(company);
-
-                CompanyMoneyLogs logs=new CompanyMoneyLogs();
-                logs.setCompanyId(company.getCompanyId());
-                logs.setRemark("扣除红包金额");
-                logs.setMoney(amount.multiply(new BigDecimal(-1)));
-                logs.setLogsType(15);
-                logs.setBalance(company.getMoney());
-                logs.setCreateTime(new Date());
-                moneyLogsMapper.insertCompanyMoneyLogs(logs);
 
                 return sendRedPacket;
             } else {
@@ -1284,7 +1259,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             redPacketLog.setCompanyId(param.getCompanyId());
             redPacketLog.setUserId(param.getUserId());
             redPacketLog.setVideoId(param.getVideoId());
-            redPacketLog.setStatus(0);
+            redPacketLog.setStatus(1);
             redPacketLog.setQwUserId(param.getQwUserId() != null ? param.getQwUserId() : null);
             redPacketLog.setCompanyUserId(param.getCompanyUserId());
             redPacketLog.setCreateTime(new Date());
@@ -1294,11 +1269,9 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             redPacketLog.setAppId(param.getAppId());
             redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
 
-            // 更新观看记录的奖励类型
-//            if (param.getLinkType() == null || param.getLinkType() == 0) {
+            // 更新观看记录的奖励类
             log.setRewardType(config.getRewardType());
             courseWatchLogMapper.updateFsCourseWatchLog(log);
-//            }
             return R.ok("红包发送成功");
         }
 
@@ -1586,7 +1559,11 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         }
 
         if (userCompanyUser.getStatus() == 2) {
-            return ResponseResult.fail(504, "已被拉黑,请联系管理员");
+            if("福本源".equals(signProjectName)){
+                return ResponseResult.fail(504, "服务暂时不可用,请联系管理员");
+            } else {
+                return ResponseResult.fail(504, "已被拉黑,请联系管理员");
+            }
         }
 
         //查询看课记录
@@ -2337,7 +2314,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         Long duration = redisCache.getCacheObject(redisKey);
 
         if (duration == null) {
-            FsUserCourseVideoQVO videoInfo = selectFsUserCourseVideoByVideoIdVO(videoId);
+            FsUserCourseVideoQVO videoInfo = selectFsUserCourseVideoByVideoIdVO(videoId,null);
             if (videoInfo == null || videoInfo.getDuration() == null) {
                 throw new IllegalArgumentException("视频时长信息不存在");
             }
@@ -2468,9 +2445,9 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     }
 
     @Override
-    public FsUserCourseVideoQVO selectFsUserCourseVideoByVideoIdVO(Long videoId) {
+    public FsUserCourseVideoQVO selectFsUserCourseVideoByVideoIdVO(Long videoId,Long userId) {
         FsUserCourseVideoQVO fsUserCourseVideoQVO = new FsUserCourseVideoQVO();
-        FsUserCourseVideo courseVideo = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId(videoId);
+        FsUserCourseVideo courseVideo = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoIdAndUserId(videoId,userId);
 
         BeanCopyUtils.copy(courseVideo,fsUserCourseVideoQVO);
 

+ 94 - 86
fs-service/src/main/java/com/fs/course/service/impl/FsUserWatchCourseStatisticsServiceImpl.java

@@ -8,6 +8,7 @@ import com.fs.course.service.IFsUserWatchCourseStatisticsService;
 import com.fs.his.mapper.FsUserMapper;
 import com.google.common.collect.Lists;
 import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.ibatis.session.ExecutorType;
 import org.apache.ibatis.session.SqlSession;
 import org.apache.ibatis.session.SqlSessionFactory;
@@ -33,6 +34,7 @@ import java.util.stream.Collectors;
  */
 @Service
 @AllArgsConstructor
+@Slf4j
 public class FsUserWatchCourseStatisticsServiceImpl extends ServiceImpl<FsUserWatchCourseStatisticsMapper, FsUserWatchCourseStatistics> implements IFsUserWatchCourseStatisticsService {
 
     private FsUserCoursePeriodDaysMapper fsUserCoursePeriodDaysMapper;
@@ -132,96 +134,102 @@ public class FsUserWatchCourseStatisticsServiceImpl extends ServiceImpl<FsUserWa
     public void insertWatchCourseStatistics() {
         // 1、获取统计数据
         // 查询课程相关数据
-        List<FsUserWatchCourseStatistics> fsUserWatchCourseStatistics = fsUserCoursePeriodDaysMapper.selectDaysCountList();
-
-        // 查询统计数据
-        List<FsUserWatchCourseStatistics> watchLog = fsUserMapper.selectWatchLogCount();
-        List<FsUserWatchCourseStatistics> redPacketLog = fsUserMapper.selectRedPacketLogCount();
-        List<FsUserWatchCourseStatistics> answerLog = fsUserMapper.selectAnswerLogCount();
-        List<FsUserWatchCourseStatistics> userTotal = fsUserMapper.selectFsUserDetail();
-
-        // 转化为自定义键的map
-        Map<String, FsUserWatchCourseStatistics> watchLogMap = watchLog.stream().collect(Collectors.toMap(k -> String.format("%s-%s-%s", k.getPeriodId(), k.getVideoId(), k.getCompanyUserId()), v -> v));
-        Map<String, FsUserWatchCourseStatistics> redPacketLogMap = redPacketLog.stream().collect(Collectors.toMap(k -> String.format("%s-%s-%s", k.getPeriodId(), k.getVideoId(), k.getCompanyUserId()), v -> v));
-        Map<String, FsUserWatchCourseStatistics> answerLogMap = answerLog.stream().collect(Collectors.toMap(k -> String.format("%s-%s-%s", k.getPeriodId(), k.getVideoId(), k.getCompanyUserId()), v -> v));
-        Map<Long, List<FsUserWatchCourseStatistics>> userTotalMap = userTotal.stream()
-                .collect(Collectors.groupingBy(FsUserWatchCourseStatistics::getCompanyUserId));
-
-        // 处理数据
-        List<FsUserWatchCourseStatistics> list = new ArrayList<>();
-        for (FsUserWatchCourseStatistics data : fsUserWatchCourseStatistics) {
-            FsUserWatchCourseStatistics vo = new FsUserWatchCourseStatistics();
-            String key = String.format("%s-%s-%s", data.getPeriodId(), data.getVideoId(), data.getCompanyUserId());
-            FsUserWatchCourseStatistics watchLogData = watchLogMap.get(key);
-            FsUserWatchCourseStatistics redPacketLogData = redPacketLogMap.get(key);
-            FsUserWatchCourseStatistics answerLogData = answerLogMap.get(key);
-            List<FsUserWatchCourseStatistics> userTotalDataList = userTotalMap.get(data.getCompanyUserId());
-            BeanUtils.copyProperties(data, vo);
-            // 改成使用营期线来表示营期开始时间
-            vo.setPeriodStartingTime(data.getPeriodLine() != null ? data.getPeriodLine() : data.getPeriodStartingTime());
-
-            // 单独一个一个set,不用copy,避免copy出来的结果被前面的覆盖
-            if(userTotalDataList != null && !userTotalDataList.isEmpty()){
-                // 获取过滤时间后的销售会员数量
-                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
-
-                int userNum = userTotalDataList.stream()
-                        .filter(v -> v.getUserCreateDate().before(data.getCourseStartDateTime())).mapToInt(FsUserWatchCourseStatistics::getUserNum).sum();
-                int newUserNum = userTotalDataList.stream()
-                        .filter(v -> sdf.format(v.getUserCreateDate()).equals(sdf.format(data.getCourseStartDateTime()))).mapToInt(FsUserWatchCourseStatistics::getUserNum).sum();
-                vo.setUserNum(userNum);
-                vo.setNewUserNum(newUserNum);
-            } else {
-                vo.setUserNum(0);
-                vo.setNewUserNum(0);
+        try{
+            List<FsUserWatchCourseStatistics> fsUserWatchCourseStatistics = fsUserCoursePeriodDaysMapper.selectDaysCountList();
+
+            // 查询统计数据
+            List<FsUserWatchCourseStatistics> watchLog = fsUserMapper.selectWatchLogCount();
+            List<FsUserWatchCourseStatistics> redPacketLog = fsUserMapper.selectRedPacketLogCount();
+            List<FsUserWatchCourseStatistics> answerLog = fsUserMapper.selectAnswerLogCount();
+            List<FsUserWatchCourseStatistics> userTotal = fsUserMapper.selectFsUserDetail();
+
+            // 转化为自定义键的map
+            Map<String, FsUserWatchCourseStatistics> watchLogMap = watchLog.stream().collect(Collectors.toMap(k -> String.format("%s-%s-%s", k.getPeriodId(), k.getVideoId(), k.getCompanyUserId()), v -> v));
+            Map<String, FsUserWatchCourseStatistics> redPacketLogMap = redPacketLog.stream().collect(Collectors.toMap(k -> String.format("%s-%s-%s", k.getPeriodId(), k.getVideoId(), k.getCompanyUserId()), v -> v));
+            Map<String, FsUserWatchCourseStatistics> answerLogMap = answerLog.stream().collect(Collectors.toMap(k -> String.format("%s-%s-%s", k.getPeriodId(), k.getVideoId(), k.getCompanyUserId()), v -> v));
+            Map<Long, List<FsUserWatchCourseStatistics>> userTotalMap = userTotal.stream()
+                    .collect(Collectors.groupingBy(FsUserWatchCourseStatistics::getCompanyUserId));
+
+            // 处理数据
+            List<FsUserWatchCourseStatistics> list = new ArrayList<>();
+            for (FsUserWatchCourseStatistics data : fsUserWatchCourseStatistics) {
+                FsUserWatchCourseStatistics vo = new FsUserWatchCourseStatistics();
+                String key = String.format("%s-%s-%s", data.getPeriodId(), data.getVideoId(), data.getCompanyUserId());
+                FsUserWatchCourseStatistics watchLogData = watchLogMap.get(key);
+                FsUserWatchCourseStatistics redPacketLogData = redPacketLogMap.get(key);
+                FsUserWatchCourseStatistics answerLogData = answerLogMap.get(key);
+                List<FsUserWatchCourseStatistics> userTotalDataList = userTotalMap.get(data.getCompanyUserId());
+                BeanUtils.copyProperties(data, vo);
+                // 改成使用营期线来表示营期开始时间
+                vo.setPeriodStartingTime(data.getPeriodLine() != null ? data.getPeriodLine() : data.getPeriodStartingTime());
+
+                // 单独一个一个set,不用copy,避免copy出来的结果被前面的覆盖
+                if(userTotalDataList != null && !userTotalDataList.isEmpty()){
+                    // 获取过滤时间后的销售会员数量
+                    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
+
+                    int userNum = userTotalDataList.stream()
+                            .filter(v -> v.getUserCreateDate().before(data.getCourseStartDateTime())).mapToInt(FsUserWatchCourseStatistics::getUserNum).sum();
+                    int newUserNum = userTotalDataList.stream()
+                            .filter(v -> sdf.format(v.getUserCreateDate()).equals(sdf.format(data.getCourseStartDateTime()))).mapToInt(FsUserWatchCourseStatistics::getUserNum).sum();
+                    vo.setUserNum(userNum);
+                    vo.setNewUserNum(newUserNum);
+                } else {
+                    vo.setUserNum(0);
+                    vo.setNewUserNum(0);
+                }
+
+                if(watchLogData != null) {
+                    vo.setWatchNum(watchLogData.getWatchNum());
+                    vo.setCompleteWatchNum(watchLogData.getCompleteWatchNum());
+                    vo.setCompleteWatchRate(watchLogData.getCompleteWatchRate());
+                } else {
+
+                    vo.setWatchNum(0);
+                    vo.setCompleteWatchNum(0);
+                    vo.setCompleteWatchRate(BigDecimal.ZERO);
+                }
+
+                if(redPacketLogData != null) {
+                    vo.setRedPacketNum(redPacketLogData.getRedPacketNum());
+                    vo.setRedPacketAmount(redPacketLogData.getRedPacketAmount());
+                } else {
+                    vo.setRedPacketNum(0);
+                    vo.setRedPacketAmount(BigDecimal.ZERO);
+                }
+
+                if(answerLogData != null) {
+                    vo.setAnswerNum(answerLogData.getAnswerNum());
+                    vo.setAnswerRightNum(answerLogData.getAnswerRightNum());
+                    vo.setAnswerRightRate(answerLogData.getAnswerRightRate());
+                } else {
+                    vo.setAnswerNum(0);
+                    vo.setAnswerRightNum(0);
+                    vo.setAnswerRightRate(BigDecimal.ZERO);
+                }
+
+                // 设置上线率
+                BigDecimal watchNum = new BigDecimal(vo.getWatchNum());
+                BigDecimal userNum = new BigDecimal(vo.getUserNum());
+                if(!userNum.equals(BigDecimal.ZERO)){
+                    BigDecimal onlineRate = watchNum.divide(userNum, 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
+                    vo.setOnlineRate(onlineRate);
+                } else{
+                    vo.setOnlineRate(BigDecimal.ZERO);
+                }
+
+                vo.setCreateTime(new Date());
+                vo.setUpdateTime(new Date());
+                list.add(vo);
             }
 
-            if(watchLogData != null) {
-                vo.setWatchNum(watchLogData.getWatchNum());
-                vo.setCompleteWatchNum(watchLogData.getCompleteWatchNum());
-                vo.setCompleteWatchRate(watchLogData.getCompleteWatchRate());
-            } else {
-                vo.setWatchNum(0);
-                vo.setCompleteWatchNum(0);
-                vo.setCompleteWatchRate(BigDecimal.ZERO);
-            }
-
-            if(redPacketLogData != null) {
-                vo.setRedPacketNum(redPacketLogData.getRedPacketNum());
-                vo.setRedPacketAmount(redPacketLogData.getRedPacketAmount());
-            } else {
-                vo.setRedPacketNum(0);
-                vo.setRedPacketAmount(BigDecimal.ZERO);
-            }
-
-            if(answerLogData != null) {
-                vo.setAnswerNum(answerLogData.getAnswerNum());
-                vo.setAnswerRightNum(answerLogData.getAnswerRightNum());
-                vo.setAnswerRightRate(answerLogData.getAnswerRightRate());
-            } else {
-                vo.setAnswerNum(0);
-                vo.setAnswerRightNum(0);
-                vo.setAnswerRightRate(BigDecimal.ZERO);
-            }
-
-            // 设置上线率
-            BigDecimal watchNum = new BigDecimal(vo.getWatchNum());
-            BigDecimal userNum = new BigDecimal(vo.getUserNum());
-            if(!userNum.equals(BigDecimal.ZERO)){
-                BigDecimal onlineRate = watchNum.divide(userNum, 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
-                vo.setOnlineRate(onlineRate);
-            } else{
-                vo.setOnlineRate(BigDecimal.ZERO);
-            }
-
-            vo.setCreateTime(new Date());
-            vo.setUpdateTime(new Date());
-            list.add(vo);
+            //2、分批次插入数据
+            this.batchInsert(list);
+        }catch (Exception e){
+            e.printStackTrace();
+            log.error("数据存在问题:{}",e.getMessage());
         }
 
-        //2、分批次插入数据
-        this.batchInsert(list);
-
     }
 
     private void batchInsert(List<FsUserWatchCourseStatistics> list) {

+ 15 - 0
fs-service/src/main/java/com/fs/course/vo/FsUserCourseParticipationRecordVO.java

@@ -64,4 +64,19 @@ public class FsUserCourseParticipationRecordVO {
      * 标签
      */
     private List<CompanyTag> tags;
+
+    /**
+     * 累计观看天数
+     */
+    private Long watchLjCount;
+
+    /**
+     * 连续观看天数
+     */
+    private Long watchLxCount;
+
+    /**
+     * 项目编号
+     */
+    private Long projectId;
 }

+ 63 - 9
fs-service/src/main/java/com/fs/ipad/IpadSendUtils.java

@@ -6,10 +6,14 @@ import com.fs.common.core.redis.RedisCache;
 import com.fs.common.core.redis.RedisCacheT;
 import com.fs.common.exception.base.BaseException;
 import com.fs.common.utils.StringUtils;
+import com.fs.ipad.param.WxGetSessionRoomListParam;
+import com.fs.ipad.param.WxRoomUserListParam;
+import com.fs.ipad.param.WxSendAtMsgParam;
 import com.fs.ipad.vo.*;
 import com.fs.wxwork.dto.*;
 import com.fs.wxwork.service.WxWorkServiceNew;
 import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 
 import java.net.MalformedURLException;
@@ -21,6 +25,7 @@ import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Supplier;
 
+@Slf4j
 @Component
 @AllArgsConstructor
 public class IpadSendUtils {
@@ -141,6 +146,25 @@ public class IpadSendUtils {
         dto.setIsRoom(vo.isRoom());
         return wxWorkService.SendCDNVideoMsg(dto, vo.getServerId());
     }
+    /**
+     * 发送视频号
+     */
+    public WxWorkResponseDTO<WxwSendVideoNumberRespDTO> sendWxVideo(WxVideoVo vo){
+        WxwSendVideoNumberMsgDTO dto = new WxwSendVideoNumberMsgDTO();
+        dto.setUuid(vo.getUuid());
+        dto.setSend_userid(userIds(vo));
+        dto.setIsRoom(vo.isRoom());
+        dto.setCoverUrl(vo.getCoverUrl());
+        dto.setThumbUrl(vo.getThumbUrl());
+        dto.setAvatar(vo.getAvatar());
+        dto.setNickname(vo.getNickname());
+        dto.setDesc(vo.getDesc());
+        dto.setUrl(vo.getUrl());
+        dto.setExtras(vo.getExtras());
+        dto.setObjectId(vo.getObjectId());
+        dto.setObjectNonceId(vo.getObjectNonceId());
+        return wxWorkService.SendVideoNumber(dto, vo.getServerId());
+    }
     /**
      * 发送小程序
      */
@@ -178,17 +202,15 @@ public class IpadSendUtils {
         }
         WxWorkUserId2VidDTO wxWorkUserId2VidDTO = new WxWorkUserId2VidDTO();
         wxWorkUserId2VidDTO.setOpenid(Collections.singletonList(vo.getExId()));
+        wxWorkUserId2VidDTO.setCorpid(vo.getCorpId());
+        wxWorkUserId2VidDTO.setScorpid(vo.getCorpCode());
         wxWorkUserId2VidDTO.setUuid(vo.getUuid());
         WxWorkResponseDTO<List<WxWorkVid2UserIdRespDTO>> WxWorkVid2UserIdRespDTO = wxWorkService.UserId2Vid(wxWorkUserId2VidDTO, vo.getServerId());
-//        if(WxWorkVid2UserIdRespDTO.getErrcode() != 0){
-//            String errmsg = WxWorkVid2UserIdRespDTO.getErrmsg();
-//            if("实例不存在或在,规定时间内未完成扫码登录uuid失效。".equals(WxWorkVid2UserIdRespDTO.getErrmsg())){
-//                errmsg += "serverId:" + vo.getServerId() + "====url:" + redisCache.getCacheObject("serverId:" + vo.getServerId());
-//            }
-//            throw new BaseException(errmsg);
-//        }
         List<WxWorkVid2UserIdRespDTO> data = WxWorkVid2UserIdRespDTO.getData();
-        if(data.isEmpty()) throw new BaseException("未找到用户");
+        if(data.isEmpty()) {
+            log.error("未找到用户数据,基础数据:{},请求数据:{},返回数据:{}", vo, JSON.toJSONString(wxWorkUserId2VidDTO), JSON.toJSONString(WxWorkVid2UserIdRespDTO));
+            throw new BaseException("未找到用户:" + vo.getId());
+        }
         return data.get(0).getUser_id();
     }
 
@@ -200,13 +222,17 @@ public class IpadSendUtils {
     private Long chatIds(BaseVo vo){
         WxWorkChatIdToRoomIdDTO tdo = new WxWorkChatIdToRoomIdDTO();
         tdo.setChatid(vo.getExId());
+        tdo.setCorpid(vo.getCorpId());
         tdo.setUuid(vo.getUuid());
         WxWorkResponseDTO<WxWorkChatIdToRoomIdResp> result = wxWorkService.ChatIdToRoomId(tdo, vo.getServerId());
         if(result.getErrcode() != 0){
             throw new BaseException(result.getErrmsg());
         }
         WxWorkChatIdToRoomIdResp data = result.getData();
-        if(data == null || data.getRoom_id() == null) throw new BaseException("未找到用户");
+        if(data == null || data.getRoom_id() == null) {
+            log.error("未找到群聊数据,请求数据:{},返回数据:{}", JSON.toJSONString(tdo), JSON.toJSONString(result));
+            throw new BaseException("未找到群聊:" + vo.getId());
+        }
         return data.getRoom_id();
     }
 
@@ -325,4 +351,32 @@ public class IpadSendUtils {
         dto.setUuid(uuid);
         wxWorkService.LoginOut(dto, serverId);
     }
+    public List<WxGetSessionRoomListVo.RoomList> getSessionRoomList(String uuid, Long serverId){
+        WxGetSessionRoomListParam param = new WxGetSessionRoomListParam();
+        param.setUuid(uuid);
+        WxWorkResponseDTO<WxGetSessionRoomListVo> result = wxWorkService.getSessionRoomList(param, serverId);
+        if(result.getErrcode() != 0) throw new BaseException("获取会话群聊失败:" + result.getErrmsg());
+        return result.getData().getRoom_list();
+    }
+
+    public List<WxRoomUserListVo.MemberList> getSessionRoomUserList(String uuid, Long roomId, Long serverId){
+        WxRoomUserListParam param = new WxRoomUserListParam();
+        param.setUuid(uuid);
+        param.setRoomid(roomId);
+        WxWorkResponseDTO<WxRoomUserListVo> result = wxWorkService.getRoomUserList(param, serverId);
+        if(result.getErrcode() != 0) throw new BaseException("获取群聊用户列表错误:" + result.getErrmsg());
+        return result.getData().getMember_list();
+    }
+
+    public void sendTextAtMsg(WxSendAtMsgParam param, Long serverId){
+        WxWorkResponseDTO<WxSendAtMsgVo> result = wxWorkService.sendTextAtMsg(param, serverId);
+        log.info("发送返回数据:{}", result);
+        if(result.getErrcode() != 0) throw new BaseException("发送@消息错误:" + result.getErrmsg());
+    }
+
+    public void sendTxtNoVo(WxWorkSendTextMsgDTO dto, Long serverId){
+        WxWorkResponseDTO<WxWorkSendTextMsgRespDTO> result = wxWorkService.SendTextMsg(dto, serverId);
+        log.info("发送返回数据:{}", result);
+        if(result.getErrcode() != 0) throw new BaseException("发送消息错误:" + result.getErrmsg());
+    }
 }

+ 12 - 0
fs-service/src/main/java/com/fs/ipad/param/WxGetSessionRoomListParam.java

@@ -0,0 +1,12 @@
+package com.fs.ipad.param;
+
+import lombok.Data;
+
+@Data
+public class WxGetSessionRoomListParam {
+
+    private String uuid;
+    private int limit = 1000;
+    private int star_index = 0;
+
+}

+ 11 - 0
fs-service/src/main/java/com/fs/ipad/param/WxRoomUserListParam.java

@@ -0,0 +1,11 @@
+package com.fs.ipad.param;
+
+import lombok.Data;
+
+@Data
+public class WxRoomUserListParam {
+
+    private String uuid;
+    private Long roomid;
+
+}

+ 18 - 0
fs-service/src/main/java/com/fs/ipad/param/WxSendAtMsgParam.java

@@ -0,0 +1,18 @@
+package com.fs.ipad.param;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class WxSendAtMsgParam {
+
+    private String uuid;
+    private String content;
+    private Long send_userid;
+    private List<Long> atids;
+    @JSONField(name = "isRoom")
+    private boolean isRoom = true;
+
+}

+ 23 - 0
fs-service/src/main/java/com/fs/ipad/vo/WxGetSessionRoomListVo.java

@@ -0,0 +1,23 @@
+package com.fs.ipad.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class WxGetSessionRoomListVo {
+
+    private Integer seq;
+    private List<RoomList> room_list;
+
+
+    @Data
+    public static class RoomList{
+        private Long room_id;
+        private Long create_user_id;
+        private Integer total;
+        private Integer flag;
+        private Long create_time;
+        private String nickname;
+    }
+}

+ 44 - 0
fs-service/src/main/java/com/fs/ipad/vo/WxRoomUserListVo.java

@@ -0,0 +1,44 @@
+package com.fs.ipad.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class WxRoomUserListVo {
+
+    private Long room_id;
+    private Long create_user_id;
+    private Long notice_sendervid;
+    private Long create_time;
+    private Long notice_time;
+    private Integer total;
+    private List<Integer> anti_spam_rules;
+    private String notice_content;
+    private String nickname;
+    private Integer flag;
+    private Integer new_flag;
+    private List<MemberList> member_list;
+
+
+    @Data
+    public static class MemberList{
+        private String unionid;
+        private Long create_time;
+        private Long jointime;
+        private Integer sex;
+        private String mobile;
+        private String acctid;
+        private Integer join_scene;
+        private String avatar;
+        private String english_name;
+        private String realname;
+        private String room_notes;
+        private String nickname;
+        private String room_nickname;
+        private String position;
+        private Long uin;
+        private Long invite_user_id;
+        private Long corp_id;
+    }
+}

+ 19 - 0
fs-service/src/main/java/com/fs/ipad/vo/WxSendAtMsgVo.java

@@ -0,0 +1,19 @@
+package com.fs.ipad.vo;
+
+import lombok.Data;
+
+@Data
+public class WxSendAtMsgVo {
+
+    private Long receiver;
+    private Long sender;
+    private Long sendtime;
+    private Long msg_id;
+    private Long server_id;
+    private Long msgtype;
+    private String EmotionType;
+    private String sender_name;
+    private String app_info;
+    private String url;
+    private Integer is_room;
+}

+ 22 - 0
fs-service/src/main/java/com/fs/ipad/vo/WxVideoVo.java

@@ -0,0 +1,22 @@
+package com.fs.ipad.vo;
+
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@Builder
+@EqualsAndHashCode(callSuper = true)
+public class WxVideoVo extends BaseVo {
+
+
+    private String coverUrl;
+    private String thumbUrl;
+    private String avatar;
+    private String nickname;
+    private String desc;
+    private String url;
+    private String extras;
+    private String objectId;
+    private String objectNonceId;
+}

+ 1 - 0
fs-service/src/main/java/com/fs/qw/domain/QwUser.java

@@ -108,4 +108,5 @@ public class QwUser extends BaseEntity
      * 是否自动发课 00、禁用,01、启用
      */
     private String isAuto;
+    private Integer videoGetStatus;
 }

+ 7 - 0
fs-service/src/main/java/com/fs/qw/domain/QwUserVideo.java

@@ -3,6 +3,8 @@ package com.fs.qw.domain;
 import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
 import lombok.Data;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
 
 /**
  * 企业微信的视频号对象 qw_user_video
@@ -58,4 +60,9 @@ public class QwUserVideo extends BaseEntity
     /** 标识 */
     @Excel(name = "标识")
     private String extras;
+
+    private String objectNonceId;
+    private Long qwUserId;
+    private Long companyUserId;
+    private Long companyId;
 }

+ 2 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java

@@ -424,4 +424,6 @@ public interface QwUserMapper extends BaseMapper<QwUser>
     List<ExternalContactQwUserVO> selectQwUserByFsUserId(@Param("fsUserId") Long fsUserId);
 
     void updateSendType(UpdateSendTypeVo vo);
+
+    QwUser selectOfflineUser();
 }

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

@@ -189,4 +189,8 @@ public interface IQwUserService
     R updateSendType(UpdateSendTypeVo vo);
 
     R getLoginQwIpadStatus(QwLoginHookParam loginParam);
+
+    void atMsg(QwUser qwUser, String s);
+
+    void changeVideoStatus(Long id);
 }

+ 71 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwUserServiceImpl.java

@@ -13,14 +13,20 @@ import com.ecloud.sdk.ecs.v1.model.VmRebootRequest;
 import com.ecloud.sdk.ecs.v1.model.VmRebootResponse;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
+import com.fs.common.utils.PubFun;
+import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.ICompanyConfigService;
+import com.fs.company.service.ICompanyService;
 import com.fs.company.service.ICompanyUserService;
 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.ipad.IpadSendUtils;
+import com.fs.ipad.param.WxSendAtMsgParam;
+import com.fs.ipad.vo.WxGetSessionRoomListVo;
+import com.fs.ipad.vo.WxRoomUserListVo;
 import com.fs.qw.domain.*;
 import com.fs.qw.dto.QwUserByToolDTO;
 import com.fs.qw.dto.QwUserKeyDTO;
@@ -42,6 +48,7 @@ import com.fs.sop.domain.QwSop;
 import com.fs.voice.utils.StringUtil;
 import com.fs.wxwork.dto.*;
 import com.fs.wxwork.service.WxWorkService;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.slf4j.Logger;
@@ -68,6 +75,7 @@ import java.util.stream.Collectors;
  * @author fs
  * @date 2024-06-20
  */
+@Slf4j
 @Service
 @EnableAsync
 public class QwUserServiceImpl implements IQwUserService
@@ -78,6 +86,8 @@ public class QwUserServiceImpl implements IQwUserService
     @Autowired
     QwWorkTaskMapper qwWorkTaskMapper;
     @Autowired
+    ICompanyService companyService;
+    @Autowired
     private QwUserMapper qwUserMapper;
     @Autowired
     ICompanyConfigService companyConfigService;
@@ -1449,6 +1459,67 @@ public class QwUserServiceImpl implements IQwUserService
         return null;
     }
 
+    @Override
+    public void atMsg(QwUser qwUser, String msg) {
+        new Thread(() -> {
+            try {
+                String corpId = qwUser.getCorpId();
+                log.info("掉线提醒通知:{}, {}, {}", qwUser.getId(), qwUser.getQwUserName(), corpId);
+                // 获取通知账号
+                QwUser user = qwUserMapper.selectOfflineUser();
+                if(user == null){
+                    log.info("qwId:{}=====未找到通知账号", qwUser.getId());
+                    return;
+                }
+                Company company = companyService.selectCompanyById(qwUser.getCompanyId());
+                log.info("查到主体:{}", qwUser);
+                List<WxGetSessionRoomListVo.RoomList> sessionRoomList = ipadSendUtils.getSessionRoomList(user.getUid(), user.getServerId());
+                Optional<WxGetSessionRoomListVo.RoomList> optional = sessionRoomList.stream().filter(e -> e.getNickname().equals(company.getGroupName()) || e.getNickname().equals(company.getCompanyName())).findFirst();
+                if(!optional.isPresent()){
+                    log.warn("qwId:{}=====会话管理未找到群聊,corpId:{},群聊名称:{}, 查到群聊名称:{}", qwUser.getId(), corpId, company.getCompanyName(), PubFun.listToNewList(sessionRoomList, WxGetSessionRoomListVo.RoomList::getNickname));
+                    log.info("qwId:{}=====会话管理未找到群聊,corpId:{},群聊名称:{}, 查到群聊名称:{}", qwUser.getId(), corpId, company.getCompanyName(), PubFun.listToNewList(sessionRoomList, WxGetSessionRoomListVo.RoomList::getNickname));
+                    return;
+                }
+                WxGetSessionRoomListVo.RoomList room = optional.get();
+                log.info("找到会话群聊:{}", room);
+                CompanyUser companyUser = companyUserService.selectCompanyUserById(qwUser.getCompanyUserId());
+                log.info("企微账号:{}", JSON.toJSONString(companyUser));
+                List<WxRoomUserListVo.MemberList> memberLists = ipadSendUtils.getSessionRoomUserList(user.getUid(), room.getRoom_id(), user.getServerId());
+                Function<WxRoomUserListVo.MemberList, String> getName = e -> StringUtils.isEmpty(e.getRoom_nickname()) ? e.getNickname() : e.getRoom_nickname();
+                Optional<WxRoomUserListVo.MemberList> first = memberLists.stream().filter(e -> getName.apply(e).equals(companyUser.getUserName()) || getName.apply(e).equals(companyUser.getNickName())).findFirst();
+                String sendMsg = "企微账号:" + qwUser.getQwUserName() + " - " + msg;
+                if(!first.isPresent()){
+                    WxWorkSendTextMsgDTO dto = new WxWorkSendTextMsgDTO();
+                    dto.setUuid(user.getUid());
+                    dto.setSend_userid(room.getRoom_id());
+                    dto.setIsRoom(true);
+                    dto.setContent(sendMsg);
+                    ipadSendUtils.sendTxtNoVo(dto, user.getServerId());
+                }else{
+                    WxRoomUserListVo.MemberList memberList = first.get();
+                    log.info("找到掉线人:{}", memberList);
+                    WxSendAtMsgParam param = new WxSendAtMsgParam();
+                    param.setUuid(user.getUid());
+                    param.setContent(sendMsg);
+                    param.setSend_userid(room.getRoom_id());
+                    param.setAtids(Collections.singletonList(memberList.getUin()));
+                    param.setRoom(true);
+                    log.info("发送数据组装:{}", param);
+                    ipadSendUtils.sendTextAtMsg(param, user.getServerId());
+                }
+            }catch (Exception e){
+                log.warn("掉线提醒发送失败", e);
+            }
+        }).start();
+    }
+
+    @Override
+    public void changeVideoStatus(Long id) {
+        QwUser qwUser = qwUserMapper.selectQwUserById(id);
+        qwUser.setVideoGetStatus(qwUser.getVideoGetStatus() == 0 ? 1 : 0);
+        qwUserMapper.updateById(qwUser);
+    }
+
 
     /**
      * 构建查询条件

+ 1 - 0
fs-service/src/main/java/com/fs/qw/vo/QwSopCourseFinishTempSetting.java

@@ -49,6 +49,7 @@ public class QwSopCourseFinishTempSetting implements Serializable,Cloneable{
         /**
          * QwSopLog的主键(用于发送)
          */
+        private Long videoId;
         private Long sopLogId;
         /**
          * 员工的id(用于发送)

+ 4 - 0
fs-service/src/main/java/com/fs/statis/dto/TrafficLogDTO.java

@@ -22,4 +22,8 @@ public class TrafficLogDTO implements Serializable {
      * 本月流量
      */
     private Long thisMonth;
+    /**
+     * 剩余流量
+     */
+    private String traffic;
 }

+ 19 - 19
fs-service/src/main/java/com/fs/task/trafficlog/TrafficlogTask.java

@@ -1,19 +1,19 @@
-package com.fs.task.trafficlog;
-
-import com.fs.course.service.IFsCourseTrafficLogService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-@Service("trafficlogTask")
-@Slf4j
-public class TrafficlogTask {
-    @Autowired
-    private IFsCourseTrafficLogService fsCourseTrafficLogService;
-    /**
-     * 红包流量统计
-     */
-    /*public void sumTrafficlog(){
-        fsCourseTrafficLogService.sumTrafficlog();
-    }*/
-}
+//package com.fs.task.trafficlog;
+//
+//import com.fs.course.service.IFsCourseTrafficLogService;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.stereotype.Service;
+//
+//@Service("trafficlogTask")
+//@Slf4j
+//public class TrafficlogTask {
+//    @Autowired
+//    private IFsCourseTrafficLogService fsCourseTrafficLogService;
+//    /**
+//     * 红包流量统计
+//     */
+//    /*public void sumTrafficlog(){
+//        fsCourseTrafficLogService.sumTrafficlog();
+//    }*/
+//}

+ 38 - 0
fs-service/src/main/java/com/fs/wxwork/dto/WxwSendVideoNumberMsgDTO.java

@@ -0,0 +1,38 @@
+package com.fs.wxwork.dto;
+
+import lombok.Data;
+
+/**
+ * 发送CDN视频消息 请求DTO
+ *
+ * @author xdd
+ * @date 2025-02-27
+ */
+@Data
+public class WxwSendVideoNumberMsgDTO {
+
+    /**
+     * 每个实例的唯一标识,根据uuid操作具体企业微信
+     */
+    private String uuid;
+
+    /**
+     * 要发送的人或群id
+     */
+    private Long send_userid;
+
+    /**
+     * 是否是群消息
+     */
+    private Boolean isRoom;
+
+    private String coverUrl;
+    private String thumbUrl;
+    private String avatar;
+    private String nickname;
+    private String desc;
+    private String url;
+    private String extras;
+    private String objectId;
+    private String objectNonceId;
+}

+ 45 - 16
fs-service/src/main/java/com/fs/wxwork/service/WxWorkServiceNew.java

@@ -1,15 +1,24 @@
 package com.fs.wxwork.service;
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.TypeReference;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.exception.CustomException;
+import com.fs.ipad.param.WxGetSessionRoomListParam;
+import com.fs.ipad.param.WxRoomUserListParam;
+import com.fs.ipad.param.WxSendAtMsgParam;
+import com.fs.ipad.vo.WxGetSessionRoomListVo;
+import com.fs.ipad.vo.WxRoomUserListVo;
+import com.fs.ipad.vo.WxSendAtMsgVo;
 import com.fs.qw.domain.QwIpadServer;
 import com.fs.qw.service.IQwIpadServerService;
 import com.fs.wxwork.dto.*;
 import com.fs.wxwork.utils.WxWorkHttpUtil;
 import com.fs.wxwork.utils.WxWorkHttpUtilNew;
 import lombok.AllArgsConstructor;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -30,7 +39,7 @@ public class WxWorkServiceNew {
         if (url != null && !url.isEmpty()) {
             return url;
         }
-        System.out.println("serverId:" + serverId);
+        log.info("serverId:" + serverId);
         QwIpadServer qwIpadServer = qwIpadServerService.selectQwIpadServerById(serverId);
         if (qwIpadServer == null||qwIpadServer.getUrl()==null) {
             throw new CustomException("未获取到服务地址与端口");
@@ -51,20 +60,20 @@ public class WxWorkServiceNew {
         });
     }
 
-    
+
     public WxWorkResponseDTO<WxWorkSendAppMsgRespDTO> SendAppMsg(WxWorkSendAppMsgDTO param,Long serverId) {
         String url = getUrl(serverId) + "/SendAppMsg";
         return WxWorkHttpUtilNew.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxWorkSendAppMsgRespDTO>>() {
         });
     }
 
-    
+
     public WxWorkResponseDTO<WxwSendLinkMsgRespDTO> SendLinkMsg(WxwSendLinkMsgDTO param,Long serverId) {
         String url = getUrl(serverId) + "/SendLinkMsg";
         return WxWorkHttpUtilNew.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxwSendLinkMsgRespDTO>>() {
         });
     }
-    
+
     public WxWorkResponseDTO<WxwSendCDNImgMsgRespDTO> SendCDNImgMsg(WxwSendCDNImgMsgDTO param,Long serverId) {
         String url = getUrl(serverId) + "/SendCDNImgMsg";
         return WxWorkHttpUtilNew.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxwSendCDNImgMsgRespDTO>>() {});
@@ -80,12 +89,17 @@ public class WxWorkServiceNew {
         String url = getUrl(serverId) + "/SendCDNVoiceMsg";
         return WxWorkHttpUtilNew.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxwSendCDNVoiceMsgRespDTO>>() {});
     }
-    
+
     public WxWorkResponseDTO<WxwSendCDNVideoMsgRespDTO> SendCDNVideoMsg(WxwSendCDNVideoMsgDTO param,Long serverId) {
         String url = getUrl(serverId) + "/SendCDNVideoMsg";
         return WxWorkHttpUtilNew.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxwSendCDNVideoMsgRespDTO>>() {});
     }
-    
+
+    public WxWorkResponseDTO<WxwSendVideoNumberRespDTO> SendVideoNumber(WxwSendVideoNumberMsgDTO param,Long serverId) {
+        String url = getUrl(serverId) + "/SendVideoNumber";
+        return WxWorkHttpUtilNew.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxwSendVideoNumberRespDTO>>() {});
+    }
+
     public String getCorpId(String uuid, Long corpId,Long serverId) {
         String sCorpId = redisCache.getCacheObject("ipad:corpId:" + corpId);
         if (sCorpId != null&& !sCorpId.isEmpty()) {
@@ -108,7 +122,7 @@ public class WxWorkServiceNew {
             String scorpId = corpInfo.getScorp_id();
 
             if (scorpId!=null&&!scorpId.isEmpty()) {
-               redisCache.setCacheObject("ipad:corpId:" + corpId,scorpId);
+                redisCache.setCacheObject("ipad:corpId:" + corpId,scorpId);
 
                 return scorpId;
             }
@@ -116,19 +130,19 @@ public class WxWorkServiceNew {
 
         return "";
     }
-    
+
     public WxWorkResponseDTO<WxwUploadCdnLinkFileRespDTO> uploadCdnLinkFile(WxwUploadCdnLinkFileDTO param, Long serverId) {
 
         String url = getUrl(serverId) + "/UploadCdnLinkFile";
         return WxWorkHttpUtilNew.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxwUploadCdnLinkFileRespDTO>>() {});
     }
-    
+
     public WxWorkResponseDTO<List<WxWorkVid2UserIdRespDTO>> UserId2Vid(WxWorkUserId2VidDTO param,Long serverId) {
         String url = getUrl(serverId) + "/UserId2Vid";
         return WxWorkHttpUtilNew.postWithType(url, param, new TypeReference<WxWorkResponseDTO<List<WxWorkVid2UserIdRespDTO>>>() {});
     }
 
-    
+
     public WxWorkResponseDTO<WxWorkChatIdToRoomIdResp> ChatIdToRoomId(WxWorkChatIdToRoomIdDTO param, Long serverId) {
         String url = getUrl(serverId) + "/ChatIdToRoomId";
         return WxWorkHttpUtilNew.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxWorkChatIdToRoomIdResp>>() {});
@@ -140,7 +154,7 @@ public class WxWorkServiceNew {
      * @param serverId  服务器ID
      * @return  WxWorkResponseDTO
      */
-    
+
     public WxWorkResponseDTO<WxCdnUploadImgLinkResp> cdnUploadImgLink(WxCdnUploadImgLinkDTO param, Long serverId) {
         String url = getUrl(serverId) + "/CdnUploadImgLink";
         return WxWorkHttpUtilNew.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxCdnUploadImgLinkResp>>() {});
@@ -151,7 +165,7 @@ public class WxWorkServiceNew {
      * @param serverId  服务器ID
      * @return  WxWorkResponseDTO
      */
-    
+
     public WxWorkResponseDTO<WxCdnUploadVideoResp> uploadCdnVideoLink(WxCdnUploadVideoLinkDTO param, Long serverId) {
         String url = getUrl(serverId) + "/UploadCdnVideoLink";
         return WxWorkHttpUtilNew.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxCdnUploadVideoResp>>() {});
@@ -163,7 +177,7 @@ public class WxWorkServiceNew {
      * @param serverId  服务器ID
      * @return  WxWorkResponseDTO
      */
-    
+
     public WxWorkResponseDTO<WxBigFileUploadLinkResp> bigFileUploadLink(WxBigFileUploadLinkDTO param, Long serverId) {
         WGetBigAuthkeyDTO dto = new WGetBigAuthkeyDTO();
         dto.setUuid(param.getUuid());
@@ -174,7 +188,7 @@ public class WxWorkServiceNew {
         return WxWorkHttpUtilNew.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxBigFileUploadLinkResp>>() {});
     }
 
-    
+
     public WxWorkResponseDTO<WxLoginResp> isLogin(WxLoginDTO param, Long serverId) {
         String url = getUrl(serverId) + "/GetRunClientByUuid";
         return WxWorkHttpUtilNew.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxLoginResp>>() {});
@@ -193,6 +207,21 @@ public class WxWorkServiceNew {
 
     public void LoginOut(WxWorkGetQrCodeDTO dto, Long serverId) {
         String url = getUrl(serverId) + "/LoginOut";
-        log.info("退出登录:{}, serverID:{}", dto, serverId);
         WxWorkHttpUtil.postWithType(url, dto, new TypeReference<WxWorkResponseDTO<WxwLoginOutRespDTO>>() {});
-    }}
+    }
+
+    public WxWorkResponseDTO<WxGetSessionRoomListVo> getSessionRoomList(WxGetSessionRoomListParam param, Long serverId) {
+        String url = getUrl(serverId) + "/GetSessionRoomList";
+        return WxWorkHttpUtil.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxGetSessionRoomListVo>>() {});
+    }
+
+    public WxWorkResponseDTO<WxRoomUserListVo> getRoomUserList(WxRoomUserListParam param, Long serverId) {
+        String url = getUrl(serverId) + "/GetRoomUserList";
+        return WxWorkHttpUtil.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxRoomUserListVo>>() {});
+    }
+
+    public WxWorkResponseDTO<WxSendAtMsgVo> sendTextAtMsg(WxSendAtMsgParam param, Long serverId) {
+        String url = getUrl(serverId) + "/SendTextAtMsg";
+        return WxWorkHttpUtil.postWithType(url, param, new TypeReference<WxWorkResponseDTO<WxSendAtMsgVo>>() {});
+    }
+}

+ 90 - 0
fs-service/src/main/resources/application-config-druid-drk-test.yml

@@ -0,0 +1,90 @@
+baidu:
+  token: 12313231232
+  back-domain: https://www.xxxx.com
+#配置
+logging:
+  level:
+    org.springframework.web: INFO
+    com.github.binarywang.demo.wx.cp: DEBUG
+    me.chanjar.weixin: DEBUG
+wx:
+  miniapp:
+    configs:
+      - appid: wx76cb55db092a41ae   #德瑞康
+        secret: c737a27415946994e977d665d87643b3
+        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
+        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
+        msgDataFormat: JSON
+  cp:
+    corpId: wwde3be9a4a7004380 #德瑞康企业id
+    appConfigs:
+      - agentId: 1000006 #德瑞康应用id
+        secret: prclvyFLiZD9XEns9ltt6vFMszuFc_wgm3MTnfY6ZEk #德瑞康
+        token: PPKOdAlCoMO
+        aesKey: PKvaxtpSv8NGpfTDm7VUHIK8Wok2ESyYX24qpXJAdMP
+  pay:
+    appId:  #微信公众号或者小程序等的appid
+    mchId:  #微信支付商户号
+    mchKey:  #微信支付商户密钥
+    subAppId:  #服务商模式下的子商户公众账号ID
+    subMchId:  #服务商模式下的子商户号
+    keyPath: c:\\cert\\apiclient_cert.p12 # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)
+    notifyUrl: https://userapp.his.runtzh.com/app/wxpay/wxPayNotify
+  mp:
+    useRedis: false
+    redisConfig:
+      host: 127.0.0.1
+      port: 6379
+      timeout: 2000
+    configs:
+      - appId: wx090c5f399d65456e # 第一个公众号的appid  //公众号名称:德瑞康
+        secret: dc70e963077d80cf61280aea6b7c52b7 # 公众号的appsecret--德瑞康
+        token: PPKOdAlCoMO # 接口配置里的Token值
+        aesKey: Eswa6VjwtVMCcw03qZy6fWllgrv5aytIA1SZPEU0kU2 # 接口配置里的EncodingAESKey值
+aifabu:  #爱链接
+  appKey: 7b471be905ab17e00f3b858c6710dd117601d008
+watch:
+  watchUrl: watch.ylrzcloud.com/prod-api
+  #  account: tcloud
+  #  password: mdf-m2h_6yw2$hq
+  account1: ccif #866655060138751
+  password1: cp-t5or_6xw7$mt
+  account2: tcloud #rt500台
+  password2: mdf-m2h_6yw2$hq
+  account3: whr
+  password3: v9xsKuqn_$d2y
+
+fs :
+  commonApi: http://127.0.0.1:7771
+  h5CommonApi: http://127.0.0.1:7771
+nuonuo:
+  key: 10924508
+  secret: A2EB20764D304D16
+
+# 存储捅配置
+tencent_cloud_config:
+  secret_id: AKIDiMq9lDf2EOM9lIfqqfKo7FNgM5meD0sT
+  secret_key: u5SuS80342xzx8FRBukza9lVNHKNMSaB
+  bucket: drk-1323137866
+  app_id: 1323137866
+  region: ap-chongqing
+  proxy: drk
+tmp_secret_config:
+  secret_id: AKIDCj7NSNAovtqeJpBau8GZ4CGB71thXIxX
+  secret_key: lTB5zwqqz7CNhzDOWivFWedgfTBgxgBT
+  bucket: fs-1319721001
+  app_id: 1319721001
+  region: ap-chongqing
+  proxy: fs
+cloud_host:
+  company_name: 德瑞康
+headerImg:
+  imgUrl: https://drk-1363981074.cos.ap-chongqing.myqcloud.com/fs/logo/30d7a0d1ec31e5ac16c6e96d5ca76ad.png
+ipad:
+  ipadUrl: http://ipad.cdwjyyh.com
+  aiApi: 1212121212
+wx_miniapp_temp:
+  pay_order_temp_id:
+  inquiry_temp_id:
+
+

+ 1 - 1
fs-service/src/main/resources/application-config-druid-kyt.yml

@@ -79,7 +79,7 @@ cloud_host:
 headerImg:
   imgUrl: https://kuanyitang-1317640934.cos.ap-shanghai.myqcloud.com/kuanyitang/20250813/6b3b62e01672407c98f0561b73e35f6a.jpg
 ipad:
-  ipadUrl:
+  ipadUrl: http://kytIpad.ylrzcloud.com
   aiApi:
 wx_miniapp_temp:
   pay_order_temp_id:

+ 1 - 1
fs-service/src/main/resources/application-config-druid-sxjz.yml

@@ -80,7 +80,7 @@ headerImg:
   imgUrl: https://jz-cos-1356808054.cos.ap-chengdu.myqcloud.com/fs/20250515/0877754b59814ea8a428fa3697b20e68.png
 ipad:
   ipadUrl: http://ipad.xintaihl.cn
-  aiApi:
+  aiApi: http://1.95.196.10:3000/api
 wx_miniapp_temp:
   pay_order_temp_id:
   inquiry_temp_id:

+ 2 - 4
fs-service/src/main/resources/application-config-druid-yjb.yml

@@ -10,8 +10,8 @@ logging:
 wx:
   miniapp:
     configs:
-      - appid: wx9e61312fe7ac85c4   #德瑞康
-        secret: 63f9c2240dd09d8beff004112181e731
+      - appid: wx76cb55db092a41ae   #医健保
+        secret: c737a27415946994e977d665d87643b3
         token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
         aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
         msgDataFormat: JSON
@@ -82,7 +82,6 @@ headerImg:
   imgUrl: https://drk-1363981074.cos.ap-chongqing.myqcloud.com/fs/logo/30d7a0d1ec31e5ac16c6e96d5ca76ad.png
 ipad:
   ipadUrl: http://ipad.cdwjyyh.com
-  aiApi: http://152.136.202.157:3000/api
 wx_miniapp_temp:
   pay_order_temp_id:
   inquiry_temp_id:
@@ -90,4 +89,3 @@ openIM:
   secret: openIM123
   userID: imAdmin
 
-

+ 3 - 20
fs-service/src/main/resources/application-config-zkzh.yml

@@ -71,26 +71,6 @@ wx:
         token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
         aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
         msgDataFormat: JSON
-      - appid: wxedde588767b358b1   #中康未来智慧药房
-        secret: 928d2961c81610d8f64b019597212fcd
-        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
-        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
-        msgDataFormat: JSON
-      - appid: wxdbaca81abc336277   #虹恺百货店
-        secret: 31b39464bad4549b6c59f79e4e2c3f94
-        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
-        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
-        msgDataFormat: JSON
-      - appid: wxb025ac4091dbd4b7   #中康智慧店T
-        secret: fa122221b6bf9fd718db6e3cc0f9bc50
-        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
-        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
-        msgDataFormat: JSON
-      - appid: wxdf9b1a4d3c5b6572   #中康智慧坊
-        secret: 489055ace816380c0fceb53447381704
-        token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
-        aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
-        msgDataFormat: JSON
 
 
 
@@ -114,6 +94,9 @@ wx:
         secret: 473a992e28d5c524b4ff3783559026cb
         token: PPKOdAlCoMO # 接口配置里的Token值
         aesKey: Eswa6VjwtVMCcw03qZy6fWllgrv5aytIA1SZPEU0kU2 # 接口配置里的EncodingAESKey值
+  open:
+    appId: wx40f3de7bd405fb5c
+    secret: 4038e9209ddaf5f23dcde35e41be3120
 jpush:
   appKey: cc9a0120a3e4270c9cba340d
   masterSecret: cfc2575d3cd7470d584c990c

+ 143 - 0
fs-service/src/main/resources/application-druid-drk-test.yml

@@ -0,0 +1,143 @@
+# 数据源配置
+spring:
+    profiles:
+        include: config-druid-drk,common
+    # redis 配置
+    redis:
+        # 地址
+        host: localhost
+        # 端口,默认为6379
+        port: 6379
+        # 数据库索引
+        database: 0
+        # 密码
+        password:
+        # 连接超时时间
+        timeout: 20s
+        lettuce:
+            pool:
+                # 连接池中的最小空闲连接
+                min-idle: 0
+                # 连接池中的最大空闲连接
+                max-idle: 8
+                # 连接池的最大数据库连接数
+                max-active: 8
+                # #连接池最大阻塞等待时间(使用负值表示没有限制)
+                max-wait: -1ms
+    datasource:
+        mysql:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://nj-cdb-r9csy22x.sql.tencentcdb.com:28653/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Ylrz_1q2w3e4r5t6y
+                # 从库数据源
+                slave:
+                    # 从数据源开关/默认关闭
+                    enabled: false
+                    url:
+                    username:
+                    password:
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+        sop:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://nj-cdb-r9csy22x.sql.tencentcdb.com:28653/fs_his_sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Ylrz_1q2w3e4r5t6y
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+rocketmq:
+    name-server: rmq-1243b25nj.rocketmq.gz.public.tencenttdmq.com:8080 # RocketMQ NameServer 地址
+    producer:
+        group: my-producer-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+    consumer:
+        group: test-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+openIM:
+    secret: openIM123
+    userID: imAdmin

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

@@ -5,9 +5,12 @@ spring:
   # redis 配置
   redis:
     # 地址
-    host: 172.17.0.4
+#    host: 172.17.0.4
+#    # 端口,默认为6379
+#    port: 6379
+    host: sh-crs-bln5ggez.sql.tencentcdb.com
     # 端口,默认为6379
-    port: 6379
+    port: 26161
     # 密码
     password: Ylrztek250218!3@.
     # 连接超时时间
@@ -30,7 +33,8 @@ spring:
       druid:
         # 主库数据源
         master:
-          url: jdbc:mysql://172.17.0.3:3306/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+#          url: jdbc:mysql://172.17.0.3:3306/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+          url: jdbc:mysql://sh-cdb-qyfybkwy.sql.tencentcdb.com:24529/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
           username: root
           password: Ylrztek250218!3@.
         # 从库数据源
@@ -85,7 +89,8 @@ spring:
       druid:
         # 主库数据源
         master:
-          url: jdbc:mysql://172.17.0.3:3306/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+#          url: jdbc:mysql://172.17.0.3:3306/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+          url: jdbc:mysql://sh-cdb-qyfybkwy.sql.tencentcdb.com:24529/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
           username: root
           password: Ylrztek250218!3@.
         # 初始连接数

+ 4 - 0
fs-service/src/main/resources/mapper/company/CompanyMapper.xml

@@ -38,6 +38,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="repeat"    column="repeat"    />
         <result property="sendIfType"    column="send_if_type"    />
         <result property="ifNum"    column="if_num"    />
+        <result property="groupName"    column="group_name"    />
     </resultMap>
 
     <sql id="selectCompanyVo">
@@ -111,6 +112,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="repeat != null">`repeat`,</if>
             <if test="sendIfType != null">send_if_type,</if>
             <if test="ifNum != null">if_num,</if>
+            <if test="groupName != null">group_name,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="companyName != null">#{companyName},</if>
@@ -143,6 +145,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="repeat != null">#{repeat},</if>
             <if test="sendIfType != null">#{sendIfType},</if>
             <if test="ifNum != null">#{ifNum},</if>
+            <if test="groupName != null">#{groupName},</if>
          </trim>
     </insert>
 
@@ -181,6 +184,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="repeat != null">`repeat` = #{repeat},</if>
             <if test="sendIfType != null">send_if_type = #{sendIfType},</if>
             <if test="ifNum != null">if_num = #{ifNum},</if>
+            <if test="groupName != null">group_name = #{groupName},</if>
         </trim>
         where company_id = #{companyId}
     </update>

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

@@ -28,6 +28,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="sort != null "> and sort = #{sort}</if>
             <if test="type != null "> and type = #{type}</if>
             <if test="questionType != null "> and question_type = #{questionType}</if>
+            <if test="userId != null "> and user_id = #{userId}</if>
             <if test="questionSubType != null "> and question_sub_type = #{questionSubType}</if>
             <if test="status != null "> and status = #{status}</if>
             <if test="question != null  and question != ''"> and question = #{question}</if>
@@ -54,6 +55,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="createBy != null">create_by,</if>
             <if test="questionType != null">question_type,</if>
             <if test="questionSubType != null">question_sub_type,</if>
+            <if test="userId != null">user_id,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="title != null">#{title},</if>
@@ -66,6 +68,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="createBy != null">#{createBy},</if>
             <if test="questionType != null">#{questionType},</if>
             <if test="questionSubType != null">#{questionSubType},</if>
+            <if test="userId != null">#{userId},</if>
          </trim>
     </insert>
 
@@ -80,7 +83,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         answer,
         create_by,
         question_type,
-        question_sub_type
+        question_sub_type,
+        user_id
         )
         VALUES
         <foreach collection="list" item="item" separator=",">
@@ -94,7 +98,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{item.answer, jdbcType=CLOB},
             #{item.createBy, jdbcType=VARCHAR},
             #{item.questionType, jdbcType=VARCHAR},
-            #{item.questionSubType, jdbcType=VARCHAR}
+            #{item.questionSubType, jdbcType=VARCHAR},
+            #{item.userId, jdbcType=BIGINT}
             )
         </foreach>
     </insert>

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

@@ -429,7 +429,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             send_type = 1
           AND video_id = #{videoId}
           AND user_id = #{fsUserId}
-          AND company_user_id = #{companyUserId}
+          AND company_user_id = #{companyUserId}  order by log_id desc limit 1
     </select>
     <select id="selectFsCourseWatchLogStatisticsListVONew"
             resultType="com.fs.course.vo.FsCourseWatchLogStatisticsListVO">

+ 3 - 0
fs-service/src/main/resources/mapper/course/FsUserCourseMapper.xml

@@ -85,6 +85,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="talentId != null "> and talent_id = #{talentId}</if>
             <if test="isNext != null "> and is_next = #{isNext}</if>
             <if test="isPrivate != null "> and is_private = #{isPrivate}</if>
+            <if test="userId != null "> and user_id = #{userId}</if>
         </where>
     </select>
 
@@ -193,6 +194,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isPrivate != null">is_private,</if>
             <if test="secondImg != null">second_img,</if>
             <if test="companyIds != null">company_ids,</if>
+            <if test="userId != null">user_id,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="cateId != null">#{cateId},</if>
@@ -232,6 +234,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isPrivate != null">#{isPrivate},</if>
             <if test="secondImg != null">#{secondImg},</if>
             <if test="companyIds != null">#{companyIds},</if>
+            <if test="userId != null">#{userId},</if>
          </trim>
     </insert>
 

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

@@ -24,7 +24,9 @@
             <if test="params.companyId != null and params.companyId != ''">
                 and ctp.company_id like concat('%',#{params.companyId},'%')
             </if>
-
+            <if test="params.userIds != null and params.userIds != ''">
+                and ctc.user_id =#{params.userIds}
+            </if>
             <if test="params.userId != null and params.userId != ''">
                 and cu.user_id = #{params.userId}
             </if>

+ 3 - 0
fs-service/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml

@@ -58,6 +58,7 @@
             <if test="questionBankId != null "> and question_bank_id = #{questionBankId}</if>
             <if test="userId != null "> and user_id = #{userId}</if>
             <if test="projectId != null "> and project_id = #{projectId}</if>
+            <if test="userId != null "> and user_id = #{userId}</if>
         </where>
     </select>
 
@@ -103,6 +104,7 @@
             <if test="productId != null">product_id,</if>
             <if test="listingStartTime != null">listing_start_time,</if>
             <if test="listingEndTime != null">listing_end_time,</if>
+            <if test="userId != null">user_id,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="fileId != null">#{fileId},</if>
@@ -139,6 +141,7 @@
             <if test="listingStartTime != null">#{listingStartTime},</if>
             <if test="listingEndTime != null">#{listingEndTime},</if>
             <if test="projectId != null">#{projectId},</if>
+            <if test="userId != null">#{userId},</if>
         </trim>
     </insert>
     <insert id="insertBatchFsUserCourseVideo" parameterType="FsUserCourseVideo" useGeneratedKeys="true" keyProperty="videoId">

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

@@ -18,6 +18,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <if test="params.typeId != null">
             and rr.type_id = #{params.typeId}
         </if>
+        <if test="params.userId != null">
+            and rr.user_id = #{params.userId}
+        </if>
         <if test="params.typeSubId != null">
             and rr.type_sub_id = #{params.typeSubId}
         </if>

+ 1 - 0
fs-service/src/main/resources/mapper/his/FsUserMapper.xml

@@ -1760,6 +1760,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             fs_course_red_packet_log flog
                 LEFT JOIN fs_user ON fs_user.user_id = flog.user_id
                 LEFT JOIN company_user ON company_user.user_id = fs_user.company_user_id
+        where flog.`status` = 1
         GROUP BY
             flog.period_id,
             flog.video_id,

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

@@ -33,10 +33,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="serverId"    column="server_id"    />
         <result property="serverStatus"    column="server_status"    />
         <result property="isAuto"    column="is_auto"    />
+        <result property="videoGetStatus"    column="video_get_status"    />
     </resultMap>
 
     <sql id="selectQwUserVo">
-        select id,is_auto, qw_user_id,server_id,server_status,ipad_status,config_id,vid,uid,contact_way,app_key, qw_user_name, department, openid, company_id, company_user_id, corp_id, status, is_del, welcome_text, welcome_image, is_send_msg,app_key,qw_hook_id,fastGpt_role_id,login_status,tool_status,login_code_url,version from qw_user
+        select id,is_auto, video_get_status, qw_user_id,server_id,server_status,ipad_status,config_id,vid,uid,contact_way,app_key, qw_user_name, department, openid, company_id, company_user_id, corp_id, status, is_del, welcome_text, welcome_image, is_send_msg,app_key,qw_hook_id,fastGpt_role_id,login_status,tool_status,login_code_url,version from qw_user
         </sql>
 
     <select id="selectQwUserList" parameterType="QwUser" resultMap="QwUserResult">
@@ -112,6 +113,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="serverId != null">server_id,</if>
             <if test="serverStatus != null">server_status,</if>
             <if test="isAuto != null">is_auto,</if>
+            <if test="videoGetStatus != null">video_get_status,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="qwUserId != null">#{qwUserId},</if>
@@ -139,6 +141,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="ipadStatus != null">#{ipadStatus},</if>
             <if test="serverId != null">#{serverId},</if>
             <if test="isAuto != null">#{isAuto},</if>
+            <if test="videoGetStatus != null">#{videoGetStatus},</if>
          </trim>
     </insert>
 
@@ -172,6 +175,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="serverId != null">server_id = #{serverId},</if>
             <if test="serverStatus != null">server_status = #{serverStatus},</if>
             <if test="isAuto != null">is_auto = #{isAuto},</if>
+            <if test="videoGetStatus != null">video_get_status = #{videoGetStatus},</if>
         </trim>
         where id = #{id}
     </update>
@@ -251,4 +255,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <update id="updateSendType">
         update qw_user set send_msg_type = #{type} where id in <foreach collection="ids" open="(" close=")" separator="," item="item">#{item}</foreach>
     </update>
+
+    <select id="selectOfflineUser" resultType="com.fs.qw.domain.QwUser">
+        select * from qw_user where send_msg_type = 2 and server_id is not null and server_status = 1 and ipad_status = 1 limit 1
+    </select>
 </mapper>

+ 32 - 5
fs-service/src/main/resources/mapper/qw/QwUserVideoMapper.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!DOCTYPE mapper
-PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.fs.qw.mapper.QwUserVideoMapper">
 
     <resultMap type="QwUserVideo" id="QwUserVideoResult">
@@ -18,10 +18,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="extras"    column="extras"    />
         <result property="createTime"    column="create_time"    />
         <result property="updateTime"    column="update_time"    />
+        <result property="objectNonceId"    column="object_nonce_id"    />
+        <result property="qwUserId"    column="qw_user_id"    />
+        <result property="companyUserId"    column="company_user_id"    />
+        <result property="companyId"    column="company_id"    />
     </resultMap>
 
     <sql id="selectQwUserVideoVo">
-        select id, app_key, sender_name, object_id, cover_url, thumb_url, avatar, nick_name, `desc`, url, extras,update_time,create_time from qw_user_video
+        select id, app_key,qw_user_id, company_user_id, company_id, object_nonce_id, sender_name, object_id, cover_url, thumb_url, avatar, nick_name, `desc`, url, extras,update_time,create_time from qw_user_video
     </sql>
 
     <select id="selectQwUserVideoList" parameterType="QwUserVideo" resultMap="QwUserVideoResult">
@@ -62,7 +66,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="extras != null">extras,</if>
             <if test="updateTime != null">update_time,</if>
             <if test="createTime != null">create_time,</if>
-         </trim>
+            <if test="objectNonceId != null">object_nonce_id,</if>
+            <if test="qwUserId != null">qw_user_id,</if>
+            <if test="companyUserId != null">company_user_id,</if>
+            <if test="companyId != null">company_id,</if>
+        </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="appKey != null">#{appKey},</if>
             <if test="senderName != null">#{senderName},</if>
@@ -76,7 +84,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="extras != null">#{extras},</if>
             <if test="updateTime != null">#{updateTime},</if>
             <if test="createTime != null">#{createTime},</if>
-         </trim>
+            <if test="objectNonceId != null">#{objectNonceId},</if>
+            <if test="qwUserId != null">#{qwUserId},</if>
+            <if test="companyUserId != null">#{companyUserId},</if>
+            <if test="companyId != null">#{companyId},</if>
+        </trim>
     </insert>
 
     <update id="updateQwUserVideo" parameterType="QwUserVideo">
@@ -94,6 +106,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="extras != null">extras = #{extras},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="objectNonceId != null">object_nonce_id = #{objectNonceId},</if>
+            <if test="qwUserId != null">qw_user_id = #{qwUserId},</if>
+            <if test="companyUserId != null">company_user_id = #{companyUserId},</if>
+            <if test="companyId != null">company_id = #{companyId},</if>
         </trim>
         where id = #{id}
     </update>
@@ -108,4 +124,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{id}
         </foreach>
     </delete>
+
+    <select id="selectQwUserVideoByIds" resultType="com.fs.qw.domain.QwUserVideo">
+        select * from qw_user_video where id in
+        <foreach item="id" collection="ids" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </select>
+
+    <select id="selectByObjectId" resultType="com.fs.qw.domain.QwUserVideo">
+        select * from qw_user_video where object_id = #{objectId} and qw_user_id = #{id}
+    </select>
 </mapper>