wangxy 1 неделя назад
Родитель
Сommit
b519d11364

+ 149 - 97
fs-admin/src/main/java/com/fs/company/controller/CompanyStatisticsController.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 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.utils.StringUtils;
 import com.fs.common.utils.TimeUtils;
 import com.fs.common.utils.poi.ExcelUtil;
@@ -28,10 +29,7 @@ import com.fs.his.service.IFsPackageOrderService;
 import com.fs.his.service.IFsStoreAfterSalesService;
 import com.fs.his.service.IFsStoreOrderService;
 import com.fs.his.service.IFsStorePaymentService;
-import com.fs.his.vo.FsCourseReportVO;
-import com.fs.his.vo.FsOrderReportVO;
-import com.fs.his.vo.FsStoreOrderAmountScrmStatsVo;
-import com.fs.his.vo.FsStoreOrderAmountStatsVo;
+import com.fs.his.vo.*;
 import com.fs.hisStore.service.IFsStoreOrderScrmService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -715,42 +713,43 @@ public class CompanyStatisticsController extends BaseController {
      * @return
      */
     @GetMapping("/orderReport")
-    public AjaxResult selectFsOrderReportVO(FsPackageOrderParam param) {
+    public TableDataInfo selectFsOrderReportVO(FsPackageOrderParam param) {
+        startPage();
         List<FsOrderReportVO> list = fsPackageOrderService.selectFsOrderReportVO(param);
-        // 创建合计对象
-        FsOrderReportVO totalVo = new FsOrderReportVO();
-        // 计算各项订单数总和
-        totalVo.setInquiryOrderCount(list.stream()
-                .mapToLong(FsOrderReportVO::getInquiryOrderCount)
-                .sum());
-
-        totalVo.setIntegralOrderCount(list.stream()
-                .mapToLong(FsOrderReportVO::getIntegralOrderCount)
-                .sum());
-
-        totalVo.setPackageOrderCount(list.stream()
-                .mapToLong(FsOrderReportVO::getPackageOrderCount)
-                .sum());
-
-        // 计算各项金额总和
-        totalVo.setInquiryOrderAmount(list.stream()
-                .map(FsOrderReportVO::getInquiryOrderAmount)
-                .filter(Objects::nonNull)
-                .reduce(BigDecimal.ZERO, BigDecimal::add));
-
-        totalVo.setIntegralOrderAmount(list.stream()
-                .map(FsOrderReportVO::getIntegralOrderAmount)
-                .filter(Objects::nonNull)
-                .reduce(BigDecimal.ZERO, BigDecimal::add));
-
-        totalVo.setPackageOrderAmount(list.stream()
-                .map(FsOrderReportVO::getPackageOrderAmount)
-                .filter(Objects::nonNull)
-                .reduce(BigDecimal.ZERO, BigDecimal::add));
-        Map<String, Object> result = new HashMap<>();
-        result.put("data", list);
-        result.put("total", totalVo);
-        return AjaxResult.success(result);
+//        // 创建合计对象
+//        FsOrderReportVO totalVo = new FsOrderReportVO();
+//        // 计算各项订单数总和
+//        totalVo.setInquiryOrderCount(list.stream()
+//                .mapToLong(FsOrderReportVO::getInquiryOrderCount)
+//                .sum());
+//
+//        totalVo.setIntegralOrderCount(list.stream()
+//                .mapToLong(FsOrderReportVO::getIntegralOrderCount)
+//                .sum());
+//
+//        totalVo.setPackageOrderCount(list.stream()
+//                .mapToLong(FsOrderReportVO::getPackageOrderCount)
+//                .sum());
+//
+//        // 计算各项金额总和
+//        totalVo.setInquiryOrderAmount(list.stream()
+//                .map(FsOrderReportVO::getInquiryOrderAmount)
+//                .filter(Objects::nonNull)
+//                .reduce(BigDecimal.ZERO, BigDecimal::add));
+//
+//        totalVo.setIntegralOrderAmount(list.stream()
+//                .map(FsOrderReportVO::getIntegralOrderAmount)
+//                .filter(Objects::nonNull)
+//                .reduce(BigDecimal.ZERO, BigDecimal::add));
+//
+//        totalVo.setPackageOrderAmount(list.stream()
+//                .map(FsOrderReportVO::getPackageOrderAmount)
+//                .filter(Objects::nonNull)
+//                .reduce(BigDecimal.ZERO, BigDecimal::add));
+//        Map<String, Object> result = new HashMap<>();
+//        result.put("data", list);
+//        result.put("total", totalVo);
+        return getDataTable(list);
     }
 
     /**
@@ -760,65 +759,118 @@ public class CompanyStatisticsController extends BaseController {
      * @return
      */
     @GetMapping("/courseReport")
-    public AjaxResult selectFsCourseReportVO(FsCourseWatchLogStatisticsListParam param) {
+    public TableDataInfo selectFsCourseReportVO(FsCourseWatchLogStatisticsListParam param) {
+        startPage();
         List<FsCourseReportVO> fsCourseReportVOS = fsCourseWatchLogService.selectFsCourseReportVO(param);
-        // 创建合计对象
-        FsCourseReportVO totalVo = new FsCourseReportVO();
-        totalVo.setCompanyName("总计");
-
-        // 计算各项人数总和
-        totalVo.setAccessCount(fsCourseReportVOS.stream()
-                .mapToInt(FsCourseReportVO::getAccessCount)
-                .sum());
-
-        totalVo.setPendingCount(fsCourseReportVOS.stream()
-                .mapToInt(FsCourseReportVO::getPendingCount)
-                .sum());
-
-        totalVo.setWatchingCount(fsCourseReportVOS.stream()
-                .mapToInt(FsCourseReportVO::getWatchingCount)
-                .sum());
-
-        totalVo.setFinishedCount(fsCourseReportVOS.stream()
-                .mapToInt(FsCourseReportVO::getFinishedCount)
-                .sum());
-
-        totalVo.setInterruptedCount(fsCourseReportVOS.stream()
-                .mapToInt(FsCourseReportVO::getInterruptedCount)
-                .sum());
-
-        totalVo.setAnswerUserCount(fsCourseReportVOS.stream()
-                .mapToInt(FsCourseReportVO::getAnswerUserCount)
-                .sum());
-
-        totalVo.setPacketUserCount(fsCourseReportVOS.stream()
-                .mapToInt(FsCourseReportVO::getPacketUserCount)
-                .sum());
-
-        // 计算金额总和
-        totalVo.setPacketAmount(fsCourseReportVOS.stream()
-                .map(FsCourseReportVO::getPacketAmount)
-                .filter(Objects::nonNull)
-                .reduce(BigDecimal.ZERO, BigDecimal::add));
-
-        // 重新计算总体看课率和完课率
-        int totalCount = totalVo.getAccessCount();
-        if (totalCount > 0) {
-            BigDecimal watchRate = new BigDecimal((totalVo.getWatchingCount() + totalVo.getFinishedCount()) * 100.0 / totalCount)
-                    .setScale(2, BigDecimal.ROUND_HALF_UP);
-            totalVo.setWatchRate(watchRate);
-
-            BigDecimal finishRate = new BigDecimal(totalVo.getFinishedCount() * 100.0 / totalCount)
-                    .setScale(2, BigDecimal.ROUND_HALF_UP);
-            totalVo.setFinishRate(finishRate);
-        } else {
-            totalVo.setWatchRate(BigDecimal.ZERO);
-            totalVo.setFinishRate(BigDecimal.ZERO);
-        }
+//        // 创建合计对象
+//        FsCourseReportVO totalVo = new FsCourseReportVO();
+//        totalVo.setCompanyName("总计");
+//
+//        // 计算各项人数总和
+//        totalVo.setAccessCount(fsCourseReportVOS.stream()
+//                .mapToInt(FsCourseReportVO::getAccessCount)
+//                .sum());
+//
+//        totalVo.setPendingCount(fsCourseReportVOS.stream()
+//                .mapToInt(FsCourseReportVO::getPendingCount)
+//                .sum());
+//
+//        totalVo.setWatchingCount(fsCourseReportVOS.stream()
+//                .mapToInt(FsCourseReportVO::getWatchingCount)
+//                .sum());
+//
+//        totalVo.setFinishedCount(fsCourseReportVOS.stream()
+//                .mapToInt(FsCourseReportVO::getFinishedCount)
+//                .sum());
+//
+//        totalVo.setInterruptedCount(fsCourseReportVOS.stream()
+//                .mapToInt(FsCourseReportVO::getInterruptedCount)
+//                .sum());
+//
+//        totalVo.setAnswerUserCount(fsCourseReportVOS.stream()
+//                .mapToInt(FsCourseReportVO::getAnswerUserCount)
+//                .sum());
+//
+//        totalVo.setPacketUserCount(fsCourseReportVOS.stream()
+//                .mapToInt(FsCourseReportVO::getPacketUserCount)
+//                .sum());
+//
+//        // 计算金额总和
+//        totalVo.setPacketAmount(fsCourseReportVOS.stream()
+//                .map(FsCourseReportVO::getPacketAmount)
+//                .filter(Objects::nonNull)
+//                .reduce(BigDecimal.ZERO, BigDecimal::add));
+//
+//        // 重新计算总体看课率和完课率
+//        int totalCount = totalVo.getAccessCount();
+//        if (totalCount > 0) {
+//            BigDecimal watchRate = new BigDecimal((totalVo.getWatchingCount() + totalVo.getFinishedCount()) * 100.0 / totalCount)
+//                    .setScale(2, BigDecimal.ROUND_HALF_UP);
+//            totalVo.setWatchRate(watchRate);
+//
+//            BigDecimal finishRate = new BigDecimal(totalVo.getFinishedCount() * 100.0 / totalCount)
+//                    .setScale(2, BigDecimal.ROUND_HALF_UP);
+//            totalVo.setFinishRate(finishRate);
+//        } else {
+//            totalVo.setWatchRate(BigDecimal.ZERO);
+//            totalVo.setFinishRate(BigDecimal.ZERO);
+//        }
+//
+//        Map<String, Object> result = new HashMap<>();
+//        result.put("data", fsCourseReportVOS);
+//        result.put("total", totalVo);
+        return getDataTable(fsCourseReportVOS);
+    }
 
-        Map<String, Object> result = new HashMap<>();
-        result.put("data", fsCourseReportVOS);
-        result.put("total", totalVo);
-        return AjaxResult.success(result);
+    /**
+     * 用户统计报表
+     *
+     * @param param
+     * @return
+     */
+    @GetMapping("/userReport")
+    public TableDataInfo selectFsUserReportVO(FsCourseWatchLogStatisticsListParam param) {
+        startPage();
+        List<FsUserReportVO> list = fsCourseWatchLogService.selectFsUserReportVO(param);
+//        // 创建合计对象
+//        FsUserReportVO totalVo = new FsUserReportVO();
+//        totalVo.setCompanyName("总计"); // 或其他标识符表示这是合计行
+//
+//        // 对各个数值型字段进行求和计算
+//        totalVo.setWatchCount(list.stream()
+//                .mapToInt(FsUserReportVO::getWatchCount)
+//                .sum());
+//
+//        totalVo.setAbsentCount(list.stream()
+//                .mapToInt(FsUserReportVO::getAbsentCount)
+//                .sum());
+//
+//        totalVo.setPeriodCount(list.stream()
+//                .mapToInt(FsUserReportVO::getPeriodCount)
+//                .sum());
+//
+//        totalVo.setConsumedIntegral(list.stream()
+//                .mapToInt(FsUserReportVO::getConsumedIntegral)
+//                .sum());
+//
+//
+//        totalVo.setReceivedAmount(list.stream()
+//                .map(FsUserReportVO::getReceivedAmount)
+//                .filter(Objects::nonNull)
+//                .reduce(BigDecimal.ZERO, BigDecimal::add));
+//
+//        totalVo.setOrderAmount(list.stream()
+//                .map(FsUserReportVO::getOrderAmount)
+//                .filter(Objects::nonNull)
+//                .reduce(BigDecimal.ZERO, BigDecimal::add));
+//
+//        totalVo.setIntegral(list.stream()
+//                .mapToInt(FsUserReportVO::getIntegral)
+//                .sum());
+//
+//        Map<String, Object> result = new HashMap<>();
+//        result.put("data", list);
+//        result.put("total", totalVo);
+        return getDataTable(list);
     }
 }

+ 30 - 30
fs-admin/src/main/java/com/fs/his/controller/FsPackageOrderController.java

@@ -73,37 +73,37 @@ public class FsPackageOrderController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('his:packageOrder:report')")
     @GetMapping("/packageOrderReport")
-    public AjaxResult  selectFsPackageOrderReportVO(FsPackageOrderParam param){
+    public TableDataInfo  selectFsPackageOrderReportVO(FsPackageOrderParam param){
         List<FsPackageOrderReportVO> list = fsPackageOrderService.selectFsPackageOrderReportVO(param);
-        // 计算合计数据
-        FsPackageOrderReportVO totalVo = new FsPackageOrderReportVO();
-        // 计算订单数总和
-        totalVo.setOrderNum(list.stream()
-                .mapToLong(FsPackageOrderReportVO::getOrderNum)
-                .sum());
-
-        // 计算金额总和
-        totalVo.setMoney(list.stream()
-                .map(FsPackageOrderReportVO::getMoney)
-                .filter(Objects::nonNull)
-                .reduce(BigDecimal.ZERO, BigDecimal::add));
-
-        // 计算确认收货订单数总和
-        totalVo.setReceiptOrder(list.stream()
-                .mapToLong(FsPackageOrderReportVO::getReceiptOrder)
-                .sum());
-
-        // 计算确认收货金额总和
-        totalVo.setReceiptMoney(list.stream()
-                .map(FsPackageOrderReportVO::getReceiptMoney)
-                .filter(Objects::nonNull)
-                .reduce(BigDecimal.ZERO, BigDecimal::add));
-
-        // 返回包含数据列表和合计信息的结构
-        Map<String, Object> result = new HashMap<>();
-        result.put("dataList", list);
-        result.put("total", totalVo);
-        return AjaxResult.success(result);
+//        // 计算合计数据
+//        FsPackageOrderReportVO totalVo = new FsPackageOrderReportVO();
+//        // 计算订单数总和
+//        totalVo.setOrderNum(list.stream()
+//                .mapToLong(FsPackageOrderReportVO::getOrderNum)
+//                .sum());
+//
+//        // 计算金额总和
+//        totalVo.setMoney(list.stream()
+//                .map(FsPackageOrderReportVO::getMoney)
+//                .filter(Objects::nonNull)
+//                .reduce(BigDecimal.ZERO, BigDecimal::add));
+//
+//        // 计算确认收货订单数总和
+//        totalVo.setReceiptOrder(list.stream()
+//                .mapToLong(FsPackageOrderReportVO::getReceiptOrder)
+//                .sum());
+//
+//        // 计算确认收货金额总和
+//        totalVo.setReceiptMoney(list.stream()
+//                .map(FsPackageOrderReportVO::getReceiptMoney)
+//                .filter(Objects::nonNull)
+//                .reduce(BigDecimal.ZERO, BigDecimal::add));
+//
+//        // 返回包含数据列表和合计信息的结构
+//        Map<String, Object> result = new HashMap<>();
+//        result.put("dataList", list);
+//        result.put("total", totalVo);
+        return getDataTable(list);
     }
 
 

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

@@ -6,6 +6,7 @@ import com.fs.course.dto.WatchLogDTO;
 import com.fs.course.param.*;
 import com.fs.course.vo.*;
 import com.fs.his.vo.FsCourseReportVO;
+import com.fs.his.vo.FsUserReportVO;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.param.QwSidebarStatsParam;
 import com.fs.sop.vo.QwRatingVO;
@@ -566,4 +567,6 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
      * @return
      */
     List<FsCourseReportVO>  selectFsCourseReportVO(FsCourseWatchLogStatisticsListParam param);
+
+    List<FsUserReportVO>  selectFsUserReportVO(FsCourseWatchLogStatisticsListParam param);
 }

+ 14 - 1
fs-service/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.core.domain.BaseEntity;
 import com.fs.common.utils.DateUtils;
 import lombok.Data;
 
@@ -8,7 +9,7 @@ import java.util.Date;
 import java.util.List;
 
 @Data
-public class FsCourseWatchLogStatisticsListParam {
+public class FsCourseWatchLogStatisticsListParam extends BaseEntity {
 
     private Long companyId;
     private Long companyUserId;
@@ -52,4 +53,16 @@ public class FsCourseWatchLogStatisticsListParam {
      * 营期id
      */
     private  Long periodId;
+
+    /**
+     * 手机号
+     */
+    private  String userPhone;
+
+    /**
+     * 部门id
+     */
+    private Long deptId;
+
+
 }

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

@@ -5,6 +5,7 @@ import com.fs.course.domain.FsCourseWatchLog;
 import com.fs.course.param.*;
 import com.fs.course.vo.*;
 import com.fs.his.vo.FsCourseReportVO;
+import com.fs.his.vo.FsUserReportVO;
 import com.fs.qw.param.QwSidebarStatsParam;
 import com.fs.qw.vo.QwWatchLogStatisticsListVO;
 
@@ -147,4 +148,11 @@ public interface IFsCourseWatchLogService extends IService<FsCourseWatchLog> {
      * @return
      */
     List<FsCourseReportVO> selectFsCourseReportVO(FsCourseWatchLogStatisticsListParam param);
+
+    /**
+     * 会员积分统计报表
+     * @param param
+     * @return
+     */
+    List<FsUserReportVO> selectFsUserReportVO(FsCourseWatchLogStatisticsListParam param);
 }

+ 11 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java

@@ -29,7 +29,9 @@ import com.fs.his.config.FsSysConfig;
 import com.fs.his.domain.FsUser;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.utils.ConfigUtil;
+import com.fs.his.utils.PhoneUtil;
 import com.fs.his.vo.FsCourseReportVO;
+import com.fs.his.vo.FsUserReportVO;
 import com.fs.qw.Bean.MsgBean;
 import com.fs.qw.cache.IQwExternalContactCacheService;
 import com.fs.qw.cache.IQwUserCacheService;
@@ -1288,5 +1290,14 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
         return fsCourseWatchLogMapper.selectFsCourseReportVO(param);
     }
 
+    @Override
+    public List<FsUserReportVO> selectFsUserReportVO(FsCourseWatchLogStatisticsListParam param) {
+        if(StringUtils.isNotEmpty(param.getUserPhone())){
+            //加密手机号
+            param.setUserPhone(PhoneUtil.encryptPhone(param.getUserPhone()));
+        }
+        return fsCourseWatchLogMapper.selectFsUserReportVO(param);
+    }
+
 
 }

+ 70 - 1
fs-service/src/main/java/com/fs/his/vo/FsUserReportVO.java

@@ -2,6 +2,9 @@ package com.fs.his.vo;
 
 import lombok.Data;
 
+import java.math.BigDecimal;
+import java.util.Date;
+
 @Data
 public class FsUserReportVO {
 
@@ -13,7 +16,7 @@ public class FsUserReportVO {
     private String nickName;
 
     /** 1为正常,0为禁止 */
-    private Integer status;
+    private String status;
 
     /**
      * 所属销售
@@ -21,4 +24,70 @@ public class FsUserReportVO {
     private String companyUserName;
 
 
+    /**
+     * 所属销售公司
+     */
+    private String companyName;
+
+    /**
+     * 注册时间
+     */
+    private Date registerDate;
+
+    /**
+     * 最近看课时间
+     */
+    private  Date lastWatchTime;
+
+
+    /**
+     *  看课数
+     */
+    private  Integer watchCount;
+
+
+    /**
+     * 缺课数
+     */
+    private  Integer absentCount;
+
+    /**
+     * 参与营期数量
+     */
+    private  Integer  periodCount;
+
+
+    /**
+     * 观看状态
+     */
+    private  String watchStatus;
+
+    /**
+     * 消耗积分
+     */
+    private  Integer consumedIntegral;
+
+    /**
+     * 已领红包金额
+     */
+    private BigDecimal receivedAmount;
+
+    /**
+     * 已产生订单金额
+     */
+    private  BigDecimal orderAmount;
+
+    /**
+     * 积分
+     */
+    private  Integer  Integral;
+
+    /**
+     * 部门名称
+     */
+    private  String  deptName;
+    /**
+     * 首次进线时间
+     */
+    private  Date firstTime;
 }

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

@@ -1136,5 +1136,184 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         ORDER BY COALESCE(watch.today_access_count, 0) DESC
 
     </select>
+    <select id="selectFsUserReportVO" resultType="com.fs.his.vo.FsUserReportVO">
+        SELECT
+        u.user_id userId,
+        u.nick_name AS nickName,
+        CASE
+        WHEN u.`status` = '1' THEN '正常'
+        WHEN u.`status` = '2' THEN '禁止'
+        ELSE '无'
+        END AS status,
+        cu.nick_name AS companyUserName,
+        c.company_name AS companyName,
+        u.register_date AS registerDate,
+        min(u.register_date) as firstTime,
+        watch_stats.last_watch_time AS lastWatchTime,
+        COALESCE(watch_stats.watch_count, 0) AS watchCount,
+        COALESCE(watch_stats.absent_count, 0) AS absentCount,
+        CASE
+        WHEN watch_stats.last_watch_status = '1' THEN '看课中'
+        WHEN watch_stats.last_watch_status = '2' THEN '完课'
+        WHEN watch_stats.last_watch_status = '3' THEN '待看课'
+        WHEN watch_stats.last_watch_status = '4' THEN '看课中断'
+        ELSE '无'
+        END AS watchStatus,
+        COALESCE(period_stats.period_count, 0) AS periodCount,
+        COALESCE(integral_stats.consumed_integral, 0) AS consumedIntegral,
+         COALESCE(integral_stats.total_integral, 0) as  Integral,
+        COALESCE(redpacket_stats.received_amount, 0) AS receivedAmount,
+        COALESCE(ordertable.order_amount,0) as orderAmount
+        <if test="deptId != null">
+            ,cd.dept_name AS deptName
+        </if>
+        FROM fs_user u
+        LEFT JOIN fs_user_company_user cuu ON u.user_id = cuu.user_id
+        LEFT JOIN company_user cu ON cuu.company_user_id = cu.user_id
+        LEFT JOIN company c on cuu.company_id=c.company_id
+        <if test="deptId != null">
+            LEFT JOIN company_dept cd ON c.company_id = cd.company_id
+        </if>
+        <!-- 通过看课记录关联营期和训练营 -->
+        LEFT JOIN fs_course_watch_log watch_log ON u.user_id = watch_log.user_id
+        LEFT JOIN fs_user_course_period cp ON watch_log.period_id = cp.period_id
+        LEFT JOIN fs_user_course_training_camp camp ON cp.training_camp_id = camp.training_camp_id
+
+        <!-- 看课统计预聚合 -->
+        LEFT JOIN (
+        SELECT
+        user_id,
+        MAX(CASE WHEN log_type = 1 THEN create_time END) AS last_watch_time,
+        COUNT(DISTINCT CASE WHEN log_type = 1 THEN log_id END) AS watch_count,
+        COUNT(DISTINCT CASE WHEN log_type = 3 THEN log_id END) AS absent_count,
+        (SELECT log_type FROM fs_course_watch_log w2 WHERE w2.user_id = w1.user_id ORDER BY create_time DESC LIMIT 1) AS
+        last_watch_status
+        FROM fs_course_watch_log w1
+        <where>
+            <if test="sTime != null and eTime != null">
+                AND create_time BETWEEN #{sTime} AND #{eTime}
+            </if>
+            <!-- 营期条件应用到看课记录 -->
+            <if test="periodId != null">
+                AND period_id = #{periodId}
+            </if>
+            <if test="trainingCampId != null">
+                AND period_id IN (
+                SELECT period_id FROM fs_user_course_period
+                WHERE training_camp_id = #{trainingCampId}
+                )
+            </if>
+        </where>
+        GROUP BY user_id
+        ) AS watch_stats ON u.user_id = watch_stats.user_id
+
+        <!-- 营期数量预聚合 - 通过看课记录关联fs_user_course_period -->
+        LEFT JOIN (
+        SELECT
+        wl.user_id,
+        COUNT(DISTINCT ucp.period_id) AS period_count
+        FROM fs_course_watch_log wl
+        INNER JOIN fs_user_course_period ucp ON wl.period_id = ucp.period_id AND ucp.del_flag = 0
+        <where>
+            <if test="periodId != null">
+                AND ucp.period_id = #{periodId}
+            </if>
+            <if test="trainingCampId != null">
+                AND ucp.period_id IN (
+                SELECT period_id FROM fs_user_course_period
+                WHERE training_camp_id = #{trainingCampId}
+                )
+            </if>
+        </where>
+        GROUP BY wl.user_id
+        ) AS period_stats ON u.user_id = period_stats.user_id
+
+        <!-- 积分统计预聚合 -->
+        LEFT JOIN (
+        SELECT
+        user_id,
+        SUM(integral) AS total_integral,
+        ABS(SUM(CASE WHEN integral &lt; 0 THEN integral ELSE 0 END)) AS consumed_integral
+        FROM fs_user_integral_logs
+        <where>
+            <if test="sTime != null and eTime != null">
+                AND create_time BETWEEN #{sTime} AND #{eTime}
+            </if>
+        </where>
+        GROUP BY user_id
+        ) AS integral_stats ON u.user_id = integral_stats.user_id
+
+        <!-- 红包统计预聚合 -->
+        LEFT JOIN (
+        SELECT
+        user_id,
+        SUM(amount) AS received_amount
+        FROM fs_course_red_packet_log
+        WHERE status = 1
+        <if test="sTime != null and eTime != null">
+            AND create_time BETWEEN #{sTime} AND #{eTime}
+        </if>
+        GROUP BY user_id
+        ) AS redpacket_stats ON u.user_id = redpacket_stats.user_id
+
+        <!-- 订单统计 -->
+        LEFT JOIN(
+        SELECT
+        user_id,
+        SUM(pay_money) as order_amount
+        FROM fs_package_order
+        WHERE `status`=3
+        <if test="sTime != null and eTime != null">
+            AND create_time BETWEEN #{sTime} AND #{eTime}
+        </if>
+        GROUP BY user_id
+        ) as ordertable on u.user_id=ordertable.user_id
+
+        <where>
+            u.user_id IS NOT NULL
+
+            <!-- 销售公司条件 -->
+            <if test="companyId != null and companyId != ''">
+                AND c.company_id = #{companyId}
+            </if>
+
+            <if test="project != null">
+                AND cuu.project_id = #{project}
+            </if>
+
+            <!-- 训练营条件 -->
+            <if test="trainingCampId != null">
+                AND camp.training_camp_id = #{trainingCampId}
+            </if>
+
+            <!-- 营期条件 -->
+            <if test="periodId != null">
+                AND cp.period_id = #{periodId}
+            </if>
+
+            <!-- 时间范围 - 使用BETWEEN -->
+            <if test="sTime != null and eTime != null">
+                AND u.register_date BETWEEN #{sTime} AND #{eTime}
+            </if>
+
+
+            <!-- 会员条件 -->
+            <if test="userId != null">
+                AND u.user_id = #{userId}
+            </if>
+            <if test="userPhone != null and userPhone != ''">
+                AND u.phone LIKE CONCAT('%', #{userPhone}, '%')
+            </if>
+            <if test="nickName != null and nickName != ''">
+                AND u.nick_name LIKE CONCAT('%', #{nickName}, '%')
+            </if>
+            <!-- 部门条件 -->
+            <if test="deptId != null">
+                AND cd.dept_id = #{deptId}
+            </if>
+        </where>
+        GROUP BY u.user_id
+        ORDER BY u.register_date DESC
+    </select>
 
 </mapper>