package com.rongyichuang.player.service; import com.rongyichuang.player.dto.ActivityRegistrationInput; import com.rongyichuang.player.dto.ActivityRegistrationResponse; import com.rongyichuang.player.dto.MediaFileInput; import com.rongyichuang.player.dto.response.PlayerRegistrationResponse; import com.rongyichuang.player.entity.ActivityPlayer; import com.rongyichuang.player.entity.Player; import com.rongyichuang.player.repository.ActivityPlayerRepository; import com.rongyichuang.player.repository.PlayerRepository; import com.rongyichuang.common.entity.Media; import com.rongyichuang.common.repository.MediaRepository; import com.rongyichuang.common.enums.MediaTargetType; import com.rongyichuang.common.util.UserContextUtil; import com.rongyichuang.user.entity.User; import com.rongyichuang.user.service.UserService; import com.rongyichuang.media.service.MediaV2Service; import com.rongyichuang.media.dto.MediaSaveInput; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; /** * 活动选手服务类 */ @Service @Transactional public class ActivityPlayerService { private static final Logger log = LoggerFactory.getLogger(ActivityPlayerService.class); @Autowired private ActivityPlayerRepository activityPlayerRepository; @Autowired private PlayerRepository playerRepository; @Autowired private MediaRepository mediaRepository; @Autowired private UserContextUtil userContextUtil; @Autowired private UserService userService; @Autowired private MediaV2Service mediaV2Service; /** * 提交活动报名 * @param input 报名输入信息 * @return 报名结果 */ public ActivityRegistrationResponse submitActivityRegistration(ActivityRegistrationInput input) { try { log.info("开始处理活动报名,活动ID: {}, 选手姓名: {}", input.getActivityId(), input.getPlayerInfo().getName()); // 1. 验证输入参数 if (input.getActivityId() == null) { log.warn("活动ID为空"); return ActivityRegistrationResponse.error("活动ID不能为空"); } if (input.getPlayerInfo() == null || input.getPlayerInfo().getName() == null || input.getPlayerInfo().getName().trim().isEmpty()) { log.warn("选手姓名为空"); return ActivityRegistrationResponse.error("选手姓名不能为空"); } if (input.getPlayerInfo().getPhone() == null || input.getPlayerInfo().getPhone().trim().isEmpty()) { log.warn("联系电话为空"); return ActivityRegistrationResponse.error("联系电话不能为空"); } log.info("输入参数验证通过"); // 2. 查找或创建选手记录 log.info("开始查找或创建选手记录,手机号: {}", input.getPlayerInfo().getPhone()); Player player = findOrCreatePlayer(input); if (player == null) { log.error("创建选手记录失败"); return ActivityRegistrationResponse.error("创建选手记录失败"); } log.info("选手记录处理成功,选手ID: {}", player.getId()); // 3. 检查是否已经报名 log.info("检查是否已经报名,活动ID: {}, 选手ID: {}", input.getActivityId(), player.getId()); Optional existingRegistration = activityPlayerRepository .findByActivityIdAndPlayerId(input.getActivityId(), player.getId()); if (existingRegistration.isPresent()) { log.warn("选手已经报名过此活动"); return ActivityRegistrationResponse.error("您已经报名过此活动"); } log.info("未发现重复报名"); // 4. 创建报名记录 log.info("开始创建报名记录"); ActivityPlayer activityPlayer = new ActivityPlayer(); activityPlayer.setActivityId(input.getActivityId()); activityPlayer.setStageId(input.getActivityId()); // 根据文档:如果比赛未定义阶段,stage_id设为activity_id activityPlayer.setPlayerId(player.getId()); activityPlayer.setRegionId(input.getRegionId()); activityPlayer.setProjectName(input.getProjectName()); // 设置项目名称 activityPlayer.setDescription(input.getDescription()); // BaseEntity会自动设置createTime和updateTime log.info("ActivityPlayer对象创建完成,准备保存到数据库"); ActivityPlayer savedActivityPlayer = activityPlayerRepository.save(activityPlayer); log.info("报名记录创建成功,ID: {}", savedActivityPlayer.getId()); // 5. 保存其他媒体文件(兼容旧版本) if (input.getMediaFiles() != null && !input.getMediaFiles().isEmpty()) { saveMediaFiles(savedActivityPlayer.getId(), input.getMediaFiles()); } // 6. 保存头像媒体记录 if (input.getPlayerInfo().getAvatarMediaId() != null && !input.getPlayerInfo().getAvatarMediaId().trim().isEmpty()) { savePlayerAvatarMedia(player.getId(), input.getPlayerInfo().getAvatarMediaId()); } // 7. 保存附件媒体记录 if (input.getAttachmentMediaIds() != null && !input.getAttachmentMediaIds().isEmpty()) { saveAttachmentMediaRecords(savedActivityPlayer.getId(), input.getAttachmentMediaIds()); } return ActivityRegistrationResponse.success("报名成功", savedActivityPlayer.getId(), player.getId(), player.getUserId()); } catch (Exception e) { log.error("处理活动报名时发生错误", e); return ActivityRegistrationResponse.error("报名失败:" + e.getMessage()); } } /** * 查找或创建选手记录 */ private Player findOrCreatePlayer(ActivityRegistrationInput input) { try { // 先根据手机号查找现有选手 String phone = input.getPlayerInfo().getPhone(); Optional existingPlayerOpt = playerRepository.findByPhone(phone); if (existingPlayerOpt.isPresent()) { Player existingPlayer = existingPlayerOpt.get(); // 更新选手信息 existingPlayer.setName(input.getPlayerInfo().getName()); if (input.getPlayerInfo().getGender() != null) { existingPlayer.setGender(input.getPlayerInfo().getGender()); } if (input.getPlayerInfo().getEducation() != null) { existingPlayer.setEducation(input.getPlayerInfo().getEducation()); } if (input.getPlayerInfo().getIntroduction() != null) { existingPlayer.setIntroduction(input.getPlayerInfo().getIntroduction()); } if (input.getPlayerInfo().getDescription() != null) { existingPlayer.setDescription(input.getPlayerInfo().getDescription()); } // 更新关联的用户信息(如果存在) updateUserInfo(existingPlayer, input); // BaseEntity会自动设置updateTime return playerRepository.save(existingPlayer); } // 创建新选手 Player newPlayer = new Player(); newPlayer.setName(input.getPlayerInfo().getName()); newPlayer.setPhone(input.getPlayerInfo().getPhone()); newPlayer.setGender(input.getPlayerInfo().getGender()); newPlayer.setEducation(input.getPlayerInfo().getEducation()); newPlayer.setIntroduction(input.getPlayerInfo().getIntroduction()); newPlayer.setDescription(input.getPlayerInfo().getDescription()); newPlayer.setRoleId(1L); // 默认角色ID为1(学员角色) newPlayer.setState(1); // 1表示有效状态 // 创建或关联用户记录 User user = createOrUpdateUser(input); newPlayer.setUserId(user.getId()); // BaseEntity会自动设置createTime和updateTime Player savedPlayer = playerRepository.save(newPlayer); log.info("新选手创建成功,ID: {}, 姓名: {}", savedPlayer.getId(), savedPlayer.getName()); return savedPlayer; } catch (Exception e) { log.error("查找或创建选手记录时发生错误", e); return null; } } /** * 创建或更新用户记录 */ private User createOrUpdateUser(ActivityRegistrationInput input) { try { // 使用UserService的findOrCreateUserByPhone方法 User user = userService.findOrCreateUserByPhone( input.getPlayerInfo().getPhone(), input.getPlayerInfo().getName(), null // 不设置密码,使用默认密码 ); // 更新用户的生日信息 if (input.getPlayerInfo().getBirthDate() != null) { user.setBirthday(input.getPlayerInfo().getBirthDate()); user = userService.save(user); log.info("更新用户生日信息成功,用户ID: {}", user.getId()); } return user; } catch (Exception e) { log.error("创建或更新用户记录时发生错误", e); throw new RuntimeException("创建或更新用户记录失败", e); } } /** * 更新现有选手关联的用户信息 */ private void updateUserInfo(Player existingPlayer, ActivityRegistrationInput input) { try { if (existingPlayer.getUserId() != null && existingPlayer.getUserId() > 0) { Optional userOpt = userService.findById(existingPlayer.getUserId()); if (userOpt.isPresent()) { User user = userOpt.get(); // 更新用户姓名 user.setName(input.getPlayerInfo().getName()); // 更新生日信息 if (input.getPlayerInfo().getBirthDate() != null) { user.setBirthday(input.getPlayerInfo().getBirthDate()); } userService.save(user); log.info("更新现有用户信息成功,用户ID: {}", user.getId()); } else { log.warn("未找到选手关联的用户记录,选手ID: {}, 用户ID: {}", existingPlayer.getId(), existingPlayer.getUserId()); } } else { log.info("选手未关联用户记录,选手ID: {}", existingPlayer.getId()); } } catch (Exception e) { log.error("更新用户信息时发生错误", e); // 不抛出异常,避免影响选手信息的更新 } } /** * 保存媒体文件 */ private void saveMediaFiles(Long activityPlayerId, List mediaFiles) { try { for (MediaFileInput mediaFile : mediaFiles) { Media media = new Media(); media.setName(mediaFile.getName()); media.setPath(mediaFile.getPath()); media.setFileExt(mediaFile.getFileExt()); media.setFileSize(mediaFile.getFileSize()); media.setMediaType(mediaFile.getMediaType()); media.setTargetType(MediaTargetType.ACTIVITY_PLAYER_SUBMISSION.getValue()); // 活动选手媒体文件 media.setTargetId(activityPlayerId); media.setState(1); // 1表示有效状态 // BaseEntity会自动设置createTime和updateTime mediaRepository.save(media); log.info("媒体文件保存成功,文件名: {}", mediaFile.getName()); } } catch (Exception e) { log.error("保存媒体文件时发生错误", e); } } /** * 获取玩家在指定活动中的报名状态 * @param activityId 活动ID * @return 报名状态信息 */ public PlayerRegistrationResponse getPlayerRegistration(Long activityId) { try { // 获取当前用户ID Long currentUserId = userContextUtil.getCurrentUserId(); if (currentUserId == null) { log.warn("未找到当前用户信息"); return null; } // 查找当前用户对应的Player记录 Optional playerOpt = playerRepository.findByUserId(currentUserId); if (!playerOpt.isPresent()) { log.info("用户 {} 尚未创建Player记录", currentUserId); return null; } Player player = playerOpt.get(); // 查找该玩家在指定活动中的报名记录 Optional activityPlayerOpt = activityPlayerRepository .findByActivityIdAndPlayerId(activityId, player.getId()); if (!activityPlayerOpt.isPresent()) { log.info("玩家 {} 未在活动 {} 中报名", player.getId(), activityId); return null; } ActivityPlayer activityPlayer = activityPlayerOpt.get(); // 构建响应对象 PlayerRegistrationResponse response = new PlayerRegistrationResponse(); response.setId(activityPlayer.getId()); response.setStatus(activityPlayer.getState()); response.setRegistrationTime(activityPlayer.getCreateTime() != null ? activityPlayer.getCreateTime().toString() : null); response.setReviewStatus(activityPlayer.getState()); // 使用state作为审核状态 response.setReviewComment(activityPlayer.getDescription()); // 使用description作为审核备注 log.info("成功获取玩家 {} 在活动 {} 中的报名状态", player.getId(), activityId); return response; } catch (Exception e) { log.error("获取玩家报名状态时发生错误,活动ID: {}", activityId, e); throw new RuntimeException("获取报名状态失败", e); } } /** * 保存学员头像 * 参考judge模块的实现,将已上传的头像媒体文件关联到学员 */ private void savePlayerAvatar(Long playerId, Long avatarMediaId) { try { // 查找现有的头像记录并删除(确保一个学员只有一个头像) mediaRepository.deleteByTargetTypeAndTargetId(MediaTargetType.STUDENT_AVATAR.getValue(), playerId); // 更新媒体文件的target信息 Media avatarMedia = mediaRepository.findById(avatarMediaId).orElse(null); if (avatarMedia != null) { avatarMedia.setTargetType(MediaTargetType.STUDENT_AVATAR.getValue()); avatarMedia.setTargetId(playerId); mediaRepository.save(avatarMedia); log.info("学员头像保存成功,学员ID: {}, 媒体ID: {}", playerId, avatarMediaId); } else { log.warn("未找到头像媒体文件,媒体ID: {}", avatarMediaId); } } catch (Exception e) { log.error("保存学员头像时发生错误,学员ID: {}, 媒体ID: {}", playerId, avatarMediaId, e); } } /** * 保存附件媒体文件 * 将已上传的附件媒体文件关联到活动报名记录 */ private void saveAttachmentMediaFiles(Long activityPlayerId, List attachmentMediaIds) { try { for (Long mediaId : attachmentMediaIds) { Media attachmentMedia = mediaRepository.findById(mediaId).orElse(null); if (attachmentMedia != null) { attachmentMedia.setTargetType(MediaTargetType.ACTIVITY_PLAYER_SUBMISSION.getValue()); attachmentMedia.setTargetId(activityPlayerId); mediaRepository.save(attachmentMedia); log.info("附件媒体文件保存成功,报名ID: {}, 媒体ID: {}", activityPlayerId, mediaId); } else { log.warn("未找到附件媒体文件,媒体ID: {}", mediaId); } } } catch (Exception e) { log.error("保存附件媒体文件时发生错误,报名ID: {}", activityPlayerId, e); } } /** * 保存选手头像媒体记录 * 使用新的媒体API保存头像媒体记录 */ private void savePlayerAvatarMedia(Long playerId, String avatarMediaId) { try { log.info("开始保存选手头像媒体记录,选手ID: {}, 媒体ID: {}", playerId, avatarMediaId); MediaSaveInput input = new MediaSaveInput(); input.setTargetType("player"); input.setTargetId(playerId); input.setUrl(avatarMediaId); // COS路径 input.setFileName("avatar.jpg"); // 默认头像文件名 input.setFileExt("jpg"); // 文件扩展名 input.setFileSize(0L); // 文件大小暂时设为0 input.setMediaType(1); // 头像类型 mediaV2Service.saveMedia(input); log.info("选手头像媒体记录保存成功,选手ID: {}", playerId); } catch (Exception e) { log.error("保存选手头像媒体记录时发生错误,选手ID: {}, 媒体ID: {}", playerId, avatarMediaId, e); } } /** * 保存附件媒体记录 * 使用新的媒体API保存附件媒体记录 */ private void saveAttachmentMediaRecords(Long activityPlayerId, List attachmentMediaIds) { try { log.info("开始保存附件媒体记录,报名ID: {}, 附件数量: {}", activityPlayerId, attachmentMediaIds.size()); for (String mediaId : attachmentMediaIds) { MediaSaveInput input = new MediaSaveInput(); input.setTargetType("activity_player"); input.setTargetId(activityPlayerId); input.setUrl(mediaId); // COS路径 input.setFileName("attachment"); // 默认附件文件名 input.setFileExt("jpg"); // 文件扩展名 input.setFileSize(0L); // 文件大小暂时设为0 input.setMediaType(2); // 附件类型 mediaV2Service.saveMedia(input); log.info("附件媒体记录保存成功,报名ID: {}, 媒体ID: {}", activityPlayerId, mediaId); } } catch (Exception e) { log.error("保存附件媒体记录时发生错误,报名ID: {}", activityPlayerId, e); } } }