Codex Assistant
18 小时以前 c8dffd157cd8b62023b26e62a0b92c152d959423
backend/src/main/java/com/rongyichuang/player/service/ActivityPlayerService.java
@@ -19,6 +19,7 @@
import com.rongyichuang.media.service.MediaV2Service;
import com.rongyichuang.media.dto.MediaSaveInput;
import com.rongyichuang.message.service.MessageService;
import com.rongyichuang.auth.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -62,8 +63,26 @@
    @Autowired
    private MessageService messageService;
    @Autowired
    private JwtUtil jwtUtil;
    public ActivityPlayer getMyActivityPlayer(Long activityId) {
        Long userId = userContextUtil.getCurrentUserId();
        if (userId == null) {
            return null;
        }
        Optional<Player> playerOpt = playerRepository.findByUserId(userId);
        if (playerOpt.isEmpty()) {
            return null;
        }
        Player player = playerOpt.get();
        List<ActivityPlayer> activityPlayers = activityPlayerRepository.findByActivityIdAndPlayerIdOrderByCreateTimeDesc(activityId, player.getId());
        if (activityPlayers.isEmpty()) {
            return null;
        }
        return activityPlayers.get(0);
    }
    /**
     * 提交活动报名
     * @param input 报名输入信息
@@ -98,28 +117,24 @@
            }
            log.info("选手记录处理成功,选手ID: {}", player.getId());
            // 3. 检查是否已经报名
            log.info("检查是否已经报名,活动ID: {}, 选手ID: {}", input.getActivityId(), player.getId());
            Optional<ActivityPlayer> existingRegistration = activityPlayerRepository
                    .findByActivityIdAndPlayerId(input.getActivityId(), player.getId());
            if (existingRegistration.isPresent()) {
                log.warn("选手已经报名过此活动");
                return ActivityRegistrationResponse.error("您已经报名过此活动");
            // 3. 检查是否已经报名(严格限定同一活动+同一选手)
            log.info("检查是否存在有效报名(state IN 0,1),活动ID: {}, 选手ID: {}", input.getActivityId(), player.getId());
            Long activeOrPendingCount = activityPlayerRepository.countActiveOrPendingByActivityAndPlayer(input.getActivityId(), player.getId());
            if (activeOrPendingCount != null && activeOrPendingCount > 0) {
                log.warn("同一活动与选手存在待审核或已通过的报名记录,禁止重复提交。count={}", activeOrPendingCount);
                return ActivityRegistrationResponse.error("您在该活动已有待审核或已通过的报名,请勿重复提交");
            }
            log.info("未发现重复报名");
            log.info("未发现有效报名,允许创建新的报名记录。");
            // 4. 查找第一阶段,如果没有则使用活动本身
            // 4. 查找第一阶段(严格:pid=活动ID 且 sort_order=1),未配置则拒绝报名
            log.info("查找活动的第一阶段,活动ID: {}", input.getActivityId());
            Activity firstStage = activityRepository.findFirstStageByActivityId(input.getActivityId());
            Long stageId;
            if (firstStage != null) {
                stageId = firstStage.getId();
                log.info("找到第一阶段,阶段ID: {}, 阶段名称: {}", firstStage.getId(), firstStage.getName());
            } else {
                // 如果没有找到第一阶段,使用活动本身作为阶段
                stageId = input.getActivityId();
                log.info("未找到第一阶段,使用活动本身作为阶段,活动ID: {}", input.getActivityId());
            if (firstStage == null) {
                log.warn("未找到第一阶段(pid={}, sort_order=1),拒绝报名。活动ID: {}", input.getActivityId(), input.getActivityId());
                return ActivityRegistrationResponse.error("活动未配置第一阶段,无法报名");
            }
            Long stageId = firstStage.getId();
            log.info("找到第一阶段,阶段ID: {}, 阶段名称: {}", firstStage.getId(), firstStage.getName());
            // 5. 创建报名记录
            log.info("开始创建报名记录");
@@ -162,16 +177,21 @@
    /**
     * 查找或创建选手记录
     * 逻辑:
     * 1. 先保存User(根据phone查询,存在则更新,否则新增)
     * 2. 再保存Player(根据userId查询,存在则更新,否则新增)
     */
    private Player findOrCreatePlayer(ActivityRegistrationInput input) {
        try {
            // 先根据手机号查找现有选手
            String phone = input.getPlayerInfo().getPhone();
            Optional<Player> existingPlayerOpt = playerRepository.findByPhone(phone);
            // 1. 先创建或更新用户记录
            User user = createOrUpdateUser(input);
            // 2. 根据userId查找现有选手
            Optional<Player> existingPlayerOpt = playerRepository.findByUserId(user.getId());
            
            if (existingPlayerOpt.isPresent()) {
                // 选手存在,更新选手信息
                Player existingPlayer = existingPlayerOpt.get();
                // 更新选手信息
                existingPlayer.setName(input.getPlayerInfo().getName());
                if (input.getPlayerInfo().getGender() != null) {
                    existingPlayer.setGender(input.getPlayerInfo().getGender());
@@ -186,31 +206,28 @@
                    existingPlayer.setDescription(input.getPlayerInfo().getDescription());
                }
                
                // 更新关联的用户信息(如果存在)
                updateUserInfo(existingPlayer, input);
                // BaseEntity会自动设置updateTime
                return playerRepository.save(existingPlayer);
                Player savedPlayer = playerRepository.save(existingPlayer);
                log.info("更新现有选手成功,ID: {}, 姓名: {}, 用户ID: {}", savedPlayer.getId(), savedPlayer.getName(), user.getId());
                return savedPlayer;
            }
            // 创建新选手
            // 选手不存在,创建新选手
            Player newPlayer = new Player();
            newPlayer.setName(input.getPlayerInfo().getName());
            newPlayer.setPhone(input.getPlayerInfo().getPhone());
            // 不再设置phone字段,phone信息统一存储在User实体中
            // 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());
            log.info("新选手创建成功,ID: {}, 姓名: {}, 用户ID: {}", savedPlayer.getId(), savedPlayer.getName(), user.getId());
            return savedPlayer;
        } catch (Exception e) {
@@ -220,25 +237,83 @@
    }
    /**
     * 创建或更新用户记录
     * 创建或更新用户记录(仅在小程序报名成功时创建新用户)
     */
    private User createOrUpdateUser(ActivityRegistrationInput input) {
        try {
            // 使用UserService的findOrCreateUserByPhone方法
            User user = userService.findOrCreateUserByPhone(
                input.getPlayerInfo().getPhone(),
                input.getPlayerInfo().getName(),
                null // 不设置密码,使用默认密码
            );
            String phone = input.getPlayerInfo().getPhone();
            String name = input.getPlayerInfo().getName();
            
            // 更新用户的生日信息
            if (input.getPlayerInfo().getBirthDate() != null) {
                user.setBirthday(input.getPlayerInfo().getBirthDate());
                user = userService.save(user);
                log.info("更新用户生日信息成功,用户ID: {}", user.getId());
            // 获取当前用户的wxopenid(从JWT token中)
            String currentWxOpenid = null;
            try {
                String token = userContextUtil.getTokenFromRequest();
                if (token != null && jwtUtil.validateToken(token)) {
                    currentWxOpenid = jwtUtil.getWxOpenidFromToken(token);
                    log.debug("从JWT token中获取到wxopenid: {}", currentWxOpenid);
                }
            } catch (Exception e) {
                log.warn("获取当前用户wxopenid时发生异常: {}", e.getMessage());
            }
            
            return user;
            // 先查找现有用户
            Optional<User> existingUserOpt = userService.findByPhone(phone);
            if (existingUserOpt.isPresent()) {
                // 用户存在,更新信息
                User user = existingUserOpt.get();
                user.setName(name);
                // 更新用户的生日信息
                if (input.getPlayerInfo().getBirthDate() != null) {
                    user.setBirthday(input.getPlayerInfo().getBirthDate());
                }
                // 更新wxopenid(如果当前token中包含且不为空)
                if (currentWxOpenid != null && !currentWxOpenid.trim().isEmpty()) {
                    // 检查这个openid是否已经被其他用户使用
                    Optional<User> existingUserWithOpenid = userService.findByWxOpenid(currentWxOpenid);
                    if (existingUserWithOpenid.isEmpty() || existingUserWithOpenid.get().getId().equals(user.getId())) {
                        user.setWxOpenid(currentWxOpenid);
                        log.info("更新用户wxopenid: {}", currentWxOpenid);
                    } else {
                        log.warn("wxopenid {} 已被其他用户使用,用户ID: {}", currentWxOpenid, existingUserWithOpenid.get().getId());
                    }
                }
                user = userService.save(user);
                log.info("更新现有用户信息成功,用户ID: {}", user.getId());
                return user;
            } else {
                // 用户不存在,创建新用户(仅在小程序报名成功时)
                log.info("用户不存在,为小程序报名成功创建新用户,手机号: {}", phone);
                User newUser = new User();
                newUser.setName(name);
                newUser.setPhone(phone);
                newUser.setPassword(userService.getPasswordEncoder().encode("123456")); // 默认密码
                // 设置生日信息
                if (input.getPlayerInfo().getBirthDate() != null) {
                    newUser.setBirthday(input.getPlayerInfo().getBirthDate());
                }
                // 设置wxopenid(如果当前token中包含且不为空)
                if (currentWxOpenid != null && !currentWxOpenid.trim().isEmpty()) {
                    // 检查这个openid是否已经被其他用户使用
                    Optional<User> existingUserWithOpenid = userService.findByWxOpenid(currentWxOpenid);
                    if (existingUserWithOpenid.isEmpty()) {
                        newUser.setWxOpenid(currentWxOpenid);
                        log.info("为新用户设置wxopenid: {}", currentWxOpenid);
                    } else {
                        log.warn("wxopenid {} 已被其他用户使用,用户ID: {}", currentWxOpenid, existingUserWithOpenid.get().getId());
                    }
                }
                newUser = userService.save(newUser);
                log.info("为小程序报名成功创建新用户,用户ID: {}", newUser.getId());
                return newUser;
            }
        } catch (Exception e) {
            log.error("创建或更新用户记录时发生错误", e);
            throw new RuntimeException("创建或更新用户记录失败", e);
@@ -322,16 +397,17 @@
            Player player = playerOpt.get();
            
            // 查找该玩家在指定活动中的报名记录
            Optional<ActivityPlayer> activityPlayerOpt = activityPlayerRepository
                    .findByActivityIdAndPlayerId(activityId, player.getId());
            // 查找该玩家在指定活动中的报名记录(获取最新的)
            List<ActivityPlayer> activityPlayers = activityPlayerRepository
                    .findByActivityIdAndPlayerIdOrderByCreateTimeDesc(activityId, player.getId());
            
            if (!activityPlayerOpt.isPresent()) {
            if (activityPlayers.isEmpty()) {
                log.info("玩家 {} 未在活动 {} 中报名", player.getId(), activityId);
                return null;
            }
            ActivityPlayer activityPlayer = activityPlayerOpt.get();
            // 获取最新的报名记录
            ActivityPlayer activityPlayer = activityPlayers.get(0);
            
            // 构建响应对象
            PlayerRegistrationResponse response = new PlayerRegistrationResponse();