diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/team/BdInviteMessageProcessExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/team/BdInviteMessageProcessExe.java index 2b0c7358..d662766a 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/team/BdInviteMessageProcessExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/team/BdInviteMessageProcessExe.java @@ -8,6 +8,8 @@ import com.red.circle.framework.core.asserts.ResponseAssert; import com.red.circle.framework.core.response.CommonErrorCode; import com.red.circle.framework.core.response.ResponseErrorCode; import com.red.circle.mq.business.model.event.BadgeOperateEvent; +import com.red.circle.mq.business.model.event.task.TaskApprovalEvent; +import com.red.circle.mq.rocket.business.producer.TaskMqMessage; import com.red.circle.mq.rocket.business.producer.UserMqMessageService; import com.red.circle.other.app.convertor.user.UserProfileAppConvertor; import com.red.circle.other.app.dto.cmd.team.DbInviteMessageProcessCmd; @@ -24,6 +26,7 @@ import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberSer import com.red.circle.other.infra.database.mongo.service.team.team.TeamProfileService; import com.red.circle.other.infra.database.rds.entity.team.BusinessDevelopmentBaseInfo; import com.red.circle.other.infra.database.rds.entity.team.BusinessDevelopmentTeam; +import com.red.circle.other.infra.database.rds.service.sys.AdministratorService; import com.red.circle.other.infra.database.rds.service.team.BusinessDevelopmentBaseInfoService; import com.red.circle.other.infra.database.rds.service.team.BusinessDevelopmentTeamService; import com.red.circle.other.infra.database.rds.service.team.UserHistoryIdentityService; @@ -40,6 +43,7 @@ import com.red.circle.other.inner.model.dto.agency.agency.TeamStatus; import com.red.circle.other.inner.enums.team.TeamMemberRole; import com.red.circle.tool.core.collection.CollectionUtils; import com.red.circle.tool.core.collection.MapBuilder; +import com.red.circle.tool.core.date.LocalDateTimeUtils; import com.red.circle.tool.core.date.TimestampUtils; import com.red.circle.tool.core.json.JacksonUtils; import com.red.circle.tool.core.sequence.IdWorkerUtils; @@ -72,6 +76,8 @@ public class BdInviteMessageProcessExe { private final BusinessDevelopmentTeamService businessDevelopmentTeamService; private final BusinessDevelopmentBaseInfoService businessDevelopmentBaseInfoService; private final UserMqMessageService userMqMessageService; + private final AdministratorService administratorService; + private final TaskMqMessage taskMqMessage; public void execute(DbInviteMessageProcessCmd cmd) { @@ -115,6 +121,9 @@ public class BdInviteMessageProcessExe { businessDevelopmentBaseInfoService.incrMemberCount(Set.of(message.getUserId())); + // 发送管理员任务消息 + sendAdminTaskMessage(message.getUserId()); + userMqMessageService.sendBadgeOperateEvent(message.getInviteUserId(), BadgeKeyEnum.AGENCY.name(), BadgeOperateEvent.OperationType.WEAR.name()); userMqMessageService.sendBadgeOperateEvent(message.getInviteUserId(), BadgeKeyEnum.HOST.name(), BadgeOperateEvent.OperationType.WEAR.name()); @@ -125,6 +134,17 @@ public class BdInviteMessageProcessExe { sendMessage(message, OfficialNoticeTypeEnum.REFUSE_BD_INVITE_AGENT); } + private void sendAdminTaskMessage(Long userId) { + boolean admin = administratorService.existsAdmin(userId); + if (admin) { + taskMqMessage.sendTask(TaskApprovalEvent.builder() + .taskId(15) + .userId(userId) + .day(LocalDateTimeUtils.nowFormat("yyyy-MM-dd")) + .build()); + } + } + private Long createTeam(DbInviteMessageProcessCmd cmd, BdInviteAgentMessage message) { BusinessDevelopmentBaseInfo bdBaseInfo = businessDevelopmentBaseInfoService.getByUserId( diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/team/BdLeaderInviteBdExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/team/BdLeaderInviteBdExe.java index e866eefd..656d0a20 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/team/BdLeaderInviteBdExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/team/BdLeaderInviteBdExe.java @@ -25,6 +25,8 @@ import com.red.circle.tool.core.date.TimestampUtils; import com.red.circle.tool.core.json.JacksonUtils; import com.red.circle.tool.core.sequence.IdWorkerUtils; import com.red.circle.tool.core.text.StringUtils; + +import java.util.List; import java.util.Map; import java.util.Objects; import lombok.RequiredArgsConstructor; @@ -108,7 +110,11 @@ public class BdLeaderInviteBdExe { roomBdLeadService.checkBdLeader(cmd.getInviteUserId())); - // 消息已发送 + List bdUserIds = businessDevelopmentBaseInfoService.listBdUserIdsByLeaderId(cmd.requiredReqUserId()); + ResponseAssert.isFalse(CommonErrorCode.INSUFFICIENT_PERMISSION, bdUserIds.contains(cmd.getInviteUserId())); + + + // 消息已发送 ResponseAssert.isFalse(TeamErrorCode.MESSAGE_PROCESSED, bdInviteAgentMessageService.existsWaitMessage(cmd.requiredReqUserId(), cmd.getInviteUserId(), MessageInviteGroup.BD_LEADER_INVITE_BD_LEADER.name())); diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/team/BdLeaderInviteMessageProcessExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/team/BdLeaderInviteMessageProcessExe.java index e9129d31..a81d1063 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/team/BdLeaderInviteMessageProcessExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/team/BdLeaderInviteMessageProcessExe.java @@ -7,6 +7,8 @@ import com.red.circle.framework.core.asserts.ResponseAssert; import com.red.circle.framework.core.response.CommonErrorCode; import com.red.circle.framework.core.response.ResponseErrorCode; import com.red.circle.mq.business.model.event.BadgeOperateEvent; +import com.red.circle.mq.business.model.event.task.TaskApprovalEvent; +import com.red.circle.mq.rocket.business.producer.TaskMqMessage; import com.red.circle.mq.rocket.business.producer.UserMqMessageService; import com.red.circle.other.app.convertor.user.UserProfileAppConvertor; import com.red.circle.other.app.dto.cmd.team.DbInviteMessageProcessCmd; @@ -18,6 +20,7 @@ import com.red.circle.other.infra.database.mongo.service.team.bd.BdInviteAgentMe import com.red.circle.other.infra.database.mongo.service.team.team.TeamApplicationProcessApprovalService; import com.red.circle.other.infra.database.rds.entity.team.BusinessDevelopmentBaseInfo; import com.red.circle.other.infra.database.rds.entity.team.RoomBdLead; +import com.red.circle.other.infra.database.rds.service.sys.AdministratorService; import com.red.circle.other.infra.database.rds.service.team.BusinessDevelopmentBaseInfoService; import com.red.circle.other.infra.database.rds.service.team.RoomBdLeadService; import com.red.circle.other.infra.database.rds.service.team.UserHistoryIdentityService; @@ -28,6 +31,7 @@ import com.red.circle.other.inner.asserts.team.TeamErrorCode; import com.red.circle.other.inner.enums.team.TeamAppProcessApprovalReason; import com.red.circle.other.inner.enums.team.TeamApplicationType; import com.red.circle.tool.core.collection.MapBuilder; +import com.red.circle.tool.core.date.LocalDateTimeUtils; import com.red.circle.tool.core.date.TimestampUtils; import com.red.circle.tool.core.json.JacksonUtils; import com.red.circle.tool.core.text.StringUtils; @@ -47,14 +51,13 @@ import org.springframework.stereotype.Component; public class BdLeaderInviteMessageProcessExe { private final RoomBdLeadService roomBdLeadService; - private final UserProfileGateway userProfileGateway; - private final OfficialNoticeClient officialNoticeClient; - private final UserProfileAppConvertor userProfileAppConvertor; private final UserHistoryIdentityService userHistoryIdentityService; private final BdInviteAgentMessageService bdInviteAgentMessageService; private final BusinessDevelopmentBaseInfoService businessDevelopmentBaseInfoService; private final TeamApplicationProcessApprovalService teamApplicationProcessApprovalService; private final UserMqMessageService userMqMessageService; + private final AdministratorService administratorService; + private final TaskMqMessage taskMqMessage; public void execute(DbInviteMessageProcessCmd cmd) { ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, cmd.getStatus() > 0); @@ -106,10 +109,24 @@ public class BdLeaderInviteMessageProcessExe { userHistoryIdentityService.saveBd(cmd.requiredReqUserId()); + // 发送管理员任务消息 + sendAdminTaskMessage(message.getUserId(), 14); + userMqMessageService.sendBadgeOperateEvent(cmd.requiredReqUserId(), BadgeKeyEnum.BD.name(), BadgeOperateEvent.OperationType.WEAR.name()); } } + private void sendAdminTaskMessage(Long userId, Integer taskId) { + boolean admin = administratorService.existsAdmin(userId); + if (admin) { + taskMqMessage.sendTask(TaskApprovalEvent.builder() + .taskId(taskId) + .userId(userId) + .day(LocalDateTimeUtils.nowFormat("yyyy-MM-dd")) + .build()); + } + } + public void executeBdleader(DbInviteMessageProcessCmd cmd) { ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, cmd.getStatus() > 0); BdInviteAgentMessage message = bdInviteAgentMessageService.getById(cmd.getId()); @@ -131,10 +148,19 @@ public class BdLeaderInviteMessageProcessExe { ResponseAssert.isTrue(CommonErrorCode.OPERATING_FAILURE, bdInviteAgentMessageService. updateStatus(cmd.getId(), message.getStatus(), cmd.getStatus(), - MessageInviteGroup.BD_LEADER_INVITE_BD.name())); + MessageInviteGroup.BD_LEADER_INVITE_BD_LEADER.name())); if (Objects.equals(cmd.getStatus(), 1)) { + // 创建BD + businessDevelopmentBaseInfoService.add(new BusinessDevelopmentBaseInfo() + .setSysOrigin(cmd.requireReqSysOrigin()) + .setBdLeadUserId(message.getUserId()) + .setUserId(cmd.requiredReqUserId()) + .setRegion(roomBdLead.getRegionId()) + .setContact(StringUtils.isBlank(cmd.getContact()) ? StringUtils.EMPTY : cmd.getContact()) + ); + teamApplicationProcessApprovalService.add(new TeamApplicationProcessApproval() .setSysOrigin(cmd.requireReqSysOrigin()) .setType(TeamApplicationType.BD) @@ -146,6 +172,8 @@ public class BdLeaderInviteMessageProcessExe { .setCreateUserOrigin(0) ); + // 发送管理员任务消息 + sendAdminTaskMessage(message.getUserId(), 13); } } diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/team/TeamMemberHeartbeatCmdExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/team/TeamMemberHeartbeatCmdExe.java index 2e0d6d9c..54aeb88d 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/team/TeamMemberHeartbeatCmdExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/team/TeamMemberHeartbeatCmdExe.java @@ -12,6 +12,7 @@ import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMemberTarg import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService; import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberService; import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberTargetService; +import com.red.circle.other.infra.database.rds.service.sys.AdministratorService; import com.red.circle.other.inner.asserts.RoomErrorCode; import java.util.Comparator; @@ -44,6 +45,7 @@ public class TeamMemberHeartbeatCmdExe { private final RoomProfileManagerService roomProfileManagerService; private final TeamMemberTargetService teamMemberTargetService; private final TaskMqMessage taskMqMessage; + private final AdministratorService administratorService; public void execute(AppRoomIdCmd cmd) { //心跳mic 每日任务 @@ -53,6 +55,15 @@ public class TeamMemberHeartbeatCmdExe { .day(LocalDateTimeUtils.nowFormat("yyyy-MM-dd")) .build()); + boolean admin = administratorService.existsAdmin(cmd.requiredReqUserId()); + if (admin) { + taskMqMessage.sendTask(TaskApprovalEvent.builder() + .taskId(12) + .userId(cmd.requiredReqUserId()) + .day(LocalDateTimeUtils.nowFormat("yyyy-MM-dd")) + .build()); + } + // redisService.increment("team:heartbeat:"+cmd.requiredReqUserId(), 1); if (Boolean.FALSE.equals(teamMemberService.existsMember(cmd.requiredReqUserId()))) { return; diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/task/TaskListener.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/task/TaskListener.java index 95cad7a9..14544b5a 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/task/TaskListener.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/task/TaskListener.java @@ -24,6 +24,9 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import java.math.BigDecimal; +import java.time.Duration; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.concurrent.TimeUnit; @Slf4j @@ -103,15 +106,15 @@ public class TaskListener implements MessageListener { handleAdminMicUsageTask(eventBody); break; case 13: - // 处理任务-12 的逻辑 管理员任务 - 新绑定 BD Leader + // 处理任务-13 的逻辑 管理员任务 - 新绑定 BD Leader handleAdminNewBdLeaderTask(eventBody.getUserId()); break; case 14: - // 处理任务-11 的逻辑 管理员任务 - 新绑定 BD + // 处理任务-14 的逻辑 管理员任务 - 新绑定 BD handleAdminNewBdTask(eventBody.getUserId()); break; case 15: - // 处理任务-11 的逻辑 管理员任务 - 新绑定代理 + // 处理任务-15 的逻辑 管理员任务 - 新绑定代理 handleAdminNewAgencyTask(eventBody.getUserId()); break; default: @@ -373,7 +376,29 @@ public class TaskListener implements MessageListener { */ private void handleAdminMicUsageTask(TaskApprovalEvent eventBody) { Long userId = eventBody.getUserId(); - int micHours = 0; + + // Redis key:用于记录心跳次数 + String redisKey = "admin:heartbeat:" + userId; + String incValue = redisService.getString(redisKey); + + // 计算当前半月周期的过期时间 + long expireSeconds = calculateHalfMonthExpireSeconds(); + + // 心跳计数:每次心跳+1 + if (StringUtils.isEmpty(incValue)) { + // 首次心跳,初始化为1,并设置过期时间 + redisService.increment(redisKey, 1, expireSeconds, TimeUnit.SECONDS); + return; + } else { + // 递增心跳计数 + long currentCount = redisService.increment(redisKey, 1, expireSeconds, TimeUnit.SECONDS); + if (currentCount % 60 != 0) { + return; + } + } + + // 满1小时,任务进度+1 + int micHours = 1; try { String MIC_TYPE = AdminTaskType.MIC_USAGE.name(); @@ -463,4 +488,49 @@ public class TaskListener implements MessageListener { log.error("处理管理员新绑定代理任务失败, userId={}", userId, e); } } + + /** + * 计算当前半月周期的过期时间(秒) + *

+ * 规则: + * - 上半月(1-15日):过期时间到16号0点0分0秒 + * - 下半月(16日-月末):过期时间到下月1号0点0分0秒 + *

+ * + * @return 距离当前周期结束的秒数 + */ + private long calculateHalfMonthExpireSeconds() { + // 使用沙特时区 + ZoneId riyadhZone = ZoneId.of("Asia/Riyadh"); + ZonedDateTime now = ZonedDateTime.now(riyadhZone); + int currentDay = now.getDayOfMonth(); + + ZonedDateTime expireTime; + + if (currentDay <= 15) { + // 上半月:过期到当月16号0点 + expireTime = now.withDayOfMonth(16) + .withHour(0) + .withMinute(0) + .withSecond(0) + .withNano(0); + } else { + // 下半月:过期到下月1号0点 + expireTime = now.plusMonths(1) + .withDayOfMonth(1) + .withHour(0) + .withMinute(0) + .withSecond(0) + .withNano(0); + } + + // 计算秒数差 + long expireSeconds = Duration.between(now, expireTime).getSeconds(); + + log.debug("计算半月周期过期时间, currentDay={}, expireTime={}, expireSeconds={}", + currentDay, expireTime, expireSeconds); + + return expireSeconds; + } + }