新增代理邀请主播功能

This commit is contained in:
tianfeng 2025-10-15 15:15:53 +08:00
parent 7878cb30df
commit 4f96321fb7
9 changed files with 383 additions and 47 deletions

View File

@ -147,6 +147,21 @@ public enum OfficialNoticeTypeEnum {
*/
BD_SEND_INVITE_AGENT,
/**
* 代理发出主播邀请.
*/
AGENT_SEND_INVITE_HOST,
/**
* 用户同意代理成为主播邀请.
*/
AGREE_AGENT_INVITE_HOST,
/**
* 用户拒绝代理成为主播邀请.
*/
REFUSE_AGENT_INVITE_HOST,
/**
* BD LEADER发出BD邀请.
*/

View File

@ -9,13 +9,9 @@ import com.red.circle.common.business.dto.cmd.app.AppUserIdCmd;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.web.controller.BaseController;
import com.red.circle.other.app.dto.clientobject.team.*;
import com.red.circle.other.app.dto.cmd.team.DateTypeQryCmd;
import com.red.circle.other.app.dto.cmd.team.TeamHandleUserApplyCmd;
import com.red.circle.other.app.dto.cmd.team.TeamMemberRoleChangeCmd;
import com.red.circle.other.app.dto.cmd.team.TeamMemberWalletWithdrawalCmd;
import com.red.circle.other.app.dto.cmd.team.TeamUserApplyCmd;
import com.red.circle.other.app.dto.cmd.team.TeamUserApplyRecordQryCmd;
import com.red.circle.other.app.dto.cmd.team.*;
import com.red.circle.other.app.service.team.TeamService;
import com.red.circle.other.infra.database.mongo.entity.team.bd.MessageInviteGroup;
import com.red.circle.other.infra.database.rds.service.sys.AdministratorAuthService;
import com.red.circle.other.inner.asserts.team.TeamErrorCode;
import com.red.circle.other.inner.endpoint.team.target.TeamProfileClient;
@ -27,11 +23,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
/**
* 团队服务(主播代理).
@ -493,4 +485,38 @@ public class TeamRestController extends BaseController {
teamProfileClient.createTeam(cmd);
}
/**
* 代理邀请成为主播
*/
@PostMapping("/invite-host")
public void inviteAgent(@RequestBody @Validated AgentInviteHostCmd cmd) {
teamService.inviteHost(cmd);
}
/**
* 代理邀请成为主播-撤销
*/
@PostMapping("/invite-host-cancel/{id}")
public void inviteAgentCancel(@PathVariable("id") String id) {
teamService.inviteHostCancel(id);
}
/**
* 代理邀请成为主播-记录
*/
@GetMapping("/invite-message-own")
public List<BdInviteMessageCO> listBdInviteMessageOwn(BdInviteQryCmd cmd) {
cmd.setGroup(MessageInviteGroup.AGENT_INVITE_HOST.name());
return teamService.listAgentInviteMessageOwn(cmd);
}
/**
* 代理邀请成为主播-处理
*/
@PostMapping("/invite-message-process")
public void processAgentInviteMessage(@RequestBody @Validated AgentInviteMessageProcessCmd cmd) {
teamService.processBdInviteMessage(cmd);
}
}

View File

@ -0,0 +1,224 @@
package com.red.circle.other.app.command.team;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.common.business.enums.OperationUserOrigin;
import com.red.circle.external.inner.endpoint.message.OfficialNoticeClient;
import com.red.circle.external.inner.model.cmd.message.notice.official.NoticeExtTemplateTypeCmd;
import com.red.circle.external.inner.model.enums.message.OfficialNoticeTypeEnum;
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.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.clientobject.team.BdInviteMessageCO;
import com.red.circle.other.app.dto.cmd.team.*;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.infra.database.cache.service.other.EnumConfigCacheService;
import com.red.circle.other.infra.database.mongo.entity.team.bd.BdInviteAgentMessage;
import com.red.circle.other.infra.database.mongo.entity.team.bd.MessageInviteGroup;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMember;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamProfile;
import com.red.circle.other.infra.database.mongo.service.team.bd.BdInviteAgentMessageService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberService;
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.team.BusinessDevelopmentBaseInfoService;
import com.red.circle.other.infra.database.rds.service.team.RoomBdLeadService;
import com.red.circle.other.inner.asserts.team.TeamErrorCode;
import com.red.circle.other.inner.asserts.user.UserErrorCode;
import com.red.circle.other.inner.enums.config.EnumConfigKey;
import com.red.circle.other.inner.enums.team.TeamMemberRole;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.collection.MapBuilder;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import com.red.circle.tool.core.text.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Component
@RequiredArgsConstructor
public class AgentInviteHostExe {
private final UserProfileGateway userProfileGateway;
private final TeamMemberService teamMemberService;
private final TeamProfileService teamProfileService;
private final OfficialNoticeClient officialNoticeClient;
private final EnumConfigCacheService enumConfigCacheService;
private final UserProfileAppConvertor userProfileAppConvertor;
private final BdInviteAgentMessageService bdInviteAgentMessageService;
public void execute(AgentInviteHostCmd cmd) {
// 检查权限
boolean teamOwn = teamProfileService.existsOwnUserId(cmd.getReqUserId());
ResponseAssert.isTrue(TeamErrorCode.USER_AGENT_ROLE_INVALID_ERROR, teamOwn);
UserProfileDTO userProfile = userProfileAppConvertor.toUserProfileDTO(
userProfileGateway.getByUserId(cmd.getInviteUserId()));
ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_RECORD_INFO, userProfile);
//已经加入团队
ResponseAssert.isNull(TeamErrorCode.JOINED_TEAM, teamMemberService.getByMemberId(userProfile.getId()));
// 消息已发送
ResponseAssert.isFalse(TeamErrorCode.MESSAGE_PROCESSED,
bdInviteAgentMessageService.existsWaitMessage(cmd.requiredReqUserId(),
cmd.getInviteUserId(), MessageInviteGroup.AGENT_INVITE_HOST.name()));
bdInviteAgentMessageService.add(new BdInviteAgentMessage()
.setId(IdWorkerUtils.getIdStr())
.setSysOrigin(cmd.requireReqSysOrigin())
.setUserId(cmd.requiredReqUserId())
.setInviteUserId(cmd.getInviteUserId())
.setMessage(cmd.getMessage())
.setGroup(MessageInviteGroup.AGENT_INVITE_HOST.name())
.setCreateTime(TimestampUtils.now())
.setUpdateTime(TimestampUtils.now())
.setStatus(0)
.setExpiredTime(TimestampUtils.nowPlusDays(2))
);
sendMessage(cmd);
}
public List<BdInviteMessageCO> messageCOList(BdInviteQryCmd cmd) {
List<BdInviteAgentMessage> messages = bdInviteAgentMessageService.listInviteMessageOwn(cmd.requiredReqUserId(), cmd.getGroup(), 50);
if (CollectionUtils.isEmpty(messages)) {
return CollectionUtils.newArrayList();
}
Map<Long, UserProfileDTO> userProfileMap = userProfileAppConvertor.toMapUserProfileDTO(
userProfileGateway.mapByUserIds(
messages.stream().map(BdInviteAgentMessage::getInviteUserId).collect(Collectors.toSet())
)
);
return messages.stream().map(msg -> new BdInviteMessageCO()
.setId(msg.getId())
.setUserProfile(Optional.ofNullable(userProfileMap.get(msg.getInviteUserId()))
.map(userProfile -> {
userProfile.setAccount(userProfile.actualAccount());
return userProfile;
})
.orElse(null))
.setMessage(msg.getMessage())
.setStatus(msg.getStatus())
.setGroup(msg.getGroup())
.setCreateTime(msg.getCreateTime())
.setExpiredTime(msg.getExpiredTime())
).collect(Collectors.toList());
}
public void cancel(String id) {
BdInviteAgentMessage agentMessage = bdInviteAgentMessageService.getById(id);
if (agentMessage == null) {
throw new RuntimeException("message not found");
}
if (agentMessage.getStatus() != 0) {
throw new RuntimeException("This message cannot be canceled ");
}
bdInviteAgentMessageService.remove(id);
}
public void processInvite(AgentInviteMessageProcessCmd cmd) {
ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, cmd.getStatus() > 0);
BdInviteAgentMessage message = bdInviteAgentMessageService.getById(cmd.getId());
ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_RECORD_INFO, message);
ResponseAssert.isTrue(CommonErrorCode.NOT_FOUND_RECORD_INFO,
Objects.equals(message.getGroup(), MessageInviteGroup.AGENT_INVITE_HOST.name()) ||
StringUtils.isBlank(message.getGroup()));
TeamProfile teamProfile = teamProfileService.getByOwnUserId(message.getUserId());
ResponseAssert.notNull(TeamErrorCode.USER_AGENT_ROLE_INVALID_ERROR, teamProfile);
ResponseAssert.isTrue(CommonErrorCode.INSUFFICIENT_PERMISSION,
Objects.equals(message.getInviteUserId(), cmd.requiredReqUserId()));
ResponseAssert.isTrue(TeamErrorCode.MESSAGE_PROCESSED, Objects.equals(message.getStatus(), 0));
// 用户已经是主播
ResponseAssert.isFalse(TeamErrorCode.USER_IS_ALREADY_A_ANCHOR,
teamMemberService.existsMember(cmd.requiredReqUserId()));
ResponseAssert.isTrue(CommonErrorCode.OPERATING_FAILURE,
bdInviteAgentMessageService.updateStatus(cmd.getId(), message.getStatus(),
cmd.getStatus(), MessageInviteGroup.AGENT_INVITE_HOST.name()));
if (Objects.equals(cmd.getStatus(), 1)) {
teamMemberService.addMember(new TeamMember()
.setSortId(IdWorkerUtils.getId())
.setSysOrigin(cmd.requireReqSysOrigin())
.setMemberId(message.getInviteUserId())
.setTeamId(teamProfile.getId())
.setRole(TeamMemberRole.MEMBER)
.setCreateTime(TimestampUtils.now())
.setActiveTime(TimestampUtils.now())
.setCreateUser(cmd.getReqUserId())
.setCreateUserOrigin(OperationUserOrigin.APP.getValue())
.setUpdateUser(cmd.getReqUserId())
.setUpdateUserOrigin(OperationUserOrigin.APP.getValue())
);
teamProfileService.incrCounterMember(teamProfile.getId());
sendMessage(message, OfficialNoticeTypeEnum.AGREE_AGENT_INVITE_HOST);
return;
}
sendMessage(message, OfficialNoticeTypeEnum.REFUSE_AGENT_INVITE_HOST);
}
private void sendMessage(BdInviteAgentMessage message, OfficialNoticeTypeEnum noticeTypeEnum) {
UserProfileDTO userProfile = userProfileAppConvertor.toUserProfileDTO(
userProfileGateway.getByUserId(message.getInviteUserId()));
ResponseAssert.notNull(UserErrorCode.USER_INFO_NOT_FOUND, userProfile);
officialNoticeClient.send(
NoticeExtTemplateTypeCmd.builder()
.toAccount(message.getUserId())
.templateParam(MapBuilder.builder()
.put("userProfile", String.format("%s(%s)", userProfile.getUserNickname(),
userProfile.actualAccount()))
.build())
.noticeType(noticeTypeEnum)
.build()
);
}
private void sendMessage(AgentInviteHostCmd cmd) {
UserProfileDTO userProfile = userProfileAppConvertor.toUserProfileDTO(userProfileGateway.getByUserId(cmd.requiredReqUserId()));
ResponseAssert.notNull(UserErrorCode.USER_INFO_NOT_FOUND, userProfile);
String h5Url = enumConfigCacheService.getValue(EnumConfigKey.H5_DOMAIN_BASE_URL_V2,cmd.requireReqSysOrigin());
if (StringUtils.isBlank(h5Url)) {
return;
}
String path = null;
if (Objects.equals(cmd.requireReqSysOriginEnum(), SysOriginPlatformEnum.TARAB)) {
path = "/team-tarab";
}
if (StringUtils.isBlank(path)) {
return;
}
officialNoticeClient.send(NoticeExtTemplateTypeCmd.builder()
.toAccount(cmd.getInviteUserId())
.noticeType(OfficialNoticeTypeEnum.AGENT_SEND_INVITE_HOST)
.templateParam(MapBuilder.builder()
.put("userProfile", String.format("%s(%s)", userProfile.getUserNickname(),
userProfile.actualAccount()))
.build())
.expand(h5Url + path)
.build()
);
}
}

View File

@ -7,22 +7,9 @@ import com.red.circle.common.business.dto.cmd.app.AppIdLongCmd;
import com.red.circle.common.business.dto.cmd.app.AppIdStringCmd;
import com.red.circle.common.business.dto.cmd.app.AppRoomIdCmd;
import com.red.circle.common.business.dto.cmd.app.AppUserIdCmd;
import com.red.circle.other.app.command.team.TeamHandleUserApplyExe;
import com.red.circle.other.app.command.team.*;
import com.red.circle.other.app.dto.clientobject.team.*;
import com.red.circle.other.app.dto.cmd.team.DateTypeQryCmd;
import com.red.circle.other.app.dto.cmd.team.TeamHandleUserApplyCmd;
import com.red.circle.other.app.dto.cmd.team.TeamMemberRoleChangeCmd;
import com.red.circle.other.app.dto.cmd.team.TeamMemberWalletWithdrawalCmd;
import com.red.circle.other.app.dto.cmd.team.TeamUserApplyCmd;
import com.red.circle.other.app.dto.cmd.team.TeamUserApplyRecordQryCmd;
import com.red.circle.other.app.command.team.TeamMemberHeartbeatCmdExe;
import com.red.circle.other.app.command.team.TeamMemberRoleChangeCmdExe;
import com.red.circle.other.app.command.team.TeamMemberWalletWithdrawalChangeCmdExe;
import com.red.circle.other.app.command.team.TeamPolicyPropsRewardExe;
import com.red.circle.other.app.command.team.TeamUserApplyJoinExe;
import com.red.circle.other.app.command.team.TeamUserApplyQuitExe;
import com.red.circle.other.app.command.team.TeamUserCancelApplyByIdCmdExe;
import com.red.circle.other.app.command.team.TeamUserCancelJoinApplyByIdCmdExe;
import com.red.circle.other.app.dto.cmd.team.*;
import com.red.circle.other.app.command.team.query.TeamBdProfileQryExe;
import com.red.circle.other.app.command.team.query.TeamBillOnQryExe;
import com.red.circle.other.app.command.team.query.TeamBillQryExe;
@ -64,6 +51,7 @@ public class TeamServiceImpl implements TeamService {
private final TeamBillQryExe teamBillQryExe;
private final TeamBillOnQryExe teamBillOnQryExe;
private final AgentInviteHostExe agentInviteHostExe;
private final TeamBdProfileQryExe teamBdProfileQryExe;
private final TeamEntryTeamQryExe teamEntryTeamQryExe;
private final TeamMemberListQryExe teamMemberListQryExe;
@ -272,4 +260,23 @@ public class TeamServiceImpl implements TeamService {
return teamExistsMessageTipsQryExe.execute(cmd);
}
@Override
public void inviteHost(AgentInviteHostCmd cmd) {
agentInviteHostExe.execute(cmd);
}
@Override
public void inviteHostCancel(String id) {
agentInviteHostExe.cancel(id);
}
@Override
public List<BdInviteMessageCO> listAgentInviteMessageOwn(BdInviteQryCmd cmd) {
return agentInviteHostExe.messageCOList(cmd);
}
@Override
public void processBdInviteMessage(AgentInviteMessageProcessCmd cmd) {
agentInviteHostExe.processInvite(cmd);
}
}

View File

@ -0,0 +1,26 @@
package com.red.circle.other.app.dto.cmd.team;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @author tf
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class AgentInviteHostCmd extends AppExtCommand {
/**
* 用户id.
*/
@NotNull(message = "inviteUserId required.")
private Long inviteUserId;
/**
* 消息.
*/
private String message;
}

View File

@ -0,0 +1,37 @@
package com.red.circle.other.app.dto.cmd.team;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @author tf
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class AgentInviteMessageProcessCmd extends AppExtCommand {
/**
* 记录id.
*
* @eo.required
*/
@NotBlank(message = "id required.")
private String id;
/**
* 状态.
*
* @eo.required
*/
@NotNull(message = "status required.")
private Integer status;
/**
* 联系方式.
*/
private String contact;
}

View File

@ -8,12 +8,7 @@ import com.red.circle.common.business.dto.cmd.app.AppIdStringCmd;
import com.red.circle.common.business.dto.cmd.app.AppRoomIdCmd;
import com.red.circle.common.business.dto.cmd.app.AppUserIdCmd;
import com.red.circle.other.app.dto.clientobject.team.*;
import com.red.circle.other.app.dto.cmd.team.DateTypeQryCmd;
import com.red.circle.other.app.dto.cmd.team.TeamHandleUserApplyCmd;
import com.red.circle.other.app.dto.cmd.team.TeamMemberRoleChangeCmd;
import com.red.circle.other.app.dto.cmd.team.TeamMemberWalletWithdrawalCmd;
import com.red.circle.other.app.dto.cmd.team.TeamUserApplyCmd;
import com.red.circle.other.app.dto.cmd.team.TeamUserApplyRecordQryCmd;
import com.red.circle.other.app.dto.cmd.team.*;
import com.red.circle.other.inner.enums.team.TeamUserIdentity;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import java.util.List;
@ -199,4 +194,12 @@ public interface TeamService {
* 主播中心是否存在消息.
*/
Boolean existsMessageTips(AppExtCommand cmd);
void inviteHost(AgentInviteHostCmd cmd);
void inviteHostCancel(String id);
List<BdInviteMessageCO> listAgentInviteMessageOwn(BdInviteQryCmd cmd);
void processBdInviteMessage(AgentInviteMessageProcessCmd cmd);
}

View File

@ -15,6 +15,11 @@ public enum MessageInviteGroup {
/**
* bd leader 邀请bd.
*/
BD_LEADER_INVITE_BD
BD_LEADER_INVITE_BD,
/**
* agent 邀请主播
*/
AGENT_INVITE_HOST
}

View File

@ -129,14 +129,6 @@ public class NoticeMessageClientServiceImpl implements NoticeMessageClientServic
.eq(NoticeMessage::getId, id)
.execute();
// 发送IM群组广播
imGroupClient.sendMessageBroadcast(
BroadcastGroupMsgBodyCmd.builder()
.toPlatform(SysOriginPlatformEnum.LIKEI)
.type(GroupMessageTypeEnum.SYS_ANNOUNCEMENT)
.data("issued an announcement")
.build());
// 创建公共消息到MongoDB
PublicMessage publicMessage = new PublicMessage();
publicMessage.setId(IdWorker.getId());
@ -159,11 +151,12 @@ public class NoticeMessageClientServiceImpl implements NoticeMessageClientServic
publicMessageService.createPublicMessage(publicMessage);
/*newsletterClient.send(new NewsletterResultCmd()
.setUserIds(List.of(1954021558348390402L))
.setEvent(NewsletterEvent.DYNAMIC_MESSAGE_QUANTITY)
.setData("list.size()")
);*/
// 发送IM群组广播
imGroupClient.sendMessageBroadcast(
BroadcastGroupMsgBodyCmd.builder()
.toPlatform(SysOriginPlatformEnum.LIKEI)
.type(GroupMessageTypeEnum.SYS_ANNOUNCEMENT)
.data(publicMessage)
.build());
}
}