Explorar el Código

Merge remote-tracking branch 'origin/Payment-Configuration' into Payment-Configuration

yys hace 3 semanas
padre
commit
2b3b769e70

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

@@ -336,7 +336,7 @@ public class FsUserCourseVideoController extends AppBaseController {
         return ResponseResult.ok(liveService.getGotoWxAppLiveLink(linkStr,appid));
     }
 
-    @ApiOperation("会员批量发送课程消息")
+    @ApiOperation("会员批量发送课程消息 发课")
     @PostMapping("/batchSendCourse")
     public OpenImResponseDTO batchSendCourse(@RequestBody BatchSendCourseDTO batchSendCourseDTO) throws JsonProcessingException {
         // 生成看课短链

+ 28 - 0
fs-company/src/main/java/com/fs/app/controller/statistic/courseStatisticController.java

@@ -14,6 +14,7 @@ import com.fs.course.service.IFsCourseWatchLogService;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
 import com.fs.his.vo.AppCourseReportVO;
+import com.fs.his.vo.AppSalesCourseStatisticsVO;
 import com.fs.his.vo.AppSalesWatchLogReportVO;
 import com.fs.his.vo.AppWatchLogReportVO;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -162,4 +163,31 @@ public class courseStatisticController extends BaseController {
     }
 
 
+    /**
+     * APP 端看课统计(销售维度)
+     * 对应前端页面:appWatchCourseStatistics.vue
+     */
+    @GetMapping("/appWatchCourseStatistics")
+    public TableDataInfo appWatchCourseStatistics(FsCourseWatchLogStatisticsListParam param) {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        List<AppSalesCourseStatisticsVO> list = courseWatchLogService.selectAppSalesCourseStatisticsVO(param);
+        return getDataTable(list);
+    }
+
+    /**
+     * APP 端看课统计导出(销售维度)
+     */
+    @Log(title = "APP 看课统计", businessType = BusinessType.EXPORT)
+    @GetMapping("/appWatchCourseStatisticsExport")
+    public AjaxResult appWatchCourseStatisticsExport(FsCourseWatchLogStatisticsListParam param) {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        List<AppSalesCourseStatisticsVO> list = courseWatchLogService.selectAppSalesCourseStatisticsVO(param);
+
+        ExcelUtil<AppSalesCourseStatisticsVO> util = new ExcelUtil<AppSalesCourseStatisticsVO>(AppSalesCourseStatisticsVO.class);
+        return util.exportExcel(list, "APP 看课统计报表");
+    }
+
+
 }

+ 4 - 0
fs-service/src/main/java/com/fs/course/mapper/FsCourseAnswerLogsMapper.java

@@ -2,7 +2,9 @@ package com.fs.course.mapper;
 
 import com.fs.course.domain.FsCourseAnswerLogs;
 import com.fs.course.param.FsCourseAnswerLogsParam;
+import com.fs.course.param.FsCourseWatchLogStatisticsListParam;
 import com.fs.course.vo.FsCourseAnswerLogsListVO;
+import com.fs.his.vo.AppSalesCourseStatisticsVO;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 
@@ -153,4 +155,6 @@ public interface FsCourseAnswerLogsMapper
      * @return 删除的行数
      */
     int batchDeleteByIds(@Param("ids") List<Long> ids);
+
+    List<AppSalesCourseStatisticsVO> selectAppSalesAnswerStatisticsVO(FsCourseWatchLogStatisticsListParam param);
 }

+ 4 - 0
fs-service/src/main/java/com/fs/course/mapper/FsCourseRedPacketLogMapper.java

@@ -10,10 +10,12 @@ import com.fs.course.domain.FsCourseRedPacketLog;
 import com.fs.course.dto.CourseRedPacketStatisticsDTO;
 import com.fs.course.param.CourseRedPacketStatisticsParam;
 import com.fs.course.param.FsCourseRedPacketLogParam;
+import com.fs.course.param.FsCourseWatchLogStatisticsListParam;
 import com.fs.course.param.FsUserCourseOrderParam;
 import com.fs.course.vo.FsCourseRedPacketLogListPVO;
 import com.fs.course.vo.FsCourseRedPacketLogListVO;
 import com.fs.course.vo.FsUserCourseOrderListPVO;
+import com.fs.his.vo.AppSalesCourseStatisticsVO;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 
@@ -207,4 +209,6 @@ public interface FsCourseRedPacketLogMapper
     int batchDeleteByIds(@Param("ids") List<Long> ids);
 
     BigDecimal getTodaySumAmountByCompanyUserId(Long userId);
+
+    List<AppSalesCourseStatisticsVO> selectAppSalesRedPacketStatisticsVO(FsCourseWatchLogStatisticsListParam param);
 }

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

@@ -5,10 +5,7 @@ import com.fs.course.domain.FsCourseWatchLog;
 import com.fs.course.dto.WatchLogDTO;
 import com.fs.course.param.*;
 import com.fs.course.vo.*;
-import com.fs.his.vo.AppCourseReportVO;
-import com.fs.his.vo.AppSalesWatchLogReportVO;
-import com.fs.his.vo.AppWatchLogReportVO;
-import com.fs.his.vo.WatchLogReportVO;
+import com.fs.his.vo.*;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.param.QwSidebarStatsParam;
 import com.fs.sop.vo.QwRatingVO;
@@ -808,4 +805,6 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
      * 销售部门维度订单统计
      */
     List<AppSalesWatchLogReportVO> selectAppDeptOrderStats(FsCourseWatchLogStatisticsListParam param);
+
+    List<AppSalesCourseStatisticsVO> selectAppSalesCourseStatisticsVO(FsCourseWatchLogStatisticsListParam param);
 }

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

@@ -46,8 +46,8 @@ public class FsCourseWatchLogStatisticsListParam {
 
     private Long project;
 
-    private Long pageNum;
-    private Long pageSize;
+    private Integer pageNum;
+    private Integer pageSize;
 
     private Integer sendType; //归属发送方式:1 个微  2 企微
 

+ 5 - 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.AppCourseReportVO;
+import com.fs.his.vo.AppSalesCourseStatisticsVO;
 import com.fs.his.vo.AppSalesWatchLogReportVO;
 import com.fs.his.vo.AppWatchLogReportVO;
 import com.fs.qw.param.QwSidebarStatsParam;
@@ -182,4 +183,8 @@ public interface IFsCourseWatchLogService extends IService<FsCourseWatchLog> {
     List<AppWatchLogReportVO> selectUserAppWatchLogReportVO(FsCourseWatchLogStatisticsListParam param);
 
     List<AppSalesWatchLogReportVO> selectAppSalesWatchLogReportVO(FsCourseWatchLogStatisticsListParam param);
+
+
+    // 在 IFsCourseWatchLogService.java 中添加
+    List<AppSalesCourseStatisticsVO> selectAppSalesCourseStatisticsVO(FsCourseWatchLogStatisticsListParam param);
 }

+ 38 - 5
fs-service/src/main/java/com/fs/course/service/impl/FsCourseWatchLogServiceImpl.java

@@ -37,10 +37,7 @@ import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.utils.ConfigUtil;
 import com.fs.his.utils.PhoneUtil;
-import com.fs.his.vo.AppCourseReportVO;
-import com.fs.his.vo.AppSalesWatchLogReportVO;
-import com.fs.his.vo.AppWatchLogReportVO;
-import com.fs.his.vo.WatchLogReportVO;
+import com.fs.his.vo.*;
 import com.fs.qw.Bean.MsgBean;
 import com.fs.qw.cache.IQwExternalContactCacheService;
 import com.fs.qw.cache.IQwUserCacheService;
@@ -90,6 +87,8 @@ import java.util.concurrent.Executors;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
+import static com.github.pagehelper.page.PageMethod.startPage;
+
 /**
  * 短链课程看课记录Service业务层处理
  *
@@ -101,6 +100,11 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
     private static final Logger log = LoggerFactory.getLogger(FsCourseWatchLogServiceImpl.class);
     @Autowired
     private FsCourseWatchLogMapper fsCourseWatchLogMapper;
+
+    @Autowired
+    private FsCourseAnswerLogsMapper fsCourseAnswerLogsMapper;
+    @Autowired
+    private FsCourseRedPacketLogMapper fsCourseRedPacketLogMapper;
     @Autowired
     private SopUserLogsMapper sopUserLogsMapper;
 
@@ -1514,7 +1518,7 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
                         pageNum, queryLog.getBeginTime(), queryLog.getEndTime());
 
                 // 使用分页查询
-                PageHelper.startPage(pageNum, pageSize);
+                startPage(pageNum, pageSize);
                 List<FsCourseWatchLog> fsCourseWatchLogs = fsCourseWatchLogMapper.selectFsCourseWatchLogList(queryLog);
 
                 if (fsCourseWatchLogs == null || fsCourseWatchLogs.isEmpty()) {
@@ -1873,6 +1877,35 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
         }
     }
 
+
+    /**
+     * @Description: app 看课统计
+     * @Param:
+     * @Return:
+     * @Author xgb
+     * @Date 2026/3/23 16:10
+     */
+
+    @Override
+    public List<AppSalesCourseStatisticsVO> selectAppSalesCourseStatisticsVO(FsCourseWatchLogStatisticsListParam param) {
+
+        // 课程统计
+        List<AppSalesCourseStatisticsVO> list = fsCourseWatchLogMapper.selectAppSalesCourseStatisticsVO(param);
+
+        // 答题统计
+        List<AppSalesCourseStatisticsVO> answerList = fsCourseAnswerLogsMapper.selectAppSalesAnswerStatisticsVO(param);
+
+        // 红包统计
+        List<AppSalesCourseStatisticsVO> redPacketList = fsCourseRedPacketLogMapper.selectAppSalesRedPacketStatisticsVO(param);
+
+
+
+
+
+
+        return Collections.emptyList();
+    }
+
     /**
      * 销售维度APP看课统计报表
      */

+ 75 - 0
fs-service/src/main/java/com/fs/his/vo/AppSalesCourseStatisticsVO.java

@@ -0,0 +1,75 @@
+package com.fs.his.vo;
+
+import com.fs.common.annotation.Excel;
+
+import java.math.BigDecimal;
+
+/**
+ * @description: TODO
+ * @author: Xgb
+ * @createDate: 2026/3/23
+ * @version: 1.0
+ */
+public class AppSalesCourseStatisticsVO {
+        /** 销售名称 */
+        @Excel(name = "销售名称")
+        private String salesName;
+
+        // APP 会员数
+        private Long appUserCount;
+
+        // 新注册 APP 会员数
+        private Long newAppUserCount;
+
+
+        /** 发课时间 */
+        @Excel(name = "发课时间", dateFormat = "yyyy-MM-dd")
+        private String sendTime;
+
+        /** 课程名称 */
+        @Excel(name = "课程名称")
+        private String courseName;
+
+        /** 课程小节 */
+        @Excel(name = "课程小节")
+        private String videoTitle;
+
+        /** 完课数 */
+        @Excel(name = "完课数")
+        private Integer finishedCount;
+
+        /** 完课率 */
+        @Excel(name = "完课率")
+        private BigDecimal completionRate;
+
+        /** 未看课数 */
+        @Excel(name = "未看课数")
+        private Integer notWatchedCount;
+
+        /** 中断数 */
+        @Excel(name = "中断数")
+        private Integer interruptCount;
+
+        /** 看课中数 */
+        @Excel(name = "看课中数")
+        private Integer watchingCount;
+
+        /** 答题数 */
+        @Excel(name = "答题数")
+        private Integer answeredCount;
+
+        /** 答题数 */
+        @Excel(name = "答题数")
+        private Integer correctCount;
+
+
+        /** 完课率 */
+        @Excel(name = "完课率")
+        private BigDecimal correctRate;
+
+        /** 红包金额 */
+        @Excel(name = "红包金额")
+        private BigDecimal redPacketAmount;
+
+    }
+

+ 2 - 2
fs-service/src/main/java/com/fs/im/service/impl/FsImMsgSendLogServiceImpl.java

@@ -155,7 +155,7 @@ public class FsImMsgSendLogServiceImpl extends ServiceImpl<FsImMsgSendLogMapper,
             if(sendCourseMap != null && !sendCourseMap.isEmpty()){
                 // 组合key
                 if(fsImMsgSendLog.getPlanSendTime() != null) {
-                    String key = fsImMsgSendLog.getCourseId() + ":" + fsImMsgSendLog.getVideoId() + ":" + fsImMsgSendLog.getPlanSendTime().getTime();
+                    String key = fsImMsgSendLog.getCourseId() + ":" + fsImMsgSendLog.getVideoId() + ":" + fsImMsgSendLog.getPlanSendTime().getTime()+ ":"+fsImMsgSendLog.getLogId();
                     redisTemplate.opsForHash().delete(sendCourseRedisKey, key);
                 }
             }
@@ -166,7 +166,7 @@ public class FsImMsgSendLogServiceImpl extends ServiceImpl<FsImMsgSendLogMapper,
                 // 组合key
                 for (FsImMsgSendLog imMsgSendLog : fsImMsgSendLogs) {
                     if(imMsgSendLog.getPlanSendTime() != null && imMsgSendLog.getMsgType() == 2) {
-                        String key = imMsgSendLog.getCourseId() + ":" + imMsgSendLog.getVideoId() + ":" + imMsgSendLog.getPlanSendTime().getTime();
+                        String key = imMsgSendLog.getCourseId() + ":" + imMsgSendLog.getVideoId() + ":" + imMsgSendLog.getPlanSendTime().getTime()+ ":"+fsImMsgSendLog.getLogId();
                         redisTemplate.opsForHash().delete(urgeCourseRedisKey, key);
                     }
                 }

+ 1 - 3
fs-service/src/main/java/com/fs/im/service/impl/OpenIMServiceImpl.java

@@ -1241,11 +1241,10 @@ public class OpenIMServiceImpl implements OpenIMService {
                             .setProject(project)
                             .setImMsgSendDetailList(imMsgSendDetailList);
 
-                    // 使用唯一的 key:课程 ID+ 视频 ID+ 时间戳 + 批次索引 +logId
+                    // 使用唯一的 key:课程 ID+ 视频 ID+ 时间戳  +logId
                     String batchKey = batchSendCourseDTO.getCourseId() + ":" +
                             batchSendCourseDTO.getVideoId() + ":" +
                             batchSendCourseDTO.getSendTime().getTime() + ":" +
-                            i + ":" +
                             imMsgSendDetailList.get(0).getLogId();
 
                     redisMap.put(batchKey, batchSendCourseAllDTO);
@@ -1329,7 +1328,6 @@ public class OpenIMServiceImpl implements OpenIMService {
                     String batchKey = batchSendCourseDTO.getCourseId() + ":" +
                             batchSendCourseDTO.getVideoId() + ":" +
                             batchSendCourseDTO.getUrgeTime().getTime() + ":" +
-                            i + ":" +
                             imMsgSendDetailUrgeList.get(0).getLogId();
 
                     redisMap.put(batchKey, batchSendCourseAllDTO);

+ 27 - 0
fs-service/src/main/resources/mapper/course/FsCourseAnswerLogsMapper.xml

@@ -217,6 +217,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             and period_id = #{periodId}
         </if>
     </select>
+
     <insert id="batchInsert" parameterType="java.util.List">
         insert into fs_course_answer_logs_1
         (
@@ -258,4 +259,30 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{id}
         </foreach>
     </delete>
+
+
+    <select id="selectAppSalesAnswerStatisticsVO" resultType="com.fs.his.vo.AppSalesCourseStatisticsVO">
+        select cal.company_user_id,cal.course_id,cal.video_id
+        count(cal.log_id) AS correctCount,
+        SUM(CASE WHEN cal.is_right = 1 THEN 1 ELSE 0 END)  AS  correctCount
+        from fs_course_answer_logs cal
+         <where>
+            <if test="companyId != null ">
+                and cal.company_id = #{companyId}
+            </if>
+            <if test="companyUserId != null ">
+                and cal.company_user_id = #{companyUserId}
+            </if>
+            <if test="courseId != null ">
+                and cal.course_id = #{courseId}
+            </if>
+            <if test="videoId != null ">
+                and cal.video_id = #{videoId}
+            </if>
+            <if test="startDate != null and startDate != '' and endDate != null and endDate != ''">
+                and cal.create_time &gt;= #{startDate} and cal.create_time &lt;= #{endDate}
+            </if>
+         </where>
+        group by company_user_id,course_id,vodio_id
+    </select>
 </mapper>

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

@@ -286,6 +286,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         and create_time &gt;= CONCAT(CURDATE(), ' 00:00:00')
         and create_time &lt;= CONCAT(CURDATE(), ' 23:59:59')
     </select>
+    <select id="selectAppSalesRedPacketStatisticsVO" resultType="com.fs.his.vo.AppSalesCourseStatisticsVO">
+
+    </select>
 
 
     <insert id="batchInsert" parameterType="java.util.List">

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

@@ -1693,6 +1693,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         GROUP BY cu.user_id
     </select>
 
+
     <sql id="commonConditions">
         <!-- 销售公司 -->
         <if test="companyId != null and companyId != ''">
@@ -1741,4 +1742,46 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             AND u.nick_name LIKE CONCAT('%', #{nickName}, '%')
         </if>
     </sql>
+
+
+     <!-- 记录类型 1看课中 2完课 3待看课 4看课中断   -->
+    <select id="selectAppSalesCourseStatisticsVO" resultType="com.fs.his.vo.AppSalesCourseStatisticsVO">
+        SELECT l.company_user_id,l.course_id,l.video_id,
+        SUM(CASE WHEN l.log_type = 2 THEN 1 ELSE 0 END) AS finishedCount,
+        SUM(CASE WHEN l.log_type = 3 THEN 1 ELSE 0 END) AS notWatchedCount,
+        SUM(CASE WHEN l.log_type = 4 THEN 1 ELSE 0 END) AS interruptCount,
+        SUM(CASE WHEN l.log_type = 1 THEN 1 ELSE 0 END) AS watchingCount,
+        from fs_course_watch_log l
+        where send_type = 1
+            <if test="companyId != null ">
+                and l.company_id = #{companyId}
+            </if>
+            <if test="companyUserId != null ">
+                and l.company_user_id = #{companyUserId}
+            </if>
+            <if test="courseId != null ">
+                and l.course_id = #{courseId}
+            </if>
+            <if test="videoId != null ">
+                and l.video_id = #{videoId}
+            </if>
+            <if test="startDate != null and startDate != '' and endDate != null and endDate != ''">
+                and l.create_time &gt;= #{startDate} and l.create_time &lt;= #{endDate}
+            </if>
+        group by company_user_id,course_id,vodio_id
+    </select>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 </mapper>