lrj
昨天 dc643ba44fd2a426263015491268a0f0d6b4671d
backend/src/main/java/com/rongyichuang/activity/service/ActivityService.java
@@ -10,12 +10,15 @@
import com.rongyichuang.activity.repository.ActivityJudgeRepository;
import com.rongyichuang.activity.repository.ActivityRepository;
import com.rongyichuang.judge.entity.Judge;
import com.rongyichuang.player.repository.ActivityPlayerRepository;
import com.rongyichuang.judge.repository.JudgeRepository;
import com.rongyichuang.common.dto.PageRequest;
import com.rongyichuang.common.dto.PageResponse;
import com.rongyichuang.rating.entity.RatingScheme;
import com.rongyichuang.rating.repository.RatingSchemeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
@@ -23,9 +26,12 @@
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@@ -44,21 +50,41 @@
    @Autowired
    private RatingSchemeRepository ratingSchemeRepository;
    
    @Autowired
    private ActivityPlayerRepository activityPlayerRepository;
    /**
     * 分页查询比赛列表
     */
    public PageResponse<ActivityResponse> findActivities(PageRequest pageRequest, String name) {
        Pageable pageable = pageRequest.toPageable();
        Page<Activity> page;
        if (StringUtils.hasText(name)) {
            page = activityRepository.findByPidAndStateAndNameContainingOrderByCreateTimeDesc(0L, 1, name, pageable);
            page = activityRepository.findByPidAndNameContainingOrderByCreateTimeDesc(0L, name, pageable);
        } else {
            page = activityRepository.findByPidAndStateOrderByCreateTimeDesc(0L, 1, pageable);
            // 查询所有主活动(pid = 0)
            page = activityRepository.findByPidOrderByCreateTimeDesc(0L, pageable);
        }
        List<ActivityResponse> content = page.getContent().stream()
            .map(ActivityResponse::new)
            .map(activity -> {
                ActivityResponse response = new ActivityResponse(activity);
                // 设置参赛人数(只统计第一阶段的审核通过学员人数)
                int playerCount = 0;
                Activity firstStage = activityRepository.findFirstStageByActivityId(activity.getId());
                if (firstStage != null) {
                    // 如果有第一阶段,统计第一阶段的审核通过人数
                    Long playerCountLong = activityPlayerRepository.countByStageIdAndState(firstStage.getId(), 1);
                    playerCount = playerCountLong != null ? playerCountLong.intValue() : 0;
                } else {
                    // 如果没有阶段,统计活动本身的审核通过人数
                    Long playerCountLong = activityPlayerRepository.countByActivityIdAndState(activity.getId(), 1);
                    playerCount = playerCountLong != null ? playerCountLong.intValue() : 0;
                }
                response.setPlayerCount(playerCount);
                return response;
            })
            .collect(Collectors.toList());
        
        return new PageResponse<>(content, page.getTotalElements(), page.getNumber(), page.getSize());
@@ -73,11 +99,23 @@
            Activity activity = activityOpt.get();
            ActivityResponse response = new ActivityResponse(activity);
            
            // 设置参赛人数(审核通过的报名数量)
            Long playerCountLong = activityPlayerRepository.countByActivityId(activity.getId());
            int playerCount = playerCountLong != null ? playerCountLong.intValue() : 0;
            response.setPlayerCount(playerCount);
            // 如果是比赛,加载其阶段
            if (activity.isMainActivity()) {
                List<Activity> stages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(id, 1);
                List<ActivityResponse> stageResponses = stages.stream()
                    .map(ActivityResponse::new)
                    .map(stage -> {
                        ActivityResponse stageResponse = new ActivityResponse(stage);
                        // 设置阶段的参赛人数
                        Long stagePlayerCountLong = activityPlayerRepository.countByActivityId(stage.getId());
                        int stagePlayerCount = stagePlayerCountLong != null ? stagePlayerCountLong.intValue() : 0;
                        stageResponse.setPlayerCount(stagePlayerCount);
                        return stageResponse;
                    })
                    .collect(Collectors.toList());
                response.setStages(stageResponses);
            }
@@ -127,6 +165,21 @@
            if (!schemeOpt.isPresent()) {
                throw new RuntimeException("评分模板不存在");
            }
        }
        // 如果是比赛,验证必须至少有一个阶段
        if (input.isMainActivity()) {
            if (input.getStages() == null || input.getStages().isEmpty()) {
                throw new RuntimeException("比赛必须至少有一个阶段");
            }
            // 验证阶段数量不超过5个
            if (input.getStages().size() > 5) {
                throw new RuntimeException("比赛阶段数量不能超过5个");
            }
            // 验证sort_order连续性
            validateSortOrderContinuity(input.getStages());
        }
        
        // 保存比赛
@@ -198,6 +251,7 @@
            stage.setMatchTime(stageInput.getMatchTime());
            stage.setAddress(stageInput.getAddress());
            stage.setPlayerMax(stageInput.getPlayerMax());
            stage.setSortOrder(stageInput.getSortOrder());
            stage.setState(stageInput.getState());
            
            // 阶段继承比赛的报名截止时间
@@ -246,7 +300,9 @@
            } else {
                // 为每个指定的阶段创建关联
                for (Long stageId : judgeInput.getStageIds()) {
                    ActivityJudge activityJudge = new ActivityJudge(activityId, judgeInput.getJudgeId(), stageId);
                    // 如果stageId等于当前比赛ID,表示评委负责整个比赛,stage_id设为null
                    Long actualStageId = stageId.equals(activityId) ? null : stageId;
                    ActivityJudge activityJudge = new ActivityJudge(activityId, judgeInput.getJudgeId(), actualStageId);
                    activityJudgeRepository.save(activityJudge);
                }
            }
@@ -279,61 +335,30 @@
    }
    
    /**
     * 获取所有有效比赛和阶段(用于下拉选择)
     * 获取所有有效主比赛(用于下拉选择)
     */
    public List<ActivityResponse> findAllActivitiesForSelection() {
        // 获取所有活动(包括比赛和阶段)
        List<Activity> activities = activityRepository.findByStateOrderByPidAscNameAsc(1);
        // 获取所有状态为1的活动
        List<Activity> allActivities = activityRepository.findByStateOrderByPidAscNameAsc(1);
        
        // 创建比赛ID到比赛对象的映射,用于快速查找父比赛
        Map<Long, Activity> mainActivityMap = activities.stream()
        // 过滤:只保留主比赛(pid=0)
        List<Activity> filteredActivities = allActivities.stream()
            .filter(activity -> activity.getPid() == 0)
            .collect(Collectors.toMap(Activity::getId, activity -> activity));
        // 转换为ActivityResponse并填充parent信息
        List<ActivityResponse> result = activities.stream()
            .map(activity -> {
                ActivityResponse response = new ActivityResponse(activity);
                // 如果是阶段(pid > 0),填充parent信息
                if (activity.getPid() > 0) {
                    Activity parentActivity = mainActivityMap.get(activity.getPid());
                    if (parentActivity != null) {
                        response.setParent(new ActivityResponse(parentActivity));
                    }
                }
                return response;
            })
            .collect(Collectors.toList());
        
        // 自定义排序:比赛和其阶段放在一起
        result.sort((a, b) -> {
            // 如果都是比赛(pid=0),按名称排序
            if (a.getPid() == 0 && b.getPid() == 0) {
                return a.getName().compareTo(b.getName());
            }
            // 如果都是阶段,先按父比赛名称排序,再按阶段名称排序
            if (a.getPid() > 0 && b.getPid() > 0) {
                String aParentName = a.getParent() != null ? a.getParent().getName() : "";
                String bParentName = b.getParent() != null ? b.getParent().getName() : "";
                int parentCompare = aParentName.compareTo(bParentName);
                if (parentCompare != 0) {
                    return parentCompare;
                }
                return a.getName().compareTo(b.getName());
            }
            // 如果一个是比赛,一个是阶段
            if (a.getPid() == 0 && b.getPid() > 0) {
                String bParentName = b.getParent() != null ? b.getParent().getName() : "";
                int compare = a.getName().compareTo(bParentName);
                return compare <= 0 ? -1 : 1; // 比赛排在其阶段前面
            }
            if (a.getPid() > 0 && b.getPid() == 0) {
                String aParentName = a.getParent() != null ? a.getParent().getName() : "";
                int compare = aParentName.compareTo(b.getName());
                return compare < 0 ? -1 : 1; // 阶段排在其比赛后面
            }
            return 0;
        });
        // 转换为ActivityResponse
        List<ActivityResponse> result = filteredActivities.stream()
            .map(activity -> {
                ActivityResponse response = new ActivityResponse(activity);
                // 设置参赛人数(所有阶段的报名数量总和)
                Long playerCountLong = activityPlayerRepository.countByActivityId(activity.getId());
                int playerCount = playerCountLong != null ? playerCountLong.intValue() : 0;
                response.setPlayerCount(playerCount);
                return response;
            })
            .sorted((a, b) -> a.getName().compareTo(b.getName()))
            .collect(Collectors.toList());
        
        return result;
    }
@@ -344,8 +369,62 @@
    public List<ActivityResponse> findStagesByActivityId(Long activityId) {
        List<Activity> stages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(activityId, 1);
        return stages.stream()
            .map(ActivityResponse::new)
            .map(activity -> {
                ActivityResponse response = new ActivityResponse(activity);
                // 设置参赛人数(审核通过的报名数量)
                Long playerCountLong = activityPlayerRepository.countByActivityId(activity.getId());
                int playerCount = playerCountLong != null ? playerCountLong.intValue() : 0;
                response.setPlayerCount(playerCount);
                return response;
            })
            .collect(Collectors.toList());
    }
    /**
     * 获取所有比赛阶段(用于评审页面下拉选择)
     * 返回所有状态为1且pid>0的比赛阶段
     */
    public List<ActivityResponse> findAllStagesForSelection() {
        // 获取所有状态为1的活动
        List<Activity> allActivities = activityRepository.findByStateOrderByPidAscNameAsc(1);
        // 分离主比赛和阶段
        Map<Long, Activity> parentActivitiesMap = allActivities.stream()
            .filter(activity -> activity.getPid() == 0)
            .collect(Collectors.toMap(Activity::getId, activity -> activity));
        // 过滤:只保留比赛阶段(pid>0)
        List<Activity> filteredStages = allActivities.stream()
            .filter(activity -> activity.getPid() > 0)
            .collect(Collectors.toList());
        // 转换为ActivityResponse
        List<ActivityResponse> result = filteredStages.stream()
            .map(activity -> {
                ActivityResponse response = new ActivityResponse(activity);
                // 设置参赛人数(审核通过的报名数量)
                Long playerCountLong = activityPlayerRepository.countByActivityId(activity.getId());
                int playerCount = playerCountLong != null ? playerCountLong.intValue() : 0;
                response.setPlayerCount(playerCount);
                // 手动设置parent信息
                Activity parentActivity = parentActivitiesMap.get(activity.getPid());
                if (parentActivity != null) {
                    ActivityResponse parentResponse = new ActivityResponse(parentActivity);
                    response.setParent(parentResponse);
                }
                return response;
            })
            .sorted((a, b) -> {
                // 先按父比赛ID排序,再按阶段名称排序
                int pidCompare = Long.compare(a.getPid(), b.getPid());
                if (pidCompare != 0) return pidCompare;
                return a.getName().compareTo(b.getName());
            })
            .collect(Collectors.toList());
        return result;
    }
    
    /**
@@ -361,7 +440,14 @@
    public List<ActivityResponse> findOngoingActivities() {
        List<Activity> activities = activityRepository.findOngoingActivities();
        return activities.stream()
            .map(ActivityResponse::new)
            .map(activity -> {
                ActivityResponse response = new ActivityResponse(activity);
                // 设置参赛人数(审核通过的报名数量)
                Long playerCountLong = activityPlayerRepository.countByActivityId(activity.getId());
                int playerCount = playerCountLong != null ? playerCountLong.intValue() : 0;
                response.setPlayerCount(playerCount);
                return response;
            })
            .collect(Collectors.toList());
    }
    
@@ -391,7 +477,10 @@
        Map<Long, List<Long>> judgeStageMap = activityJudges.stream()
            .collect(Collectors.groupingBy(
                ActivityJudge::getJudgeId,
                Collectors.mapping(ActivityJudge::getStageId, Collectors.toList())
                Collectors.mapping(
                    aj -> aj.getStageId() != null ? aj.getStageId() : activityId, // 如果stage_id为null,表示负责整个比赛,使用activityId
                    Collectors.toList()
                )
            ));
        
        // 查询评委详细信息并构建响应
@@ -416,4 +505,38 @@
        
        return result;
    }
    /**
     * 验证阶段的sort_order连续性
     */
    private void validateSortOrderContinuity(List<ActivityStageInput> stages) {
        if (stages == null || stages.isEmpty()) {
            return;
        }
        // 收集所有的sortOrder值
        List<Integer> sortOrders = stages.stream()
            .map(ActivityStageInput::getSortOrder)
            .filter(Objects::nonNull)
            .sorted()
            .collect(Collectors.toList());
        // 检查是否从1开始
        if (sortOrders.isEmpty() || sortOrders.get(0) != 1) {
            throw new RuntimeException("阶段排序必须从1开始");
        }
        // 检查连续性
        for (int i = 0; i < sortOrders.size(); i++) {
            if (sortOrders.get(i) != i + 1) {
                throw new RuntimeException("阶段排序必须连续,不能跳跃(如:1,2,3...)");
            }
        }
        // 检查是否有重复的sortOrder
        Set<Integer> uniqueSortOrders = new HashSet<>(sortOrders);
        if (uniqueSortOrders.size() != sortOrders.size()) {
            throw new RuntimeException("阶段排序不能重复");
        }
    }
}