Browse Source

修改统计接口查询,增加修复定时任务间隔执行数据重复问题。

Guos 1 tuần trước cách đây
mục cha
commit
96353b6d97

+ 1 - 1
fs-admin/src/main/java/com/fs/api/controller/StatisticManageController.java

@@ -52,7 +52,7 @@ public class StatisticManageController {
     }
 
     /**
-     * 根据公司id获取部门下拉
+     * 根据部门id获取用户下拉信息
      * @return
      */
     @GetMapping("/getSearchUserInfo")

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

@@ -22,7 +22,7 @@ public class ComprehensiveStatisticsTask {
      * 每隔一小时执行一次
      */
     public void execute() {
-        iStatisticManageService.executeTask();
+        iStatisticManageService.executeTask(null);
     }
 
 }

+ 16 - 2
fs-admin/src/main/java/com/fs/task/SgTestController.java

@@ -1,11 +1,15 @@
 package com.fs.task;
 
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
  import com.fs.company.service.IStatisticManageService;
 
 import javax.annotation.Resource;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
 
 /**
  * @description:
@@ -29,8 +33,18 @@ public class SgTestController {
     }
 
     @RequestMapping("/statistic")
-    public void executeTask(){
-        iStatisticManageService.executeTask();
+    public void executeTask(@RequestParam(required = false) String dateTime){
+        Date date = null;
+        if (dateTime != null && !dateTime.isEmpty()) {
+            try {
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+                date = sdf.parse(dateTime);
+            } catch (ParseException e) {
+                // 处理日期解析异常
+                e.printStackTrace();
+            }
+        }
+        iStatisticManageService.executeTask(date);
     }
 
 }

+ 5 - 0
fs-service/src/main/java/com/fs/company/domain/CompanyDeptUserInfo.java

@@ -30,6 +30,11 @@ public class CompanyDeptUserInfo {
     */
    private String deptName;
 
+   /**
+    * 部门名称
+    */
+   private Long parentId;
+
    /**
     * 员工id
     */

+ 53 - 0
fs-service/src/main/java/com/fs/company/domain/CourseWatchLogData.java

@@ -0,0 +1,53 @@
+package com.fs.company.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * @description: 接受单个人查询的结果
+ * @author: Guos
+ * @time: 2025/11/10 上午9:52
+ */
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class CourseWatchLogData {
+
+
+    private Long companyUserId;
+
+    private Long videoId;
+
+    private Long courseId;
+
+    private String project;
+
+    private Integer logType;
+
+    private java.util.Date createTime;
+
+    private BigDecimal redPacketAmount;
+
+    private Integer redPacketNum;
+
+    private Integer answerNum;
+
+    // toString method
+    @Override
+    public String toString() {
+        return "CourseWatchLog{" +
+                "companyUserId=" + companyUserId +
+                ", videoId=" + videoId +
+                ", courseId=" + courseId +
+                ", project='" + project + '\'' +
+                ", logType='" + logType + '\'' +
+                ", createTime=" + createTime +
+                '}';
+    }
+
+}

+ 49 - 0
fs-service/src/main/java/com/fs/company/domain/CourseWatchLogStatistics.java

@@ -0,0 +1,49 @@
+package com.fs.company.domain;
+
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * @description: 统计表实体类
+ * @author: Guos
+ * @time: 2025/11/10 上午10:11
+ */
+@Data
+public class CourseWatchLogStatistics {
+
+    private Long id;
+
+    private Long companyUserId;
+
+    private Long companyId;
+
+    private Integer deptId;
+
+    private java.util.Date statisticsTime;
+
+    private Long courseId;
+
+    private Long videoId;
+
+    private Long projectId;
+
+    private Integer logType;
+
+    private Integer sendCount;
+
+    private Date createTime;
+
+    private Date updateTime;
+
+    private Integer answerNum;
+
+    private Integer redPacketNum;
+
+    private BigDecimal redPacketAmount;
+
+
+}

+ 0 - 42
fs-service/src/main/java/com/fs/company/dto/ComprehensiveStatisticsDTO.java

@@ -1,42 +0,0 @@
-package com.fs.company.dto;
-
-import lombok.Data;
-
-/**
- * @description:
- * @author: Guos
- * @time: 2025/11/3 下午3:24
- */
-@Data
-public class ComprehensiveStatisticsDTO {
-
-    /**
-     * 日期
-     */
-    private String dateStr;
-
-    /**
-     * 进线数量
-     */
-    private Long lineNum;
-
-    /**
-     * 激活数
-     */
-    private Long activeNum;
-
-    /**
-     * 完课数量
-     */
-    private Long completeNum;
-
-    /**
-     * 答题数量
-     */
-    private Long answerNum;
-
-    /**
-     * 红包数量
-     */
-    private Long redPacketNum;
-}

+ 60 - 0
fs-service/src/main/java/com/fs/company/mapper/CourseWatchLogStatisticsMapper.java

@@ -0,0 +1,60 @@
+package com.fs.company.mapper;
+
+import com.fs.company.domain.CourseWatchLogStatistics;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @description:
+ * @author: Guos
+ * @time: 2025/11/10 上午10:13
+ */
+public interface CourseWatchLogStatisticsMapper {
+
+    /**
+     * 插入新的课程观看统计记录
+     */
+    int insert(CourseWatchLogStatistics record);
+
+    /**
+     * 根据主键更新记录
+     */
+    int updateByPrimaryKey(CourseWatchLogStatistics record);
+
+    /**
+     * 根据主键删除记录
+     */
+    int deleteByPrimaryKey(Long id);
+
+    /**
+     * 根据主键查询记录
+     */
+    CourseWatchLogStatistics selectByPrimaryKey(Long id);
+
+    /**
+     * 根据公司员工ID查询记录
+     */
+    List<CourseWatchLogStatistics> selectByCompanyUserId(Long companyUserId);
+
+    /**
+     * 根据统计时间范围查询记录
+     */
+    List<CourseWatchLogStatistics> selectByStatisticsTimeRange(@Param("startTime") Date startTime,
+                                                            @Param("endTime") Date endTime);
+    /**
+     * 获取需要更新的数据
+     * @return
+     */
+    List<CourseWatchLogStatistics> getNeedUpdateData(@Param("statisticsTime") Date statisticsTime);
+
+    /**
+     * 按照公司、部门更新之前先删除数据
+     * @param deptId
+     * @param statisticsTime
+     */
+    Integer deleteByStatisticsTimeAndDeptId(@Param("userId")Long userId,
+                                            @Param("deptId") Long deptId,
+                                            @Param("statisticsTime") Date statisticsTime);
+}

+ 47 - 15
fs-service/src/main/java/com/fs/company/mapper/StatisticManageMapper.java

@@ -2,8 +2,10 @@ package com.fs.company.mapper;
 
 import com.fs.company.domain.CompanyDeptUserInfo;
 import com.fs.company.domain.ComprehensiveDailyStats;
+import com.fs.company.domain.CourseWatchLogData;
 import com.fs.company.dto.CompanyDeptUserInfoDTO;
-import com.fs.company.dto.ComprehensiveStatisticsDTO;
+import com.fs.statis.dto.ComprehensiveStatisticsDTO;
+import com.fs.statis.param.ComprehensiveStatisticsParam;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.Date;
@@ -61,13 +63,6 @@ public interface StatisticManageMapper {
      */
     Integer deleteById(@Param("id") Long id);
 
-    //获取公司、部门、员工信息
-    List<CompanyDeptUserInfo> getCompanyAndDeptAndDeptUserList(@Param("companyId") Long companyId);
-
-    List<CompanyDeptUserInfo> getCompanyInfo();
-
-    CompanyDeptUserInfoDTO getStatisticNum(@Param("userIds") Long userIds);
-
     /**
      * 按照个人统计
      * @param dimension 维度
@@ -85,13 +80,14 @@ public interface StatisticManageMapper {
      */
     List<ComprehensiveDailyStats> getStatisticNumByDeptId(@Param("startTime") Date startTime, @Param("endTime") Date endTime, @Param("deptIds") Long... deptIds);
 
-    /**
-     * 按照公司统计
-     * @param startTime
-     * @param endTime
-     * @param companyIds
-     */
-    List<ComprehensiveDailyStats> getStatisticNumByCompanyId(@Param("startTime") Date startTime, @Param("endTime") Date endTime, @Param("companyIds") Long... companyIds);
+    //========================
+
+    //获取公司、部门、员工信息
+    List<CompanyDeptUserInfo> getCompanyAndDeptAndDeptUserList(@Param("companyId") Long companyId);
+
+    List<CompanyDeptUserInfo> getCompanyInfo();
+
+    CompanyDeptUserInfoDTO getStatisticNum(@Param("userIds") Long userIds);
 
     /**
      * 根据公司id获取部门下拉搜索信息
@@ -105,4 +101,40 @@ public interface StatisticManageMapper {
      */
     List<CompanyDeptUserInfo> getSearchUserInfo(@Param("id") Long id);
 
+    /**
+     *
+     * 获取部门统计数据
+     * @param companyUserId
+     * @param dateTime
+     * @return
+     */
+    List<CourseWatchLogData> getCourseWatchLogData(@Param("companyUserId") Long companyUserId, @Param("dateTime") Date dateTime);
+
+    /**
+     *
+     * 获取部门统计数据
+     * @param companyUserId
+     * @param videoId
+     * @param dateTime
+     * @return
+     */
+    CourseWatchLogData getAnswerAndRedPacketData(@Param("companyUserId")Long companyUserId, @Param("videoId")Long videoId, @Param("dateTime") Date dateTime);
+
+    /**
+     * 按照部门获取数据
+     * @param param
+     */
+    ComprehensiveStatisticsDTO getStatisticDataByDeptId(ComprehensiveStatisticsParam param);
+
+    /**
+     * 根据用户id获取用户的详细信息
+     * @param id
+     */
+    CompanyDeptUserInfo getUserInfoByUserId(@Param("userId") Long id);
+
+    /**
+     * 根据用户id获取用户的详细信息
+     * @param id
+     */
+    CompanyDeptUserInfo getUserInfoByDeptId(@Param("deptId") Long id);
 }

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

@@ -3,6 +3,7 @@ package com.fs.company.service;
 import com.fs.company.domain.CompanyDeptUserInfo;
 import com.fs.statis.param.ComprehensiveStatisticsParam;
 
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -39,6 +40,6 @@ public interface IStatisticManageService {
     /**
      * 用来执行定时任务
      */
-    void executeTask();
+    void executeTask(Date dateTime);
 
 }

+ 359 - 89
fs-service/src/main/java/com/fs/company/service/impl/StatisticManageServiceImpl.java

@@ -3,22 +3,27 @@ package com.fs.company.service.impl;
 import cn.hutool.core.date.StopWatch;
 import com.fs.common.enums.DimensionEnum;
 import com.fs.company.domain.CompanyDeptUserInfo;
-import com.fs.company.domain.ComprehensiveDailyStats;
-import com.fs.company.dto.CompanyDeptUserInfoDTO;
+import com.fs.company.domain.CourseWatchLogData;
+import com.fs.company.domain.CourseWatchLogStatistics;
+import com.fs.company.mapper.CourseWatchLogStatisticsMapper;
 import com.fs.company.mapper.StatisticManageMapper;
 import com.fs.company.service.IStatisticManageService;
+import com.fs.statis.dto.ComprehensiveStatisticsDTO;
 import com.fs.statis.param.ComprehensiveStatisticsParam;
+import com.google.common.collect.Lists;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.ObjectUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.util.Assert;
 
 import javax.annotation.Resource;
 import java.math.BigDecimal;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
+
 /**
- * @description:
+ * @description: sql的代码以及整合了大部门,这里很多代码都可以整合按照不同的维度进行
  * @author: Guos
  * @time: 2025/10/30 上午9:21
  */
@@ -29,6 +34,9 @@ public class StatisticManageServiceImpl implements IStatisticManageService {
     @Resource
     private StatisticManageMapper statisticManageMapper;
 
+    @Resource
+    private CourseWatchLogStatisticsMapper courseWatchLogStatisticsMapper;
+
     /**
      * 统计
      * 按照部门分组情况
@@ -38,145 +46,407 @@ public class StatisticManageServiceImpl implements IStatisticManageService {
     public Object statisticMain(ComprehensiveStatisticsParam param) {
         if(param.getDimension() == DimensionEnum.COMPANY.getValue()){
             Assert.notNull(param.getId(), "按公司展示查询条件不能为空!");
-            return getStatisticNumByCompanyId(param.getStartTime(), param.getEndTime(), param.getId());
+            return getStatisticNumByCompanyId(param);
         }
         if(param.getDimension() == DimensionEnum.DEPARTMENT.getValue()){
             Assert.notNull(param.getId(), "按部门展示查询条件不能为空!");
-            return getStatisticNumByDeptId(param.getStartTime(), param.getEndTime(), param.getId());
+            return getStatisticNumByDeptId(param);
         }
         if (param.getDimension() == DimensionEnum.PERSONAL.getValue()){
             Assert.notNull(param.getId(), "按个人展示查询条件不能为空!");
-            return getStatisticNumByPersonal(DimensionEnum.PERSONAL.getValue(), param.getStartTime(), param.getEndTime(), param.getId());
+            return getStatisticNumByPersonal(param);
         }
         return null;
     }
 
     /**
-     * 获取搜索公司信息
+     * 获取个人统计数据
      */
-    @Override
-    public List<CompanyDeptUserInfo> getSearchCompanyInfo(){
-        return statisticManageMapper.getCompanyInfo();
+    public List getStatisticNumByDeptId(ComprehensiveStatisticsParam param){
+        //先获取部门下的用户的信息
+        Long id = param.getId();
+        List<CompanyDeptUserInfo> searchUserInfo = statisticManageMapper.getSearchUserInfo(id);
+        List result = Lists.newArrayList();
+        List<Date> dates = generateDateList(param.getStartTime(), param.getEndTime());
+        for (Date date : dates){
+            param.setStartTime(date);
+            param.setEndTime(date);
+            for (CompanyDeptUserInfo companyDeptUserInfo : searchUserInfo) {
+                String deptName = companyDeptUserInfo.getDeptName();
+                String companyName = companyDeptUserInfo.getCompanyName();
+                Long deptId = companyDeptUserInfo.getDeptId();
+                Long companyId = companyDeptUserInfo.getCompanyId();
+                param.setUserId(companyDeptUserInfo.getUserId());
+                ComprehensiveStatisticsDTO statisticDataByDeptId =
+                        statisticManageMapper.getStatisticDataByDeptId(param);
+                if(ObjectUtils.isEmpty(statisticDataByDeptId)){
+                    statisticDataByDeptId = new ComprehensiveStatisticsDTO();
+                    statisticDataByDeptId.setAnswerNum(BigDecimal.ZERO.intValue());
+                    statisticDataByDeptId.setRedPacketNum(BigDecimal.ZERO.intValue());
+                    statisticDataByDeptId.setSendCount(BigDecimal.ZERO.intValue());
+                    statisticDataByDeptId.setRedPacketAmount(BigDecimal.ZERO);
+                }
+                statisticDataByDeptId.setCompanyUserName(companyDeptUserInfo.getNickName());
+                statisticDataByDeptId.setCompanyUserId(companyDeptUserInfo.getUserId());
+                statisticDataByDeptId.setDeptName(deptName);
+                statisticDataByDeptId.setDeptId(deptId.intValue());
+                statisticDataByDeptId.setCompanyName(companyName);
+                statisticDataByDeptId.setCompanyId(companyId);
+                statisticDataByDeptId.setStatisticsTime(date);
+                result.add(statisticDataByDeptId);
+            }
+        }
+        return result;
     }
 
     /**
-     * 根据公司id获取部门下拉搜索信息
-     * @param id
+     * 获取个人统计数据
      */
-    @Override
-    public List<CompanyDeptUserInfo> getSearchDeptInfo(Long id){
-        return statisticManageMapper.getSearchDeptInfo(id);
+    public List getStatisticNumByPersonal(ComprehensiveStatisticsParam param){
+        //先获取用户的信息
+        Long id = param.getId();
+        CompanyDeptUserInfo userInfoByUserId = statisticManageMapper.getUserInfoByUserId(id);
+        List result = Lists.newArrayList();
+        List<Date> dates = generateDateList(param.getStartTime(), param.getEndTime());
+        for (Date date : dates){
+            param.setStartTime(date);
+            param.setEndTime(date);
+            param.setDeptId(userInfoByUserId.getDeptId());
+            param.setUserId(id);
+            ComprehensiveStatisticsDTO statisticDataByDeptId = statisticManageMapper.getStatisticDataByDeptId(param);
+            if(ObjectUtils.isEmpty(statisticDataByDeptId)){
+                statisticDataByDeptId = new ComprehensiveStatisticsDTO();
+                statisticDataByDeptId.setAnswerNum(BigDecimal.ZERO.intValue());
+                statisticDataByDeptId.setRedPacketNum(BigDecimal.ZERO.intValue());
+                statisticDataByDeptId.setSendCount(BigDecimal.ZERO.intValue());
+                statisticDataByDeptId.setRedPacketAmount(BigDecimal.ZERO);
+            }
+            statisticDataByDeptId.setDeptName(userInfoByUserId.getDeptName());
+            statisticDataByDeptId.setCompanyUserName(userInfoByUserId.getNickName());
+            statisticDataByDeptId.setCompanyUserId(userInfoByUserId.getUserId());
+            statisticDataByDeptId.setDeptName(userInfoByUserId.getDeptName());
+            statisticDataByDeptId.setDeptId(userInfoByUserId.getDeptId().intValue());
+            statisticDataByDeptId.setCompanyName(userInfoByUserId.getCompanyName());
+            statisticDataByDeptId.setCompanyId(userInfoByUserId.getCompanyId());
+            statisticDataByDeptId.setStatisticsTime(date);
+            result.add(statisticDataByDeptId);
+        }
+        return result;
     }
 
     /**
-     * 根据部门id获取用户下拉信息
-     * @param id
+     * 根据公司获取统计数据
      */
-    @Override
-    public List<CompanyDeptUserInfo> getSearchUserInfo(Long id){
-        return statisticManageMapper.getSearchUserInfo(id);
+    public List getStatisticNumByCompanyId(ComprehensiveStatisticsParam param){
+        //先从公司拿到公司和部门的信息
+        List<CompanyDeptUserInfo> searchDeptInfo = getSearchDeptInfo(param.getId());
+        List result = Lists.newArrayList();
+
+        List<Date> dates = generateDateList(param.getStartTime(), param.getEndTime());
+        for (Date date : dates){
+            param.setStartTime(date);
+            param.setEndTime(date);
+            for (CompanyDeptUserInfo companyDeptUserInfo : searchDeptInfo) {
+                String deptName = companyDeptUserInfo.getDeptName();
+                String companyName = companyDeptUserInfo.getCompanyName();
+                Long deptId = companyDeptUserInfo.getDeptId();
+                Long companyId = companyDeptUserInfo.getCompanyId();
+                param.setDeptId(deptId);
+                ComprehensiveStatisticsDTO statisticDataByDeptId =
+                        statisticManageMapper.getStatisticDataByDeptId(param);
+                if(ObjectUtils.isEmpty(statisticDataByDeptId)){
+                    statisticDataByDeptId = new ComprehensiveStatisticsDTO();
+                    statisticDataByDeptId.setAnswerNum(BigDecimal.ZERO.intValue());
+                    statisticDataByDeptId.setRedPacketNum(BigDecimal.ZERO.intValue());
+                    statisticDataByDeptId.setSendCount(BigDecimal.ZERO.intValue());
+                    statisticDataByDeptId.setRedPacketAmount(BigDecimal.ZERO);
+                }
+                statisticDataByDeptId.setDeptName(deptName);
+                statisticDataByDeptId.setDeptId(deptId.intValue());
+                statisticDataByDeptId.setCompanyName(companyName);
+                statisticDataByDeptId.setCompanyId(companyId);
+                statisticDataByDeptId.setStatisticsTime(date);
+                result.add(statisticDataByDeptId);
+            }
+        }
+        return result;
     }
 
     /**
-     * 获取个人统计数据
-     * @param dimension 维度
+     * 生成开始时间到结束时间之间的每日时间数组
      * @param startTime 开始时间
      * @param endTime 结束时间
-     * @param userIds 用户id
-     * @return
+     * @return 时间数组列表
      */
-    public List<ComprehensiveDailyStats> getStatisticNumByPersonal(Integer dimension, Date startTime, Date endTime, Long... userIds) {
-        return statisticManageMapper.getStatisticNumByPersonal(dimension, startTime, endTime, userIds);
+    public List<Date> generateDateList(Date startTime, Date endTime) {
+        List<Date> dateList = new ArrayList<>();
+        if (startTime == null || endTime == null) {
+            return dateList;
+        }
+
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(startTime);
+
+        // 设置时间为当天00:00:00,确保按天计算
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+
+        Date currentDate = calendar.getTime();
+        Date finalEndTime = getStartOfDay(endTime);
+
+        while (!currentDate.after(finalEndTime)) {
+            dateList.add(currentDate);
+            calendar.add(Calendar.DAY_OF_MONTH, 1);
+            currentDate = calendar.getTime();
+        }
+
+        return dateList;
     }
 
     /**
-     * 获取部门统计数据
-     * @param startTime 开始时间
-     * @param endTime 结束时间
-     * @param deptId 用户id
-     * @return
+     * 获取指定日期的开始时间(00:00:00)
+     * @param date 指定日期
+     * @return 当天开始时间
      */
-    public List<ComprehensiveDailyStats> getStatisticNumByDeptId(Date startTime, Date endTime, Long... deptId) {
-        return statisticManageMapper.getStatisticNumByDeptId(startTime, endTime, deptId);
+    private Date getStartOfDay(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        return calendar.getTime();
     }
 
     /**
-     * 获取部门统计数据
-     * @param startTime 开始时间
-     * @param endTime 结束时间
-     * @param deptId 用户id
-     * @return
+     * 获取搜索公司信息
+     */
+    @Override
+    public List<CompanyDeptUserInfo> getSearchCompanyInfo(){
+        return statisticManageMapper.getCompanyInfo();
+    }
+
+    /**
+     * 根据公司id获取部门下拉搜索信息
+     * @param id
+     */
+    @Override
+    public List<CompanyDeptUserInfo> getSearchDeptInfo(Long id){
+        return statisticManageMapper.getSearchDeptInfo(id);
+    }
+
+    /**
+     * 根据部门id获取用户下拉信息
+     * @param id
      */
-    public List<ComprehensiveDailyStats> getStatisticNumByCompanyId(Date startTime, Date endTime, Long... deptId) {
-        return statisticManageMapper.getStatisticNumByCompanyId(startTime, endTime, deptId);
+    @Override
+    public List<CompanyDeptUserInfo> getSearchUserInfo(Long id){
+        return statisticManageMapper.getSearchUserInfo(id);
     }
 
     /**
-     * 执行定时任务
+     * 执行定时任务3.0
+     * 公司,部门,人,【课程,项目,视频id】,【发送,看视频】,【答题,完课,红包领取,红包金额】
      * 还需要考虑在统计部门数据时,部门下面没有用户,某个时候这个部门下面又加入新的用户了,这个时候就会出现数据偏差
      */
     @Override
-    public void executeTask() {
+    public void executeTask(Date dateTime) {
         StopWatch stopWatch = new StopWatch();
         stopWatch.start("gs-执行数据统计任务");
         List<CompanyDeptUserInfo> companyDeptdUserList = statisticManageMapper.getCompanyAndDeptAndDeptUserList(null);
         log.info("统计人数列表:{}", companyDeptdUserList.size());
+        if(null == dateTime){
+            dateTime = new Date();
+        }
+        Date finalDateTime = dateTime;
         companyDeptdUserList.forEach(companyDeptUserInfo -> {
-            CompanyDeptUserInfoDTO statisticNum =  new CompanyDeptUserInfoDTO();
-            boolean empty = null == companyDeptUserInfo.getUserId(); //用户id为空返回true
-            if(!empty){
-                statisticNum = statisticManageMapper.getStatisticNum(companyDeptUserInfo.getUserId());
-            }
-            ComprehensiveDailyStats comprehensiveDailyStats = component(companyDeptUserInfo, statisticNum);
-            ComprehensiveDailyStats selectResult = null;
-            if(!empty){
-                //用户id不为空,我们就用用户id去查询这个日期是否有数据
-                selectResult = statisticManageMapper.selectByUserAndDate(comprehensiveDailyStats.getUserId(), comprehensiveDailyStats.getStatisticsTime());
-            }else{
-                //如果用户id为空,说明部门下面没有人(没人情况下,部门id只会在当天的日期中存在一条),先按照部门去查询后删除(或者直接按照id更新就可以了)
-                selectResult = statisticManageMapper.selectByDeptAndDate(companyDeptUserInfo.getDeptId(), comprehensiveDailyStats.getStatisticsTime());
-            }
-            if(!ObjectUtils.isEmpty(selectResult)){
-                comprehensiveDailyStats.setId(selectResult.getId());
-                statisticManageMapper.updateById(comprehensiveDailyStats);
+            Long userId = companyDeptUserInfo.getUserId();
+            courseWatchLogStatisticsMapper.deleteByStatisticsTimeAndDeptId(userId, companyDeptUserInfo.getDeptId(), finalDateTime);
+            //第一步通过人去查询【课程,项目,视频id】,【发送,看视频状态】
+            List<CourseWatchLogData> courseWatchLogData = statisticManageMapper.getCourseWatchLogData(userId, finalDateTime);
+            CourseWatchLogStatistics courseWatchLogStatistics = component(companyDeptUserInfo, finalDateTime);
+            if(CollectionUtils.isEmpty(courseWatchLogData)){
+                //如果为空,那么这个人其他数据都是0直接放入数据库
+                //TODO 需要判断当天是否有数据了,如果有数据,就需要更新(为空就刷新一下更新时间就可以了)
+                courseWatchLogStatisticsMapper.insert(courseWatchLogStatistics);
+                log.info("companyUserId:{}, 统计时间:{},无数据!", userId, finalDateTime);
             }else{
-                statisticManageMapper.insert(comprehensiveDailyStats);
+                //先按照project分组,这里过滤了为空的项目,有的数据project字段就是空的,这个统计时候去处理就麻烦了
+                Map<String, List<CourseWatchLogData>> projectIdCollect = courseWatchLogData.stream().filter(c -> c.getProject() != null)
+                        .collect(Collectors.groupingBy(CourseWatchLogData::getProject));
+                for (Map.Entry<String, List<CourseWatchLogData>> entry : projectIdCollect.entrySet()) {
+                    String projectId = entry.getKey();
+                    List<CourseWatchLogData> courseWatchLogDataList = entry.getValue();
+                    //有时候这个字段是空的
+                    courseWatchLogStatistics.setProjectId(Long.parseLong(projectId));
+                    int size = courseWatchLogDataList.size();
+                    if (size == 1) {
+                        CourseWatchLogData detail = courseWatchLogDataList.get(0);
+                        courseWatchLogStatistics.setCourseId(detail.getCourseId());
+                        courseWatchLogStatistics.setVideoId(detail.getVideoId());
+                        courseWatchLogStatistics.setLogType(detail.getLogType());
+                        courseWatchLogStatistics.setSendCount(1);
+                        courseWatchLogStatisticsMapper.insert(courseWatchLogStatistics);
+                    }else{
+                        //按照courseId分组
+                        Map<Long, List<CourseWatchLogData>> courseIdCollect = courseWatchLogDataList.stream()
+                                .collect(Collectors.groupingBy(CourseWatchLogData::getCourseId));
+                        for (Map.Entry<Long, List<CourseWatchLogData>> courseEntry : courseIdCollect.entrySet()) {
+                            Long courseId = courseEntry.getKey();
+                            List<CourseWatchLogData> byCourseIdList = courseEntry.getValue();
+                            courseWatchLogStatistics.setCourseId(courseId);
+                            int byCourseIdListSize = byCourseIdList.size();
+                            if(byCourseIdListSize == 1){
+                                CourseWatchLogData detail = courseWatchLogDataList.get(0);
+                                courseWatchLogStatistics.setVideoId(detail.getVideoId());
+                                courseWatchLogStatistics.setLogType(detail.getLogType());
+                                courseWatchLogStatistics.setSendCount(1);
+                                courseWatchLogStatisticsMapper.insert(courseWatchLogStatistics);
+                            }else{
+                                //按照VideoId分组
+                                Map<Long, List<CourseWatchLogData>> videoIdCollect = byCourseIdList.stream()
+                                        .collect(Collectors.groupingBy(CourseWatchLogData::getVideoId));
+                                for (Map.Entry<Long, List<CourseWatchLogData>> videoIdEntry : videoIdCollect.entrySet()) {
+                                    Long videoId = videoIdEntry.getKey();
+                                    List<CourseWatchLogData> byVideoIdList = videoIdEntry.getValue();
+                                    courseWatchLogStatistics.setVideoId(videoId);
+                                    int byVideoIdListSize = byVideoIdList.size();
+                                    if(byVideoIdListSize == 1){
+                                        CourseWatchLogData detail = courseWatchLogDataList.get(0);
+                                        courseWatchLogStatistics.setLogType(detail.getLogType());
+                                        courseWatchLogStatistics.setSendCount(1);
+                                        courseWatchLogStatisticsMapper.insert(courseWatchLogStatistics);
+                                    }else{
+                                        // 直接统计按照不同的logType进行数量统计
+                                        Map<Integer, List<CourseWatchLogData>> logTypeCollect = byVideoIdList.stream()
+                                                .collect(Collectors.groupingBy(CourseWatchLogData::getLogType));
+                                        for (Map.Entry<Integer, List<CourseWatchLogData>> logTypeEntry : logTypeCollect.entrySet()) {
+                                            Integer logType = logTypeEntry.getKey();
+                                            List<CourseWatchLogData> logTypeList = logTypeEntry.getValue();
+                                            courseWatchLogStatistics.setLogType(logType);
+                                            courseWatchLogStatistics.setSendCount(logTypeList.size());
+                                            courseWatchLogStatisticsMapper.insert(courseWatchLogStatistics);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                log.info("companyUserId:{}, 统计时间:{},有数据,数据条数:{}!", userId, finalDateTime, courseWatchLogData.size());
             }
         });
         stopWatch.stop();
+        stopWatch.start("反查数据更新红包等信息");
+        //上面代码其实都是差不多,为了方便之后优化代码,保持整个逻辑清晰,先将整个数据保存后,再反查数据将答题数量、红包领取数量,以及金额统计更新
+        updateCourseRedPacket(finalDateTime);
+        stopWatch.stop();
         log.info("gs-执行数据统计任务完成,耗时:{}", stopWatch.getTotalTimeSeconds());
     }
 
-    private ComprehensiveDailyStats component(CompanyDeptUserInfo source, CompanyDeptUserInfoDTO statisticNum){
-        ComprehensiveDailyStats target = new ComprehensiveDailyStats();
-        target.setCompanyId(source.getCompanyId());
-        target.setCompanyName(source.getCompanyName());
-        target.setDeptId(source.getDeptId());
-        target.setDeptName(source.getDeptName());
-        target.setStatisticsTime(new Date());
-        target.setCreateTime(new Date());
-        target.setUpdateTime(new Date());
-        if(null != source.getUserId()){
-            target.setUserId(source.getUserId());
-            target.setUserName(source.getUserName());
-            target.setNickName(source.getNickName());
-            target.setAnswerNum(statisticNum.getAnswerNum());
-            target.setCompleteNum(statisticNum.getCompleteNum());
-            target.setLineNum(statisticNum.getLineNum());
-            target.setActiveNum(statisticNum.getActiveNum());
-            target.setRedPacketNum(statisticNum.getRedPacketNum());
-            target.setRedPacketAmount(new BigDecimal(0.00));
-        }else{
-            target.setAnswerNum(0);
-            target.setCompleteNum(0);
-            target.setLineNum(0);
-            target.setActiveNum(0);
-            target.setRedPacketNum(0);
-            target.setRedPacketAmount(new BigDecimal(0.00));
+    /**
+     * 通过反查数据来更新红包信息
+     */
+    public void updateCourseRedPacket(Date dateTime){
+        List<CourseWatchLogStatistics> needUpdateData = courseWatchLogStatisticsMapper.getNeedUpdateData(dateTime);
+        for(CourseWatchLogStatistics courseWatchLogStatistics:needUpdateData){
+            CourseWatchLogData answerAndRedPacketData = statisticManageMapper.getAnswerAndRedPacketData(courseWatchLogStatistics.getCompanyUserId(),
+                    courseWatchLogStatistics.getVideoId(), dateTime);
+            courseWatchLogStatistics.setAnswerNum(answerAndRedPacketData.getAnswerNum());
+            courseWatchLogStatistics.setRedPacketNum(answerAndRedPacketData.getRedPacketNum());
+            courseWatchLogStatistics.setRedPacketAmount(answerAndRedPacketData.getRedPacketAmount());
+            courseWatchLogStatisticsMapper.updateByPrimaryKey(courseWatchLogStatistics);
         }
-      return target;
     }
 
+    //返回一个所有数据都是空的对象
+    public CourseWatchLogStatistics component(CompanyDeptUserInfo companyDeptUserInfo, Date dateTime){
+        CourseWatchLogStatistics build = new CourseWatchLogStatistics();
+                build.setCompanyId(companyDeptUserInfo.getCompanyId());
+                build.setCompanyUserId(companyDeptUserInfo.getUserId());
+                build.setDeptId(companyDeptUserInfo.getDeptId().intValue());
+                build.setStatisticsTime(dateTime);
+                build.setLogType(null);
+                build.setSendCount(null);
+                build.setProjectId(null);
+                build.setVideoId(null);
+                build.setCourseId(null);
+                build.setRedPacketAmount(BigDecimal.ZERO);
+                build.setAnswerNum(BigDecimal.ZERO.intValue());
+                build.setRedPacketNum(BigDecimal.ZERO.intValue());
+                build.setCreateTime(new Date());
+                build.setUpdateTime(new Date());
+        return build;
+    }
+
+
+//    /**
+//     * 执行定时任务
+//     * 还需要考虑在统计部门数据时,部门下面没有用户,某个时候这个部门下面又加入新的用户了,这个时候就会出现数据偏差
+//     */
+//    @Override
+//    public void executeTask() {
+//        StopWatch stopWatch = new StopWatch();
+//        stopWatch.start("gs-执行数据统计任务");
+//        List<CompanyDeptUserInfo> companyDeptdUserList = statisticManageMapper.getCompanyAndDeptAndDeptUserList(null);
+//        log.info("统计人数列表:{}", companyDeptdUserList.size());
+//        companyDeptdUserList.forEach(companyDeptUserInfo -> {
+//            CompanyDeptUserInfoDTO statisticNum =  new CompanyDeptUserInfoDTO();
+//            boolean empty = null == companyDeptUserInfo.getUserId(); //用户id为空返回true
+//            if(!empty){
+//                statisticNum = statisticManageMapper.getStatisticNum(companyDeptUserInfo.getUserId());
+//            }
+//            ComprehensiveDailyStats comprehensiveDailyStats = component(companyDeptUserInfo, statisticNum);
+//            ComprehensiveDailyStats selectResult = null;
+//            if(!empty){
+//                //用户id不为空,我们就用用户id去查询这个日期是否有数据
+//                selectResult = statisticManageMapper.selectByUserAndDate(comprehensiveDailyStats.getUserId(), comprehensiveDailyStats.getStatisticsTime());
+//            }else{
+//                //如果用户id为空,说明部门下面没有人(没人情况下,部门id只会在当天的日期中存在一条),先按照部门去查询后删除(或者直接按照id更新就可以了)
+//                selectResult = statisticManageMapper.selectByDeptAndDate(companyDeptUserInfo.getDeptId(), comprehensiveDailyStats.getStatisticsTime());
+//            }
+//            if(!ObjectUtils.isEmpty(selectResult)){
+//                comprehensiveDailyStats.setId(selectResult.getId());
+//                statisticManageMapper.updateById(comprehensiveDailyStats);
+//            }else{
+//                statisticManageMapper.insert(comprehensiveDailyStats);
+//            }
+//        });
+//        stopWatch.stop();
+//        log.info("gs-执行数据统计任务完成,耗时:{}", stopWatch.getTotalTimeSeconds());
+//    }
+//
+//    private ComprehensiveDailyStats component(CompanyDeptUserInfo source, CompanyDeptUserInfoDTO statisticNum){
+//        ComprehensiveDailyStats target = new ComprehensiveDailyStats();
+//        target.setCompanyId(source.getCompanyId());
+//        target.setCompanyName(source.getCompanyName());
+//        target.setDeptId(source.getDeptId());
+//        target.setDeptName(source.getDeptName());
+//        target.setStatisticsTime(new Date());
+//        target.setCreateTime(new Date());
+//        target.setUpdateTime(new Date());
+//        if(null != source.getUserId()){
+//            target.setUserId(source.getUserId());
+//            target.setUserName(source.getUserName());
+//            target.setNickName(source.getNickName());
+//            target.setAnswerNum(statisticNum.getAnswerNum());
+//            target.setCompleteNum(statisticNum.getCompleteNum());
+//            target.setLineNum(statisticNum.getLineNum());
+//            target.setActiveNum(statisticNum.getActiveNum());
+//            target.setRedPacketNum(statisticNum.getRedPacketNum());
+//            target.setRedPacketAmount(new BigDecimal(0.00));
+//        }else{
+//            target.setAnswerNum(0);
+//            target.setCompleteNum(0);
+//            target.setLineNum(0);
+//            target.setActiveNum(0);
+//            target.setRedPacketNum(0);
+//            target.setRedPacketAmount(new BigDecimal(0.00));
+//        }
+//      return target;
+//    }
 
 }
 

+ 40 - 0
fs-service/src/main/java/com/fs/statis/dto/ComprehensiveStatisticsDTO.java

@@ -0,0 +1,40 @@
+package com.fs.statis.dto;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * @description:
+ * @author: Guos
+ * @time: 2025/11/11 下午1:29
+ */
+@Data
+public class ComprehensiveStatisticsDTO {
+
+    private Long companyId;
+
+    private String companyName;
+
+    private Long companyUserId;
+
+    private String companyUserName;
+
+    private Integer deptId;
+
+    private String deptName;
+
+    private Integer sendCount;
+
+    private Integer logType;
+
+    private Integer answerNum;
+
+    private Integer redPacketNum;
+
+    private BigDecimal redPacketAmount;
+
+    private Date statisticsTime;
+
+}

+ 17 - 0
fs-service/src/main/java/com/fs/statis/param/ComprehensiveStatisticsParam.java

@@ -36,5 +36,22 @@ public class ComprehensiveStatisticsParam {
      * id 在不同的维度下,id代表的意义不同
      */
     private Long id;
+
+    private Long deptId;
+
+    private Long userId;
+
+    private Long videoId;
+
+    private Long courseId;
+
+    private Long projectId;
+
+    private String companyName;
+
+    private String deptName;
+
+    private Long logType;
+
 }
 

+ 146 - 0
fs-service/src/main/resources/mapper/company/CourseWatchLogStatisticsMapper.xml

@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.fs.company.mapper.CourseWatchLogStatisticsMapper">
+
+    <!-- 结果映射 -->
+    <resultMap id="BaseResultMap" type="CourseWatchLogStatistics">
+        <id column="id" property="id" />
+        <result column="company_user_id" property="companyUserId" />
+        <result column="company_id" property="companyId" />
+        <result column="dept_id" property="deptId" />
+        <result column="statistics_time" property="statisticsTime" />
+        <result column="course_id" property="courseId" />
+        <result column="video_id" property="videoId" />
+        <result column="project_id" property="projectId" />
+        <result column="log_type" property="logType" />
+        <result column="send_count" property="sendCount" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+    </resultMap>
+
+    <!-- 插入记录 -->
+    <insert id="insert" parameterType="CourseWatchLogStatistics">
+        INSERT INTO fs_statistics(
+            id,
+            company_user_id,
+            company_id,
+            dept_id,
+            statistics_time,
+            course_id,
+            video_id,
+            project_id,
+            log_type,
+            answer_num,
+            red_packet_num,
+            red_packet_amount,
+            send_count,
+            create_time,
+            update_time
+        ) VALUES (
+            #{id},
+            #{companyUserId},
+            #{companyId},
+            #{deptId},
+            #{statisticsTime},
+            #{courseId},
+            #{videoId},
+            #{projectId},
+            #{logType},
+            #{answerNum},
+            #{redPacketNum},
+            #{redPacketAmount},
+            #{sendCount},
+            #{createTime},
+            #{updateTime}
+        )
+    </insert>
+
+    <!-- 根据主键更新 -->
+    <update id="updateByPrimaryKey" parameterType="CourseWatchLogStatistics">
+        UPDATE fs_statistics
+        <set>
+            <if test="companyUserId != null">company_user_id = #{companyUserId},</if>
+            <if test="companyId != null">company_id = #{companyId},</if>
+            <if test="deptId != null">dept_id = #{deptId},</if>
+            <if test="statisticsTime != null">statistics_time = #{statisticsTime},</if>
+            <if test="courseId != null">course_id = #{courseId},</if>
+            <if test="videoId != null">video_id = #{videoId},</if>
+            <if test="projectId != null">project_id = #{projectId},</if>
+            <if test="logType != null">log_type = #{logType},</if>
+            <if test="answerNum != null">answer_num = #{answerNum},</if>
+            <if test="redPacketNum != null">red_packet_num = #{redPacketNum},</if>
+            <if test="redPacketAmount != null">red_packet_amount = #{redPacketAmount},</if>
+            <if test="sendCount != null">send_count = #{sendCount},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+        </set>
+        WHERE id = #{id}
+    </update>
+
+    <!-- 根据主键删除 -->
+    <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
+        DELETE FROM fs_statistics WHERE id = #{id}
+    </delete>
+
+    <!-- 根据主键查询 -->
+    <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
+        SELECT * FROM fs_statistics WHERE id = #{id}
+    </select>
+
+    <!-- 根据公司员工ID查询 -->
+    <select id="selectByCompanyUserId" parameterType="java.lang.Long" resultMap="BaseResultMap">
+        SELECT * FROM fs_statistics WHERE company_user_id = #{companyUserId}
+    </select>
+
+    <!-- 根据统计时间范围查询 -->
+    <select id="selectByStatisticsTimeRange" resultMap="BaseResultMap">
+        SELECT * FROM fs_statistics
+        WHERE statistics_time BETWEEN #{startTime} AND #{endTime}
+    </select>
+
+    <resultMap id="getNeedUpDataMap" type="com.fs.company.domain.CourseWatchLogStatistics">
+        <id column="id" property="id" />
+        <result column="company_user_id" property="companyUserId" />
+        <result column="company_id" property="companyId" />
+        <result column="dept_id" property="deptId" />
+        <result column="project_id" property="projectId" />
+        <result column="course_id" property="courseId" />
+        <result column="video_id" property="videoId" />
+        <result column="statistics_time" property="statisticsTime" />
+    </resultMap>
+
+    <select id="getNeedUpdateData" resultMap="getNeedUpDataMap">
+        SELECT
+            fs.id,
+            fs.company_user_id,
+            fs.company_id,
+            fs.dept_id,
+            fs.project_id,
+            fs.course_id,
+            fs.video_id,
+            fs.statistics_time
+        FROM
+            fs_statistics AS fs
+        WHERE
+            fs.company_user_id IS NOT NULL
+          AND fs.video_id IS NOT NULL
+          AND fs.log_type = 2
+          and DATE_FORMAT(fs.statistics_time, '%Y-%m-%d' ) = DATE_FORMAT(#{statisticsTime}, '%Y-%m-%d')
+    </select>
+
+    <delete id="deleteByStatisticsTimeAndDeptId">
+        DELETE FROM fs_statistics
+        <where>
+            dept_id = #{deptId}
+            and DATE_FORMAT(statistics_time, '%Y-%m-%d' ) = DATE_FORMAT(#{statisticsTime}, '%Y-%m-%d')
+            <if test="userId != null">
+                and  company_user_id = #{userId}
+            </if>
+        </where>
+    </delete>
+
+
+
+</mapper>

+ 186 - 48
fs-service/src/main/resources/mapper/company/StatisticManageMapper.xml

@@ -4,34 +4,6 @@
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.fs.company.mapper.StatisticManageMapper">
 
-    <resultMap id="CompanyDeptUserListMap" type="com.fs.company.domain.CompanyDeptUserInfo">
-        <id column="company_id" property="companyId" />
-        <result column="company_name" property="companyName"/>
-        <result column="dept_id" property="deptId"/>
-        <result column="dept_name" property="deptName"/>
-        <result column="user_id" property="userId"/>
-        <result column="user_name" property="userName"/>
-        <result column="nick_name" property="nickName"/>
-    </resultMap>
-
-    <select id="getCompanyAndDeptAndDeptUserList" resultMap="CompanyDeptUserListMap">
-        SELECT
-            ci.company_id,
-            ci.company_name,
-            cd.dept_id,
-            cd.dept_name,
-            cu.user_id,
-            cu.user_name,
-            cu.nick_name
-        FROM company AS ci
-        LEFT JOIN company_dept AS cd ON ci.company_id = cd.company_id AND cd.STATUS = 0
-        LEFT JOIN company_user AS cu ON cu.dept_id = cd.dept_id AND cu.del_flag = 0
-        WHERE ci.is_del = 0 AND cd.del_flag = 0
-        <if test="companyId != null">
-            and ci.company_id = #{companyId}
-        </if>
-    </select>
-
     <select id="getStatisticNum" resultType="com.fs.company.dto.CompanyDeptUserInfoDTO">
         WITH t1 AS (
             SELECT
@@ -58,17 +30,6 @@
         SELECT * FROM t1,t2,t3,t4,t5
     </select>
 
-
-    <select id="getCompanyInfo" resultType="com.fs.company.domain.CompanyDeptUserInfo">
-        SELECT
-            ci.company_id,
-            ci.company_name
-        FROM
-            company AS ci
-        WHERE
-            ci.is_del = 0
-    </select>
-
     <!-- 基础字段映射(复用) -->
     <sql id="Base_Column_List">
         id, company_id, company_name, dept_id, dept_name, 
@@ -95,15 +56,6 @@
         </where>
     </select>
 
-    <select id="getStatisticNumByCompanyId" resultType="com.fs.company.domain.ComprehensiveDailyStats">
-        select <include refid="Base_Column_List"/> from user_daily_stats as uds
-        <where>
-            uds.company_id = #{companyIds[0]}
-            and statistics_time >=date_format(#{startTime},'%y%m%d')
-            and statistics_time &lt;= date_format(#{endTime},'%y%m%d')
-        </where>
-    </select>
-
     <!-- 1. 插入数据(全字段插入) -->
     <insert id="insert" parameterType="com.fs.company.domain.ComprehensiveDailyStats">
         INSERT INTO user_daily_stats (
@@ -238,4 +190,190 @@
         DELETE FROM user_daily_stats WHERE user_id = #{userId} AND statistics_time = date_format(#{statisticsTime},'%y%m%d')
     </delete>
 
+<!--   上面的方法需要逐个删除 -->
+
+    <resultMap id="CompanyDeptUserListMap" type="com.fs.company.domain.CompanyDeptUserInfo">
+        <id column="company_id" property="companyId" />
+        <result column="company_name" property="companyName"/>
+        <result column="dept_id" property="deptId"/>
+        <result column="dept_name" property="deptName"/>
+        <result column="parent_id" property="parentId"/>
+        <result column="user_id" property="userId"/>
+        <result column="user_name" property="userName"/>
+        <result column="nick_name" property="nickName"/>
+    </resultMap>
+    
+    <select id="getCompanyAndDeptAndDeptUserList" resultMap="CompanyDeptUserListMap">
+        SELECT
+            ci.company_id,
+            ci.company_name,
+            cd.dept_id,
+            cd.dept_name,
+            cd.parent_id,
+            cu.user_id,
+            cu.user_name,
+            cu.nick_name
+        FROM company AS ci
+        LEFT JOIN company_dept AS cd ON ci.company_id = cd.company_id AND cd.STATUS = 0
+        LEFT JOIN company_user AS cu ON cu.dept_id = cd.dept_id AND cu.del_flag = 0
+        WHERE ci.is_del = 0 AND cd.del_flag = 0
+        <if test="companyId != null">
+            and ci.company_id = #{companyId}
+        </if>
+    </select>
+
+    <select id="getCompanyInfo" resultMap="CompanyDeptUserListMap">
+        SELECT
+            ci.company_id,
+            ci.company_name
+        FROM
+            company AS ci
+        WHERE
+            ci.is_del = 0
+    </select>
+
+    <select id="getSearchDeptInfo" resultMap="CompanyDeptUserListMap">
+        SELECT
+            ci.company_id,
+            ci.company_name,
+            cd.parent_id,
+            cd.dept_id,
+            cd.dept_name
+        FROM company AS ci
+        LEFT JOIN company_dept AS cd ON ci.company_id = cd.company_id AND cd.STATUS = 0
+        where ci.company_id = #{id}
+    </select>
+
+    <select id="getSearchUserInfo" resultMap="CompanyDeptUserListMap">
+        SELECT
+            ci.company_id,
+            ci.company_name,
+            cd.dept_id,
+            cd.dept_name,
+            cu.user_id,
+            cu.user_name,
+            cu.nick_name
+        FROM company AS ci
+                 LEFT JOIN company_dept AS cd ON ci.company_id = cd.company_id AND cd.STATUS = 0
+                 LEFT JOIN company_user AS cu ON cu.dept_id = cd.dept_id AND cu.del_flag = 0
+        WHERE ci.is_del = 0 AND cd.del_flag = 0 and cu.dept_id = #{id}
+    </select>
+
+    <select id="getCourseWatchLogData" resultType="com.fs.company.domain.CourseWatchLogData">
+        SELECT
+            company_user_id,
+            video_id,
+            course_id,
+            project,
+            log_type,
+            create_time
+        FROM
+            fs_course_watch_log
+        WHERE
+            company_user_id = #{companyUserId}
+          and DATE_FORMAT(create_time, '%Y-%m-%d') = DATE_FORMAT(#{dateTime}, '%Y-%m-%d')
+    </select>
+
+    <select id="getAnswerAndRedPacketData" resultType="com.fs.company.domain.CourseWatchLogData">
+        WITH t1 as (
+            SELECT
+                count(DISTINCT fcal.watch_log_id) as answer_num
+            FROM
+                fs_course_answer_logs AS fcal
+            WHERE
+                fcal.company_user_id = #{companyUserId}
+              and fcal.video_id = #{videoId}
+              AND DATE_FORMAT( fcal.create_time, '%Y-%m-%d') = DATE_FORMAT(#{dateTime}, '%Y-%m-%d')
+        ),t2 as (
+            SELECT
+                fcrpl.log_id,
+                fcrpl.amount
+            FROM
+                fs_course_red_packet_log AS fcrpl
+            WHERE
+                fcrpl.company_user_id =  #{companyUserId}
+              AND fcrpl.video_id =  #{videoId}
+              AND DATE_FORMAT(fcrpl.create_time, '%Y-%m-%d') = DATE_FORMAT(#{dateTime}, '%Y-%m-%d')
+        ),
+             t3 AS ( SELECT count(t2.log_id)  as red_packet_num FROM t2 ),
+             t4 AS ( SELECT sum(t2.amount) as red_packet_amount FROM t2 )
+        SELECT #{companyUserId}, t1.* , t3.* , t4.* FROM t1, t3, t4
+    </select>
+
+    <select id="getStatisticDataByDeptId" resultType="com.fs.statis.dto.ComprehensiveStatisticsDTO">
+        SELECT
+            SUM(IFNULL(fs.send_count, 0)) as sendCount,
+            SUM(IFNULL(fs.log_type, 0)) as logType,
+            SUM(IFNULL(fs.answer_num, 0)) as answerNum,
+            SUM(IFNULL(fs.red_packet_num, 0)) as redPacketNum,
+            SUM(IFNULL(fs.red_packet_amount, 0)) as redPacketAmount,
+            fs.statistics_time
+        FROM
+        fs_statistics AS fs
+        WHERE
+          DATE_FORMAT(fs.statistics_time, '%Y-%m-%d' ) >= DATE_FORMAT(#{startTime}, '%Y-%m-%d' )
+          ANd DATE_FORMAT(fs.statistics_time, '%Y-%m-%d' ) &lt;= DATE_FORMAT(#{endTime}, '%Y-%m-%d' )
+        <if test="deptId != null">
+             and fs.dept_id = #{deptId}
+        </if>
+        <if test="userId != null">
+            and fs.company_user_id =#{userId}
+        </if>
+        <if test="videoId != null">
+            and fs.video_id = #{videoId}
+        </if>
+        <if test="projectId != null">
+            and fs.project_id= #{projectId}
+        </if>
+        <if test="logType != null">
+            and fs.log_type = #{logType}
+        </if>
+        <if test="courseId != null">
+            and fs.course_id = #{courseId}
+        </if>
+        GROUP BY fs.statistics_time
+        order by fs.statistics_time
+        <if test="dimension != null">
+            <if test="dimension == 2">
+                , fs.dept_id
+            </if>
+            <if test="dimension == 3">
+                , fs.company_user_id
+            </if>
+        </if>
+    </select>
+
+    <select id="getUserInfoByUserId" resultMap="CompanyDeptUserListMap">
+        select
+            c.company_id,
+            c.company_name,
+            cd.dept_id,
+            cd.dept_name,
+            cd.parent_id,
+            cu.user_id,
+            cu.user_name,
+            cu.nick_name
+        from company_user as cu
+        left join company_dept as cd on cu.dept_id = cd.dept_id AND cd.STATUS = 0
+        left join company as c on c.company_id = cd.company_id and c.is_del = 0
+        where cu.user_id = #{userId}
+    </select>
+
+    <select id="getUserInfoByDeptId" resultType="com.fs.company.domain.CompanyDeptUserInfo">
+        select
+            c.company_id,
+            c.company_name,
+            cd.dept_id,
+            cd.dept_name,
+            cd.parent_id,
+            cu.user_id,
+            cu.user_name,
+            cu.nick_name
+        from company_dept as cd
+        left join company as c on cd.company_id = c.company_id and c.is_del = 0
+        left join company_user as cu on cu.dept_id = cd.dept_id AND cu.del_flag = 0
+        where cd.dept_id = #{deptId}
+    </select>
+
+
 </mapper>