admin 任务功能初步完成

This commit is contained in:
tianfeng 2025-11-25 12:25:52 +08:00
parent 79ef0e68f6
commit f56f5b20e6
7 changed files with 221 additions and 47 deletions

View File

@ -3,10 +3,12 @@ package com.red.circle.other.app.command.admintask;
import com.red.circle.other.domain.admintask.AdminTaskRecord;
import com.red.circle.other.domain.gateway.AdminTaskGateway;
import com.red.circle.other.app.dto.cmd.AdminTaskQueryCmd;
import com.red.circle.other.infra.database.mongo.service.team.TeamBillCycleUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
/**
@ -22,21 +24,18 @@ public class AdminTaskQueryCmdExe {
private final AdminTaskGateway adminTaskGateway;
public List<AdminTaskRecord> execute(AdminTaskQueryCmd cmd) {
LocalDate cycleStartDate = cmd.getCycleStartDate() != null ? cmd.getCycleStartDate() : getCurrentCycleStartDate();
LocalDate cycleStartDate = cmd.getCycleStartDate() != null ? cmd.getCycleStartDate() :
LocalDate.parse(TeamBillCycleUtils.getCalcBillBelong().toString(), DateTimeFormatter.ofPattern("yyyyMMdd"));
return adminTaskGateway.findByUserIdAndCycle(cmd.getUserId(), cycleStartDate);
}
/**
* 获取当前周期开始日期
* 查询单个任务
*/
private LocalDate getCurrentCycleStartDate() {
LocalDate now = LocalDate.now();
int dayOfMonth = now.getDayOfMonth();
if (dayOfMonth <= 15) {
return LocalDate.of(now.getYear(), now.getMonth(), 1);
} else {
return LocalDate.of(now.getYear(), now.getMonth(), 16);
}
public AdminTaskRecord findByUserIdAndTaskTypeAndCycle(Long userId, String taskType, LocalDate cycleStartDate) {
LocalDate queryDate = cycleStartDate != null ? cycleStartDate :
LocalDate.parse(TeamBillCycleUtils.getCalcBillBelong().toString(), DateTimeFormatter.ofPattern("yyyyMMdd"));
return adminTaskGateway.findByUserIdAndTaskTypeAndCycle(userId, taskType, queryDate);
}
}

View File

@ -1,9 +1,6 @@
package com.red.circle.other.app.listener.task;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.base.Throwables;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.common.business.enums.SendPropsOrigin;
import com.red.circle.component.mq.MessageEventProcess;
import com.red.circle.component.mq.MessageEventProcessDescribe;
import com.red.circle.component.mq.config.RocketMqMessageListener;
@ -11,47 +8,23 @@ import com.red.circle.component.mq.service.Action;
import com.red.circle.component.mq.service.ConsumerMessage;
import com.red.circle.component.mq.service.MessageListener;
import com.red.circle.component.redis.service.RedisService;
import com.red.circle.external.inner.endpoint.message.ImGroupClient;
import com.red.circle.mq.business.model.event.task.TaskApprovalEvent;
import com.red.circle.mq.rocket.business.streams.TaskSink;
import com.red.circle.other.app.dto.cmd.AdminTaskProgressUpdateCmd;
import com.red.circle.other.app.dto.cmd.SpinsTaskProgressUpdateCmd;
import com.red.circle.other.app.service.AdminTaskService;
import com.red.circle.other.app.service.SpinsUserTaskProgressService;
import com.red.circle.other.app.service.room.RoomProfileService;
import com.red.circle.other.app.service.task.TaskService;
import com.red.circle.other.app.util.DateTimeAsiaRiyadhUtils;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.domain.admintask.AdminTaskType;
import com.red.circle.other.domain.gateway.user.ability.InviteUserGateway;
import com.red.circle.other.domain.model.user.UserConsumptionLevel;
import com.red.circle.other.infra.database.rds.dao.h5.UserInviteTaskRecordDAO;
import com.red.circle.other.infra.database.rds.dao.user.user.UserInviteUserDAO;
import com.red.circle.other.infra.database.rds.entity.h5.UserInviteTaskRecord;
import com.red.circle.other.infra.database.rds.entity.user.user.LatestMobileDevice;
import com.red.circle.other.infra.database.rds.entity.user.user.UserInviteUser;
import com.red.circle.other.infra.database.rds.enums.h5.MemberActiveEnum;
import com.red.circle.other.infra.database.rds.service.family.FamilyMemberInfoService;
import com.red.circle.other.infra.database.rds.service.sys.EnumConfigService;
import com.red.circle.other.infra.database.rds.service.sys.GameListConfigService;
import com.red.circle.other.infra.database.rds.service.user.device.LatestMobileDeviceService;
import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService;
import com.red.circle.other.infra.database.rds.service.user.user.RelationshipFriendService;
import com.red.circle.other.inner.endpoint.activity.PropsActivityClient;
import com.red.circle.other.inner.model.cmd.activity.SendActivityRewardCmd;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.LocalDateUtils;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Slf4j
@RocketMqMessageListener(groupId = TaskSink.INPUT, tag = TaskSink.TAG)
@ -63,6 +36,7 @@ public class TaskListener implements MessageListener {
private final RelationshipFriendService relationshipFriendService;
private final InviteUserGateway inviteUserGateway;
private final SpinsUserTaskProgressService spinsUserTaskProgressService;
private final AdminTaskService adminTaskService;
@Override
public Action consume(ConsumerMessage message) {
@ -151,6 +125,16 @@ public class TaskListener implements MessageListener {
// 处理 Spins 上麦任务进度
handleSpinsMicTask(eventBody.getUserId(), inc);
// 处理管理员麦克风使用时长任务每次心跳 = 1分钟累积60次 = 1小时
if (StringUtils.isNotEmpty(inc)) {
int micMinutes = Integer.parseInt(inc);
// 每60分钟算一次更新
if (micMinutes % 60 == 0) {
int micHours = micMinutes / 60;
handleAdminMicUsageTask(eventBody.getUserId(), 1);
}
}
}
/**
@ -375,4 +359,99 @@ public class TaskListener implements MessageListener {
updateTaskStatus(eventBody);
}
// ==================== 管理员任务处理 ====================
/**
* 处理管理员任务 - 麦克风使用时长
*/
private void handleAdminMicUsageTask(Long userId, int micHours) {
try {
String MIC_TYPE = AdminTaskType.MIC_USAGE.name();
if (adminTaskService.isTaskCompleted(userId, MIC_TYPE, null)) {
log.info("管理员麦克风使用时长任务已完成,跳过更新, userId={}", userId);
return;
}
// 更新任务进度
AdminTaskProgressUpdateCmd updateCmd = new AdminTaskProgressUpdateCmd();
updateCmd.setUserId(userId);
updateCmd.setTaskType(MIC_TYPE);
updateCmd.setIncrementValue(micHours);
adminTaskService.updateTaskProgress(updateCmd);
log.info("管理员麦克风使用时长任务进度更新成功, userId={}, micHours={}", userId, micHours);
} catch (Exception e) {
log.error("处理管理员麦克风使用时长任务失败, userId={}, micHours={}", userId, micHours, e);
}
}
/**
* 处理管理员任务 - 新绑定 BD Leader
*/
private void handleAdminNewBdLeaderTask(Long userId) {
try {
String BD_LEADER_TYPE = AdminTaskType.NEW_BD_LEADERS.name();
// 检查任务是否已完成
if (adminTaskService.isTaskCompleted(userId, BD_LEADER_TYPE, null)) {
log.info("管理员新绑定 BD Leader 任务已完成,跳过更新, userId={}", userId);
return;
}
// 更新任务进度
AdminTaskProgressUpdateCmd updateCmd = new AdminTaskProgressUpdateCmd();
updateCmd.setUserId(userId);
updateCmd.setTaskType(BD_LEADER_TYPE);
updateCmd.setIncrementValue(1);
adminTaskService.updateTaskProgress(updateCmd);
log.info("管理员新绑定 BD Leader 任务进度更新成功, userId={}", userId);
} catch (Exception e) {
log.error("处理管理员新绑定 BD Leader 任务失败, userId={}", userId, e);
}
}
/**
* 处理管理员任务 - 新绑定 BD
*/
private void handleAdminNewBdTask(Long userId) {
try {
String BD_TYPE = AdminTaskType.NEW_BDS.name();
if (adminTaskService.isTaskCompleted(userId, BD_TYPE, null)) {
log.info("管理员新绑定 BD 任务已完成,跳过更新, userId={}", userId);
return;
}
// 更新任务进度
AdminTaskProgressUpdateCmd updateCmd = new AdminTaskProgressUpdateCmd();
updateCmd.setUserId(userId);
updateCmd.setTaskType(BD_TYPE);
updateCmd.setIncrementValue(1);
adminTaskService.updateTaskProgress(updateCmd);
log.info("管理员新绑定 BD 任务进度更新成功, userId={}", userId);
} catch (Exception e) {
log.error("处理管理员新绑定 BD 任务失败, userId={}", userId, e);
}
}
/**
* 处理管理员任务 - 新绑定代理
*/
private void handleAdminNewAgencyTask(Long userId) {
try {
String AGENCY_TYPE = AdminTaskType.NEW_AGENCIES.name();
if (adminTaskService.isTaskCompleted(userId, AGENCY_TYPE, null)) {
log.info("管理员新绑定代理任务已完成,跳过更新, userId={}", userId);
return;
}
// 更新任务进度
AdminTaskProgressUpdateCmd updateCmd = new AdminTaskProgressUpdateCmd();
updateCmd.setUserId(userId);
updateCmd.setTaskType(AGENCY_TYPE);
updateCmd.setIncrementValue(1);
adminTaskService.updateTaskProgress(updateCmd);
log.info("管理员新绑定代理任务进度更新成功, userId={}", userId);
} catch (Exception e) {
log.error("处理管理员新绑定代理任务失败, userId={}", userId, e);
}
}
}

View File

@ -10,10 +10,15 @@ import com.red.circle.other.app.dto.cmd.AdminTaskInitCmd;
import com.red.circle.other.app.dto.cmd.AdminTaskProgressUpdateCmd;
import com.red.circle.other.app.dto.cmd.AdminTaskQueryCmd;
import com.red.circle.other.domain.admintask.AdminTaskRecord;
import com.red.circle.other.domain.gateway.AdminTaskGateway;
import com.red.circle.other.infra.database.mongo.service.team.TeamBillCycleUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
@ -23,6 +28,7 @@ import java.util.stream.Collectors;
* @author tf
* @date 2025-11-25
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class AdminTaskServiceImpl implements AdminTaskService {
@ -31,6 +37,7 @@ public class AdminTaskServiceImpl implements AdminTaskService {
private final AdminTaskProgressUpdateCmdExe adminTaskProgressUpdateCmdExe;
private final AdminTaskQueryCmdExe adminTaskQueryCmdExe;
private final AdminTaskConvertor adminTaskConvertor;
private final AdminTaskGateway adminTaskGateway;
@Override
@Transactional(rollbackFor = Exception.class)
@ -41,13 +48,38 @@ public class AdminTaskServiceImpl implements AdminTaskService {
@Override
@Transactional(rollbackFor = Exception.class)
public AdminTaskRecordCO updateTaskProgress(AdminTaskProgressUpdateCmd cmd) {
// 先检查当前周期是否已初始化未初始化则自动初始化兜底
ensureTasksInitialized(cmd.getUserId(), cmd.getCycleStartDate());
AdminTaskRecord record = adminTaskProgressUpdateCmdExe.execute(cmd);
return adminTaskConvertor.toRecordCO(record);
}
@Override
public AdminTaskSummaryCO queryTaskSummary(AdminTaskQueryCmd cmd) {
LocalDate cycleStartDate = cmd.getCycleStartDate() != null ? cmd.getCycleStartDate() :
LocalDate.parse(TeamBillCycleUtils.getCalcBillBelong().toString(), DateTimeFormatter.ofPattern("yyyyMMdd"));
List<AdminTaskRecord> records = adminTaskQueryCmdExe.execute(cmd);
if (records.isEmpty()) {
log.info("用户当前周期无任务记录,自动初始化, userId={}, cycleStart={}",
cmd.getUserId(), cycleStartDate);
try {
LocalDate cycleEndDate = calculateCycleEndDate(cycleStartDate);
AdminTaskInitCmd initCmd = new AdminTaskInitCmd();
initCmd.setUserId(cmd.getUserId());
initCmd.setCycleStartDate(cycleStartDate);
initCmd.setCycleEndDate(cycleEndDate);
adminTaskInitCmdExe.execute(initCmd);
records = adminTaskQueryCmdExe.execute(cmd);
} catch (Exception e) {
log.error("自动初始化任务失败, userId={}", cmd.getUserId(), e);
// 即使初始化失败也返回空列表避免接口报错
}
}
// 转换为 CO
List<AdminTaskRecordCO> taskCOList = records.stream()
@ -68,10 +100,60 @@ public class AdminTaskServiceImpl implements AdminTaskService {
// 设置周期信息
if (!records.isEmpty()) {
summary.setCycleStartDate(records.get(0).getCycleStartDate());
summary.setCycleEndDate(records.get(0).getCycleEndDate());
summary.setCycleStartDate(records.get(0).getCycleStartDate().toString());
summary.setCycleEndDate(records.get(0).getCycleEndDate().toString());
}
return summary;
}
@Override
public boolean isTaskCompleted(Long userId, String taskType, LocalDate cycleStartDate) {
LocalDate queryDate = cycleStartDate != null ? cycleStartDate :
LocalDate.parse(TeamBillCycleUtils.getCalcBillBelong().toString(), DateTimeFormatter.ofPattern("yyyyMMdd"));
AdminTaskRecord record = adminTaskQueryCmdExe.findByUserIdAndTaskTypeAndCycle(userId, taskType, queryDate);
return record != null && record.isCompleted();
}
/**
* 确保任务已初始化兜底逻辑
*/
private void ensureTasksInitialized(Long userId, LocalDate cycleStartDate) {
LocalDate queryDate = cycleStartDate != null ? cycleStartDate :
LocalDate.parse(TeamBillCycleUtils.getCalcBillBelong().toString(), DateTimeFormatter.ofPattern("yyyyMMdd"));
// 检查是否存在任务记录
boolean exists = adminTaskGateway.existsByUserIdAndCycle(userId, queryDate);
if (!exists) {
log.info("任务更新时发现未初始化,自动初始化, userId={}, cycleStart={}", userId, queryDate);
try {
LocalDate cycleEndDate = calculateCycleEndDate(queryDate);
AdminTaskInitCmd initCmd = new AdminTaskInitCmd();
initCmd.setUserId(userId);
initCmd.setCycleStartDate(queryDate);
initCmd.setCycleEndDate(cycleEndDate);
adminTaskInitCmdExe.execute(initCmd);
} catch (Exception e) {
log.error("任务更新时自动初始化失败, userId={}", userId, e);
throw e; // 更新时初始化失败应该抛异常避免数据不一致
}
}
}
/**
* 计算周期结束日期
*/
private LocalDate calculateCycleEndDate(LocalDate cycleStartDate) {
int dayOfMonth = cycleStartDate.getDayOfMonth();
if (dayOfMonth == 1) {
// 1号开始结束于15号
return LocalDate.of(cycleStartDate.getYear(), cycleStartDate.getMonth(), 15);
} else {
// 16号开始结束于月末
return cycleStartDate.withDayOfMonth(cycleStartDate.lengthOfMonth());
}
}
}

View File

@ -1,5 +1,7 @@
package com.red.circle.other.app.dto.clientobject;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import java.time.LocalDate;
@ -22,12 +24,12 @@ public class AdminTaskSummaryCO {
/**
* 周期开始日期
*/
private LocalDate cycleStartDate;
private String cycleStartDate;
/**
* 周期结束日期
*/
private LocalDate cycleEndDate;
private String cycleEndDate;
/**
* 已完成任务数

View File

@ -6,6 +6,8 @@ import com.red.circle.other.app.dto.cmd.AdminTaskInitCmd;
import com.red.circle.other.app.dto.cmd.AdminTaskProgressUpdateCmd;
import com.red.circle.other.app.dto.cmd.AdminTaskQueryCmd;
import java.time.LocalDate;
/**
* 管理员任务服务接口
*
@ -28,4 +30,14 @@ public interface AdminTaskService {
* 查询任务汇总
*/
AdminTaskSummaryCO queryTaskSummary(AdminTaskQueryCmd cmd);
/**
* 查询单个任务是否已完成
*
* @param userId 用户ID
* @param taskType 任务类型
* @param cycleStartDate 周期开始日期可选
* @return 是否已完成
*/
boolean isTaskCompleted(Long userId, String taskType, LocalDate cycleStartDate);
}

View File

@ -17,7 +17,7 @@ public class AdminTaskRecord {
/**
* 主键 ID
*/
private Long id;
private String id;
/**
* 用户 ID

View File

@ -122,7 +122,7 @@ public class AdminTaskGatewayImpl implements AdminTaskGateway {
private AdminTaskRecord toDomain(AdminTaskRecordDO dobj) {
AdminTaskRecord record = new AdminTaskRecord();
record.setId(dobj.getId() != null ? Long.parseLong(dobj.getId()) : null);
record.setId(dobj.getId());
record.setUserId(dobj.getUserId());
record.setUserRole(dobj.getUserRole());
record.setCycleStartDate(dobj.getCycleStartDate());