统计接口完善

This commit is contained in:
easonzhu 2025-02-23 17:40:17 +08:00
parent 2e9fc9025a
commit 04e005a2c8
7 changed files with 236 additions and 28 deletions

View File

@ -29,7 +29,7 @@ public class CodeGenerator {
DataSourceConfig dsc = new DataSourceConfig
.Builder("jdbc:mysql://47.96.178.171:3306/advisor_video?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8",
"eason",
"mysql2025helloSyzb")
"mysql2025easonzhu")
// .Builder("jdbc:mysql://172.16.9.44:3306/db_crm_dyqh?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false",
// "taf",
// "taf2015")

View File

@ -0,0 +1,124 @@
package com.syzb.group.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* <p>
* 交易圈用户统计信息
* </p>
*
* @author helloSyzb
* @since 2025-02-23
*/
public class GroupUserCollect implements Serializable {
/**
* ID
*/
@TableField("group_id")
private Integer groupId;
/**
* 用户ID
*/
@TableField("user_id")
private String userId;
/**
* 日期
*/
private LocalDate date;
/**
* 在线分钟数
*/
@TableField("online_minutes")
private Integer onlineMinutes;
/**
* 进入时间
*/
@TableField("start_time")
private LocalDateTime startTime;
/**
* 退出时间
*/
@TableField("end_time")
private LocalDateTime endTime;
/**
* 创建时间
*/
@TableField("create_time")
private LocalDateTime createTime;
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public LocalDate getDate() {
return date;
}
public void setDate(LocalDate date) {
this.date = date;
}
public Integer getOnlineMinutes() {
return onlineMinutes;
}
public void setOnlineMinutes(Integer onlineMinutes) {
this.onlineMinutes = onlineMinutes;
}
public LocalDateTime getStartTime() {
return startTime;
}
public void setStartTime(LocalDateTime startTime) {
this.startTime = startTime;
}
public LocalDateTime getEndTime() {
return endTime;
}
public void setEndTime(LocalDateTime endTime) {
this.endTime = endTime;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "GroupUserCollect{" +
"groupId=" + groupId +
", userId=" + userId +
", date=" + date +
", onlineMinutes=" + onlineMinutes +
", startTime=" + startTime +
", endTime=" + endTime +
", createTime=" + createTime +
"}";
}
}

View File

@ -0,0 +1,17 @@
package com.syzb.group.mapper;
import com.syzb.common.mapper.EasyBaseMapper;
import com.syzb.group.entity.GroupUserCollect;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 交易圈用户统计信息 Mapper 接口
* </p>
*
* @author helloSyzb
* @since 2025-02-23
*/
public interface GroupUserCollectMapper extends EasyBaseMapper<GroupUserCollect> {
}

View File

@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.syzb.common.entity.OnlineUser;
import com.syzb.common.mapper.EasyBaseMapper;
import com.syzb.common.vo.IdCountVO;
import com.syzb.group.entity.GroupUserCollect;
import com.syzb.group.entity.GroupUserFlow;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
@ -27,15 +28,15 @@ public interface GroupUserFlowMapper extends EasyBaseMapper<GroupUserFlow> {
"${ew.customSqlSegment}")
List<OnlineUser> loadHis(@Param(Constants.WRAPPER) LambdaQueryWrapper<GroupUserFlow> wrapper);
@Select("SELECT \n" +
" group_id as id, \n" +
" COUNT(DISTINCT user_id) AS count \n" +
"FROM \n" +
" group_user_flow \n" +
"WHERE \n" +
" time >= #{startTime} \n" +
" AND time < #{endTime} \n" +
"GROUP BY \n" +
" group_id")
@Select("SELECT group_id as id, COUNT(DISTINCT user_id) AS count \n" +
"FROM group_user_flow \n" +
"WHERE time >= #{startTime} AND time < #{endTime} \n" +
"GROUP BY group_id")
List<IdCountVO> selectGroupUserCount(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
@Select("SELECT group_id, user_id, MIN(TIME) AS start_time, MAX(TIME) AS end_time, COUNT(0) AS online_minutes \n" +
"FROM group_user_flow \n" +
"WHERE time >= #{startTime} AND time < #{endTime} \n" +
"GROUP BY group_id, user_id")
List<GroupUserCollect> selectGroupUserCollect(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
}

View File

@ -3,9 +3,12 @@ package com.syzb.group.query;
import com.syzb.common.query.PageQuery;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
public class ListGroupCustomerQuery extends PageQuery {
@ApiModelProperty("交易圈ID")
@NotNull
private Integer groupId;
@ApiModelProperty("用户ID")

View File

@ -53,7 +53,10 @@ public class GroupTask {
cacheService.lock(CacheKey.LockKey.COLLECT_GROUP_DATA,
0, TimeUnit.SECONDS,
4, TimeUnit.MINUTES,
() -> adminGroupCollectService.collectGroupData()
() -> {
adminGroupCollectService.collectGroupData();
adminGroupCollectService.collectGroupUserData();
}
);
}

View File

@ -22,10 +22,8 @@ import com.syzb.group.constant.GroupMessageUserType;
import com.syzb.group.entity.GroupCollect;
import com.syzb.group.entity.GroupInfo;
import com.syzb.group.entity.GroupMessage;
import com.syzb.group.mapper.GroupCollectMapper;
import com.syzb.group.mapper.GroupInfoMapper;
import com.syzb.group.mapper.GroupMessageMapper;
import com.syzb.group.mapper.GroupUserFlowMapper;
import com.syzb.group.entity.GroupUserCollect;
import com.syzb.group.mapper.*;
import com.syzb.group.query.ListGroupCustomerQuery;
import com.syzb.group.query.QueryGroupCollectQuery;
import com.syzb.group.service.common.GroupCacheService;
@ -36,9 +34,11 @@ import com.syzb.rbac.entity.WxUser;
import com.syzb.rbac.mapper.WxUserMapper;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -55,6 +55,9 @@ public class AdminGroupCollectService {
@Resource
private GroupCollectMapper groupCollectMapper;
@Resource
private GroupUserCollectMapper groupUserCollectMapper;
@Resource
private GroupCommonService groupCommonService;
@ -80,15 +83,12 @@ public class AdminGroupCollectService {
private GroupMessageMapper groupMessageMapper;
public void collectGroupData() {
LocalDate today = LocalDate.now();
LocalDate yesterday = today.minusDays(1);
LambdaQueryWrapper<GroupInfo> groupWrapper = Wrappers.<GroupInfo>lambdaQuery()
.select(GroupInfo::getId);
List<GroupInfo> groups = groupInfoMapper.selectList(groupWrapper);
if (CollUtil.isEmpty(groups)) {
List<Integer> groupIds = getGroupIds();
if (CollUtil.isEmpty(groupIds)) {
return;
}
List<Integer> groupIds = groups.stream().map(GroupInfo::getId).collect(Collectors.toList());
LocalDate today = LocalDate.now();
LocalDate yesterday = today.minusDays(1);
// 获取昨日数据
// 如果昨天数据还是昨天统计的那需要重新计算否则不需计算
QueryWrapper<GroupCollect> collectWrapper = Wrappers.<GroupCollect>query()
@ -171,6 +171,36 @@ public class AdminGroupCollectService {
}
}
public void collectGroupUserData() {
LocalDate today = LocalDate.now();
LocalDate yesterday = today.minusDays(1);
// 获取昨日数据
// 如果昨天数据还是昨天统计的那需要重新计算否则不需计算
QueryWrapper<GroupUserCollect> collectWrapper = Wrappers.<GroupUserCollect>query()
.select("max(create_time) as create_time")
.eq("date", yesterday);
GroupUserCollect yesterdayLatest = groupUserCollectMapper.selectOne(collectWrapper);
if (yesterdayLatest != null && yesterdayLatest.getCreateTime().isBefore(today.atStartOfDay())) {
collectGroupUserData(yesterday);
}
collectGroupUserData(today);
}
public void collectGroupUserData(LocalDate date) {
LocalDateTime startTime = date.atStartOfDay();
LocalDateTime endTime = date.plusDays(1).atStartOfDay();
LocalDateTime now = LocalDateTime.now();
List<GroupUserCollect> collectList = groupUserFlowMapper.selectGroupUserCollect(startTime, endTime);
collectList.forEach(groupUserCollect -> {
groupUserCollect.setDate(date);
groupUserCollect.setCreateTime(now);
});
if (CollUtil.isNotEmpty(collectList)) {
groupUserCollectMapper.delete(Wrappers.<GroupUserCollect>lambdaQuery().eq(GroupUserCollect::getDate, date));
groupUserCollectMapper.insertBatchSomeColumn(collectList);
}
}
public List<GroupCollectVO> queryCollect(QueryGroupCollectQuery query, BackendUserVO backendUserVO) {
Integer groupId = query.getGroupId();
LocalDate startDate = query.getStartDate();
@ -183,10 +213,6 @@ public class AdminGroupCollectService {
return list.stream().map(GroupCollectVO::new).collect(Collectors.toList());
}
public void clearCache(Integer id) {
groupCache.delete(CacheKey.GroupKey.GROUP_INFO + id);
}
public GroupCollectVO queryTodayCollect(OnlyIdQuery query, BackendUserVO backendUserVO) {
Integer groupId = query.getId();
LocalDate date = LocalDate.now();
@ -219,6 +245,8 @@ public class AdminGroupCollectService {
Map<String, WxUser> wxUserMap = wxUserList.stream().collect(Collectors.toMap(WxUser::getId, Function.identity()));
Set<String> blackUserIds = commentBlackService.getBlackUserIds(groupId, ProductType.GROUP.value);
Set<String> onlineUserIds = groupCacheService.getOnlineUserIds(groupId);
Map<String, LocalDateTime> lastVisitTimeMap = queryLastVisitTime(groupId);
Map<String, LocalDateTime> lastChatTimeMap = queryLastChatTime(groupId);
Stream<ModuleUser> stream = moduleUserList.stream();
if (StrUtil.isNotEmpty(userId)) {
stream = stream.filter(m -> userId.equals(m.getUserId()));
@ -233,6 +261,8 @@ public class AdminGroupCollectService {
vo.setIsOnline(onlineUserIds.contains(moduleUser.getUserId()) ? IsOrNot.IS.value : IsOrNot.NOT.value);
vo.setCommentBlackStatus(blackUserIds.contains(moduleUser.getUserId()) ? IsOrNot.IS.value : IsOrNot.NOT.value);
vo.setCustomerStatus(calCustomerStatus(moduleUser).value);
vo.setLastVisitTime(lastVisitTimeMap.get(moduleUser.getUserId()));
vo.setLastChatTime(lastChatTimeMap.get(moduleUser.getUserId()));
return vo;
}).collect(Collectors.toList());
Stream<GroupCustomerVO> voStream = list.stream();
@ -253,7 +283,26 @@ public class AdminGroupCollectService {
return new Pager<>(pageList, voList.size());
}
public GroupCustomerStatus calCustomerStatus(ModuleUser moduleUser) {
private Map<String, LocalDateTime> queryLastVisitTime(Integer groupId) {
QueryWrapper<GroupUserCollect> wrapper = Wrappers.<GroupUserCollect>query()
.select("user_id", "max(end_time) as end_time")
.eq("group_id", groupId)
.groupBy("user_id");
List<GroupUserCollect> list = groupUserCollectMapper.selectList(wrapper);
return list.stream().collect(Collectors.toMap(GroupUserCollect::getUserId, GroupUserCollect::getEndTime));
}
private Map<String, LocalDateTime> queryLastChatTime(Integer groupId) {
QueryWrapper<GroupMessage> wrapper = Wrappers.<GroupMessage>query()
.select("user_id", "max(create_time) as create_time")
.eq("group_id", groupId)
.eq("user_type", GroupMessageUserType.CUSTOMER.value)
.groupBy("user_id");
List<GroupMessage> list = groupMessageMapper.selectList(wrapper);
return list.stream().collect(Collectors.toMap(GroupMessage::getUserId, GroupMessage::getCreateTime));
}
private GroupCustomerStatus calCustomerStatus(ModuleUser moduleUser) {
LocalDateTime endTime = moduleUser.getEndTime();
LocalDateTime createTime = moduleUser.getCreateTime();
LocalDateTime now = LocalDateTime.now();
@ -269,4 +318,15 @@ public class AdminGroupCollectService {
return GroupCustomerStatus.IN_PERIOD;
}
private List<Integer> getGroupIds() {
LambdaQueryWrapper<GroupInfo> groupWrapper = Wrappers.<GroupInfo>lambdaQuery()
.select(GroupInfo::getId);
List<GroupInfo> groups = groupInfoMapper.selectList(groupWrapper);
if (CollUtil.isEmpty(groups)) {
return Collections.emptyList();
}
List<Integer> groupIds = groups.stream().map(GroupInfo::getId).collect(Collectors.toList());
return groupIds;
}
}