浏览代码

feat:会员-根据各个销售公司查看看课的会员数量和最近看课天数

caoliqin 2 周之前
父节点
当前提交
9a2e23c68e

+ 19 - 1
fs-admin/src/main/java/com/fs/his/controller/FsUserController.java

@@ -5,7 +5,9 @@ import java.util.stream.Collectors;
 
 import com.alibaba.fastjson.JSON;
 import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fs.common.constant.HttpStatus;
 import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.core.domain.entity.SysRole;
 import com.fs.common.core.domain.entity.SysUser;
@@ -63,7 +65,6 @@ import com.fs.common.enums.BusinessType;
 import com.fs.his.domain.FsUser;
 import com.fs.his.service.IFsUserService;
 import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.common.core.page.TableDataInfo;
 
 import static com.fs.his.utils.PhoneUtil.*;
 
@@ -423,4 +424,21 @@ public class FsUserController extends BaseController
         }
     }
 
+    @PreAuthorize("@ss.hasPermi('his:user:statistics')")
+    @GetMapping("/statisticsList")
+    @ApiOperation("按照销售公司查询会员数据(按会员去重,含近3/5/7自然日看课天数;关系多行取create_time最新)")
+    public TableDataInfo statisticsList(FsUser param) {
+        if (param.getCompanyId() == null) {
+            TableDataInfo dataInfo = new TableDataInfo();
+            dataInfo.setCode(HttpStatus.SUCCESS);
+            dataInfo.setMsg("需要传入公司id");
+            dataInfo.setRows(Collections.emptyList());
+            dataInfo.setTotal(0);
+            return dataInfo;
+        }
+        startPage();
+        List<FsUserVO> list = fsUserService.selectStatisticsList(param);
+        return getDataTable(list);
+    }
+
 }

+ 13 - 0
fs-service/src/main/java/com/fs/his/mapper/FsUserMapper.java

@@ -14,6 +14,7 @@ import com.fs.his.param.FindUserByParam;
 import com.fs.his.param.FsUserParam;
 import com.fs.his.vo.FsUserVO;
 import com.fs.his.vo.FsUserExportListVO;
+import com.fs.his.vo.FsUserWatchDaysStatVO;
 import com.fs.his.vo.OptionsVO;
 import com.fs.hisStore.vo.FsCompanyUserListQueryVO;
 import com.fs.qw.dto.FsUserTransferParamDTO;
@@ -487,4 +488,16 @@ public interface FsUserMapper
      * @param userIds
      * **/
     List<FsUser> selectUserListByUserIds(@Param("userIds") List<Long> userIds);
+
+    /**
+     * 去重查询以会员为维度的会员列表
+     * @param fsUser 参数
+     * @return
+     */
+    List<FsUserVO> selectStatisticsList(FsUser fsUser);
+
+    /**
+     * 按公司 + 当页用户,查询最近3/5/7自然日看课天数(去重按DATE(last_heartbeat_time))
+     */
+    List<FsUserWatchDaysStatVO> selectWatchDaysStatByUserIds(@Param("companyId") Long companyId, @Param("userIds") List<Long> userIds);
 }

+ 3 - 0
fs-service/src/main/java/com/fs/his/service/IFsUserService.java

@@ -245,4 +245,7 @@ public interface IFsUserService
      * @return List<FsUser>
      * **/
     List<FsUser> selectUserListByUserIds(List<Long> userIds);
+
+    List<FsUserVO> selectStatisticsList(FsUser fsUser);
+
 }

+ 37 - 4
fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java

@@ -55,10 +55,7 @@ import com.fs.his.service.IFsUserIntegralLogsService;
 import com.fs.his.service.IFsUserProjectTagService;
 import com.fs.his.service.IFsUserWxService;
 import com.fs.his.utils.PhoneUtil;
-import com.fs.his.vo.FsUserVO;
-import com.fs.his.vo.FsUserExportListVO;
-import com.fs.his.vo.FsUserFollowDoctorVO;
-import com.fs.his.vo.UserVo;
+import com.fs.his.vo.*;
 import com.fs.im.config.ImTypeConfig;
 import com.fs.im.service.OpenIMService;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
@@ -1626,4 +1623,40 @@ public class FsUserServiceImpl implements IFsUserService {
     public List<FsUser> selectUserListByUserIds(List<Long> userIds) {
         return fsUserMapper.selectUserListByUserIds(userIds);
     }
+
+    @Override
+    public List<FsUserVO> selectStatisticsList(FsUser fsUser) {
+        // 查询会员
+        List<FsUserVO> list = fsUserMapper.selectStatisticsList(fsUser);
+        if (list == null || list.isEmpty()) {
+            return list;
+        }
+
+        List<Long> userIds = list.stream().map(FsUserVO::getUserId).collect(Collectors.toList());
+        if (userIds.isEmpty()) {
+            return list;
+        }
+
+        // 将数据以userid为key放入map中
+        List<FsUserWatchDaysStatVO> watchNum = fsUserMapper.selectWatchDaysStatByUserIds(fsUser.getCompanyId(), userIds);
+        Map<Long, FsUserWatchDaysStatVO> map = new HashMap<>();
+        if (watchNum != null) {
+            for (FsUserWatchDaysStatVO s : watchNum) {
+                if (s != null && s.getUserId() != null) {
+                    map.put(s.getUserId(), s);
+                }
+            }
+        }
+
+        list.stream()
+                .filter(Objects::nonNull)
+                .filter(vo -> vo.getUserId() != null)
+                .forEach(vo -> {
+                    FsUserWatchDaysStatVO s = map.get(vo.getUserId());
+                    vo.setWatchDaysLast3(s == null || s.getWatchDaysLast3() == null ? 0 : s.getWatchDaysLast3());
+                    vo.setWatchDaysLast5(s == null || s.getWatchDaysLast5() == null ? 0 : s.getWatchDaysLast5());
+                    vo.setWatchDaysLast7(s == null || s.getWatchDaysLast7() == null ? 0 : s.getWatchDaysLast7());
+                });
+        return list;
+    }
 }

+ 9 - 0
fs-service/src/main/java/com/fs/his/vo/FsUserVO.java

@@ -174,4 +174,13 @@ public class FsUserVO extends FsUser implements Serializable
 
     @ApiModelProperty(value = "app来源")
     private String source;
+
+    @ApiModelProperty(value = "最近3天看课天数")
+    private Integer watchDaysLast3;
+
+    @ApiModelProperty(value = "最近5天看课天数")
+    private Integer watchDaysLast5;
+
+    @ApiModelProperty(value = "最近7天看课天数")
+    private Integer watchDaysLast7;
 }

+ 15 - 0
fs-service/src/main/java/com/fs/his/vo/FsUserWatchDaysStatVO.java

@@ -0,0 +1,15 @@
+package com.fs.his.vo;
+
+import lombok.Data;
+
+/**
+ * 会员看课天数统计(按自然日、last_heartbeat_time)
+ */
+@Data
+public class FsUserWatchDaysStatVO {
+    private Long userId;
+    private Integer watchDaysLast3;
+    private Integer watchDaysLast5;
+    private Integer watchDaysLast7;
+}
+

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

@@ -2540,4 +2540,57 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </foreach>
     </select>
 
+    <select id="selectStatisticsList" resultType="com.fs.his.vo.FsUserVO">
+        SELECT
+            u.user_id AS userId,
+            u.nick_name AS nickname,
+            u.avatar,
+            u.phone,
+            u.status,
+            c.company_name AS companyName
+        FROM fs_user u
+        INNER JOIN (
+            -- 多套一层是处理边界,以防有create_time相同的数据
+            SELECT ucu.user_id, MAX(ucu.id) AS latest_ucu_id
+            FROM fs_user_company_user ucu
+            INNER JOIN (
+                SELECT user_id, MAX(create_time) AS max_ct
+                FROM fs_user_company_user
+                WHERE company_id = #{companyId}
+                GROUP BY user_id
+            ) mx ON mx.user_id = ucu.user_id
+                AND ucu.create_time = mx.max_ct
+                AND ucu.company_id = #{companyId}
+            GROUP BY ucu.user_id
+        ) pick ON pick.user_id = u.user_id
+        INNER JOIN fs_user_company_user ucu ON ucu.id = pick.latest_ucu_id
+        LEFT JOIN company c ON c.company_id = ucu.company_id
+        WHERE u.is_del = 0
+        ORDER BY u.user_id DESC
+    </select>
+
+    <select id="selectWatchDaysStatByUserIds" resultType="com.fs.his.vo.FsUserWatchDaysStatVO">
+        SELECT
+            user_id AS userId,
+            COUNT(DISTINCT CASE
+                WHEN last_heartbeat_time &gt;= DATE_SUB(CURDATE(), INTERVAL 2 DAY)
+                THEN DATE(last_heartbeat_time) END) AS watchDaysLast3,
+            COUNT(DISTINCT CASE
+                WHEN last_heartbeat_time &gt;= DATE_SUB(CURDATE(), INTERVAL 4 DAY)
+                THEN DATE(last_heartbeat_time) END) AS watchDaysLast5,
+            COUNT(DISTINCT CASE
+                WHEN last_heartbeat_time &gt;= DATE_SUB(CURDATE(), INTERVAL 6 DAY)
+                THEN DATE(last_heartbeat_time) END) AS watchDaysLast7
+        FROM fs_course_watch_log
+        WHERE company_id = #{companyId}
+          AND last_heartbeat_time IS NOT NULL
+          AND last_heartbeat_time &gt;= DATE_SUB(CURDATE(), INTERVAL 6 DAY)
+          AND last_heartbeat_time &lt; NOW()
+          AND user_id IN
+        <foreach collection="userIds" item="userId" open="(" separator="," close=")">
+            #{userId}
+        </foreach>
+        GROUP BY user_id
+    </select>
+
 </mapper>