Quellcode durchsuchen

同步scrm代码

Long vor 4 Wochen
Ursprung
Commit
195f296a8f
100 geänderte Dateien mit 2207 neuen und 493 gelöschten Zeilen
  1. 22 0
      fs-admin/src/main/java/com/fs/api/controller/IndexStatisticsController.java
  2. 38 30
      fs-admin/src/main/java/com/fs/company/controller/CompanyController.java
  3. 53 12
      fs-admin/src/main/java/com/fs/company/controller/CompanyUserController.java
  4. 1 0
      fs-admin/src/main/java/com/fs/core/config/SecurityConfig.java
  5. 9 0
      fs-admin/src/main/java/com/fs/core/exception/FSExceptionHandler.java
  6. 1 1
      fs-admin/src/main/java/com/fs/course/controller/FsCourseTrafficLogController.java
  7. 9 1
      fs-admin/src/main/java/com/fs/course/controller/FsCourseWatchLogController.java
  8. 72 27
      fs-admin/src/main/java/com/fs/course/controller/FsUserCoursePeriodController.java
  9. 14 1
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseTrainingCampController.java
  10. 27 1
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseVideoController.java
  11. 3 2
      fs-admin/src/main/java/com/fs/course/controller/FsUserVideoController.java
  12. 2 0
      fs-admin/src/main/java/com/fs/course/controller/FsVideoResourceController.java
  13. 2 1
      fs-admin/src/main/java/com/fs/course/controller/qw/QwFsCourseWatchLogController.java
  14. 62 0
      fs-admin/src/main/java/com/fs/stats/FsStatsMemberController.java
  15. 15 1
      fs-admin/src/main/java/com/fs/store/controller/FsExpressController.java
  16. 14 1
      fs-admin/src/main/java/com/fs/store/controller/FsStoreProductController.java
  17. 2 2
      fs-admin/src/main/java/com/fs/store/controller/FsStoreProductPackageController.java
  18. 3 4
      fs-admin/src/main/java/com/fs/store/controller/FsTestReportController.java
  19. 32 11
      fs-admin/src/main/java/com/fs/store/controller/FsUserController.java
  20. 29 0
      fs-admin/src/main/java/com/fs/task/period/PeriodTask.java
  21. 18 0
      fs-admin/src/main/java/com/fs/task/stats/FsStatsMemberDailyTask.java
  22. 35 5
      fs-admin/src/main/java/com/fs/user/FsUserAdminController.java
  23. 1 1
      fs-common/pom.xml
  24. 247 8
      fs-common/src/main/java/com/fs/common/config/FSSysConfig.java
  25. 51 3
      fs-common/src/main/java/com/fs/common/utils/DateUtils.java
  26. 1 1
      fs-common/src/main/java/com/fs/common/utils/TimeUtils.java
  27. 14 5
      fs-common/src/main/java/com/fs/common/utils/date/DateUtil.java
  28. 240 0
      fs-company/src/main/java/com/fs/company/controller/IndexStatisticsController.java
  29. 2 1
      fs-company/src/main/java/com/fs/course/controller/FsCourseWatchLogController.java
  30. 22 11
      fs-company/src/main/java/com/fs/qw/QwExternalContactController.java
  31. 13 8
      fs-company/src/main/java/com/fs/qw/vo/QwExternalContactVO.java
  32. 11 9
      fs-company/src/main/java/com/fs/user/FsUserAdminController.java
  33. 20 0
      fs-qw-task/src/main/java/com/fs/app/task/CourseWatchLogScheduler.java
  34. 42 0
      fs-qw-task/src/main/java/com/fs/app/task/UserCourseWatchCountTask.java
  35. 1 1
      fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java
  36. 16 16
      fs-service-system/pom.xml
  37. 9 0
      fs-service-system/src/main/java/com/fs/company/cache/ICompanyTagCacheService.java
  38. 9 0
      fs-service-system/src/main/java/com/fs/company/cache/ICompanyUserCacheService.java
  39. 36 0
      fs-service-system/src/main/java/com/fs/company/cache/impl/CompanyTagCacheServiceImpl.java
  40. 35 2
      fs-service-system/src/main/java/com/fs/company/cache/impl/CompanyUserCacheServiceImpl.java
  41. 1 1
      fs-service-system/src/main/java/com/fs/company/cache/impl/ICompanyCacheServiceImpl.java
  42. 1 0
      fs-service-system/src/main/java/com/fs/company/domain/CompanyMoneyLogs.java
  43. 4 149
      fs-service-system/src/main/java/com/fs/company/domain/CompanyRecharge.java
  44. 0 1
      fs-service-system/src/main/java/com/fs/company/domain/CompanyUser.java
  45. 13 0
      fs-service-system/src/main/java/com/fs/company/dto/CompanyIdAndUserDTO.java
  46. 11 2
      fs-service-system/src/main/java/com/fs/company/mapper/CompanyMapper.java
  47. 14 8
      fs-service-system/src/main/java/com/fs/company/mapper/CompanyTagMapper.java
  48. 14 2
      fs-service-system/src/main/java/com/fs/company/mapper/CompanyUserMapper.java
  49. 1 0
      fs-service-system/src/main/java/com/fs/company/param/CompanyRechargeParam.java
  50. 12 5
      fs-service-system/src/main/java/com/fs/company/service/ICompanyService.java
  51. 14 8
      fs-service-system/src/main/java/com/fs/company/service/ICompanyTagService.java
  52. 18 1
      fs-service-system/src/main/java/com/fs/company/service/ICompanyUserService.java
  53. 10 9
      fs-service-system/src/main/java/com/fs/company/service/impl/CompanyRoleServiceImpl.java
  54. 17 5
      fs-service-system/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java
  55. 19 8
      fs-service-system/src/main/java/com/fs/company/service/impl/CompanyTagServiceImpl.java
  56. 42 2
      fs-service-system/src/main/java/com/fs/company/service/impl/CompanyUserServiceImpl.java
  57. 2 1
      fs-service-system/src/main/java/com/fs/company/vo/CompanyRechargeVO.java
  58. 6 2
      fs-service-system/src/main/java/com/fs/course/domain/FsCourseLink.java
  59. 1 0
      fs-service-system/src/main/java/com/fs/course/domain/FsCourseQuestionBank.java
  60. 4 0
      fs-service-system/src/main/java/com/fs/course/domain/FsCourseRealLink.java
  61. 3 0
      fs-service-system/src/main/java/com/fs/course/domain/FsCourseWatchLog.java
  62. 23 2
      fs-service-system/src/main/java/com/fs/course/domain/FsUserCoursePeriod.java
  63. 12 1
      fs-service-system/src/main/java/com/fs/course/domain/FsUserCoursePeriodDays.java
  64. 5 0
      fs-service-system/src/main/java/com/fs/course/domain/FsVideoResource.java
  65. 9 0
      fs-service-system/src/main/java/com/fs/course/mapper/FsCourseTrafficLogMapper.java
  66. 6 4
      fs-service-system/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java
  67. 3 3
      fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseMapper.java
  68. 29 4
      fs-service-system/src/main/java/com/fs/course/mapper/FsUserCoursePeriodDaysMapper.java
  69. 28 5
      fs-service-system/src/main/java/com/fs/course/mapper/FsUserCoursePeriodMapper.java
  70. 8 0
      fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseTrainingCampMapper.java
  71. 13 3
      fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java
  72. 4 2
      fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseVideoRedPackageMapper.java
  73. 1 1
      fs-service-system/src/main/java/com/fs/course/mapper/HyWatchLogMapper.java
  74. 11 0
      fs-service-system/src/main/java/com/fs/course/param/BatchRedUpdate.java
  75. 1 0
      fs-service-system/src/main/java/com/fs/course/param/BatchVideoSvae.java
  76. 3 0
      fs-service-system/src/main/java/com/fs/course/param/FsCourseLinkCreateParam.java
  77. 1 0
      fs-service-system/src/main/java/com/fs/course/param/FsCourseSendRewardUParam.java
  78. 12 0
      fs-service-system/src/main/java/com/fs/course/param/FsCourseWatchLogStatisticsListParam.java
  79. 3 0
      fs-service-system/src/main/java/com/fs/course/param/newfs/FsCourseSortLinkParam.java
  80. 13 0
      fs-service-system/src/main/java/com/fs/course/param/newfs/FsUserCourseVideoLinkParam.java
  81. 3 0
      fs-service-system/src/main/java/com/fs/course/param/newfs/FsUserCourseVideoUParam.java
  82. 6 1
      fs-service-system/src/main/java/com/fs/course/service/IFsCourseWatchLogService.java
  83. 30 4
      fs-service-system/src/main/java/com/fs/course/service/IFsUserCoursePeriodDaysService.java
  84. 13 1
      fs-service-system/src/main/java/com/fs/course/service/IFsUserCoursePeriodService.java
  85. 5 5
      fs-service-system/src/main/java/com/fs/course/service/IFsUserCourseService.java
  86. 8 1
      fs-service-system/src/main/java/com/fs/course/service/IFsUserCourseTrainingCampService.java
  87. 1 0
      fs-service-system/src/main/java/com/fs/course/service/IFsUserCourseVideoRedPackageService.java
  88. 12 2
      fs-service-system/src/main/java/com/fs/course/service/IFsUserCourseVideoService.java
  89. 8 7
      fs-service-system/src/main/java/com/fs/course/service/impl/FsCourseQuestionBankServiceImpl.java
  90. 134 3
      fs-service-system/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java
  91. 120 19
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodDaysServiceImpl.java
  92. 71 6
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodServiceImpl.java
  93. 32 7
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseTrainingCampServiceImpl.java
  94. 5 0
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseVideoRedPackageServiceImpl.java
  95. 112 33
      fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  96. 4 0
      fs-service-system/src/main/java/com/fs/course/vo/FsPeriodCountVO.java
  97. 3 0
      fs-service-system/src/main/java/com/fs/course/vo/FsUserCoursePeriodVO.java
  98. 6 5
      fs-service-system/src/main/java/com/fs/course/vo/FsUserCourseVideoQVO.java
  99. 2 2
      fs-service-system/src/main/java/com/fs/course/vo/FsVideoResourceVO.java
  100. 7 2
      fs-service-system/src/main/java/com/fs/course/vo/PeriodRedPacketVO.java

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

@@ -172,4 +172,26 @@ public class IndexStatisticsController {
 
         return R.ok().put("data", authorizationInfoDTO);
     }
+
+
+    /**
+     * 当月订单数统计
+     * @return
+     */
+    @GetMapping("/thisMonthOrderCount")
+    public R thisMonthOrderCount(){
+        R result = redisCache.getCacheObject(StatisticsRedisConstant.THIS_MONTH_ORDER_COUNT);
+        return result;
+    }
+
+    /**
+     * 当月收益统计
+     * @return
+     */
+
+    @GetMapping("/thisMonthRecvCount")
+    public R thisMonthRecvCount(){
+        R result = redisCache.getCacheObject(StatisticsRedisConstant.THIS_MONTH_RECV_COUNT);
+        return result;
+    }
 }

+ 38 - 30
fs-admin/src/main/java/com/fs/company/controller/CompanyController.java

@@ -1,18 +1,16 @@
 package com.fs.company.controller;
 
-import java.math.BigDecimal;
-import java.sql.Timestamp;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.List;
-
 import cn.hutool.core.util.IdUtil;
+import com.fs.common.annotation.Log;
 import com.fs.common.annotation.RepeatSubmit;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
-import com.fs.common.utils.OrderUtils;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.common.utils.sign.Md5Utils;
 import com.fs.company.domain.*;
 import com.fs.company.param.CompanyDeductParam;
@@ -27,26 +25,17 @@ import com.fs.core.security.LoginUser;
 import com.fs.core.security.SecurityUtils;
 import com.fs.core.web.service.TokenService;
 import com.fs.his.vo.OptionsVO;
-import lombok.Synchronized;
-import org.springframework.security.access.prepost.PreAuthorize;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.common.core.page.TableDataInfo;
+import org.springframework.web.bind.annotation.*;
 
-import javax.swing.*;
+import java.text.ParseException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * 企业Controller
@@ -147,9 +136,11 @@ public class CompanyController extends BaseController
                 callerService.updateCompanyVoiceCaller(caller);
             }
         }else {
-            CompanyUser companyUser1 = userService.selectCompanyUserAdminByCompanyId(company.getCompanyId());
-            companyUser1.setStatus("0");
-            userService.updateCompanyUser(companyUser1);
+//            CompanyUser companyUser1 = userService.selectCompanyUserAdminByCompanyId(company.getCompanyId());
+//            if(companyUser1 != null){
+//                companyUser1.setStatus("0");
+//                userService.updateCompanyUser(companyUser1);
+//            }
         }
         return toAjax(companyService.updateCompany(company));
     }
@@ -161,7 +152,7 @@ public class CompanyController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('company:company:remove')")
     @Log(title = "企业", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{companyIds}")
+    @DeleteMapping("/{companyIds}")
     public AjaxResult remove(@PathVariable Long[] companyIds)
     {
         return toAjax(companyService.deleteCompanyByIds(companyIds));
@@ -176,7 +167,7 @@ public class CompanyController extends BaseController
         return R.ok().put("data",list);
     }
 
-//  @PreAuthorize("@ss.hasPermi('company:company:crmDayCountlist')")
+    //  @PreAuthorize("@ss.hasPermi('company:company:crmDayCountlist')")
     @GetMapping("/crmDayCountlist")
     public TableDataInfo companyCrmDayCountList(CompanyParam param)
     {
@@ -222,6 +213,7 @@ public class CompanyController extends BaseController
         recharge.setStatus(0);
         recharge.setRemark(param.getRemark());
         recharge.setPayType(3);
+        recharge.setImgs(param.getImgs());
         rechargeService.insertCompanyRecharge(recharge);
         return R.ok("提交成功,等待审核");
 
@@ -254,5 +246,21 @@ public class CompanyController extends BaseController
         return getDataTable(list);
     }
 
+    /**
+     * 根据公司名称模糊查询
+     * @param name  名称
+     * @return  list
+     */
+    @GetMapping("/getCompanyListLikeName")
+    public R getCompanyUserListLikeName(@RequestParam(required = false) String name,
+                                        @RequestParam(required = false, defaultValue = "1") Integer pageNum,
+                                        @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
+        Map<String,Object> params = new HashMap<>();
+        params.put("companyName", name);
+
+        PageHelper.startPage(pageNum, pageSize);
+        List<OptionsVO> companyUserList = companyService.selectCompanyListByMap(params);
+        return R.ok().put("data", new PageInfo<>(companyUserList));
+    }
 
 }

+ 53 - 12
fs-admin/src/main/java/com/fs/company/controller/CompanyUserController.java

@@ -1,22 +1,25 @@
 package com.fs.company.controller;
 
-import java.util.List;
-
-import com.fs.common.constant.UserConstants;
-import com.fs.common.core.domain.R;
-import com.fs.common.utils.ServletUtils;
-import com.fs.core.security.LoginUser;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
 import com.fs.common.annotation.Log;
+import com.fs.common.constant.UserConstants;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.ICompanyUserService;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.common.core.page.TableDataInfo;
+import com.fs.his.vo.OptionsVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * 企业员工信息Controller
@@ -110,7 +113,7 @@ public class CompanyUserController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('company:companyUser:remove')")
     @Log(title = "企业员工信息", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{userIds}")
+    @DeleteMapping("/{userIds}")
     public AjaxResult remove(@PathVariable Long[] userIds)
     {
         return toAjax(companyUserService.deleteCompanyUserByIds(userIds));
@@ -139,4 +142,42 @@ public class CompanyUserController extends BaseController
         List<CompanyUser> list = companyUserService.getUserListByDeptId(user);
         return R.ok().put("data",list);
     }
+
+    /**
+     * 根据登录的用户公司获取所有的销售
+     * @return
+     */
+    @GetMapping("/getCompanyUserList")
+    public R getCompanyUserList()
+    {
+        CompanyUser cu = new CompanyUser();
+        List<CompanyUser> list = companyUserService.selectCompanyUserList(cu);
+        return  R.ok().put("data",list);
+    }
+
+    /**
+     * 更换会员归属销售
+     * @return
+     */
+    @Log(title = "更换会员归属", businessType = BusinessType.OTHER)
+    @PostMapping("/changeCompanyUser")
+    public AjaxResult changeCompanyUser(@RequestBody List<Long> userIds, @RequestParam Long companyUserId, @RequestParam Long companyId)
+    {
+        return toAjax(companyUserService.changeCompanyUser(userIds, companyUserId, companyId));
+    }
+
+
+    @GetMapping("/getCompanyUserListLikeName")
+    public R getCompanyUserListLikeName(@RequestParam(required = false) String name,
+                                        @RequestParam(required = false) Long companyId,
+                                        @RequestParam(required = false, defaultValue = "1") Integer pageNum,
+                                        @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
+        Map<String,Object> params = new HashMap<>();
+        params.put("companyUserName", name);
+        params.put("companyId", companyId);
+
+        PageHelper.startPage(pageNum, pageSize);
+        List<OptionsVO> companyUserList = companyUserService.selectCompanyUserListByMap(params);
+        return R.ok().put("data", new PageInfo<>(companyUserList));
+    }
 }

+ 1 - 0
fs-admin/src/main/java/com/fs/core/config/SecurityConfig.java

@@ -114,6 +114,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
 //                .antMatchers("/hwcloud/upload/progress").anonymous()
                 .antMatchers("/common/uploadHuaWeiObs").anonymous()
 //                .antMatchers("/hwcloud/upload/videoUrl").anonymous()
+                .antMatchers("/store/express/expressNotify").anonymous()
                 .antMatchers("/common/uploadWang").anonymous()
                 .antMatchers("/common/upload").anonymous()
                 .antMatchers("/profile/**").anonymous()

+ 9 - 0
fs-admin/src/main/java/com/fs/core/exception/FSExceptionHandler.java

@@ -5,6 +5,7 @@ package com.fs.core.exception;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
+import com.fs.common.exception.ServiceException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.dao.DuplicateKeyException;
@@ -34,6 +35,14 @@ public class FSExceptionHandler {
 		return r;
 	}
 
+	@ExceptionHandler(ServiceException.class)
+	public R handleServiceException(ServiceException e){
+		R r = new R();
+		r.put("code", e.getCode());
+		r.put("msg", e.getMessage());
+		return r;
+	}
+
 	@ExceptionHandler(NoHandlerFoundException.class)
 	public R handlerNoFoundException(Exception e) {
 		logger.error(e.getMessage(), e);

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

@@ -112,7 +112,7 @@ public class FsCourseTrafficLogController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('course:courseTrafficLog:remove')")
     @Log(title = "短链课程流量记录", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{logIds}")
+    @DeleteMapping("/{logIds}")
     public AjaxResult remove(@PathVariable Long[] logIds)
     {
         return toAjax(fsCourseTrafficLogService.deleteFsCourseTrafficLogByLogIds(logIds));

+ 9 - 1
fs-admin/src/main/java/com/fs/course/controller/FsCourseWatchLogController.java

@@ -103,6 +103,9 @@ public class FsCourseWatchLogController extends BaseController
         if (param.getSTime()==null||param.getETime()==null){
             return getDataTable(new ArrayList<>());
         }
+        if(param.getCompanyId() == null){
+            throw new CustomException("必须选择公司!");
+        }
         return qwWatchLogService.selectQwWatchLogStatisticsListVONew(param);
     }
     @GetMapping("/myQwWatchLogStatisticsList")
@@ -120,6 +123,11 @@ public class FsCourseWatchLogController extends BaseController
     @GetMapping("/qwWatchLogAllStatisticsList")
     public TableDataInfo qwWatchLogAllStatisticsList(QwWatchLogStatisticsListParam param)
     {
+        logger.info("会员课程数据汇总 参数: {}",param);
+
+        if(param.getCompanyId() == null){
+            throw new CustomException("必须选择公司!");
+        }
         if (param.getSTime()==null||param.getETime()==null){
             return getDataTable(new ArrayList<>());
         }
@@ -250,7 +258,7 @@ public class FsCourseWatchLogController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('course:courseWatchLog:remove')")
     @Log(title = "短链课程看课记录", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{logIds}")
+    @DeleteMapping("/{logIds}")
     public AjaxResult remove(@PathVariable Long[] logIds)
     {
         return toAjax(fsCourseWatchLogService.deleteFsCourseWatchLogByLogIds(logIds));

+ 72 - 27
fs-admin/src/main/java/com/fs/course/controller/FsUserCoursePeriodController.java

@@ -1,38 +1,38 @@
 package com.fs.course.controller;
 
-import java.util.List;
-
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.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.PeriodRedPacketParam;
 import com.fs.course.service.IFsUserCoursePeriodDaysService;
+import com.fs.course.service.IFsUserCoursePeriodService;
 import com.fs.course.service.IFsUserCourseVideoRedPackageService;
 import com.fs.course.vo.FsPeriodCountVO;
 import com.fs.course.vo.FsUserCoursePeriodVO;
+import com.fs.course.vo.PeriodRedPacketVO;
+import com.fs.course.vo.UpdateCourseTimeVo;
+import com.fs.his.vo.OptionsVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.enums.BusinessType;
-import com.fs.course.domain.FsUserCoursePeriod;
-import com.fs.course.service.IFsUserCoursePeriodService;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.common.core.page.TableDataInfo;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 
 /**
  * 会员营期Controller
@@ -63,11 +63,17 @@ public class FsUserCoursePeriodController extends BaseController {
 
     @PostMapping("/page")
     @ApiOperation("自定义查询主列表分页")
-    public TableDataInfo pageList(@RequestBody FsUserCoursePeriod fsUserCoursePeriod)
+    public R pageList(@RequestBody FsUserCoursePeriod fsUserCoursePeriod)
     {
-        startPage();
+//        startPage();
+        PageHelper.startPage(fsUserCoursePeriod.getPageNum(), fsUserCoursePeriod.getPageSize());
         List<FsUserCoursePeriodVO> list = fsUserCoursePeriodService.selectFsUserCoursePeriodPage(fsUserCoursePeriod);
-        return getDataTable(list);
+        PageInfo<FsUserCoursePeriodVO> pageInfo = new PageInfo<>(list);
+        Map<String, Object> result = new HashMap<>();
+        result.put("rows", pageInfo.getList());
+        result.put("total", pageInfo.getTotal());
+        return R.ok(result);
+//        return getDataTable(list);
     }
 
     /**
@@ -120,7 +126,7 @@ public class FsUserCoursePeriodController extends BaseController {
      */
     @PreAuthorize("@ss.hasPermi('course:period:remove')")
     @Log(title = "会员营期", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{periodIds}")
+    @DeleteMapping("/{periodIds}")
     public AjaxResult remove(@PathVariable Long[] periodIds)
     {
         return toAjax(fsUserCoursePeriodService.deleteFsUserCoursePeriodByIds(periodIds));
@@ -137,6 +143,14 @@ public class FsUserCoursePeriodController extends BaseController {
     public R addCourse(@RequestBody FsUserCoursePeriodDays entity){
         return fsUserCoursePeriodDaysService.addCourse(entity);
     }
+    @PostMapping("/updateCourseTime")
+    public R updateCourseTime(@RequestBody UpdateCourseTimeVo vo){
+        return fsUserCoursePeriodDaysService.updateCourseTime(vo);
+    }
+    @PostMapping("/updateCourseDate")
+    public R updateCourseDate(@RequestBody UpdateCourseTimeVo vo){
+        return fsUserCoursePeriodDaysService.updateCourseDate(vo);
+    }
     @PostMapping("/updateListCourseData")
     public R updateListCourseData(@RequestBody List<FsUserCoursePeriodDays> entity){
         return fsUserCoursePeriodDaysService.updateListCourseData(entity);
@@ -152,7 +166,7 @@ public class FsUserCoursePeriodController extends BaseController {
     @ApiOperation("获取设置红包金额列表")
     @GetMapping("/redPacketList")
     public R getPeriodRedPacketList(Long periodId, Long companyId) {
-        List<PeriodRedPacketParam> periodRedPacketList = fsUserCoursePeriodDaysService.getPeriodRedPacketList(periodId, companyId);
+        List<PeriodRedPacketVO> periodRedPacketList = fsUserCoursePeriodDaysService.getPeriodRedPacketList(periodId, companyId);
         return R.ok().put("data", periodRedPacketList);
     }
 
@@ -182,10 +196,41 @@ public class FsUserCoursePeriodController extends BaseController {
 
     @PostMapping("/periodCount")
     @ApiOperation("营期统计")
-    public TableDataInfo periodCourseCount(@RequestBody PeriodCountParam param) {
-        startPage();
+    public R periodCourseCount(@RequestBody PeriodCountParam param) {
+        PageHelper.startPage(param.getPageNum(), param.getPageSize());
         List<FsPeriodCountVO> list = fsUserCoursePeriodDaysService.periodCourseCount(param);
-        return getDataTable(list);
+        PageInfo<FsPeriodCountVO> pageInfo = new PageInfo<>(list);
+        Map<String, Object> result = new HashMap<>();
+        result.put("rows", pageInfo.getList());
+        result.put("total", pageInfo.getTotal());
+        return R.ok(result);
+    }
+
+    @GetMapping("/getPeriodListLikeName")
+    public R getPeriodListLikeName(@RequestParam(required = false) String name,
+                                   @RequestParam(required = false) Long campId,
+                                   @RequestParam(required = false, defaultValue = "1") Integer pageNum,
+                                   @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
+        Map<String,Object> params = new HashMap<>();
+        params.put("name", name);
+        params.put("campId", campId);
+
+        PageHelper.startPage(pageNum, pageSize);
+        List<OptionsVO> periodList = fsUserCoursePeriodDaysService.selectPeriodListByMap(params);
+        return R.ok().put("data", new PageInfo<>(periodList));
+    }
+
+    @ApiOperation("营期课程-上移/下移")
+    @PutMapping("/courseMove")
+    public R periodCourseMove(Long id, Long targetId) {
+        return fsUserCoursePeriodDaysService.periodCourseMove(id, targetId);
+    }
+
+    @ApiOperation("结束营期")
+    @PostMapping("/closePeriod")
+    public R closePeriod(Long id) {
+        fsUserCoursePeriodService.closePeriod(id);
+        return R.ok();
     }
 
 }

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

@@ -2,6 +2,7 @@ package com.fs.course.controller;
 
 import com.fs.common.annotation.Log;
 import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.SortUtils;
 import com.fs.course.domain.FsUserCourseTrainingCamp;
@@ -9,10 +10,10 @@ 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.his.vo.OptionsVO;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import lombok.AllArgsConstructor;
-import org.assertj.core.util.Arrays;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
@@ -106,4 +107,16 @@ public class FsUserCourseTrainingCampController {
         return AjaxResult.success();
     }
 
+    @GetMapping("/getCampListLikeName")
+    public R getCampListLikeName(@RequestParam(required = false) String name,
+                                 @RequestParam(required = false, defaultValue = "1") Integer pageNum,
+                                 @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
+        Map<String,Object> params = new HashMap<>();
+        params.put("name", name);
+
+        PageHelper.startPage(pageNum, pageSize);
+        List<OptionsVO> campList = fsUserCourseTrainingCampService.selectCampListByMap(params);
+        return R.ok().put("data", new PageInfo<>(campList));
+    }
+
 }

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

@@ -9,14 +9,20 @@ import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.course.domain.FsUserCourseVideo;
 import com.fs.course.mapper.FsUserCourseVideoMapper;
+import com.fs.course.param.BatchRedUpdate;
 import com.fs.course.param.BatchVideoSvae;
 import com.fs.course.param.CourseVideoUpdates;
 import com.fs.course.service.IFsUserCourseVideoService;
+import com.fs.his.vo.OptionsVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 课堂视频Controller
@@ -100,7 +106,7 @@ public class FsUserCourseVideoController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('course:userCourseVideo:remove')")
     @Log(title = "课堂视频", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{videoIds}")
+    @DeleteMapping("/{videoIds}")
     public AjaxResult remove(@PathVariable String[] videoIds)
     {
         return toAjax(fsUserCourseVideoService.deleteFsUserCourseVideoByVideoIds(videoIds));
@@ -131,4 +137,24 @@ public class FsUserCourseVideoController extends BaseController
         fsUserCourseVideoService.batchSaveVideo(vo);
         return R.ok();
     }
+    @PostMapping("/batchUpdateRed")
+    public R batchUpdateRed(@RequestBody List<BatchRedUpdate> list){
+        fsUserCourseVideoService.batchUpdateRed(list);
+        return R.ok();
+    }
+
+
+    @GetMapping("/getVideoListLikeName")
+    public R getVideoListLikeName(@RequestParam(required = false) String name,
+                                  @RequestParam(required = false) String periodId,
+                                  @RequestParam(required = false, defaultValue = "1") Integer pageNum,
+                                  @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
+        Map<String,Object> params = new HashMap<>();
+        params.put("name", name);
+        params.put("periodId", periodId);
+
+        PageHelper.startPage(pageNum, pageSize);
+        List<OptionsVO> periodList = fsUserCourseVideoService.selectVideoListByMap(params);
+        return R.ok().put("data", new PageInfo<>(periodList));
+    }
 }

+ 3 - 2
fs-admin/src/main/java/com/fs/course/controller/FsUserVideoController.java

@@ -116,7 +116,7 @@ public class FsUserVideoController extends BaseController
 //            }
 //            productPackage.setProductList(productList);
 //        }
-       return R.ok().put("data", videoPVO);
+        return R.ok().put("data", videoPVO);
     }
 
     /**
@@ -146,7 +146,7 @@ public class FsUserVideoController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('course:userVideo:remove')")
     @Log(title = "课堂视频", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{videoIds}")
+    @DeleteMapping("/{videoIds}")
     public AjaxResult remove(@PathVariable String[] videoIds)
     {
         return toAjax(fsUserVideoService.deleteFsUserVideoByVideoIds(videoIds));
@@ -277,4 +277,5 @@ public class FsUserVideoController extends BaseController
             throw new RuntimeException("FFmpeg 执行失败,退出代码:" + exitCode);
         }
     }
+
 }

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

@@ -37,6 +37,7 @@ public class FsVideoResourceController extends BaseController {
     public TableDataInfo list(@RequestParam(required = false) String resourceName,
                               @RequestParam(required = false) String fileName,
                               @RequestParam(required = false) Integer typeId,
+                              @RequestParam(required = false) Integer typeSubId,
                               @RequestParam(required = false, defaultValue = "1") Integer pageNum,
                               @RequestParam(required = false, defaultValue = "10") Integer pageSize)
     {
@@ -44,6 +45,7 @@ public class FsVideoResourceController extends BaseController {
         params.put("resourceName", resourceName);
         params.put("fileName", fileName);
         params.put("typeId", typeId);
+        params.put("typeSubId", typeSubId);
 
         PageHelper.startPage(pageNum, pageSize);
         List<FsVideoResourceVO> list = fsVideoResourceService.selectVideoResourceListByMap(params);

+ 2 - 1
fs-admin/src/main/java/com/fs/course/controller/qw/QwFsCourseWatchLogController.java

@@ -109,6 +109,7 @@ public class QwFsCourseWatchLogController extends BaseController
     @GetMapping("/qwWatchLogAllStatisticsList")
     public TableDataInfo qwWatchLogAllStatisticsList(QwWatchLogStatisticsListParam param)
     {
+        logger.info("企微课程数据汇总 参数:{}",param);
         startPage();
         if (param.getSTime()==null||param.getETime()==null){
             return getDataTable(new ArrayList<>());
@@ -249,7 +250,7 @@ public class QwFsCourseWatchLogController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('course:courseWatchLog:remove')")
     @Log(title = "短链课程看课记录", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{logIds}")
+    @DeleteMapping("/{logIds}")
     public AjaxResult remove(@PathVariable Long[] logIds)
     {
         return toAjax(fsCourseWatchLogService.deleteFsCourseWatchLogByLogIds(logIds));

+ 62 - 0
fs-admin/src/main/java/com/fs/stats/FsStatsMemberController.java

@@ -0,0 +1,62 @@
+package com.fs.stats;
+
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.statis.service.IFsStatsMemberDailyService;
+import com.fs.statis.vo.FsStatsMemberDailyVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.time.LocalDate;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/stats/member")
+@AllArgsConstructor
+public class FsStatsMemberController {
+
+    private final IFsStatsMemberDailyService statsMemberDailyService;
+
+    @GetMapping("/dailyData")
+    public AjaxResult dailyData(@RequestParam String startDate,
+                                @RequestParam String endDate,
+                                @RequestParam Integer type,
+                                @RequestParam(required = false) Long companyId,
+                                @RequestParam(required = false) Long companyUserId,
+                                @RequestParam(required = false) Long userId,
+                                @RequestParam(required = false) String phone,
+                                @RequestParam(required = false) Long trainCampId,
+                                @RequestParam(required = false) Long periodId,
+                                @RequestParam(required = false) Long courseId,
+                                @RequestParam(required = false) Long videoId,
+                                @RequestParam(required = false, defaultValue = "1") Integer pageNum,
+                                @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
+        Map<String, Object> params = new HashMap<>();
+        params.put("companyId", companyId);
+        params.put("companyUserId", companyUserId);
+        params.put("userId", userId);
+        params.put("phone", phone);
+        params.put("trainCampId", trainCampId);
+        params.put("periodId", periodId);
+        params.put("courseId", courseId);
+        params.put("videoId", videoId);
+
+        if (type == 1) {
+            params.put("startDate", LocalDate.parse(startDate));
+            params.put("endDate", LocalDate.parse(endDate).plusDays(1));
+        } else {
+            params.put("startDate", LocalDate.parse(startDate).withDayOfMonth(1));
+            params.put("endDate", LocalDate.parse(endDate).withDayOfMonth(1).plusMonths(1));
+        }
+
+        PageHelper.startPage(pageNum, pageSize);
+        List<FsStatsMemberDailyVO> list = statsMemberDailyService.selectDailyData(params);
+        return AjaxResult.success(new PageInfo<>(list));
+    }
+}

+ 15 - 1
fs-admin/src/main/java/com/fs/store/controller/FsExpressController.java

@@ -5,6 +5,10 @@ import java.util.List;
 import com.fs.common.core.domain.R;
 import com.fs.company.domain.Company;
 import com.fs.company.service.ICompanyService;
+import com.fs.store.dto.ExpressNotifyDTO;
+import com.fs.store.dto.ExpressResultDTO;
+import com.fs.store.service.IFsStoreOrderService;
+import io.swagger.annotations.ApiOperation;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -40,6 +44,9 @@ public class FsExpressController extends BaseController
     @Autowired
     private ICompanyService companyService;
 
+    @Autowired
+    private IFsStoreOrderService orderService;
+
     /**
      * 查询快递公司列表
      */
@@ -112,7 +119,7 @@ public class FsExpressController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('store:express:remove')")
     @Log(title = "快递公司", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{ids}")
+    @DeleteMapping("/{ids}")
     public AjaxResult remove(@PathVariable Long[] ids)
     {
         return toAjax(fsExpressService.deleteFsExpressByIds(ids));
@@ -131,4 +138,11 @@ public class FsExpressController extends BaseController
         List<Long> list = companyService.selectCompanyByOmsCode(omsCode);
         return R.ok().put("data2",list);
     }
+
+    @ApiOperation("物流信息回调")
+    @PostMapping(path = "/expressNotify" )
+    public ExpressResultDTO expressNotify(ExpressNotifyDTO notifyDTO) throws Exception
+    {
+        return orderService.updateDeliveryItem(notifyDTO);
+    }
 }

+ 14 - 1
fs-admin/src/main/java/com/fs/store/controller/FsStoreProductController.java

@@ -6,6 +6,7 @@ import java.util.Date;
 import java.util.List;
 
 import com.fs.common.core.domain.R;
+import com.fs.statis.dto.ModifyMoreDTO;
 import com.fs.store.domain.FsStoreProductAttr;
 import com.fs.store.domain.FsStoreProductPackage;
 import com.fs.store.param.FsProductAttrValueParam;
@@ -59,6 +60,18 @@ public class FsStoreProductController extends BaseController
     private IFsStoreProductAttrValueService attrValueService;
 
 
+    /**
+     * 批量修改商品
+     * @param modifyMoreDTO
+     * @return
+     */
+    @PreAuthorize("@ss.hasPermi('store:storeProduct:list')")
+    @PostMapping("/batchModify")
+    public R batchModify(@RequestBody ModifyMoreDTO modifyMoreDTO){
+        fsStoreProductService.batchModify(modifyMoreDTO);
+        return R.ok();
+    }
+
     /**
      * 查询商品列表
      */
@@ -144,7 +157,7 @@ public class FsStoreProductController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('store:storeProduct:remove')")
     @Log(title = "商品", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{productIds}")
+    @DeleteMapping("/{productIds}")
     public AjaxResult remove(@PathVariable Long[] productIds)
     {
         return toAjax(fsStoreProductService.deleteFsStoreProductByIds(productIds));

+ 2 - 2
fs-admin/src/main/java/com/fs/store/controller/FsStoreProductPackageController.java

@@ -149,7 +149,7 @@ public class FsStoreProductPackageController extends BaseController
     @Log(title = "商品组合套餐", businessType = BusinessType.UPDATE)
     @PostMapping("/modifyMore")
     public AjaxResult modifyMore(@RequestBody FsStoreProductPackageModifyParam param) {
-        return toAjax(fsStoreProductPackageService.updateFsStoreProductPackages(param.getPackageIds(),param.getStatus()));
+        return toAjax(fsStoreProductPackageService.updateFsStoreProductPackages(param.getPackageIds(),param.getStatus(),param.getCompanyId()));
     }
 
     /**
@@ -186,7 +186,7 @@ public class FsStoreProductPackageController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('store:storeProductPackage:remove')")
     @Log(title = "商品组合套餐", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{packageIds}")
+    @DeleteMapping("/{packageIds}")
     public AjaxResult remove(@PathVariable Long[] packageIds)
     {
         return toAjax(fsStoreProductPackageService.deleteFsStoreProductPackageByIds(packageIds));

+ 3 - 4
fs-admin/src/main/java/com/fs/store/controller/FsTestReportController.java

@@ -5,6 +5,7 @@ import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.store.domain.FsTestReport;
 import com.fs.store.param.FsTestReportParam;
@@ -39,9 +40,7 @@ public class FsTestReportController extends BaseController
     {
         startPage();
         List<FsTestReportListVO> list = fsTestReportService.selectFsTestReportListVO(fsTestReport);
-        for (FsTestReportListVO vo : list) {
-            vo.setPhone(vo.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
-        }
+        list.stream().filter(e -> StringUtils.isNotEmpty(e.getPhone())).forEach(e -> e.setPhone(e.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2")));
         return getDataTable(list);
     }
 
@@ -100,7 +99,7 @@ public class FsTestReportController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('his:testReport:remove')")
     @Log(title = "测试报告", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{reportIds}")
+    @DeleteMapping("/{reportIds}")
     public AjaxResult remove(@PathVariable Long[] reportIds)
     {
         return toAjax(fsTestReportService.deleteFsTestReportByReportIds(reportIds));

+ 32 - 11
fs-admin/src/main/java/com/fs/store/controller/FsUserController.java

@@ -1,21 +1,25 @@
 package com.fs.store.controller;
 
-import java.util.List;
-
-import com.fs.common.core.domain.R;
-import com.fs.common.utils.ParseUtils;
-import com.fs.store.vo.FSUserVO;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.domain.ResponseResult;
+import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ParseUtils;
+import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.store.domain.FsUser;
+import com.fs.store.param.h5.FsUserPageListParam;
 import com.fs.store.service.IFsUserService;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.common.core.page.TableDataInfo;
+import com.fs.store.vo.FSUserVO;
+import com.fs.store.vo.h5.FsUserPageListVO;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
 
 /**
  * 用户Controller
@@ -124,7 +128,7 @@ public class FsUserController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('store:user:remove')")
     @Log(title = "用户", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{userIds}")
+    @DeleteMapping("/{userIds}")
     public AjaxResult remove(@PathVariable Long[] userIds)
     {
         return toAjax(fsUserService.deleteFsUserByIds(userIds));
@@ -145,4 +149,21 @@ public class FsUserController extends BaseController
         List<FsUser> list = fsUserService.selectFsUserList(user);
         return R.ok().put("data",list);
     }
+
+    @PreAuthorize("@ss.hasPermi('store:user:darkRoomList')")
+    @GetMapping("/darkRoomList")
+    @ApiOperation("小黑屋")
+    public TableDataInfo darkRoomList(FsUserPageListParam param) {
+        startPage();
+        List<FsUserPageListVO> list = fsUserService.selectFsUserPageList(param);
+        return getDataTable(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('store:user:darkRoomList')")
+    @PostMapping("/enabledUsers")
+    @ApiOperation("批量启用会员")
+    public ResponseResult<Boolean> enabledUsers(@RequestBody String[] ids) {
+        Boolean r = fsUserService.disabledUser(ids, true);
+        return ResponseResult.ok(r);
+    }
 }

+ 29 - 0
fs-admin/src/main/java/com/fs/task/period/PeriodTask.java

@@ -0,0 +1,29 @@
+package com.fs.task.period;
+
+import com.fs.course.service.IFsUserCoursePeriodDaysService;
+import com.fs.course.service.IFsUserCoursePeriodService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component("periodTask")
+public class PeriodTask {
+
+    @Autowired
+    private IFsUserCoursePeriodService userCoursePeriodService;
+    @Autowired
+    private IFsUserCoursePeriodDaysService userCoursePeriodDaysService;
+
+    /**
+     * 更新营期状态
+     */
+    public void refreshPeriod() {
+        userCoursePeriodService.changePeriodStatus();
+    }
+
+    /**
+     * 更新营期课程状态
+     */
+    public void refreshPeriodDays() {
+        userCoursePeriodDaysService.changePeriodCourseStatus();
+    }
+}

+ 18 - 0
fs-admin/src/main/java/com/fs/task/stats/FsStatsMemberDailyTask.java

@@ -0,0 +1,18 @@
+package com.fs.task.stats;
+
+import com.fs.statis.service.IFsStatsMemberDailyService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class FsStatsMemberDailyTask {
+
+    @Autowired
+    private IFsStatsMemberDailyService fsStatsMemberDailyService;
+
+    public void refreshMemberDailyData() {
+        fsStatsMemberDailyService.refreshMemberDailyData();
+    }
+}

+ 35 - 5
fs-admin/src/main/java/com/fs/user/FsUserAdminController.java

@@ -1,17 +1,28 @@
 package com.fs.user;
 
 import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
+import com.fs.his.vo.OptionsVO;
 import com.fs.store.param.h5.FsUserPageListParam;
 import com.fs.store.service.IFsUserService;
 import com.fs.store.vo.h5.*;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.fs.store.vo.h5.FsUserPageListVO;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
-import java.util.*;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 @Api(tags = "会员管理接口")
 @RestController
@@ -25,11 +36,30 @@ public class FsUserAdminController extends BaseController {
     @PreAuthorize("@ss.hasPermi('user:fsUser:list')")
     @PostMapping("/list")
     @ApiOperation("会员列表(与移动端使用的相同查询)")
-    public TableDataInfo pageList(@RequestBody FsUserPageListParam param) {
-        startPage();
-        List<FsUserPageListVO> list = fsUserService.selectFsUserPageList(param);
-        return getDataTable(list);
+    public R pageList(@RequestBody FsUserPageListParam param) {
+//        PageHelper.startPage(param.getPageNum(), param.getPageSize());
+        TableDataInfo tableDataInfo = fsUserService.selectFsUserPageListNew(param);
+//        PageInfo<FsUserPageListVO> pageInfo = new PageInfo<>(list);
+        Map<String, Object> result = new HashMap<>();
+        result.put("rows", tableDataInfo.getRows());
+        result.put("total", tableDataInfo.getTotal());
+        return R.ok(result);
     }
 
+    /**
+     * 根据会员名称模糊查询
+     * @param name  名称
+     * @return  list
+     */
+    @GetMapping("/getUserListLikeName")
+    public R getUserListLikeName(@RequestParam(required = false) String name,
+                                 @RequestParam(required = false, defaultValue = "1") Integer pageNum,
+                                 @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
+        Map<String,Object> params = new HashMap<>();
+        params.put("nickName", name);
 
+        PageHelper.startPage(pageNum, pageSize);
+        List<OptionsVO> userList = fsUserService.selectUserListByMap(params);
+        return R.ok().put("data", new PageInfo<>(userList));
+    }
 }

+ 1 - 1
fs-common/pom.xml

@@ -117,7 +117,7 @@
         <dependency>
             <groupId>cn.hutool</groupId>
             <artifactId>hutool-all</artifactId>
-            <version>5.3.3</version>
+            <version>5.8.22</version> <!-- 强制指定最新版本 -->
         </dependency>
         <dependency>
             <groupId>org.projectlombok</groupId>

+ 247 - 8
fs-common/src/main/java/com/fs/common/config/FSSysConfig.java

@@ -1,17 +1,14 @@
 package com.fs.common.config;
 
 
-import lombok.Data;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.stereotype.Component;
 
 /**
  * 读取项目相关配置
  *
-
  */
 @Component
-@Data
 @ConfigurationProperties(prefix = "fs-config")
 public class FSSysConfig
 {
@@ -30,7 +27,7 @@ public class FSSysConfig
     String appId;
     String manuId;
     String callbackUrl;
-    //管易云erp接口
+    //erp接口
     Integer erpOpen;//是否开启ERP
     String erpAppKey;
     String erpSessionKey;
@@ -45,8 +42,250 @@ public class FSSysConfig
     String payNotifyUrl;
     String refundNotifyUrl;
     //金博erp
-    String kingbosan;//账套名称
-    String kingbosSecret;//金博密钥
-    String kingbosUrl;//金博地址
-    String corgid;//机构编码
+    private String kingbosan;//账套名称
+    private String kingbosSecret;//金博密钥
+    private String kingbosUrl;//金博地址
+    private String corgid;//机构编码
+    private String cwarehouseCode;
+    private String cwarehouseName;
+
+    public String getKdnId() {
+        return kdnId;
+    }
+
+    public void setKdnId(String kdnId) {
+        this.kdnId = kdnId;
+    }
+
+    public String getKdnKeyId() {
+        return kdnKeyId;
+    }
+
+    public void setKdnKeyId(String kdnKeyId) {
+        this.kdnKeyId = kdnKeyId;
+    }
+
+    public String getKdnUrl() {
+        return kdnUrl;
+    }
+
+    public void setKdnUrl(String kdnUrl) {
+        this.kdnUrl = kdnUrl;
+    }
+
+    public String getKdnSubscribeUrl() {
+        return kdnSubscribeUrl;
+    }
+
+    public void setKdnSubscribeUrl(String kdnSubscribeUrl) {
+        this.kdnSubscribeUrl = kdnSubscribeUrl;
+    }
+
+    public String getKdnAddressUrl() {
+        return kdnAddressUrl;
+    }
+
+    public void setKdnAddressUrl(String kdnAddressUrl) {
+        this.kdnAddressUrl = kdnAddressUrl;
+    }
+
+    public Long getSdkAppId() {
+        return sdkAppId;
+    }
+
+    public void setSdkAppId(Long sdkAppId) {
+        this.sdkAppId = sdkAppId;
+    }
+
+    public String getSdkAppKey() {
+        return sdkAppKey;
+    }
+
+    public void setSdkAppKey(String sdkAppKey) {
+        this.sdkAppKey = sdkAppKey;
+    }
+
+    public String getPrescribeUrl() {
+        return prescribeUrl;
+    }
+
+    public void setPrescribeUrl(String prescribeUrl) {
+        this.prescribeUrl = prescribeUrl;
+    }
+
+    public String getActId() {
+        return actId;
+    }
+
+    public void setActId(String actId) {
+        this.actId = actId;
+    }
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
+    public String getManuId() {
+        return manuId;
+    }
+
+    public void setManuId(String manuId) {
+        this.manuId = manuId;
+    }
+
+    public String getCallbackUrl() {
+        return callbackUrl;
+    }
+
+    public void setCallbackUrl(String callbackUrl) {
+        this.callbackUrl = callbackUrl;
+    }
+
+    public Integer getErpOpen() {
+        return erpOpen;
+    }
+
+    public void setErpOpen(Integer erpOpen) {
+        this.erpOpen = erpOpen;
+    }
+
+    public String getErpAppKey() {
+        return erpAppKey;
+    }
+
+    public void setErpAppKey(String erpAppKey) {
+        this.erpAppKey = erpAppKey;
+    }
+
+    public String getErpSessionKey() {
+        return erpSessionKey;
+    }
+
+    public void setErpSessionKey(String erpSessionKey) {
+        this.erpSessionKey = erpSessionKey;
+    }
+
+    public String getErpSecret() {
+        return erpSecret;
+    }
+
+    public void setErpSecret(String erpSecret) {
+        this.erpSecret = erpSecret;
+    }
+
+    public String getErpUrl() {
+        return erpUrl;
+    }
+
+    public void setErpUrl(String erpUrl) {
+        this.erpUrl = erpUrl;
+    }
+
+    public String getErpShopCode() {
+        return erpShopCode;
+    }
+
+    public void setErpShopCode(String erpShopCode) {
+        this.erpShopCode = erpShopCode;
+    }
+
+    public Integer getPayOpen() {
+        return payOpen;
+    }
+
+    public void setPayOpen(Integer payOpen) {
+        this.payOpen = payOpen;
+    }
+
+    public String getPayPartnerId() {
+        return payPartnerId;
+    }
+
+    public void setPayPartnerId(String payPartnerId) {
+        this.payPartnerId = payPartnerId;
+    }
+
+    public String getPayKey() {
+        return payKey;
+    }
+
+    public void setPayKey(String payKey) {
+        this.payKey = payKey;
+    }
+
+    public String getPayGateWayUrl() {
+        return payGateWayUrl;
+    }
+
+    public void setPayGateWayUrl(String payGateWayUrl) {
+        this.payGateWayUrl = payGateWayUrl;
+    }
+
+    public String getPayNotifyUrl() {
+        return payNotifyUrl;
+    }
+
+    public void setPayNotifyUrl(String payNotifyUrl) {
+        this.payNotifyUrl = payNotifyUrl;
+    }
+
+    public String getRefundNotifyUrl() {
+        return refundNotifyUrl;
+    }
+
+    public void setRefundNotifyUrl(String refundNotifyUrl) {
+        this.refundNotifyUrl = refundNotifyUrl;
+    }
+
+    public String getKingbosan() {
+        return kingbosan;
+    }
+
+    public void setKingbosan(String kingbosan) {
+        this.kingbosan = kingbosan;
+    }
+
+    public String getCorgid() {
+        return corgid;
+    }
+
+    public void setCorgid(String corgid) {
+        this.corgid = corgid;
+    }
+
+    public String getKingbosUrl() {
+        return kingbosUrl;
+    }
+
+    public void setKingbosUrl(String kingbosUrl) {
+        this.kingbosUrl = kingbosUrl;
+    }
+
+    public String getKingbosSecret() {
+        return kingbosSecret;
+    }
+
+    public void setKingbosSecret(String kingbosSecret) {
+        this.kingbosSecret = kingbosSecret;
+    }
+
+    public String getCwarehouseCode() {
+        return cwarehouseCode;
+    }
+
+    public void setCwarehouseCode(String cwarehouseCode) {
+        this.cwarehouseCode = cwarehouseCode;
+    }
+
+    public String getCwarehouseName() {
+        return cwarehouseName;
+    }
+
+    public void setCwarehouseName(String cwarehouseName) {
+        this.cwarehouseName = cwarehouseName;
+    }
 }

+ 51 - 3
fs-common/src/main/java/com/fs/common/utils/DateUtils.java

@@ -3,9 +3,8 @@ package com.fs.common.utils;
 import java.lang.management.ManagementFactory;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.time.Instant;
-import java.time.LocalDate;
-import java.time.ZoneId;
+import java.time.*;
+import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoUnit;
 import java.util.Calendar;
 import java.util.Date;
@@ -32,6 +31,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
             "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
             "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
             "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
+    private static final DateTimeFormatter OUTPUT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
 
     /**
      * 获取当前Date型日期
@@ -217,4 +217,52 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
         return daysBetween;
     }
 
+    /**
+     * 获取指定日期当天的开始时间字符串 (格式: yyyy-MM-dd 00:00:00)
+     *
+     * @param date 输入的 Date 对象
+     * @return 当天开始时间的字符串表示,如果输入为 null 则返回 null
+     */
+    public static String getStartOfDayString(Date date) {
+        // 使用 Objects.requireNonNull(date, "输入日期不能为 null"); 如果希望在输入为 null 时抛出异常
+        if (date == null) {
+            return null;
+        }
+        // 1. 将 Date 转换为更现代的 LocalDateTime (考虑时区)
+        //    使用系统默认时区。如果需要特定时区,请替换 ZoneId.systemDefault()
+        //    例如:ZoneId.of("Asia/Shanghai")
+        LocalDateTime localDateTime = date.toInstant()
+                .atZone(ZoneId.systemDefault())
+                .toLocalDateTime();
+        // 2. 获取该日期的开始时间 (00:00:00)
+        LocalDateTime startOfDay = localDateTime.toLocalDate().atStartOfDay();
+        // 3. 格式化为目标字符串
+        return startOfDay.format(OUTPUT_FORMATTER);
+    }
+    /**
+     * 获取指定日期当天的结束时间字符串 (格式: yyyy-MM-dd 23:59:59)
+     *
+     * @param date 输入的 Date 对象
+     * @return 当天结束时间的字符串表示,如果输入为 null 则返回 null
+     */
+    public static String getEndOfDayString(Date date) {
+        if (date == null) {
+            return null;
+        }
+        // 1. 将 Date 转换为 LocalDateTime (考虑时区)
+        LocalDateTime localDateTime = date.toInstant()
+                .atZone(ZoneId.systemDefault())
+                .toLocalDateTime();
+        // 2. 获取该日期的 LocalDate 部分
+        LocalDate localDate = localDateTime.toLocalDate();
+        // 3. 创建当天的结束时间 (23:59:59)
+        LocalDateTime endOfDay = LocalDateTime.of(localDate, LocalTime.of(23, 59, 59));
+        // 注意: 如果需要的是一天的最后一纳秒 (23:59:59.999999999),可以使用:
+        // LocalDateTime endOfDay = LocalDateTime.of(localDate, LocalTime.MAX);
+        // 但根据 "23:59:59" 的要求,明确指定秒更符合。
+        // 4. 格式化为目标字符串
+        return endOfDay.format(OUTPUT_FORMATTER);
+    }
+
+
 }

+ 1 - 1
fs-common/src/main/java/com/fs/common/utils/TimeUtils.java

@@ -230,7 +230,7 @@ public class TimeUtils
         }
 
         public Map<String, Object> toMap() {
-            return BeanUtil.beanToMap(this);
+            return BeanUtil.beanToMap(this, false, true);
         }
 
         public String getSqlDateFormat() {

+ 14 - 5
fs-common/src/main/java/com/fs/common/utils/date/DateUtil.java

@@ -111,8 +111,8 @@ public final class DateUtil {
 		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
 		LocalDateTime startTime=LocalDateTime.parse(dateTime, formatter);
 		ZoneId zoneId = ZoneId.systemDefault();
-        ZonedDateTime zdtStart = startTime.atZone(zoneId);
-    	return Date.from(zdtStart.toInstant());
+		ZonedDateTime zdtStart = startTime.atZone(zoneId);
+		return Date.from(zdtStart.toInstant());
 	}
 
 	public static String formatLocalDate(LocalDate localDate){
@@ -331,7 +331,7 @@ public final class DateUtil {
 	 * @return
 	 */
 	public static <T> T calculatingTime(T t, CalculateTypeEnum calculateTypeEnum,
-									   long num, TimeTypeEnum timeTypeEnum){
+										long num, TimeTypeEnum timeTypeEnum){
 		LocalDateTime localDateTime;
 		if(t instanceof Date){
 			localDateTime = dateToLocalDateTime((Date) t);
@@ -376,7 +376,7 @@ public final class DateUtil {
 	 * @return
 	 */
 	private static LocalDateTime calculation(long num, CalculateTypeEnum calculateTypeEnum,
-								 LongFunction<LocalDateTime> addDeal, LongFunction<LocalDateTime> subDeal) {
+											 LongFunction<LocalDateTime> addDeal, LongFunction<LocalDateTime> subDeal) {
 		switch (calculateTypeEnum){
 			case ADD: return addDeal.apply(num);
 			case SUBTRACT: return subDeal.apply(num);
@@ -493,5 +493,14 @@ public final class DateUtil {
 		return itemEdate;
 	}
 
-
+	public static boolean isWithinRangeSafe(LocalDate targetDate, LocalDate startDate, LocalDate endDate) {
+		LocalDate actualStart = startDate.isBefore(endDate) ? startDate : endDate;
+		LocalDate actualEnd = startDate.isBefore(endDate) ? endDate : startDate;
+		return !targetDate.isBefore(actualStart) && !targetDate.isAfter(actualEnd);
+	}
+	public static boolean isWithinRangeSafe(LocalDateTime targetDate, LocalDateTime startDate, LocalDateTime endDate) {
+		LocalDateTime actualStart = startDate.isBefore(endDate) ? startDate : endDate;
+		LocalDateTime actualEnd = startDate.isBefore(endDate) ? endDate : startDate;
+		return !targetDate.isBefore(actualStart) && !targetDate.isAfter(actualEnd);
+	}
 }

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

@@ -0,0 +1,240 @@
+package com.fs.company.controller;
+
+import com.fs.common.core.domain.R;
+import com.fs.common.core.redis.RedisCache;
+import com.fs.common.utils.ServletUtils;
+import com.fs.core.security.LoginUser;
+import com.fs.core.web.service.TokenService;
+import com.fs.statis.StatisticsRedisConstant;
+import com.fs.statis.dto.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.fs.statis.StatisticsRedisConstant.*;
+
+/**
+ * 首页-统计
+ */
+@RestController
+@RequestMapping("/index/statistics")
+public class IndexStatisticsController {
+    @Autowired
+    private RedisCache redisCache;
+
+    @Autowired
+    private TokenService tokenService;
+    /**
+     * 分析概览
+     */
+    @PostMapping("/analysisPreview")
+    public R analysisPreview(@RequestBody AnalysisPreviewQueryDTO param){
+        AnalysisPreviewDTO analysisPreviewDTO = null;
+        Integer type = param.getType();
+        Integer userType = param.getUserType();
+
+        if(type == null) {
+            type = 0;
+        }
+
+        if(userType == null) {
+            userType = 0;
+        }
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        analysisPreviewDTO = redisCache.getCacheObject(String.format("%s:%d:%d:%d",DATA_OVERVIEW_DEALER_ANALYSISPREVIEW,type,userType,param.getCompanyId()));
+
+        return R.ok().put("data",analysisPreviewDTO);
+    }
+
+
+    /**
+     * 消费余额
+     */
+    @GetMapping("/rechargeComsumption")
+    public R rechargeComsumption(){
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyId = loginUser.getCompany().getCompanyId();
+
+        ConsumptionBalanceDataDTO consumptionBalanceDataDTO = redisCache.getCacheObject(String.format("%s:%d",StatisticsRedisConstant.DATA_OVERVIEW_DEALER_BALANCE,companyId));
+        return R.ok().put("data", consumptionBalanceDataDTO);
+    }
+
+    /**
+     * 获取统计流量
+     * @return
+     */
+    @GetMapping("/trafficLog")
+    public R getTrafficLog(){
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyId = loginUser.getCompany().getCompanyId();
+        TrafficLogDTO trafficLogDTO = redisCache.getCacheObject(String.format("%s:%d",DATA_OVERVIEW_TRAFFIC_LOG,companyId));
+        return R.ok().put("data",trafficLogDTO);
+    }
+
+    /**
+     * 观看趋势
+     */
+    @PostMapping("/watchEndPlayTrend")
+    public R watchEndPlayTrend(@RequestBody AnalysisPreviewQueryDTO param){
+        Integer type = param.getType();
+        Integer userType = param.getUserType();
+
+        if(type == null) {
+            type = 0;
+        }
+        if(userType == null){
+            userType = 0;
+        }
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyId = loginUser.getCompany().getCompanyId();
+        param.setCompanyId(companyId);
+
+        String key = String.format("%s:%d:%d:%d", DATA_OVERVIEW_DEALER_CHARTS, type,userType,param.getCompanyId());
+        List<DeaMemberTopTenDTO> deaMemberTopTenDTOS = redisCache.getCacheObject(key);
+        return R.ok().put("data", deaMemberTopTenDTOS);
+    }
+
+    /**
+     * 经销商会员观看
+     */
+    @PostMapping("/deaMemberTopTen")
+    public R deaMemberTopTen(@RequestBody AnalysisPreviewQueryDTO param){
+        Integer type = param.getType();
+        Integer statisticalType = param.getStatisticalType();
+        Integer userType = param.getUserType();
+
+        if(type == null) {
+            type = 0;
+        }
+        if(userType == null){
+            userType = 0;
+        }
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyId = loginUser.getCompany().getCompanyId();
+        param.setCompanyId(companyId);
+
+        List<DeaMemberTopTenDTO> deaMemberTopTenDTOS = redisCache.getCacheObject(String.format("%s:%d:%d:%d:%d", CHARTS_MEMBER_TOP_TEN_WATCH, type, statisticalType,userType,param.getCompanyId()));
+        if(deaMemberTopTenDTOS == null){
+            deaMemberTopTenDTOS = new ArrayList<>();
+        }
+        return R.ok().put("data", deaMemberTopTenDTOS);
+    }
+
+    /**
+     * 奖励金额top10
+     */
+    @PostMapping("/rewardMoneyTopTen")
+    public R rewardMoneyTopTen(@RequestBody AnalysisPreviewQueryDTO param){
+        Integer type = param.getType();
+        Integer dataType = param.getDataType();
+        Integer userType = param.getUserType();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyId = loginUser.getCompany().getCompanyId();
+        param.setCompanyId(companyId);
+
+        List<RewardMoneyTopTenDTO> rewardMoneyTopTenDTOS = redisCache.getCacheObject( String.format("%s:%d:%d:%d:%d", CHARTS_REWARD_MONEY_TOP_TEN, type,dataType,userType,param.getCompanyId()));
+        return R.ok().put("data", rewardMoneyTopTenDTOS);
+    }
+
+    /**
+     * 答题红包金额趋势图
+     */
+    @PostMapping("/rewardMoneyTrend")
+    public R rewardMoneyTrend(@RequestBody AnalysisPreviewQueryDTO param){
+        Integer type = param.getType();
+        Integer userType = param.getUserType();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyId = loginUser.getCompany().getCompanyId();
+        param.setCompanyId(companyId);
+
+        List<RewardMoneyTrendDTO> rewardMoneyTrendDTOS = redisCache.getCacheObject( String.format("%s:%d:%d:%d", CHARTS_REWARD_MONEY_TREND, type,userType,param.getCompanyId()));
+        return R.ok().put("data", rewardMoneyTrendDTOS);
+    }
+
+    /**
+     * 课程观看top10
+     */
+    @PostMapping("/watchCourseTopTen")
+    public R watchCourseTopTen(@RequestBody AnalysisPreviewQueryDTO param){
+        Integer type = param.getType();
+        String sort = param.getSort();
+        Integer statisticalType = param.getStatisticalType();
+        Integer userType = param.getUserType();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyId = loginUser.getCompany().getCompanyId();
+        param.setCompanyId(companyId);
+
+        List<CourseStatsDTO> courseStatsDTOS = redisCache.getCacheObject(String.format("%s:%d:%d:%d:%s:%d", CHARTS_WATCH_TOP_TEN, type,statisticalType,userType,sort,param.getCompanyId()));
+        return R.ok().put("data", courseStatsDTOS);
+    }
+
+    /**
+     * 数据概览
+     */
+    @GetMapping("/dealerAggregated")
+    public R dealerAggregated(){
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyId = loginUser.getCompany().getCompanyId();
+
+        DealerAggregatedDTO dealerAggregatedDTO = redisCache.getCacheObject(String.format("%s:%d",StatisticsRedisConstant.DATA_OVERVIEW_DEALER_AGGREGATED,companyId));
+
+        return R.ok().put("data",dealerAggregatedDTO);
+    }
+
+    /**
+     * 短信余额
+     */
+    @GetMapping("/smsBalance")
+    public R smsBalance(){
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyId = loginUser.getCompany().getCompanyId();
+
+        Long smsBalance = redisCache.getCacheObject(String.format("%s:%d",StatisticsRedisConstant.DATA_OVERVIEW_DEALER_SMS_BALANCE,companyId));
+
+        return R.ok().put("data", smsBalance);
+    }
+
+
+    /**
+     * 授权信息
+     */
+    @GetMapping("/authorizationInfo")
+    public R authorizationInfo(){
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyId = loginUser.getCompany().getCompanyId();
+
+        AuthorizationInfoDTO authorizationInfoDTO = redisCache.getCacheObject(String.format("%s:%d",StatisticsRedisConstant.DATA_OVERVIEW_DEALER_AUTHORIZATION_INFO,companyId));
+
+        return R.ok().put("data", authorizationInfoDTO);
+    }
+
+
+    /**
+     * 当月订单数统计
+     * @return
+     */
+    @GetMapping("/thisMonthOrderCount")
+    public R thisMonthOrderCount(){
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyId = loginUser.getCompany().getCompanyId();
+
+        R result = redisCache.getCacheObject(String.format("%s:%d",StatisticsRedisConstant.THIS_MONTH_ORDER_COUNT,companyId));
+        return result;
+    }
+
+    /**
+     * 当月收益统计
+     * @return
+     */
+    @GetMapping("/thisMonthRecvCount")
+    public R thisMonthRecvCount(){
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyId = loginUser.getCompany().getCompanyId();
+
+        R result = redisCache.getCacheObject(String.format("%s:%d",StatisticsRedisConstant.THIS_MONTH_RECV_COUNT,companyId));
+        return result;
+    }
+}

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

@@ -184,6 +184,7 @@ public class FsCourseWatchLogController extends BaseController
     {
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         param.setCompanyId( loginUser.getCompany().getCompanyId());
+        param.setCompanyUserId(loginUser.getUser().getUserId());
         List<FsCourseWatchLogListVO> list = fsCourseWatchLogService.selectFsCourseWatchLogListVONew(param);
         TableDataInfo rspData = new TableDataInfo();
         rspData.setCode(HttpStatus.SUCCESS);
@@ -257,7 +258,7 @@ public class FsCourseWatchLogController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('course:courseWatchLog:remove')")
     @Log(title = "短链课程看课记录", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{logIds}")
+    @DeleteMapping("/{logIds}")
     public AjaxResult remove(@PathVariable Long[] logIds)
     {
         return toAjax(fsCourseWatchLogService.deleteFsCourseWatchLogByLogIds(logIds));

+ 22 - 11
fs-company/src/main/java/com/fs/qw/QwExternalContactController.java

@@ -17,6 +17,8 @@ import com.fs.crm.service.ICrmCustomerService;
 import com.fs.crm.vo.CrmMyCustomerListQueryVO;
 import com.fs.core.security.LoginUser;
 import com.fs.core.web.service.TokenService;
+import com.fs.qw.dto.GetQwRepeatDataDTO;
+import com.fs.qw.vo.GetQwRepeatDataVO;
 import com.fs.store.service.IFsUserService;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.param.*;
@@ -73,6 +75,15 @@ public class QwExternalContactController extends BaseController
         List<QwExternalContactVO> list = qwExternalContactService.selectQwExternalContactListVO(qwExternalContact);
         return getDataTable(list);
     }
+
+    /**
+     * 企微获取重粉数据
+     */
+    @PostMapping("/qwRepeatData")
+    public R getQwRepeatData(@RequestBody GetQwRepeatDataDTO dto){
+        List<GetQwRepeatDataVO> qwRepeatData = qwExternalContactService.getQwRepeatData(dto);
+        return R.ok().put("data",qwRepeatData);
+    }
     /**
      * 同步企业微信客户
      */
@@ -187,8 +198,8 @@ public class QwExternalContactController extends BaseController
     }
 
     /**
-    * 在职转接 分配客户
-    */
+     * 在职转接 分配客户
+     */
     @PreAuthorize("@ss.hasPermi('qw:externalContact:transfer')")
     @Log(title = "企业微信客户", businessType = BusinessType.UPDATE)
     @PutMapping("/transfer")
@@ -229,8 +240,8 @@ public class QwExternalContactController extends BaseController
     }
 
     /**
-    * 绑定小程序用户
-    */
+     * 绑定小程序用户
+     */
     @PutMapping("/bindUserId")
     public R bindUserId(@RequestBody QwExternalContact qwExternalContact)
     {
@@ -252,7 +263,7 @@ public class QwExternalContactController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('qw:externalContact:remove')")
     @Log(title = "企业微信客户", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{ids}")
+    @DeleteMapping("/{ids}")
     public AjaxResult remove(@PathVariable Long[] ids)
     {
         return toAjax(qwExternalContactService.deleteQwExternalContactByIds(ids));
@@ -304,8 +315,8 @@ public class QwExternalContactController extends BaseController
     }
 
     /**
-    * 获取CRM在学课程记录
-    */
+     * 获取CRM在学课程记录
+     */
     @GetMapping("/getCourseStudyList")
     public TableDataInfo getMyCourseList(FsUserCourseListUParam param)
     {
@@ -328,8 +339,8 @@ public class QwExternalContactController extends BaseController
     }
 
     /**
-    * 查询是否已经设置过客户-某个课节的SOP
-    */
+     * 查询是否已经设置过客户-某个课节的SOP
+     */
     @GetMapping("/getCustomerCourseSop")
     public Boolean getCustomerCourseSop(QwFsCustomerCourseSopGetParam param){
 //
@@ -341,8 +352,8 @@ public class QwExternalContactController extends BaseController
     }
 
     /**
-    * 批量设置客户-课节SOP
-    */
+     * 批量设置客户-课节SOP
+     */
     @PostMapping("/setCustomerCourseSopList")
     public R setCustomerCourseSopList(@RequestBody QwFsCustomerCourseSopListParam param){
 

+ 13 - 8
fs-company/src/main/java/com/fs/qw/vo/QwExternalContactVO.java

@@ -15,13 +15,13 @@ public class QwExternalContactVO {
     private String userId;
 
     /**
-    *  属于用户名称
-    */
+     *  属于用户名称
+     */
     private String qwUserName;
 
     /**
-    * 员工所属部门
-    */
+     * 员工所属部门
+     */
     private String departmentName;
 
 
@@ -32,13 +32,13 @@ public class QwExternalContactVO {
     private Long companyUserId;
 
     /**
-    * 是否绑定企业微信
-    */
+     * 是否绑定企业微信
+     */
     private Long customerId;
 
     /**
-    * CRM 绑定的小程序id
-    */
+     * CRM 绑定的小程序id
+     */
     private Long miniUserId;
 
     /** 名称 */
@@ -111,4 +111,9 @@ public class QwExternalContactVO {
     private Long level;
     @Excel(name = "等级升降")
     private Long levelType;
+
+    /**
+     * 是否重粉
+     */
+    private Integer isRepeat;
 }

+ 11 - 9
fs-company/src/main/java/com/fs/user/FsUserAdminController.java

@@ -6,6 +6,7 @@ import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.utils.ServletUtils;
+import com.fs.company.cache.ICompanyUserCacheService;
 import com.fs.core.security.LoginUser;
 import com.fs.core.web.service.TokenService;
 import com.fs.store.param.h5.FsUserPageListParam;
@@ -32,6 +33,9 @@ public class FsUserAdminController extends BaseController {
     @Autowired
     private IFsUserService fsUserService;
 
+    @Autowired
+    private ICompanyUserCacheService companyUserCacheService;
+
     @Autowired
     private TokenService tokenService;
 
@@ -39,18 +43,16 @@ public class FsUserAdminController extends BaseController {
     @PostMapping("/list")
     @ApiOperation("会员列表(与移动端使用的相同查询)")
     public TableDataInfo pageList(@RequestBody FsUserPageListParam param) {
+//        startPage();
+
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         param.setCompanyId(loginUser.getCompany().getCompanyId());
-        param.setPcLoginUserId(loginUser.getUser().getUserId());
+        param.setCompanyUserId(String.valueOf(loginUser.getUser().getUserId()));
 
-        List<FsUserPageListVO> list = fsUserService.selectFsUserPageListNew(param);
-        Long total = fsUserService.selectFsUserCount(param);
-        TableDataInfo rspData = new TableDataInfo();
-        rspData.setCode(HttpStatus.SUCCESS);
-        rspData.setMsg("查询成功");
-        rspData.setRows(list);
-        rspData.setTotal(total);
-        return rspData;
+        if(param.getCompanyUserId() == null) {
+            throw new IllegalArgumentException("当前销售不存在!");
+        }
+        return fsUserService.selectFsUserPageListNew(param);
     }
 
     @PostMapping("/auditUser")

+ 20 - 0
fs-qw-task/src/main/java/com/fs/app/task/CourseWatchLogScheduler.java

@@ -123,6 +123,26 @@ public class CourseWatchLogScheduler {
 
     }
 
+    @Scheduled(fixedRate = 60000) // 每分钟执行一次
+    public void checkFsUserWatchStatus() {
+        // 尝试设置标志为 true,表示任务开始执行
+        if (!isRunning1.compareAndSet(false, true)) {
+            log.warn("WXH5-检查会员看课中任务执行 - 上一个任务尚未完成,跳过此次执行");
+            return;
+        }
+        try {
+            log.info("WXH5-检查会员看课中任务执行>>>>>>>>>>>>");
+            courseWatchLogService.scheduleUpdateDurationToDatabase();
+            courseWatchLogService.checkFsUserWatchStatus();
+            log.info("WXH5-检查会员看课中任务执行完成>>>>>>>>>>>>");
+        }catch (Exception e) {
+            log.error("WXH5-检查会员看课中任务执行完成 - 定时任务执行失败", e);
+        } finally {
+            // 重置标志为 false,表示任务已完成
+            isRunning1.set(false);
+        }
+
+    }
 
 
 

+ 42 - 0
fs-qw-task/src/main/java/com/fs/app/task/UserCourseWatchCountTask.java

@@ -0,0 +1,42 @@
+package com.fs.app.task;
+
+import com.fs.common.core.redis.RedisCache;
+import com.fs.course.mapper.FsCourseWatchLogMapper;
+import com.fs.course.service.IFsCourseWatchLogService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+@Component
+@Slf4j
+public class UserCourseWatchCountTask {
+
+    @Autowired
+    private FsCourseWatchLogMapper courseWatchLogMapper;
+
+    @Autowired
+    RedisCache redisCache;
+
+    @Autowired
+    private IFsCourseWatchLogService courseWatchLogService;
+
+
+    /**
+     * 每天两点进行会员看课统计
+     */
+    @Scheduled(cron = "0 0 2 * * ?")  // 2点0分0秒执行
+    public void userCourseCountTask() {
+        try {
+            log.info("会员看课统计任务执行----------开始");
+            //
+
+            log.info("会员看课统计任务执行----------结束");
+        } catch (Exception e) {
+            log.error("会员看课统计任务执行----------定时任务执行失败", e);
+        }
+
+    }
+
+
+}

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

@@ -678,7 +678,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                     ruleTimeVO.setRemark("客户群催课");
                     QwSopLogs sopLogs = createBaseLog(formattedSendTime, logVo, ruleTimeVO, user.getUserId(), user.getName(), null);
                     handleLogBasedOnType(sopLogs, content, logVo, sendTime, courseId, videoId,
-                            type, qwUserId, companyUserId, companyId, user.getUserId(), welcomeText, qwUserName, null, false);
+                            type, qwUserId, companyUserId, companyId, user.getId().toString(), welcomeText, qwUserName, null, false);
                 });
             }
         } else {

+ 16 - 16
fs-service-system/pom.xml

@@ -40,11 +40,11 @@
             <version>1.5.21</version>
         </dependency>
 
-        <dependency>
-            <groupId>cn.hutool</groupId>
-            <artifactId>hutool-all</artifactId>
-            <version>5.3.7</version>
-        </dependency>
+        <!--        <dependency>-->
+        <!--            <groupId>cn.hutool</groupId>-->
+        <!--            <artifactId>hutool-all</artifactId>-->
+        <!--            <version>5.3.7</version>-->
+        <!--        </dependency>-->
         <!-- oss -->
         <dependency>
             <groupId>com.qiniu</groupId>
@@ -105,17 +105,17 @@
             <artifactId>httpclient5</artifactId>
             <version>5.2.1</version>
         </dependency>
-<!--        <dependency>-->
-<!--            <groupId>redis.clients</groupId>-->
-<!--            <artifactId>jedis</artifactId>-->
-<!--            <version>2.9.0</version>-->
-<!--        </dependency>-->
-
-<!--        <dependency>-->
-<!--            <groupId>com.github.jedis-lock</groupId>-->
-<!--            <artifactId>jedis-lock</artifactId>-->
-<!--            <version>1.0.0</version>-->
-<!--        </dependency>-->
+        <!--        <dependency>-->
+        <!--            <groupId>redis.clients</groupId>-->
+        <!--            <artifactId>jedis</artifactId>-->
+        <!--            <version>2.9.0</version>-->
+        <!--        </dependency>-->
+
+        <!--        <dependency>-->
+        <!--            <groupId>com.github.jedis-lock</groupId>-->
+        <!--            <artifactId>jedis-lock</artifactId>-->
+        <!--            <version>1.0.0</version>-->
+        <!--        </dependency>-->
 
         <dependency>
             <groupId>com.hc</groupId>

+ 9 - 0
fs-service-system/src/main/java/com/fs/company/cache/ICompanyTagCacheService.java

@@ -0,0 +1,9 @@
+package com.fs.company.cache;
+
+import java.util.Map;
+
+public interface ICompanyTagCacheService {
+    String findUserTagByUserId(Long userId);
+
+    Map<Long, String> queryAllTagMap();
+}

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

@@ -12,6 +12,7 @@ import com.fs.qw.vo.QwUserVO;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 ;
 
@@ -29,5 +30,13 @@ public interface ICompanyUserCacheService {
      * @return 物业公司管理员信息
      */
     public CompanyUser selectCompanyUserById(Long userId);
+    public String selectCompanyUserNameUserById(Long userId);
+
+    /**
+     * 查询当前用户所有的下级销售
+     * @param companyUserId
+     * @return String
+     */
+    public Set<Long> selectUserAllCompanyUserId(Long companyUserId);
 
 }

+ 36 - 0
fs-service-system/src/main/java/com/fs/company/cache/impl/CompanyTagCacheServiceImpl.java

@@ -0,0 +1,36 @@
+package com.fs.company.cache.impl;
+
+import com.fs.company.cache.ICompanyTagCacheService;
+import com.fs.company.service.ICompanyTagService;
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+@Service
+public class CompanyTagCacheServiceImpl implements ICompanyTagCacheService {
+
+    @Autowired
+    private ICompanyTagService companyTagService;
+    private static final Cache<Long,String> COMPANY_TAG_CACHE = Caffeine.newBuilder()
+            .maximumSize(1000)
+            .expireAfterWrite(5, TimeUnit.MINUTES)
+            .build();
+
+    private static final Cache<Long,Map<Long, String>> COMPANY_USER_TAG_CACHE = Caffeine.newBuilder()
+            .maximumSize(1000)
+            .expireAfterWrite(5, TimeUnit.MINUTES)
+            .build();
+    @Override
+    public String findUserTagByUserId(Long key) {
+        return COMPANY_TAG_CACHE.get(key,e-> companyTagService.findUserTagByUserId(key));
+    }
+
+    @Override
+    public Map<Long, String> queryAllTagMap() {
+        return COMPANY_USER_TAG_CACHE.get(0L, e-> companyTagService.queryAllTagMap());
+    }
+}

+ 35 - 2
fs-service-system/src/main/java/com/fs/company/cache/impl/CompanyUserCacheServiceImpl.java

@@ -1,5 +1,6 @@
 package com.fs.company.cache.impl;
 
+import com.fasterxml.jackson.databind.util.ArrayIterator;
 import com.fs.company.cache.ICompanyCacheService;
 import com.fs.company.cache.ICompanyUserCacheService;
 import com.fs.company.domain.Company;
@@ -9,24 +10,56 @@ import com.github.benmanes.caffeine.cache.Cache;
 import com.github.benmanes.caffeine.cache.Caffeine;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Service;
 
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 @Service
 @Slf4j
-@RequiredArgsConstructor
 public class CompanyUserCacheServiceImpl implements ICompanyUserCacheService {
 
-    private final ICompanyUserService companyUserService;
+    @Autowired
+    private ICompanyUserService companyUserService;
 
     private static final Cache<Long, CompanyUser> USER_CACHE = Caffeine.newBuilder()
             .maximumSize(1000)
             .expireAfterWrite(3, TimeUnit.MINUTES)
             .build();
+
+    private static final Cache<Long,Set<Long>> COMPANY_USER_CACHE = Caffeine.newBuilder()
+            .maximumSize(1000)
+            .expireAfterWrite(5, TimeUnit.MINUTES)
+            .build();
+
+    private static final Cache<Long,String> COMPANY_USER_NAME_CACHE = Caffeine.newBuilder()
+            .maximumSize(1000)
+            .expireAfterWrite(5, TimeUnit.MINUTES)
+            .build();
+
+
     @Override
     public CompanyUser selectCompanyUserById(Long userId) {
         return USER_CACHE.get(userId,e-> companyUserService.selectCompanyUserByUserId(userId));
     }
+
+    @Override
+    public String selectCompanyUserNameUserById(Long userId) {
+        return COMPANY_USER_NAME_CACHE.get(userId,e-> companyUserService.selectCompanyUserNameUserById(userId));
+    }
+
+    @Override
+    public Set<Long> selectUserAllCompanyUserId(Long companyUserId) {
+        return COMPANY_USER_CACHE.get(companyUserId,e->{
+            List<Long> longs = companyUserService.selectUserAllCompanyUserId(companyUserId);
+            Set<Long> set = new HashSet<>(longs);
+            set.add(companyUserId);
+            return set;
+        });
+    }
 }

+ 1 - 1
fs-service-system/src/main/java/com/fs/company/cache/impl/ICompanyCacheServiceImpl.java

@@ -23,7 +23,7 @@ public class ICompanyCacheServiceImpl implements ICompanyCacheService {
             .build();
     private static final Cache<Long, String> COMPANY_NAME_CACHE = Caffeine.newBuilder()
             .maximumSize(1000)
-            .expireAfterWrite(3, TimeUnit.MINUTES)
+            .expireAfterWrite(7, TimeUnit.DAYS)
             .build();
     @Override
     public Company selectCompanyById(Long companyId) {

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

@@ -42,5 +42,6 @@ public class CompanyMoneyLogs extends BaseEntity
     private String businessId;
 
     private Integer type;
+    private String imgs;
 
 }

+ 4 - 149
fs-service-system/src/main/java/com/fs/company/domain/CompanyRecharge.java

@@ -5,15 +5,17 @@ import java.util.Date;
 import com.fasterxml.jackson.annotation.JsonFormat;
 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;
 
 /**
  * 充值对象 company_recharge
- * 
+ *
  * @author fs
  * @date 2023-02-27
  */
+@Data
 public class CompanyRecharge extends BaseEntity
 {
     private static final long serialVersionUID = 1L;
@@ -72,152 +74,5 @@ public class CompanyRecharge extends BaseEntity
     private Date auditTime;
 
     private String remark;
-
-    @Override
-    public String getRemark() {
-        return remark;
-    }
-
-    @Override
-    public void setRemark(String remark) {
-        this.remark = remark;
-    }
-
-    public void setRechargeId(Long rechargeId)
-    {
-        this.rechargeId = rechargeId;
-    }
-
-    public Long getRechargeId() 
-    {
-        return rechargeId;
-    }
-    public void setCompanyId(Long companyId) 
-    {
-        this.companyId = companyId;
-    }
-
-    public Long getCompanyId() 
-    {
-        return companyId;
-    }
-    public void setRechargeNo(String rechargeNo) 
-    {
-        this.rechargeNo = rechargeNo;
-    }
-
-    public String getRechargeNo() 
-    {
-        return rechargeNo;
-    }
-    public void setMoney(BigDecimal money) 
-    {
-        this.money = money;
-    }
-
-    public BigDecimal getMoney() 
-    {
-        return money;
-    }
-    public void setPayTime(Date payTime) 
-    {
-        this.payTime = payTime;
-    }
-
-    public Date getPayTime() 
-    {
-        return payTime;
-    }
-    public void setStatus(Integer status) 
-    {
-        this.status = status;
-    }
-
-    public Integer getStatus() 
-    {
-        return status;
-    }
-    public void setPayType(Integer payType) 
-    {
-        this.payType = payType;
-    }
-
-    public Integer getPayType() 
-    {
-        return payType;
-    }
-    public void setTradeNo(String tradeNo) 
-    {
-        this.tradeNo = tradeNo;
-    }
-
-    public String getTradeNo() 
-    {
-        return tradeNo;
-    }
-    public void setBalance(BigDecimal balance) 
-    {
-        this.balance = balance;
-    }
-
-    public BigDecimal getBalance() 
-    {
-        return balance;
-    }
-    public void setCreateUserId(Long createUserId) 
-    {
-        this.createUserId = createUserId;
-    }
-
-    public Long getCreateUserId() 
-    {
-        return createUserId;
-    }
-    public void setIsAudit(Integer isAudit) 
-    {
-        this.isAudit = isAudit;
-    }
-
-    public Integer getIsAudit() 
-    {
-        return isAudit;
-    }
-    public void setAuditUserId(Long auditUserId) 
-    {
-        this.auditUserId = auditUserId;
-    }
-
-    public Long getAuditUserId() 
-    {
-        return auditUserId;
-    }
-    public void setAuditTime(Date auditTime) 
-    {
-        this.auditTime = auditTime;
-    }
-
-    public Date getAuditTime() 
-    {
-        return auditTime;
-    }
-
-    @Override
-    public String toString() {
-        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
-            .append("rechargeId", getRechargeId())
-            .append("companyId", getCompanyId())
-            .append("rechargeNo", getRechargeNo())
-            .append("money", getMoney())
-            .append("createTime", getCreateTime())
-            .append("payTime", getPayTime())
-            .append("status", getStatus())
-            .append("payType", getPayType())
-            .append("tradeNo", getTradeNo())
-            .append("balance", getBalance())
-            .append("createUserId", getCreateUserId())
-            .append("isAudit", getIsAudit())
-            .append("auditUserId", getAuditUserId())
-            .append("auditTime", getAuditTime())
-            .toString();
-    }
+    private String imgs;
 }

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

@@ -158,7 +158,6 @@ public class CompanyUser extends BaseEntity
     }
 
     @NotBlank(message = "二级域名不能为空")
-    @Pattern(regexp = "^(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,})|(?:\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}))$", message = "域名格式不正确")
     public String getDomain() {
         return domain;
     }

+ 13 - 0
fs-service-system/src/main/java/com/fs/company/dto/CompanyIdAndUserDTO.java

@@ -0,0 +1,13 @@
+package com.fs.company.dto;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+
+@EqualsAndHashCode
+@Data
+public class CompanyIdAndUserDTO implements Serializable {
+    private Long companyId;
+    private Long companyUserId;
+}

+ 11 - 2
fs-service-system/src/main/java/com/fs/company/mapper/CompanyMapper.java

@@ -1,7 +1,5 @@
 package com.fs.company.mapper;
 
-import java.math.BigDecimal;
-import java.util.List;
 import com.fs.company.domain.Company;
 import com.fs.company.param.CompanyParam;
 import com.fs.company.vo.CompanyCrmVO;
@@ -12,6 +10,10 @@ import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
 
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+
 /**
  * 企业Mapper接口
  *
@@ -146,4 +148,11 @@ public interface CompanyMapper
     List<OptionsVO> selectAllCompanyList();
 
     void updateMoney(@Param("id") Long id, @Param("money") BigDecimal money);
+
+    /**
+     * 根据条件查询公司选项列表
+     * @param params    参数
+     * @return list
+     */
+    List<OptionsVO> selectCompanyListByMap(@Param("params") Map<String, Object> params);
 }

+ 14 - 8
fs-service-system/src/main/java/com/fs/company/mapper/CompanyTagMapper.java

@@ -4,19 +4,21 @@ import java.util.List;
 import java.util.Map;
 
 import com.fs.company.domain.CompanyTag;
+import com.fs.company.dto.CompanyIdAndUserDTO;
+import org.apache.ibatis.annotations.MapKey;
 import org.apache.ibatis.annotations.Param;
 
 /**
  * companyMapper接口
- * 
+ *
  * @author fs
  * @date 2025-04-02
  */
-public interface CompanyTagMapper 
+public interface CompanyTagMapper
 {
     /**
      * 查询company
-     * 
+     *
      * @param tagId companyID
      * @return company
      */
@@ -24,7 +26,7 @@ public interface CompanyTagMapper
 
     /**
      * 查询company列表
-     * 
+     *
      * @param companyTag company
      * @return company集合
      */
@@ -32,7 +34,7 @@ public interface CompanyTagMapper
 
     /**
      * 新增company
-     * 
+     *
      * @param companyTag company
      * @return 结果
      */
@@ -40,7 +42,7 @@ public interface CompanyTagMapper
 
     /**
      * 修改company
-     * 
+     *
      * @param companyTag company
      * @return 结果
      */
@@ -48,7 +50,7 @@ public interface CompanyTagMapper
 
     /**
      * 删除company
-     * 
+     *
      * @param tagId companyID
      * @return 结果
      */
@@ -56,7 +58,7 @@ public interface CompanyTagMapper
 
     /**
      * 批量删除company
-     * 
+     *
      * @param tagIds 需要删除的数据ID
      * @return 结果
      */
@@ -75,4 +77,8 @@ public interface CompanyTagMapper
      * @return  list
      */
     List<CompanyTag> selectCompanyTagListByUserId(@Param("userId") Long userId);
+
+    String findUserTagByUserId(@Param("userId") Long userId);
+    @MapKey("tag_id")
+    Map<Long,String> queryAllTagMap();
 }

+ 14 - 2
fs-service-system/src/main/java/com/fs/company/mapper/CompanyUserMapper.java

@@ -7,6 +7,7 @@ import com.fs.company.vo.CompanyQwUserByIdsVo;
 import com.fs.company.vo.CompanyUserQwListVO;
 import com.fs.company.vo.CompanyUserVO;
 import com.fs.company.vo.DocCompanyUserVO;
+import com.fs.his.vo.OptionsVO;
 import com.fs.qw.param.QwWatchLogStatisticsListParam;
 import com.fs.qw.vo.CompanyUserQwVO;
 import com.fs.qw.vo.QwUserVO;
@@ -16,6 +17,7 @@ import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
 
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -91,7 +93,7 @@ public interface CompanyUserMapper
     int resetUserPwdByUserId( @Param("userId")Long userId, @Param("password") String encryptPassword);
 
     List<CompanyUser> selectAllUsersList(CompanyUser user);
-//    @Select({"<script> " +
+    //    @Select({"<script> " +
 //            "select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,u.open_id,u.id_card, d.dept_name, d.leader from company_user u\n" +
 //            "        left join company_dept d on u.dept_id = d.dept_id\n" +
 //            "        where u.del_flag = '0' and u.status=0\n" +
@@ -134,7 +136,7 @@ public interface CompanyUserMapper
     @Select("select u.* from company_user u   where u.company_id=#{companyId} and u.nick_name=#{nickName} limit 1 ")
     CompanyUser selectCompanyUserByCompanyIdAndNickName(@Param("companyId")long companyId,@Param("nickName") String nickName);
 
-//    @Select({"<script> " +
+    //    @Select({"<script> " +
 //            "select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,u.open_id,u.id_card, d.dept_name, d.leader ,\n" +
 //            "        (select count(1) from crm_customer cc where u.user_id= cc.receive_user_id and date_format(cc.receive_time,'%y%m%d') = date_format(now(),'%y%m%d')  ) as now_day_customer_count\n" +
 //            "        from company_user u\n" +
@@ -279,4 +281,14 @@ public interface CompanyUserMapper
     @Select("select * from company_user where phonenumber = #{phoneNumber}")
     CompanyUser getCompanyUserByPhone(String phoneNumber);
 
+    /**
+     * 查询销售选项列表
+     * @param params    参数
+     * @return  list
+     */
+    List<OptionsVO> selectCompanyUserListByMap(@Param("params") Map<String, Object> params);
+
+    List<Long> selectUserAllCompanyUserId(@Param("companyUserId") Long companyUserId);
+
+    String selectCompanyUserNameUserById(@Param("userId") Long userId);
 }

+ 1 - 0
fs-service-system/src/main/java/com/fs/company/param/CompanyRechargeParam.java

@@ -16,5 +16,6 @@ public class CompanyRechargeParam implements Serializable
     private BigDecimal money;
 
     private String remark;
+    private String imgs;
 
 }

+ 12 - 5
fs-service-system/src/main/java/com/fs/company/service/ICompanyService.java

@@ -1,18 +1,18 @@
 package com.fs.company.service;
 
-import java.math.BigDecimal;
-import java.util.List;
-import java.util.Map;
-
 import com.fs.common.core.domain.R;
 import com.fs.company.domain.Company;
 import com.fs.company.param.CompanyParam;
 import com.fs.company.vo.CompanyCrmVO;
 import com.fs.company.vo.CompanyNameVO;
 import com.fs.company.vo.CompanyVO;
+import com.fs.his.vo.OptionsVO;
 import com.fs.store.domain.FsStoreOrder;
 import com.fs.store.domain.FsStorePayment;
-import com.fs.his.vo.OptionsVO;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
 
 /**
  * 企业Service接口
@@ -107,4 +107,11 @@ public interface ICompanyService
     void updateMoney(Long companyId, BigDecimal money);
 
     void configUserCheck(Long companyId, Integer userIsDefaultBlack);
+
+    /**
+     * 根据条件查询公司选项列表
+     * @param params    参数
+     * @return list
+     */
+    List<OptionsVO> selectCompanyListByMap(Map<String, Object> params);
 }

+ 14 - 8
fs-service-system/src/main/java/com/fs/company/service/ICompanyTagService.java

@@ -4,18 +4,20 @@ import java.util.List;
 import java.util.Map;
 
 import com.fs.company.domain.CompanyTag;
+import com.fs.company.dto.CompanyIdAndUserDTO;
+import org.apache.ibatis.annotations.MapKey;
 
 /**
  * companyService接口
- * 
+ *
  * @author fs
  * @date 2025-04-02
  */
-public interface ICompanyTagService 
+public interface ICompanyTagService
 {
     /**
      * 查询company
-     * 
+     *
      * @param tagId companyID
      * @return company
      */
@@ -23,7 +25,7 @@ public interface ICompanyTagService
 
     /**
      * 查询company列表
-     * 
+     *
      * @param companyTag company
      * @return company集合
      */
@@ -31,7 +33,7 @@ public interface ICompanyTagService
 
     /**
      * 新增company
-     * 
+     *
      * @param companyTag company
      * @return 结果
      */
@@ -39,7 +41,7 @@ public interface ICompanyTagService
 
     /**
      * 修改company
-     * 
+     *
      * @param companyTag company
      * @return 结果
      */
@@ -47,7 +49,7 @@ public interface ICompanyTagService
 
     /**
      * 批量删除company
-     * 
+     *
      * @param tagIds 需要删除的companyID
      * @return 结果
      */
@@ -55,7 +57,7 @@ public interface ICompanyTagService
 
     /**
      * 删除company信息
-     * 
+     *
      * @param tagId companyID
      * @return 结果
      */
@@ -73,4 +75,8 @@ public interface ICompanyTagService
      * @return list
      */
     List<CompanyTag> selectCompanyTagListByMap(Map<String, Object> params);
+
+    Map<Long,String> queryAllTagMap();
+
+    String findUserTagByUserId(Long key);
 }

+ 18 - 1
fs-service-system/src/main/java/com/fs/company/service/ICompanyUserService.java

@@ -9,9 +9,9 @@ import com.fs.company.vo.CompanyUserQwListVO;
 import com.fs.company.vo.CompanyUserVO;
 import com.fs.company.vo.DocCompanyUserVO;
 import com.fs.his.vo.CitysAreaVO;
+import com.fs.his.vo.OptionsVO;
 import com.fs.qw.vo.CompanyUserQwVO;
 import com.fs.qw.vo.QwUserVO;
-import com.fs.his.vo.OptionsVO;
 
 import java.util.List;
 import java.util.Map;
@@ -31,6 +31,9 @@ public interface ICompanyUserService {
      * @return 物业公司管理员信息
      */
     public CompanyUser selectCompanyUserById(Long userId);
+    public String selectCompanyUserNameUserById(Long userId);
+
+    public List<Long> selectUserAllCompanyUserId(Long companyUserId);
 
     /**
      * 查询物业公司管理员信息列表
@@ -174,4 +177,18 @@ public interface ICompanyUserService {
      * @return
      */
     CompanyUser getCompanyUserByPhone(String phoneNumber);
+
+    /**
+     * 更改会员归属
+     * @param userIds
+     * @return
+     */
+    int changeCompanyUser(List<Long> userIds, Long companyUserId, Long companyId);
+
+    /**
+     * 查询销售选项列表
+     * @param params    参数
+     * @return  list
+     */
+    List<OptionsVO> selectCompanyUserListByMap(Map<String, Object> params);
 }

+ 10 - 9
fs-service-system/src/main/java/com/fs/company/service/impl/CompanyRoleServiceImpl.java

@@ -20,7 +20,7 @@ import java.util.*;
 
 /**
  * 角色信息Service业务层处理
- * 
+ *
  * @author fs
  * @date 2021-05-25
  */
@@ -37,7 +37,7 @@ public class CompanyRoleServiceImpl implements ICompanyRoleService
     private CompanyUserRoleMapper userRoleMapper;
     /**
      * 查询角色信息
-     * 
+     *
      * @param roleId 角色信息ID
      * @return 角色信息
      */
@@ -49,7 +49,7 @@ public class CompanyRoleServiceImpl implements ICompanyRoleService
 
     /**
      * 查询角色信息列表
-     * 
+     *
      * @param companyRole 角色信息
      * @return 角色信息
      */
@@ -61,7 +61,7 @@ public class CompanyRoleServiceImpl implements ICompanyRoleService
 
     /**
      * 新增角色信息
-     * 
+     *
      * @param companyRole 角色信息
      * @return 结果
      */
@@ -74,7 +74,7 @@ public class CompanyRoleServiceImpl implements ICompanyRoleService
 
     /**
      * 修改角色信息
-     * 
+     *
      * @param companyRole 角色信息
      * @return 结果
      */
@@ -87,7 +87,7 @@ public class CompanyRoleServiceImpl implements ICompanyRoleService
 
     /**
      * 批量删除角色信息
-     * 
+     *
      * @param roleIds 需要删除的角色信息ID
      * @return 结果
      */
@@ -99,7 +99,7 @@ public class CompanyRoleServiceImpl implements ICompanyRoleService
 
     /**
      * 删除角色信息信息
-     * 
+     *
      * @param roleId 角色信息ID
      * @return 结果
      */
@@ -126,9 +126,10 @@ public class CompanyRoleServiceImpl implements ICompanyRoleService
 
     @Override
     public String checkRoleNameUnique(CompanyRole role) {
-        Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
+        long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
+        long companyId = StringUtils.isNull(role.getCompanyId()) ? -1L : role.getCompanyId();
         CompanyRole info = companyRoleMapper.checkRoleNameUnique(role.getRoleName());
-        if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue())
+        if (StringUtils.isNotNull(info) && info.getRoleId() != roleId && info.getCompanyId() != companyId)
         {
             return UserConstants.NOT_UNIQUE;
         }

+ 17 - 5
fs-service-system/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java

@@ -1,32 +1,34 @@
 package com.fs.company.service.impl;
 
-import java.math.BigDecimal;
-import java.util.*;
-
 import cn.hutool.json.JSONUtil;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
 import com.fs.company.domain.*;
 import com.fs.company.mapper.*;
 import com.fs.company.param.CompanyParam;
+import com.fs.company.service.ICompanyService;
 import com.fs.company.vo.CompanyCrmVO;
 import com.fs.company.vo.CompanyNameVO;
 import com.fs.company.vo.CompanyVO;
 import com.fs.course.mapper.FsCourseRedPacketLogMapper;
+import com.fs.his.vo.OptionsVO;
 import com.fs.store.config.StoreConfig;
 import com.fs.store.domain.FsStoreOrder;
 import com.fs.store.domain.FsStorePayment;
 import com.fs.store.mapper.FsStoreOrderMapper;
-import com.fs.his.vo.OptionsVO;
 import com.fs.system.service.ISysConfigService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
-import com.fs.company.service.ICompanyService;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
 /**
  * 企业Service业务层处理
  *
@@ -447,4 +449,14 @@ public class CompanyServiceImpl implements ICompanyService
             companyMapper.updateCompany(company);
         }
     }
+
+    /**
+     * 根据条件查询公司选项列表
+     * @param params    参数
+     * @return list
+     */
+    @Override
+    public List<OptionsVO> selectCompanyListByMap(Map<String, Object> params) {
+        return companyMapper.selectCompanyListByMap(params);
+    }
 }

+ 19 - 8
fs-service-system/src/main/java/com/fs/company/service/impl/CompanyTagServiceImpl.java

@@ -5,6 +5,7 @@ import java.util.List;
 import java.util.Map;
 
 import com.fs.common.utils.DateUtils;
+import com.fs.company.dto.CompanyIdAndUserDTO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.fs.company.mapper.CompanyTagMapper;
@@ -13,19 +14,19 @@ import com.fs.company.service.ICompanyTagService;
 
 /**
  * companyService业务层处理
- * 
+ *
  * @author fs
  * @date 2025-04-02
  */
 @Service
-public class CompanyTagServiceImpl implements ICompanyTagService 
+public class CompanyTagServiceImpl implements ICompanyTagService
 {
     @Autowired
     private CompanyTagMapper companyTagMapper;
 
     /**
      * 查询company
-     * 
+     *
      * @param tagId companyID
      * @return company
      */
@@ -37,7 +38,7 @@ public class CompanyTagServiceImpl implements ICompanyTagService
 
     /**
      * 查询company列表
-     * 
+     *
      * @param companyTag company
      * @return company
      */
@@ -49,7 +50,7 @@ public class CompanyTagServiceImpl implements ICompanyTagService
 
     /**
      * 新增company
-     * 
+     *
      * @param companyTag company
      * @return 结果
      */
@@ -62,7 +63,7 @@ public class CompanyTagServiceImpl implements ICompanyTagService
 
     /**
      * 修改company
-     * 
+     *
      * @param companyTag company
      * @return 结果
      */
@@ -74,7 +75,7 @@ public class CompanyTagServiceImpl implements ICompanyTagService
 
     /**
      * 批量删除company
-     * 
+     *
      * @param tagIds 需要删除的companyID
      * @return 结果
      */
@@ -86,7 +87,7 @@ public class CompanyTagServiceImpl implements ICompanyTagService
 
     /**
      * 删除company信息
-     * 
+     *
      * @param tagId companyID
      * @return 结果
      */
@@ -117,4 +118,14 @@ public class CompanyTagServiceImpl implements ICompanyTagService
     public List<CompanyTag> selectCompanyTagListByMap(Map<String, Object> params) {
         return companyTagMapper.selectCompanyTagListByMap(params);
     }
+
+    @Override
+    public Map<Long, String> queryAllTagMap() {
+        return companyTagMapper.queryAllTagMap();
+    }
+
+    @Override
+    public String findUserTagByUserId(Long key) {
+        return companyTagMapper.findUserTagByUserId(key);
+    }
 }

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

@@ -1,20 +1,27 @@
 package com.fs.company.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.annotation.DataScope;
 import com.fs.common.core.domain.R;
+import com.fs.common.exception.ServiceException;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.*;
 import com.fs.company.mapper.*;
 import com.fs.company.param.CompanyUserAreaParam;
 import com.fs.company.param.CompanyUserQwParam;
-import com.fs.company.param.CompanyVoiceCallerParam;
 import com.fs.company.service.ICompanyUserService;
-import com.fs.company.vo.*;
+import com.fs.company.vo.CompanyQwUserByIdsVo;
+import com.fs.company.vo.CompanyUserQwListVO;
+import com.fs.company.vo.CompanyUserVO;
+import com.fs.company.vo.DocCompanyUserVO;
 import com.fs.his.vo.CitysAreaVO;
+import com.fs.his.vo.OptionsVO;
 import com.fs.qw.vo.CompanyUserQwVO;
 import com.fs.qw.vo.QwUserVO;
 import com.fs.his.vo.OptionsVO;
+import com.fs.store.mapper.FsUserMapper;
 import com.fs.store.service.IFsCityService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -52,6 +59,9 @@ public class CompanyUserServiceImpl implements ICompanyUserService
     @Autowired
     public IFsCityService iFsCityService;
 
+    @Autowired
+    private FsUserMapper fsUserMapper;
+
     /**
      * 查询物业公司管理员信息
      *
@@ -64,6 +74,16 @@ public class CompanyUserServiceImpl implements ICompanyUserService
         return companyUserMapper.selectCompanyUserById(userId);
     }
 
+    @Override
+    public String selectCompanyUserNameUserById(Long userId) {
+        return companyUserMapper.selectCompanyUserNameUserById(userId);
+    }
+
+    @Override
+    public List<Long> selectUserAllCompanyUserId(Long companyUserId) {
+        return companyUserMapper.selectUserAllCompanyUserId(companyUserId);
+    }
+
     /**
      * 查询物业公司管理员信息列表
      *
@@ -444,6 +464,26 @@ public class CompanyUserServiceImpl implements ICompanyUserService
         return companyUserMapper.getCompanyUserByPhone(phoneNumber);
     }
 
+    @Override
+    public int changeCompanyUser(List<Long> userIds, Long companyUserId, Long companyId) {
+
+        CompanyUser toUser = companyUserMapper.selectCompanyUserById(companyUserId);
+        if (Objects.isNull(toUser)) {
+            throw new ServiceException("需要更换归属的销售不存在");
+        }
+        return fsUserMapper.batchUpdateUserCompanyUser(userIds, companyUserId, companyId);
+    }
+
+    /**
+     * 查询销售选项列表
+     * @param params    参数
+     * @return  list
+     */
+    @Override
+    public List<OptionsVO> selectCompanyUserListByMap(Map<String, Object> params) {
+        return companyUserMapper.selectCompanyUserListByMap(params);
+    }
+
     /**
      * 批量审核用户
      * @param userIds 用户ID集合

+ 2 - 1
fs-service-system/src/main/java/com/fs/company/vo/CompanyRechargeVO.java

@@ -13,7 +13,7 @@ import java.util.Date;
 
 /**
  * 充值对象 company_recharge
- * 
+ *
  * @author fs
  * @date 2021-10-04
  */
@@ -67,6 +67,7 @@ public class CompanyRechargeVO implements Serializable {
     private String createUserNickName;
 
     private String auditUserNickName;
+    private String imgs;
 
 }
 

+ 6 - 2
fs-service-system/src/main/java/com/fs/course/domain/FsCourseLink.java

@@ -2,6 +2,7 @@ package com.fs.course.domain;
 
 import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 /**
@@ -48,8 +49,8 @@ public class FsCourseLink extends BaseEntity
 
     private Long courseId;
     /**
-    * 企微外部联系表主键
-    */
+     * 企微外部联系表主键
+     */
     private Long qwExternalId;
 
     private Integer linkType; //链接类型 0:正常链接  1:应急链接
@@ -62,4 +63,7 @@ public class FsCourseLink extends BaseEntity
     @Excel(name = "营期id")
     private Long periodId;
 
+    @ApiModelProperty(value = "营期课程id")
+    private Long id;
+
 }

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

@@ -42,4 +42,5 @@ public class FsCourseQuestionBank extends BaseEntity
     @Excel(name = "答案")
     private String answer;
     private Long questionType;
+    private Long questionSubType;
 }

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

@@ -1,5 +1,6 @@
 package com.fs.course.domain;
 
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -38,4 +39,7 @@ public class FsCourseRealLink implements Serializable
 
     private Long periodId;
 
+    @ApiModelProperty(value = "营期课程id")
+    private Long id;
+
 }

+ 3 - 0
fs-service-system/src/main/java/com/fs/course/domain/FsCourseWatchLog.java

@@ -85,4 +85,7 @@ public class FsCourseWatchLog extends BaseEntity
     /** 营期id */
     private Long periodId;
 
+    /** 项目id */
+    private Long project;
+
 }

+ 23 - 2
fs-service-system/src/main/java/com/fs/course/domain/FsUserCoursePeriod.java

@@ -2,6 +2,7 @@ package com.fs.course.domain;
 
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.LocalTime;
 import java.util.Date;
 import java.util.List;
 
@@ -9,8 +10,6 @@ import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import lombok.Data;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
 
 /**
  * 会员营期对象 fs_user_course_period
@@ -23,6 +22,12 @@ public class FsUserCoursePeriod
 {
     private static final long serialVersionUID = 1L;
 
+    @TableField(exist = false)
+    private Integer pageNum;
+
+    @TableField(exist = false)
+    private Integer pageSize;
+
     /** 营期id */
     private Long periodId;
 
@@ -74,6 +79,22 @@ public class FsUserCoursePeriod
     @Excel(name = "开营日期-结束时间", width = 30, dateFormat = "yyyy-MM-dd")
     private LocalDate periodEndTime;
 
+    /** 营期状态,1-未开始,2-进行中,3-已结束 */
+    @Excel(name = "营期状态,1-未开始,2-进行中,3-已结束")
+    private Long periodStatus;
+
+    @JsonFormat(pattern = "HH:mm:ss")
+    @Excel(name = "开始看课时间")
+    private LocalTime viewStartTime;
+
+    @JsonFormat(pattern = "HH:mm:ss")
+    @Excel(name = "结束看课时间")
+    private LocalTime viewEndTime;
+
+    @JsonFormat(pattern = "HH:mm:ss")
+    @Excel(name = "领取红包结束时间")
+    private LocalTime lastJoinTime;
+
     @TableField(exist = false)
     private List<Long> companyIdList;
 }

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

@@ -3,6 +3,7 @@ package com.fs.course.domain;
 import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.LocalTime;
 import java.util.Date;
 import java.util.List;
 
@@ -47,11 +48,15 @@ public class FsUserCoursePeriodDays extends BaseEntityTow {
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime startDateTime;
-
     /** 结束时间 */
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime endDateTime;
+    /** 领取红包时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "领取红包时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime lastJoinTime;
+
 
     /** 课程ID */
     @Excel(name = "课程ID")
@@ -75,4 +80,10 @@ public class FsUserCoursePeriodDays extends BaseEntityTow {
     private String courseName;
     @TableField(exist = false)
     private String videoName;
+    @TableField(exist = false)
+    private LocalTime startTime;
+    @TableField(exist = false)
+    private LocalTime endTime1;
+    @TableField(exist = false)
+    private LocalTime joinTime;
 }

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

@@ -27,6 +27,11 @@ public class FsVideoResource {
      */
     private Long typeId;
 
+    /**
+     * 子分类ID
+     */
+    private Long typeSubId;
+
     /**
      * 文件名称
      */

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

@@ -80,11 +80,20 @@ public interface FsCourseTrafficLogMapper
      * @return Long
      */
     Long getTodayTrafficLog();
+    Long getTodayTrafficLogCompanyId(@Param("companyId") Long companyId);
 
     /**
      * 获取当月统计流量
      * @return Long
      */
     Long getMonthTrafficLog();
+    Long getMonthTrafficLogCompanyId(@Param("companyId") Long companyId);
+
+    /**
+     * 昨天
+     * @return Long
+     */
+    Long getYesterdayTrafficLog();
+    Long getYesterdayTrafficLogCompanyId(@Param("companyId") Long companyId);
 
 }

+ 6 - 4
fs-service-system/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java

@@ -98,8 +98,8 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
     //临时看课记录
     @Select("select * from fs_course_watch_log where user_id = #{userId} and video_id = #{videoId} and company_user_id = #{companyUserId}")
     FsCourseWatchLog getWatchLogByTemporary(@Param("userId") Long userId,
-                                          @Param("videoId") Long videoId,
-                                          @Param("companyUserId") Long companyUserId);
+                                            @Param("videoId") Long videoId,
+                                            @Param("companyUserId") Long companyUserId);
 
     @Select("select * from fs_course_watch_log " +
             "where user_id = #{userId} " +
@@ -301,13 +301,13 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
     @Select("select log_id from fs_course_watch_log where create_time < '2025-03-01'")
     List<Long> selectFsCourseWatchLogByLastmonth();
 
-    FsCourseWatchLog getWatchLogByFsUser(@Param("videoId") Long videoId, @Param("fsUserId") Long fsUserId);
+    FsCourseWatchLog getWatchLogByFsUser(@Param("videoId") Long videoId, @Param("fsUserId") Long fsUserId, @Param("companyUserId") Long companyUserId);
 
     @Select("select * from fs_course_watch_log " +
             "where video_id = #{videoId} " +
             "and company_user_id = #{companyUserId} " +
             "and user_id = #{userId} and send_type = 1 ")
-    FsCourseWatchLog getWatchCourseVideoByFsUser(Long userId, Long videoId, Long companyUserId);
+    FsCourseWatchLog getWatchCourseVideoByFsUser(@Param("userId") Long userId, @Param("videoId") Long videoId, @Param("companyUserId") Long companyUserId);
 
     /**
      * 聚合查询
@@ -318,4 +318,6 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
      */
     @Select("select count(log_id) AS watchCount, count(case when log_type = 2 then log_id end) AS finishCount, sum(duration) AS watchTime from fs_course_watch_log where user_id = #{userId} and video_id = #{videoId}")
     Map<String, Object> selectSumByUserIdAndVideoId(@Param("userId") Long userId, @Param("videoId") Long videoId);
+
+    void batchUpdateFsUserWatchLog(@Param("list") List<FsCourseWatchLog> logs);
 }

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

@@ -1,8 +1,5 @@
 package com.fs.course.mapper;
 
-import java.util.List;
-import java.util.Map;
-
 import com.fs.course.domain.FsUserCourse;
 import com.fs.course.param.FsUserCourseAddStudyCourseParam;
 import com.fs.course.param.FsUserCourseListUParam;
@@ -15,6 +12,9 @@ import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
 
+import java.util.List;
+import java.util.Map;
+
 /**
  * 课程Mapper接口
  *

+ 29 - 4
fs-service-system/src/main/java/com/fs/course/mapper/FsUserCoursePeriodDaysMapper.java

@@ -1,12 +1,14 @@
 package com.fs.course.mapper;
 
-import java.util.List;
-import java.util.Set;
-
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.course.domain.FsUserCoursePeriodDays;
+import com.fs.his.vo.OptionsVO;
 import org.apache.ibatis.annotations.Param;
-import org.apache.ibatis.annotations.Select;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * 营期课程Mapper接口
@@ -70,4 +72,27 @@ public interface FsUserCoursePeriodDaysMapper extends BaseMapper<FsUserCoursePer
      */
     List<FsUserCoursePeriodDays> selectCourseVideoList(@Param("periodIds") Set<Long> periodIds);
 
+    /**
+     * 查询营期选项列表
+     * @param params    参数
+     * @return  list
+     */
+    List<OptionsVO> selectPeriodListByMap(@Param("params") Map<String, Object> params);
+    /**
+     * 批量修改
+     * @param fsUserCoursePeriodDaysList
+     */
+    void batchUpdateCoursePeriodDays(List<FsUserCoursePeriodDays> fsUserCoursePeriodDaysList);
+
+    /**
+     * 开启课程
+     * @param now  时间
+     */
+    void startPeriodCourse(@Param("now") LocalDateTime now);
+
+    /**
+     * 关闭课程
+     * @param now  时间
+     */
+    void endPeriodCourse(@Param("now") LocalDateTime now);
 }

+ 28 - 5
fs-service-system/src/main/java/com/fs/course/mapper/FsUserCoursePeriodMapper.java

@@ -1,14 +1,17 @@
 package com.fs.course.mapper;
 
-import java.util.List;
-import java.util.Set;
-
 import com.fs.course.domain.FsUserCoursePeriod;
 import com.fs.course.param.CompanyRedPacketParam;
-import com.fs.course.param.PeriodRedPacketParam;
 import com.fs.course.vo.FsUserCoursePeriodVO;
+import com.fs.course.vo.PeriodRedPacketVO;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * 会员营期Mapper接口
@@ -95,7 +98,7 @@ public interface FsUserCoursePeriodMapper
      */
     List<CompanyRedPacketParam> selectCompanyByPeriod(@Param("periodId")Long periodId);
 
-    List<PeriodRedPacketParam> selectPeriodRedPacket(@Param("periodId")Long periodId, @Param("companyId")Long companyId);
+    List<PeriodRedPacketVO> selectPeriodRedPacket(@Param("periodId")Long periodId, @Param("companyId")Long companyId);
 
     /**
      * 根据营期ids批量获取营期数据
@@ -104,4 +107,24 @@ public interface FsUserCoursePeriodMapper
      */
     List<FsUserCoursePeriod> selectFsUserCoursePeriodsByIds(@Param("periodIds") Set<Long> periodIds);
 
+    /**
+     * 查询训练营进行中的营期条数
+     * @param params    参数
+     * @return  count
+     */
+    int countPeriodByCampIds(@Param("params") Map<String, Object> params);
+
+    /**
+     * 开营
+     * @param now   当前日期
+     */
+    @Update("update fs_user_course_period set period_status = 2, update_time = now() where period_status = 1 and period_starting_time >= #{now}")
+    void startPeriod(@Param("now") LocalDate now);
+
+    /**
+     * 关营
+     * @param now   当前日期
+     */
+    @Update("update fs_user_course_period set period_status = 3, update_time = now() where period_status = 2 and period_end_time < #{now}")
+    void endPeriod(@Param("now") LocalDate now);
 }

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

@@ -4,6 +4,7 @@ package com.fs.course.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.course.domain.FsUserCourseTrainingCamp;
 import com.fs.course.vo.FsUserCourseTrainingCampVO;
+import com.fs.his.vo.OptionsVO;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 
@@ -32,4 +33,11 @@ public interface FsUserCourseTrainingCampMapper extends BaseMapper<FsUserCourseT
      */
     @Select("select ifnull(max(order_number), 0) + 1 from fs_user_course_training_camp")
     Long getOrderNumber();
+
+    /**
+     * 查询训练营选项列表
+     * @param params    参数
+     * @return  list
+     */
+    List<OptionsVO> selectCampListByMap(@Param("params") Map<String, Object> params);
 }

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

@@ -1,8 +1,5 @@
 package com.fs.course.mapper;
 
-import java.util.List;
-import java.util.Map;
-
 import com.fs.course.domain.FsUserCourseVideo;
 import com.fs.course.param.CourseVideoUpdates;
 import com.fs.course.param.FsUserCourseVideoListUParam;
@@ -15,6 +12,10 @@ import com.fs.his.vo.OptionsVO;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+
 /**
  * 课堂视频Mapper接口
  *
@@ -170,4 +171,13 @@ public interface FsUserCourseVideoMapper
     void updates(CourseVideoUpdates vo);
 
     void insertBatchFsUserCourseVideo(@Param("collect") List<FsUserCourseVideo> collect);
+
+    void updateRedPacketMoney(@Param("videoId") Long videoId, @Param("redPacketMoney") BigDecimal redPacketMoney);
+
+    /**
+     * 获取选项列表
+     * @param params    参数
+     * @return  list
+     */
+    List<OptionsVO> selectVideoListByMap(@Param("params") Map<String, Object> params);
 }

+ 4 - 2
fs-service-system/src/main/java/com/fs/course/mapper/FsUserCourseVideoRedPackageMapper.java

@@ -68,8 +68,8 @@ public interface FsUserCourseVideoRedPackageMapper
             "ON DUPLICATE KEY UPDATE red_packet_money = VALUES(red_packet_money);")
     void insertOrUpdateFsUserCourseVideoRedPackage(FsUserCourseVideoParam fsUserCourseVideo);
 
-    @Select("select * from fs_user_course_video_red_package where video_id =#{videoId} and company_id = #{companyId}")
-    FsUserCourseVideoRedPackage selectRedPacketByCompanyId(@Param("videoId") Long videoId,@Param("companyId") Long companyId);
+    @Select("select * from fs_user_course_video_red_package where video_id =#{videoId} and company_id = #{companyId} and period_id = #{periodId}")
+    FsUserCourseVideoRedPackage selectRedPacketByCompanyId(@Param("videoId") Long videoId,@Param("companyId") Long companyId, @Param("periodId") Long periodId);
 
     int batchSaveFsUserCourseVideoRedPackage(@Param("list") List<FsUserCourseVideoRedPackage> redPackageList);
 
@@ -95,4 +95,6 @@ public interface FsUserCourseVideoRedPackageMapper
     List<FsUserCourseVideoRedPackage> selectByParamsList(@Param("list") List<FsUserCourseVideoRedPackage> list);
 
     int updateRedPackageByParams(FsUserCourseVideoRedPackage videoRedPackage);
+
+    List<FsUserCourseVideoRedPackage> selectByRuleIds(@Param("ruleIds") List<Long> ruleIds);
 }

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

@@ -81,5 +81,5 @@ public interface HyWatchLogMapper {
             "FROM hy_watch_log WHERE status = #{status}")
     List<HyWatchLog> selectByStatus(@Param("status") Integer status);
 
-    void insertHyWatchLogBatch(List<HyWatchLog> hyWatchLogs);
+    void insertHyWatchLogBatch(@Param("hyWatchLogs") List<HyWatchLog> hyWatchLogs);
 }

+ 11 - 0
fs-service-system/src/main/java/com/fs/course/param/BatchRedUpdate.java

@@ -0,0 +1,11 @@
+package com.fs.course.param;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class BatchRedUpdate {
+    private Long videoId;
+    private BigDecimal redPacketMoney;
+}

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

@@ -3,6 +3,7 @@ package com.fs.course.param;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 
+import java.math.BigDecimal;
 import java.time.LocalTime;
 import java.util.List;
 

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

@@ -34,4 +34,7 @@ public class FsCourseLinkCreateParam {
 
     private Long periodId;
 
+    @ApiModelProperty(value = "营期课程id")
+    private Long id;
+
 }

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

@@ -25,5 +25,6 @@ public class FsCourseSendRewardUParam implements Serializable
     private Integer source=1;//来源 1:h5  2:小程序
     private Integer isRoom;
     private Integer sendType;
+    private Long periodId;
 
 }

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

@@ -1,6 +1,7 @@
 package com.fs.course.param;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.utils.DateUtils;
 import lombok.Data;
 
 import java.util.Date;
@@ -23,6 +24,17 @@ public class FsCourseWatchLogStatisticsListParam {
     @JsonFormat(pattern = "yyyy-MM-dd")
     private Date sTime;
 
+    private String startDate;
+    private String endDate;
+
+    public String getStartDate() {
+        return DateUtils.getStartOfDayString(sTime);
+    }
+
+    public String getEndDate() {
+        return DateUtils.getEndOfDayString(eTime);
+    }
+
     private Long project;
 
     private Long pageNum;

+ 3 - 0
fs-service-system/src/main/java/com/fs/course/param/newfs/FsCourseSortLinkParam.java

@@ -35,4 +35,7 @@ public class FsCourseSortLinkParam {
     @ApiModelProperty(value = "营期id")
     private Long periodId;
 
+    @ApiModelProperty(value = "营期课程id")
+    private Long id;
+
 }

+ 13 - 0
fs-service-system/src/main/java/com/fs/course/param/newfs/FsUserCourseVideoLinkParam.java

@@ -3,10 +3,12 @@ package com.fs.course.param.newfs;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import javax.validation.constraints.NotNull;
 import java.io.Serializable;
 
 @Data
 public class FsUserCourseVideoLinkParam implements Serializable {
+    @NotNull(message = "销售id不能为空")
     @ApiModelProperty(value = "视频id")
     private Long videoId;
 
@@ -18,4 +20,15 @@ public class FsUserCourseVideoLinkParam implements Serializable {
 
     @ApiModelProperty(value = "链接类型,0:正常链接;1:应急链接")
     private Integer linkType;
+
+    @NotNull(message = "销售id不能为空")
+    @ApiModelProperty(value = "销售id")
+    private Long companyUserId;
+
+    @ApiModelProperty(value = "营期课程ID")
+    private Long id;
+
+    @ApiModelProperty(value = "营期id")
+    private Long periodId;
+
 }

+ 3 - 0
fs-service-system/src/main/java/com/fs/course/param/newfs/FsUserCourseVideoUParam.java

@@ -20,4 +20,7 @@ public class FsUserCourseVideoUParam implements Serializable {
 
     private Integer linkType;
 
+    @NotNull(message = "销售id不能为空")
+    private Long companyUserId;
+
 }

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

@@ -125,5 +125,10 @@ public interface IFsCourseWatchLogService extends IService<FsCourseWatchLog> {
      * @param fsUserId
      * @return
      */
-    FsCourseWatchLog getWatchLogByFsUser(Long videoId, Long fsUserId);
+    FsCourseWatchLog getWatchLogByFsUser(Long videoId, Long fsUserId, Long companyUserId);
+
+    void scheduleUpdateDurationToDatabase();
+
+    void checkFsUserWatchStatus();
+
 }

+ 30 - 4
fs-service-system/src/main/java/com/fs/course/service/IFsUserCoursePeriodDaysService.java

@@ -1,14 +1,17 @@
 package com.fs.course.service;
 
-import java.util.List;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.common.core.domain.R;
 import com.fs.course.domain.FsUserCoursePeriodDays;
 import com.fs.course.param.CompanyRedPacketParam;
 import com.fs.course.param.PeriodCountParam;
-import com.fs.course.param.PeriodRedPacketParam;
 import com.fs.course.vo.FsPeriodCountVO;
-import com.fs.course.vo.newfs.FsCourseAnalysisCountVO;
+import com.fs.course.vo.PeriodRedPacketVO;
+import com.fs.course.vo.UpdateCourseTimeVo;
+import com.fs.his.vo.OptionsVO;
+
+import java.util.List;
+import java.util.Map;
 
 /**
  * 营期课程Service接口
@@ -83,7 +86,7 @@ public interface IFsUserCoursePeriodDaysService extends IService<FsUserCoursePer
      * @param companyId 公司id
      * @return
      */
-    List<PeriodRedPacketParam> getPeriodRedPacketList(Long periodId, Long companyId);
+    List<PeriodRedPacketVO> getPeriodRedPacketList(Long periodId, Long companyId);
 
     /**
      * 根据营期按课程统计
@@ -91,4 +94,27 @@ public interface IFsUserCoursePeriodDaysService extends IService<FsUserCoursePer
      * @return
      */
     List<FsPeriodCountVO> periodCourseCount(PeriodCountParam param);
+
+    /**
+     * 查询营期选项列表
+     * @param params    参数
+     * @return  list
+     */
+    List<OptionsVO> selectPeriodListByMap(Map<String, Object> params);
+
+    /**
+     * 上移/下移(调整课程的营期时间)
+     * @param id 当前数据
+     * @param targetId 需要移动到的数据
+     * @return
+     */
+    R periodCourseMove(Long id, Long targetId);
+
+    R updateCourseTime(UpdateCourseTimeVo vo);
+
+    R updateCourseDate(UpdateCourseTimeVo vo);
+    /**
+     * 更新营期课程状态
+     */
+    void changePeriodCourseStatus();
 }

+ 13 - 1
fs-service-system/src/main/java/com/fs/course/service/IFsUserCoursePeriodService.java

@@ -1,9 +1,10 @@
 package com.fs.course.service;
 
-import java.util.List;
 import com.fs.course.domain.FsUserCoursePeriod;
 import com.fs.course.vo.FsUserCoursePeriodVO;
 
+import java.util.List;
+
 /**
  * 会员营期Service接口
  *
@@ -66,4 +67,15 @@ public interface IFsUserCoursePeriodService
      * @return vo
      */
     List<FsUserCoursePeriodVO> selectFsUserCoursePeriodPage(FsUserCoursePeriod fsUserCoursePeriod);
+
+    /**
+     * 结束营期
+     * @param id    营期ID
+     */
+    void closePeriod(Long id);
+
+    /**
+     * 更新营期状态
+     */
+    void changePeriodStatus();
 }

+ 5 - 5
fs-service-system/src/main/java/com/fs/course/service/IFsUserCourseService.java

@@ -1,10 +1,5 @@
 package com.fs.course.service;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-import java.util.Map;
-
 import com.fs.common.core.domain.R;
 import com.fs.course.domain.FsUserCourse;
 import com.fs.course.param.*;
@@ -13,6 +8,11 @@ import com.fs.course.vo.*;
 import com.fs.course.vo.newfs.FsUserCourseListVO;
 import com.fs.his.vo.OptionsVO;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
 /**
  * 课程Service接口
  *

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

@@ -5,8 +5,8 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.course.domain.FsUserCourseTrainingCamp;
 import com.fs.course.dto.FsUserCourseTrainingCampDTO;
 import com.fs.course.vo.FsUserCourseTrainingCampVO;
+import com.fs.his.vo.OptionsVO;
 
-import javax.validation.Valid;
 import java.util.List;
 import java.util.Map;
 
@@ -43,4 +43,11 @@ public interface IFsUserCourseTrainingCampService extends IService<FsUserCourseT
      * @param id    id
      */
     void copy(Long id);
+
+    /**
+     * 查询训练营选项列表
+     * @param params    参数
+     * @return  list
+     */
+    List<OptionsVO> selectCampListByMap(Map<String, Object> params);
 }

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

@@ -91,4 +91,5 @@ public interface IFsUserCourseVideoRedPackageService
      */
     void batchRedPacketByPeriod(List<FsBatchPeriodRedPackageParam> periodRedPackageList);
 
+    List<FsUserCourseVideoRedPackage> selectByRuleIds(List<Long> ruleIds);
 }

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

@@ -9,12 +9,13 @@ import com.fs.course.param.newfs.FsUserCourseVideoLinkParam;
 import com.fs.course.param.newfs.FsUserCourseVideoUParam;
 import com.fs.course.param.newfs.UserCourseVideoPageParam;
 import com.fs.course.vo.FsUserCourseVideoListUVO;
+import com.fs.course.vo.FsUserCourseVideoQVO;
+import com.fs.course.vo.FsUserCourseVideoVO;
 import com.fs.course.vo.newfs.FsUserCourseVideoDetailsVO;
 import com.fs.course.vo.newfs.FsUserCourseVideoLinkDetailsVO;
 import com.fs.course.vo.newfs.FsUserCourseVideoPageListVO;
-import com.fs.course.vo.FsUserCourseVideoQVO;
-import com.fs.course.vo.FsUserCourseVideoVO;
 import com.fs.course.vo.newfs.FsUserVideoListVO;
+import com.fs.his.vo.OptionsVO;
 
 import java.util.List;
 import java.util.Map;
@@ -147,4 +148,13 @@ public interface IFsUserCourseVideoService
     void updates(CourseVideoUpdates vo);
 
     void batchSaveVideo(BatchVideoSvae vo);
+
+    void batchUpdateRed(List<BatchRedUpdate> list);
+
+    /**
+     * 获取选项列表
+     * @param params    参数
+     * @return  list
+     */
+    List<OptionsVO> selectVideoListByMap(Map<String, Object> params);
 }

+ 8 - 7
fs-service-system/src/main/java/com/fs/course/service/impl/FsCourseQuestionBankServiceImpl.java

@@ -148,7 +148,8 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
         //日志id
         Long logId = null;
 
-        FsCourseAnswerLogs rightLog = new FsCourseAnswerLogs();
+        new FsCourseAnswerLogs();
+        FsCourseAnswerLogs rightLog;
         //判断短链类型
         if (param.getLinkType()!=null&&param.getLinkType()==1){
             rightLog = courseAnswerLogsMapper.selectRightLogByCourseVideo(param.getVideoId(), param.getUserId(),null);
@@ -160,7 +161,7 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
         }else {
             FsCourseWatchLog log;
             if(isH5User){
-               log = courseWatchLogMapper.getWatchLogByFsUser(param.getVideoId(), param.getUserId());
+                log = courseWatchLogMapper.getWatchLogByFsUser(param.getVideoId(), param.getUserId(), param.getCompanyUserId());
             } else {
                 log = courseWatchLogMapper.getWatchCourseVideo(param.getUserId(), param.getVideoId(), param.getQwUserId(), param.getQwExternalId());
             }
@@ -174,11 +175,11 @@ public class FsCourseQuestionBankServiceImpl implements IFsCourseQuestionBankSer
 
             rightLog = courseAnswerLogsMapper.selectRightLogByCourseVideo(param.getVideoId(), param.getUserId(), param.getQwUserId());
             if (rightLog != null) {
-                if (log.getRewardType() != null) {
-                    return R.error("该课程已答题完成,不可重复答题");
-                } else {
-                    return R.ok("答题成功");
-                }
+//                if (log.getRewardType() != null) {
+//                    return R.error("该课程已答题完成,不可重复答题");
+//                } else {
+//                }
+                return R.error("该课程已答题完成,不可重复答题");
             }
             errorCount = courseAnswerLogsMapper.selectErrorCountByCourseVideo(param.getVideoId(), param.getUserId(),param.getQwUserId());
         }

+ 134 - 3
fs-service-system/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java

@@ -709,7 +709,9 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
                         HyWatchLog qwWatchLog = new HyWatchLog();
                         qwWatchLog.setExtId(fsCourseWatchLog.getQwExternalContactId());
                         qwWatchLog.setLineTime(fsCourseWatchLog.getLineTime());
-                        qwWatchLog.setQwUserId(Long.parseLong(fsCourseWatchLog.getQwUserId()));
+                        if(fsCourseWatchLog.getQwUserId() != null) {
+                            qwWatchLog.setQwUserId(Long.parseLong(fsCourseWatchLog.getQwUserId()));
+                        }
                         qwWatchLog.setDay(day);
                         qwWatchLog.setStatus(fsCourseWatchLog.getLogType()==3?0:fsCourseWatchLog.getLogType()==2?2:1);
                         qwWatchLog.setProject(project);
@@ -848,11 +850,140 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
     }
 
     @Override
-    public FsCourseWatchLog getWatchLogByFsUser(Long videoId, Long fsUserId) {
-        return fsCourseWatchLogMapper.getWatchLogByFsUser(videoId, fsUserId);
+    public FsCourseWatchLog getWatchLogByFsUser(Long videoId, Long fsUserId, Long companyUserId) {
+        return fsCourseWatchLogMapper.getWatchLogByFsUser(videoId, fsUserId, companyUserId);
+    }
+
+    @Override
+    public void scheduleUpdateDurationToDatabase() {
+        log.info("WXH5-开始更新会员看课时长,检查完课>>>>>>");
+        //读取所有的key
+        Collection<String> keys = redisCache.keys("h5wxuser:watch:duration:*");
+
+        //读取看课配置
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+
+        List<FsCourseWatchLog> logs = new ArrayList<>();
+        for (String key : keys) {
+            //取key中数据
+            String[] parts = key.split(":");
+            Long userId = Long.parseLong(parts[3]);
+            Long videoId = Long.parseLong(parts[4]);
+            Long companyUserId = Long.parseLong(parts[5]);
+            String durationStr = redisCache.getCacheObject(key);
+            if(durationStr==null){
+                log.error("key中数据为null:{}",key);
+                continue;  // 如果 Redis 中没有记录,跳过
+            }
+            Long duration = Long.valueOf(durationStr);
+
+            FsCourseWatchLog watchLog = new FsCourseWatchLog();
+            watchLog.setVideoId(videoId);
+            watchLog.setUserId(userId);
+            watchLog.setCompanyUserId(companyUserId);
+            watchLog.setDuration(duration);
+
+            //取对应视频的时长
+            Long videoDuration = getFsUserVideoDuration(videoId);
+            if (videoDuration != null && videoDuration != 0) {
+                //判断是否完课
+                long percentage = (duration * 100 / videoDuration);
+                if (percentage >= config.getAnswerRate()) {
+                    watchLog.setLogType(2); // 设置状态为“已完成”checkFsUserWatchStatus
+                    watchLog.setFinishTime(new Date());
+                    String heartbeatKey ="h5wxuser:watch:heartbeat:" + userId+ ":" + videoId + ":" + companyUserId;
+                    // 完课删除心跳记录
+                    redisCache.deleteObject(heartbeatKey);
+                    // 完课删除看课时长记录
+                    redisCache.deleteObject(key);
+                }
+            }
+            //集合中增加
+            logs.add(watchLog);
+        }
+        batchUpdateFsUserCourseWatchLog(logs,100);
+    }
+
+    public Long getFsUserVideoDuration(Long videoId){
+        //将视频时长也存到redis
+        String videoRedisKey = "h5wxuser:video:duration:" + videoId;
+        Long videoDuration = redisCache.getCacheObject(videoRedisKey);
+        if (videoDuration==null){
+            FsUserCourseVideo video = courseVideoMapper.selectFsUserCourseVideoByVideoId(videoId);
+            videoDuration=video.getDuration();
+            redisCache.setCacheObject(videoRedisKey,video.getDuration().toString());
+        }
+        return videoDuration;
+    }
+
+    @Override
+    public void checkFsUserWatchStatus() {
+        log.info("WXH5-开始更新会员看课中断记录>>>>>");
+        // 从 Redis 中获取所有正在看课的用户记录
+        Collection<String> keys = redisCache.keys("h5wxuser:watch:heartbeat:*");
+        LocalDateTime now = LocalDateTime.now();
+        List<FsCourseWatchLog> logs = new ArrayList<>();
+        for (String key : keys) {
+            FsCourseWatchLog watchLog = new FsCourseWatchLog();
+            String[] parts = key.split(":");
+            Long userId = Long.parseLong(parts[3]);
+            Long videoId = Long.parseLong(parts[4]);
+            Long companyUserId = Long.parseLong(parts[5]);
+            // 获取最后心跳时间
+            String lastHeartbeatStr = redisCache.getCacheObject(key);
+            if (lastHeartbeatStr == null) {
+                continue; // 如果 Redis 中没有记录,跳过
+            }
+            LocalDateTime lastHeartbeatTime = LocalDateTime.parse(lastHeartbeatStr);
+            Duration duration = Duration.between(lastHeartbeatTime, now);
+
+            watchLog.setVideoId(videoId);
+            watchLog.setUserId(userId);
+            watchLog.setCompanyUserId(companyUserId);
+            // 如果超过一分钟没有心跳,标记为“观看中断”
+            if (duration.getSeconds() >= 60) {
+                watchLog.setLogType(4);
+                // 从 Redis 中删除该记录
+                redisCache.deleteObject(key);
+            }else {
+                watchLog.setLogType(1);
+            }
+            logs.add(watchLog);
+        }
+        batchUpdateFsUserCourseWatchLog(logs,100);
+
     }
 
     private void processDelCourseLogs(List<Long> logIds) {
 
     }
+
+    public void batchUpdateFsUserCourseWatchLog(List<FsCourseWatchLog> logs, int batchSize) {
+        if (logs == null || logs.isEmpty()) {
+            log.info("待更新的日志列表为空,无需处理");
+            return;
+        }
+
+        // 记录总日志数量
+        log.info("开始批量更新日志,总日志数量: {}", logs.size());
+
+        // 分批处理
+        for (int i = 0; i < logs.size(); i += batchSize) {
+            int end = Math.min(i + batchSize, logs.size());
+            List<FsCourseWatchLog> batchList = logs.subList(i, end);
+
+            // 记录当前批次的数量
+            log.info("正在更新第 {} 批日志,数量: {}", (i / batchSize) + 1, batchList.size());
+
+            // 执行批量更新
+            fsCourseWatchLogMapper.batchUpdateFsUserWatchLog(batchList);
+
+            // 记录当前批次更新完成
+            log.info("第 {} 批日志更新完成,数量: {}", (i / batchSize) + 1, batchList.size());
+        }
+
+        // 记录全部更新完成
+        log.info("所有日志更新完成,总日志数量: {}", logs.size());
+    }
 }

+ 120 - 19
fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodDaysServiceImpl.java

@@ -1,35 +1,42 @@
 package com.fs.course.service.impl;
 
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.common.utils.date.DateUtil;
 import com.fs.common.utils.date.TimeTypeEnum;
 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.CompanyRedPacketParam;
 import com.fs.course.param.PeriodCountParam;
-import com.fs.course.param.PeriodRedPacketParam;
+import com.fs.course.service.IFsUserCoursePeriodDaysService;
 import com.fs.course.vo.FsPeriodCountVO;
+import com.fs.course.vo.PeriodRedPacketVO;
+import com.fs.course.vo.UpdateCourseTimeVo;
 import com.fs.course.vo.newfs.FsCourseAnalysisCountVO;
+import com.fs.his.vo.OptionsVO;
 import com.fs.store.mapper.FsUserMapper;
 import com.fs.store.param.h5.CourseAnalysisParam;
 import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
-import com.fs.course.mapper.FsUserCoursePeriodDaysMapper;
-import com.fs.course.domain.FsUserCoursePeriodDays;
-import com.fs.course.service.IFsUserCoursePeriodDaysService;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 /**
  * 营期课程Service业务层处理
@@ -39,12 +46,15 @@ import com.fs.course.service.IFsUserCoursePeriodDaysService;
  */
 @Service
 @AllArgsConstructor
+@Slf4j
 public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCoursePeriodDaysMapper, FsUserCoursePeriodDays> implements IFsUserCoursePeriodDaysService {
 
     private final FsUserCoursePeriodMapper fsUserCoursePeriodMapper;
 
     private final FsUserMapper  fsUserMapper;
 
+    private final FsUserCoursePeriodDaysMapper fsUserCoursePeriodDaysMapper;
+
     /**
      * 查询营期课程
      *
@@ -122,7 +132,7 @@ public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCourseP
     @Override
     public R addCourse(FsUserCoursePeriodDays entity) {
         FsUserCoursePeriod period = fsUserCoursePeriodMapper.selectFsUserCoursePeriodById(entity.getPeriodId());
-        int num = count(new QueryWrapper<FsUserCoursePeriodDays>().eq("period_id", period.getPeriodId()));
+        List<FsUserCoursePeriodDays> dayList = list(new QueryWrapper<FsUserCoursePeriodDays>().eq("period_id", period.getPeriodId()));
         long days;
         if(period.getPeriodType() == 2){
             days = 1;
@@ -130,16 +140,27 @@ public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCourseP
             days = DateUtil.differenceTime(period.getPeriodStartingTime(), period.getPeriodEndTime(), TimeTypeEnum.DAY);
         }
         days++;
-        if(num + entity.getVideoIds().size() > days) return R.error("课程不能超过营期范围");
+        if(dayList.size() + entity.getVideoIds().size() > days) return R.error("课程不能超过营期范围");
+        if(dayList.stream().anyMatch(e -> entity.getVideoIds().contains(e.getVideoId()))) return R.error("不能添加相同章节");
         AtomicInteger i = new AtomicInteger(0);
         List<FsUserCoursePeriodDays> collect = entity.getVideoIds().stream().map(e -> {
             FsUserCoursePeriodDays day = new FsUserCoursePeriodDays();
             day.setPeriodId(entity.getPeriodId());
-            day.setLesson(num + i.getAndIncrement());
+            day.setLesson(dayList.size() + i.getAndIncrement());
             day.setDayDate(period.getPeriodStartingTime().plusDays(day.getLesson()));
             day.setCourseId(entity.getCourseId());
+            day.setStartDateTime(LocalDateTime.of(day.getDayDate(), entity.getStartTime()));
+            day.setEndDateTime(LocalDateTime.of(day.getDayDate(), entity.getEndTime1()));
+            day.setLastJoinTime(LocalDateTime.of(day.getDayDate(), entity.getJoinTime()));
             day.setVideoId(e);
             day.setCreateTime(new Date());
+            // 默认开启今天及以后的两天
+            LocalDate compareDay = LocalDate.now().plusDays(1);
+            if(day.getDayDate().isBefore(compareDay)){
+                day.setStatus(1);
+            } else {
+                day.setStatus(0);
+            }
             return day;
         }).collect(Collectors.toList());
         super.saveBatch(collect);
@@ -167,7 +188,7 @@ public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCourseP
     }
 
     @Override
-    public List<PeriodRedPacketParam> getPeriodRedPacketList(Long periodId, Long companyId) {
+    public List<PeriodRedPacketVO> getPeriodRedPacketList(Long periodId, Long companyId) {
         return fsUserCoursePeriodMapper.selectPeriodRedPacket(periodId, companyId);
     }
 
@@ -217,13 +238,83 @@ public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCourseP
         }).collect(Collectors.toList());
     }
 
+    @Override
+    public R periodCourseMove(Long id, Long targetId) {
+        List<Long> idList = new ArrayList<>();
+        idList.add(id);
+        idList.add(targetId);
+        List<FsUserCoursePeriodDays> fsUserCoursePeriodDays = baseMapper.selectBatchIds(idList);
+        if(fsUserCoursePeriodDays.isEmpty()){
+            return R.error(404, "当前数据或者移动的目标数据不存在");
+        }
+
+        List<FsUserCoursePeriodDays> list = new ArrayList<>();
+        FsUserCoursePeriodDays periodDays = fsUserCoursePeriodDays.get(0);
+        LocalDate currentDayDate = periodDays.getDayDate();
+        Integer lesson = periodDays.getLesson();
+
+        FsUserCoursePeriodDays periodDaysTarget = fsUserCoursePeriodDays.get(1);
+        periodDays.setDayDate(periodDaysTarget.getDayDate());
+        periodDays.setLesson(periodDaysTarget.getLesson());
+        list.add(periodDays);
+
+        periodDaysTarget.setDayDate(currentDayDate);
+        periodDaysTarget.setLesson(lesson);
+        list.add(periodDaysTarget);
+        try {
+            fsUserCoursePeriodDaysMapper.batchUpdateCoursePeriodDays(list);
+        } catch (RuntimeException e) {
+            log.error("上移/下移异常,当前id:{}, 目标id:{}", id, targetId);
+            return R.error();
+        }
+        return R.ok();
+    }
+
+    @Override
+    public R updateCourseTime(UpdateCourseTimeVo vo) {
+        List<FsUserCoursePeriodDays> list = fsUserCoursePeriodDaysMapper.selectBatchIds(vo.getIds());
+        list.forEach(day -> {
+            day.setStartDateTime(LocalDateTime.of(day.getDayDate(), vo.getStartTime()));
+            day.setEndDateTime(LocalDateTime.of(day.getDayDate(), vo.getEndTime1()));
+            day.setLastJoinTime(LocalDateTime.of(day.getDayDate(), vo.getJoinTime()));
+            fsUserCoursePeriodDaysMapper.updateById(day);
+        });
+        return R.ok();
+    }
+
+    @Override
+    public R updateCourseDate(UpdateCourseTimeVo vo) {
+        FsUserCoursePeriodDays day = getById(vo.getId());
+        FsUserCoursePeriod period = fsUserCoursePeriodMapper.selectFsUserCoursePeriodById(day.getPeriodId());
+        if(!DateUtil.isWithinRangeSafe(vo.getDayDate(), period.getPeriodStartingTime(), period.getPeriodEndTime())) return R.error("时间不在营期范围内");
+        day.setDayDate(vo.getDayDate());
+        day.setStartDateTime(LocalDateTime.of(day.getDayDate(), day.getStartDateTime().toLocalTime()));
+        day.setEndDateTime(LocalDateTime.of(day.getDayDate(), day.getEndDateTime().toLocalTime()));
+        day.setLastJoinTime(LocalDateTime.of(day.getDayDate(), day.getLastJoinTime().toLocalTime()));
+        updateById(day);
+        return R.ok();
+    }
+
+    /**
+     * 更新营期课程状态
+     */
+    @Transactional(rollbackFor = RuntimeException.class)
+    @Override
+    public void changePeriodCourseStatus() {
+        // 开启
+        fsUserCoursePeriodDaysMapper.startPeriodCourse(LocalDateTime.now());
+
+        // 关闭
+        fsUserCoursePeriodDaysMapper.endPeriodCourse(LocalDateTime.now());
+    }
+
     private static FsCourseAnalysisCountVO getCourseAnalysisCountVO(FsUserCoursePeriodDays v, Map<Long, FsCourseAnalysisCountVO> courseMap, Map<Long, FsCourseAnalysisCountVO> redPacketMap, Map<Long, FsCourseAnalysisCountVO> answerMap) {
         FsCourseAnalysisCountVO countVO = new FsCourseAnalysisCountVO();
         FsCourseAnalysisCountVO courseVO = courseMap.getOrDefault(v.getVideoId(), countVO);
         FsCourseAnalysisCountVO redPacketVO = redPacketMap.getOrDefault(v.getVideoId(), countVO);
         FsCourseAnalysisCountVO answerVO = answerMap.getOrDefault(v.getVideoId(), countVO);
         //单独赋值
-        countVO.setVideoId(v.getVideoId()).setCourseWatchNum(courseVO.getCourseWatchNum()).setCourseCompleteNum(courseVO.getCourseWatchNum())
+        countVO.setVideoId(v.getVideoId()).setCourseWatchNum(courseVO.getCourseWatchNum()).setCourseCompleteNum(courseVO.getCourseCompleteNum())
                 .setCompleteRate(courseVO.getCompleteRate() != null ? courseVO.getCompleteRate() : new BigDecimal(BigInteger.ZERO))
                 .setCourseWatchTimes(courseVO.getCourseWatchTimes()).setCourseCompleteTimes(courseVO.getCourseCompleteTimes());
         countVO.setRedPacketNum(redPacketVO.getRedPacketNum())
@@ -233,4 +324,14 @@ public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCourseP
                 .setAnswerTimes(answerVO.getAnswerTimes()).setAnswerRightTimes(answerVO.getAnswerRightTimes());
         return countVO;
     }
+
+    /**
+     * 查询营期选项列表
+     * @param params    参数
+     * @return  list
+     */
+    @Override
+    public List<OptionsVO> selectPeriodListByMap(Map<String, Object> params) {
+        return baseMapper.selectPeriodListByMap(params);
+    }
 }

+ 71 - 6
fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodServiceImpl.java

@@ -1,14 +1,23 @@
 package com.fs.course.service.impl;
 
-import java.time.LocalDateTime;
-import java.util.List;
-import com.fs.common.utils.DateUtils;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.fs.common.exception.ServiceException;
+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.service.IFsUserCoursePeriodService;
 import com.fs.course.vo.FsUserCoursePeriodVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import com.fs.course.mapper.FsUserCoursePeriodMapper;
-import com.fs.course.domain.FsUserCoursePeriod;
-import com.fs.course.service.IFsUserCoursePeriodService;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Objects;
 
 /**
  * 会员营期Service业务层处理
@@ -21,6 +30,8 @@ public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService
 {
     @Autowired
     private FsUserCoursePeriodMapper fsUserCoursePeriodMapper;
+    @Resource
+    private FsUserCoursePeriodDaysMapper fsUserCoursePeriodDaysMapper;
 
     /**
      * 查询会员营期
@@ -56,6 +67,14 @@ public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService
     public int insertFsUserCoursePeriod(FsUserCoursePeriod fsUserCoursePeriod)
     {
         fsUserCoursePeriod.setCreateTime(LocalDateTime.now());
+        // 设置营期状态
+        if(LocalDate.now().isBefore(fsUserCoursePeriod.getPeriodStartingTime())){
+            fsUserCoursePeriod.setPeriodStatus(1L);
+        } else if(LocalDate.now().isAfter(fsUserCoursePeriod.getPeriodEndTime())){
+            fsUserCoursePeriod.setPeriodStatus(3L);
+        } else{
+            fsUserCoursePeriod.setPeriodStatus(2L);
+        }
         return fsUserCoursePeriodMapper.insertFsUserCoursePeriod(fsUserCoursePeriod);
     }
 
@@ -100,4 +119,50 @@ public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService
     public List<FsUserCoursePeriodVO> selectFsUserCoursePeriodPage(FsUserCoursePeriod fsUserCoursePeriod) {
         return fsUserCoursePeriodMapper.selectFsUserCoursePeriodPage(fsUserCoursePeriod);
     }
+
+    /**
+     * 结束营期
+     * @param id    营期ID
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void closePeriod(Long id) {
+        // 修改营期结束时间
+        FsUserCoursePeriod fsUserCoursePeriod = fsUserCoursePeriodMapper.selectFsUserCoursePeriodById(id);
+        if (Objects.isNull(fsUserCoursePeriod)) {
+            throw new ServiceException("结束营期失败:营期不存在");
+        }
+
+        if (fsUserCoursePeriod.getPeriodStatus() == 1) {
+            throw new ServiceException("结束营期失败:营期未开始不能进行结束操作!");
+        }
+
+        if (fsUserCoursePeriod.getPeriodStatus() == 3) {
+            throw new ServiceException("结束营期失败:营期已结束不能进行结束操作!");
+        }
+
+        fsUserCoursePeriod.setPeriodEndTime(LocalDate.now());
+        fsUserCoursePeriodMapper.updateFsUserCoursePeriod(fsUserCoursePeriod);
+
+        // 修改大于当前时间的课程状态
+        Wrapper<FsUserCoursePeriodDays> updateWrapper = Wrappers.<FsUserCoursePeriodDays>lambdaUpdate()
+                .set(FsUserCoursePeriodDays::getStatus, 2)
+                .eq(FsUserCoursePeriodDays::getPeriodId, fsUserCoursePeriod.getPeriodId())
+                .eq(FsUserCoursePeriodDays::getStatus, 0)
+                .gt(FsUserCoursePeriodDays::getDayDate, LocalDate.now());
+        fsUserCoursePeriodDaysMapper.update(null, updateWrapper);
+    }
+
+    /**
+     * 更新营期状态
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void changePeriodStatus() {
+        // 开营
+        fsUserCoursePeriodMapper.startPeriod(LocalDate.now());
+
+        // 关营
+        fsUserCoursePeriodMapper.endPeriod(LocalDate.now());
+    }
 }

+ 32 - 7
fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseTrainingCampServiceImpl.java

@@ -2,27 +2,25 @@ package com.fs.course.service.impl;
 
 
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.common.exception.ServiceException;
-import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.bean.BeanUtils;
 import com.fs.course.domain.FsUserCoursePeriod;
 import com.fs.course.domain.FsUserCoursePeriodDays;
+import com.fs.course.domain.FsUserCourseTrainingCamp;
 import com.fs.course.dto.FsUserCourseTrainingCampDTO;
-import com.fs.course.mapper.FsUserCoursePeriodDaysMapper;
 import com.fs.course.mapper.FsUserCoursePeriodMapper;
+import com.fs.course.mapper.FsUserCourseTrainingCampMapper;
 import com.fs.course.service.IFsUserCoursePeriodDaysService;
+import com.fs.course.service.IFsUserCourseTrainingCampService;
 import com.fs.course.vo.FsUserCourseTrainingCampVO;
-import com.fs.store.service.IFsUserService;
+import com.fs.his.vo.OptionsVO;
 import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
-import com.fs.course.mapper.FsUserCourseTrainingCampMapper;
-import com.fs.course.domain.FsUserCourseTrainingCamp;
-import com.fs.course.service.IFsUserCourseTrainingCampService;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -68,11 +66,28 @@ public class FsUserCourseTrainingCampServiceImpl extends ServiceImpl<FsUserCours
      * 删除训练营
      * @param ids   ids
      */
+    @Transactional(rollbackFor = Exception.class)
     @Override
     public void del(Long[] ids) {
+        // 检查是否存在进行中的营期
+        if (checkPeriodStatus(ids)) {
+            throw new ServiceException("存在进行中的营期,请营期结束后再操作");
+        }
+
         baseMapper.deleteBatchIds(Arrays.asList(ids));
     }
 
+    /**
+     * 检查是否存在进行中的营期
+     * @param ids 训练营ID集合
+     */
+    private boolean checkPeriodStatus(Long[] ids) {
+        Map<String, Object> params = new HashMap<>();
+        params.put("ids", ids);
+        params.put("date", LocalDate.now());
+        return fsUserCoursePeriodMapper.countPeriodByCampIds(params) > 0;
+    }
+
     /**
      * 复制训练营
      * @param id    id
@@ -114,4 +129,14 @@ public class FsUserCourseTrainingCampServiceImpl extends ServiceImpl<FsUserCours
             }
         });
     }
+
+    /**
+     * 查询训练营选项列表
+     * @param params    参数
+     * @return  list
+     */
+    @Override
+    public List<OptionsVO> selectCampListByMap(Map<String, Object> params) {
+        return baseMapper.selectCampListByMap(params);
+    }
 }

+ 5 - 0
fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseVideoRedPackageServiceImpl.java

@@ -239,5 +239,10 @@ public class FsUserCourseVideoRedPackageServiceImpl implements IFsUserCourseVide
         this.batchSaveCompanyRedPackage(fsRedPackageList);
     }
 
+    @Override
+    public List<FsUserCourseVideoRedPackage> selectByRuleIds(List<Long> ruleIds) {
+        return fsUserCourseVideoRedPackageMapper.selectByRuleIds(ruleIds);
+    }
+
 
 }

+ 112 - 33
fs-service-system/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -9,6 +9,7 @@ import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
+import com.fs.common.utils.date.DateUtil;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.mapper.CompanyUserMapper;
 import com.fs.course.config.CourseConfig;
@@ -27,13 +28,7 @@ import com.fs.course.vo.FsUserCourseVideoQVO;
 import com.fs.course.vo.FsUserCourseVideoVO;
 import com.fs.course.vo.newfs.*;
 import com.fs.his.param.WxSendRedPacketParam;
-import com.fs.sop.mapper.SopUserLogsInfoMapper;
-import com.fs.store.domain.FsUser;
-import com.fs.store.domain.FsUserIntegralLogs;
-import com.fs.store.mapper.FsUserIntegralLogsMapper;
-import com.fs.store.mapper.FsUserMapper;
-import com.fs.store.service.IFsStorePaymentService;
-import com.fs.store.service.IFsUserService;
+import com.fs.his.vo.OptionsVO;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.domain.QwUser;
 import com.fs.qw.mapper.QwExternalContactMapper;
@@ -42,25 +37,30 @@ import com.fs.qwApi.Result.QwAddContactWayResult;
 import com.fs.qwApi.param.QwAddContactWayParam;
 import com.fs.qwApi.service.QwApiService;
 import com.fs.sop.mapper.QwSopLogsMapper;
+import com.fs.sop.mapper.SopUserLogsInfoMapper;
+import com.fs.store.domain.FsUser;
+import com.fs.store.domain.FsUserIntegralLogs;
+import com.fs.store.mapper.FsUserIntegralLogsMapper;
+import com.fs.store.mapper.FsUserMapper;
+import com.fs.store.service.IFsStorePaymentService;
+import com.fs.store.service.IFsUserService;
 import com.fs.store.service.cache.IFsUserCourseCacheService;
 import com.fs.system.service.ISysConfigService;
 import com.github.binarywang.wxpay.bean.transfer.TransferBillsResult;
+import lombok.extern.slf4j.Slf4j;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.CollectionUtils;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.time.LocalDateTime;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
+import java.time.LocalTime;
+import java.util.*;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.stream.Collectors;
 
@@ -70,6 +70,7 @@ import java.util.stream.Collectors;
  * @author fs
  * @date 2024-05-17
  */
+@Slf4j
 @Service
 public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 {
@@ -97,7 +98,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     private FsCourseSopLogsMapper courseSopLogsMapper;
     @Autowired
     private QwApiService qwApiService;
-//    @Autowired
+    //    @Autowired
 //    private IAdHtmlClickLogService adHtmlClickLogService;
     @Autowired
     private QwUserMapper qwUserMapper;
@@ -133,6 +134,15 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     @Autowired
     private FsVideoResourceMapper fsVideoResourceMapper;
 
+    @Autowired
+    private FsUserCourseMapper fsUserCourseMapper;
+
+    @Autowired
+    private FsUserCoursePeriodMapper fsUserCoursePeriodMapper;
+
+    @Autowired
+    private FsUserCoursePeriodDaysMapper fsUserCoursePeriodDaysMapper;
+
     /**
      * 查询课堂视频
      *
@@ -304,6 +314,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
         // 从Redis中获取观看时长
         String redisKey = "h5user:watch:duration:" + param.getQwUserId()+ ":" + param.getQwExternalId() + ":" + param.getVideoId();
+        log.info("看课redis-key:{}", redisKey);
         try {
             String durationStr = redisCache.getCacheObject(redisKey);
             Long duration = durationStr != null ? Long.parseLong(durationStr) : 0L;
@@ -725,9 +736,23 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
      * @return 处理结果
      */
     private R sendRedPacketReward(FsCourseSendRewardUParam param, FsUser user, FsCourseWatchLog log, FsUserCourseVideo video, CourseConfig config) {
+        // 判断是否属于领取红包时间(会员看课发放红包)
+        FsUserCoursePeriodDays periodDays = new FsUserCoursePeriodDays();
+        periodDays.setVideoId(param.getVideoId());
+        periodDays.setPeriodId(param.getPeriodId());
+        //正常情况是只能查询到一条,之前可能存在重复的脏数据,暂使用查询list的方式
+        List<FsUserCoursePeriodDays> fsUserCoursePeriodDays = fsUserCoursePeriodDaysMapper.selectFsUserCoursePeriodDaysList(periodDays);
+        if(fsUserCoursePeriodDays != null && !fsUserCoursePeriodDays.isEmpty()){
+            periodDays = fsUserCoursePeriodDays.get(0);
+        }
+
+        if(periodDays != null && periodDays.getLastJoinTime() !=null && LocalDateTime.now().isAfter(periodDays.getLastJoinTime())) {
+            return R.error(403,"已超过领取红包时间");
+        }
+
         // 确定红包金额
         BigDecimal amount = BigDecimal.ZERO;
-        FsUserCourseVideoRedPackage redPackage = fsUserCourseVideoRedPackageMapper.selectRedPacketByCompanyId(param.getVideoId(), param.getCompanyId());
+        FsUserCourseVideoRedPackage redPackage = fsUserCourseVideoRedPackageMapper.selectRedPacketByCompanyId(param.getVideoId(), param.getCompanyId(), param.getPeriodId());
 
         if (redPackage != null) {
             amount = redPackage.getRedPacketMoney();
@@ -771,13 +796,14 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             redPacketLog.setCreateTime(new Date());
             redPacketLog.setAmount(amount);
             redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
+            redPacketLog.setPeriodId(param.getPeriodId());
             redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
 
             // 更新观看记录的奖励类型
-            if (param.getLinkType() == null || param.getLinkType() == 0) {
-                log.setRewardType(config.getRewardType());
-                courseWatchLogMapper.updateFsCourseWatchLog(log);
-            }
+//            if (param.getLinkType() == null || param.getLinkType() == 0) {
+            log.setRewardType(config.getRewardType());
+            courseWatchLogMapper.updateFsCourseWatchLog(log);
+//            }
             return sendRedPacket;
         } else {
             return R.error("奖励发送失败,请联系客服");
@@ -809,6 +835,11 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         integralLogs.setCreateTime(new Date());
         fsUserIntegralLogsMapper.insertFsUserIntegralLogs(integralLogs);
 
+        //更新看课记录的奖励类型
+        log.setRewardType(config.getRewardType());
+        courseWatchLogMapper.updateFsCourseWatchLog(log);
+        logger.info("发放奖励====================》看课记录,{}",log);
+
         return R.ok("奖励发放成功");
     }
 
@@ -913,21 +944,31 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             log.setCompanyUserId(param.getCompanyUserId());
             log.setVideoId(param.getVideoId());
             List<FsCourseWatchLog> fsCourseWatchLogs = courseWatchLogMapper.selectFsCourseWatchLogList(log);
+
+            // 获取课程所属项目id
+            FsUserCourse fsUserCourse = fsUserCourseMapper.selectFsUserCourseByCourseId(param.getCourseId());
+            Long courseProject = null;
+            if(fsUserCourse != null){
+                courseProject = fsUserCourse.getProject();
+            }
             //如果存在,则更新
             if (fsCourseWatchLogs != null && !fsCourseWatchLogs.isEmpty()){
                 FsCourseWatchLog updateLog = new FsCourseWatchLog();
+                updateLog.setPeriodId(param.getPeriodId());
+                updateLog.setProject(courseProject);
                 updateLog.setUpdateTime(new Date());
                 courseWatchLogMapper.updateFsCourseWatchLog(updateLog);
+            } else {
+                //如果是会员,则需要添加看课记录
+                FsCourseWatchLog fsCourseWatchLog = new FsCourseWatchLog();
+                BeanUtils.copyProperties(param, fsCourseWatchLog);
+                fsCourseWatchLog.setSendType(1);
+                fsCourseWatchLog.setDuration(0L);
+                fsCourseWatchLog.setCreateTime(new Date());
+                fsCourseWatchLog.setLogType(1);
+                fsCourseWatchLog.setProject(courseProject);
+                courseWatchLogMapper.insertFsCourseWatchLog(fsCourseWatchLog);
             }
-
-            //如果是会员,则需要添加看课记录
-            FsCourseWatchLog fsCourseWatchLog = new FsCourseWatchLog();
-            BeanUtils.copyProperties(param, fsCourseWatchLog);
-            fsCourseWatchLog.setSendType(1);
-            fsCourseWatchLog.setDuration(0L);
-            fsCourseWatchLog.setCreateTime(new Date());
-            fsCourseWatchLog.setLogType(1);
-            courseWatchLogMapper.insertFsCourseWatchLog(fsCourseWatchLog);
         } else {
             return ResponseResult.ok(Boolean.FALSE);
         }
@@ -936,6 +977,19 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
     @Override
     public ResponseResult<FsUserCourseVideoLinkDetailsVO> getLinkCourseVideoDetails(FsUserCourseVideoLinkParam param) {
+        //判断营期的课程状态是否是进行中
+        FsUserCoursePeriodDays periodDays = new FsUserCoursePeriodDays();
+        periodDays.setVideoId(param.getVideoId());
+        periodDays.setPeriodId(param.getPeriodId());
+        //正常情况是只能查询到一条,之前可能存在重复的脏数据,暂使用查询list的方式
+        List<FsUserCoursePeriodDays> fsUserCoursePeriodDays = fsUserCoursePeriodDaysMapper.selectFsUserCoursePeriodDaysList(periodDays);
+        if(fsUserCoursePeriodDays != null && !fsUserCoursePeriodDays.isEmpty()){
+            periodDays = fsUserCoursePeriodDays.get(0);
+        }
+        if(periodDays.getStatus() != 1){
+            return ResponseResult.fail(403, "当前课程未开始或已结束,暂不能看课");
+        }
+
         String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
 
@@ -957,15 +1011,15 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             ResponseResult.ok(vo);
         }
         // 从Redis中获取用户目前的观看时长
-        String redisKey = "h5wxuser:watch:duration:" + param.getFsUserId() + ":" + param.getVideoId();
+        String redisKey = "h5wxuser:watch:duration:" + param.getFsUserId() + ":" + param.getVideoId() + ":" + param.getCompanyUserId();
         String durationCurrent = redisCache.getCacheObject(redisKey);
 
         //3、获取看课记录
-        FsCourseWatchLog watchLog = courseWatchLogMapper.getWatchLogByFsUser(param.getVideoId(), param.getFsUserId());
+        FsCourseWatchLog watchLog = courseWatchLogMapper.getWatchLogByFsUser(param.getVideoId(), param.getFsUserId(), param.getCompanyUserId());
         if (durationCurrent != null) {
             duration = Long.parseLong(durationCurrent);
         } else {
-            duration = watchLog.getDuration();
+            duration = Objects.isNull(watchLog) ? 0 : watchLog.getDuration();
         }
 //
 //        if (course.getDuration()!=null){
@@ -980,10 +1034,16 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         String videoRedisKey = "h5wxuser:video:duration:" + param.getVideoId();
         Long videoDuration = redisCache.getCacheObject(videoRedisKey);
         if (videoDuration == null) {
-            redisCache.setCacheObject(videoRedisKey, courseVideoDetails != null ? courseVideoDetails.getDuration() : 0);
+            redisCache.setCacheObject(videoRedisKey, courseVideoDetails != null ? courseVideoDetails.getDuration() != null ? courseVideoDetails.getDuration() : 0 : 0);
         }
         vo.setIsFinish(isFinish);
         vo.setPlayDuration(duration);
+        if(param.getId() != null){
+            FsUserCoursePeriodDays days = fsUserCoursePeriodDaysMapper.selectById(param.getId());
+            vo.setStartDateTime(days.getStartDateTime());
+            vo.setEndDateTime(days.getEndDateTime());
+            vo.setRang(DateUtil.isWithinRangeSafe(LocalDateTime.now(), days.getStartDateTime(), days.getEndDateTime()));
+        }
         return ResponseResult.ok(vo);
     }
 
@@ -1001,9 +1061,11 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         }
 
         // 从Redis中获取观看时长
-        String redisKey = "h5wxuser:watch:duration:" + param.getUserId() + ":" + param.getVideoId();
+        String redisKey = "h5wxuser:watch:duration:" + param.getUserId() + ":" + param.getVideoId() + ":" + param.getCompanyUserId();
+        log.info("看课redis缓存key:{}", redisKey);
         try {
             String durationStr = redisCache.getCacheObject(redisKey);
+            log.info("看课记录:{}", durationStr);
             long duration = durationStr != null ? Long.parseLong(durationStr) : 0L;
 
             // 更新Redis中的观看时长
@@ -1059,9 +1121,26 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         fsUserCourseVideoMapper.insertBatchFsUserCourseVideo(collect);
     }
 
+    @Override
+    public void batchUpdateRed(List<BatchRedUpdate> list) {
+        list.forEach(e -> {
+            fsUserCourseVideoMapper.updateRedPacketMoney(e.getVideoId(), e.getRedPacketMoney());
+        });
+    }
+
+    /**
+     * 获取选项列表
+     * @param params    参数
+     * @return  list
+     */
+    @Override
+    public List<OptionsVO> selectVideoListByMap(Map<String, Object> params) {
+        return fsUserCourseVideoMapper.selectVideoListByMap(params);
+    }
+
     //会员-更新心跳时间
     public void updateHeartbeatWx(FsUserCourseVideoUParam param) {
-        String redisKey = "h5wxuser:watch:heartbeat:" + param.getUserId() + ":" + param.getVideoId();
+        String redisKey = "h5wxuser:watch:heartbeat:" + param.getUserId() + ":" + param.getVideoId() + ":" + param.getCompanyUserId();
         redisCache.setCacheObject(redisKey, LocalDateTime.now().toString());
         // 设置 Redis 记录的过期时间(例如 5 分钟)
         redisCache.expire(redisKey, 300, TimeUnit.SECONDS);

+ 4 - 0
fs-service-system/src/main/java/com/fs/course/vo/FsPeriodCountVO.java

@@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.time.LocalDate;
 @Data
 @ApiModel
 public class FsPeriodCountVO {
@@ -21,6 +22,9 @@ public class FsPeriodCountVO {
     @ApiModelProperty(value = "视频标题")
     private String title;
 
+    @ApiModelProperty(value = "营期日期")
+    private LocalDate dayDate;
+
     @ApiModelProperty(value = "统计明细")
     private FsCourseAnalysisCountVO countDetailsVO;
 

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

@@ -82,4 +82,7 @@ public class FsUserCoursePeriodVO implements Serializable {
     @Excel(name = "开营日期-结束时间", width = 30, dateFormat = "yyyy-MM-dd")
     private LocalDate periodEndTime;
 
+    @Excel(name = "营期状态")
+    private Long periodStatus;
+
 }

+ 6 - 5
fs-service-system/src/main/java/com/fs/course/vo/FsUserCourseVideoQVO.java

@@ -6,12 +6,13 @@ import com.fs.common.core.domain.BaseEntity;
 import com.fs.course.domain.FsCourseQuestionBank;
 import lombok.Data;
 
+import java.math.BigDecimal;
 import java.time.LocalTime;
 import java.util.List;
 
 /**
-* 含课题 的课程小节
-*/
+ * 含课题 的课程小节
+ */
 @Data
 public class FsUserCourseVideoQVO extends BaseEntity {
 
@@ -68,7 +69,7 @@ public class FsUserCourseVideoQVO extends BaseEntity {
     private String lineTwo; //线路二 电信 前缀ctev
     private String lineThree; //线路三 华为云obs
     private Integer uploadType;
-    private String redPacketMoney;
+    private BigDecimal redPacketMoney;
     private Long fileSize;//文件大小  字节
     private String fileKey;//文件key 对用存储桶
     private String round;//轮次
@@ -78,8 +79,8 @@ public class FsUserCourseVideoQVO extends BaseEntity {
     private String questionBankId;
 
     /**
-    * 课题数组
-    */
+     * 课题数组
+     */
     private List<FsCourseQuestionBank> questionBankList;
 
     private String packageJson;

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

@@ -23,9 +23,9 @@ public class FsVideoResourceVO {
     private Long typeId;
 
     /**
-     * 分类名称
+     * 子分类ID
      */
-    private String typeName;
+    private Long typeSubId;
 
     /**
      * 文件名称

+ 7 - 2
fs-service-system/src/main/java/com/fs/course/param/PeriodRedPacketParam.java → fs-service-system/src/main/java/com/fs/course/vo/PeriodRedPacketVO.java

@@ -1,14 +1,16 @@
-package com.fs.course.param;
+package com.fs.course.vo;
 
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+
 import java.io.Serializable;
 import java.math.BigDecimal;
+import java.time.LocalDate;
 
 @Data
 @ApiModel("营期红包金额列表")
-public class PeriodRedPacketParam implements Serializable {
+public class PeriodRedPacketVO implements Serializable {
     private static final long serialVersionUID = 1L;
 
     @ApiModelProperty(value = "课程id")
@@ -23,6 +25,9 @@ public class PeriodRedPacketParam implements Serializable {
     @ApiModelProperty(value = "视频名称")
     private String videoName;
 
+    @ApiModelProperty(value = "营期日期")
+    private LocalDate dayDate;
+
     @ApiModelProperty(value = "金额")
     private BigDecimal amount;
 

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.