package com.rongyichuang.activity.service; import com.rongyichuang.activity.dto.ActivityInput; import com.rongyichuang.activity.dto.ActivityJudgeInput; import com.rongyichuang.activity.dto.ActivityJudgeResponse; import com.rongyichuang.activity.dto.ActivityResponse; import com.rongyichuang.activity.dto.ActivityStageInput; import com.rongyichuang.activity.entity.Activity; import com.rongyichuang.activity.entity.ActivityJudge; 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; import org.springframework.transaction.annotation.Transactional; 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 @Transactional public class ActivityService { @Autowired private ActivityRepository activityRepository; @Autowired private ActivityJudgeRepository activityJudgeRepository; @Autowired private JudgeRepository judgeRepository; @Autowired private RatingSchemeRepository ratingSchemeRepository; @Autowired private ActivityPlayerRepository activityPlayerRepository; /** * 分页查询比赛列表 */ public PageResponse findActivities(PageRequest pageRequest, String name) { Pageable pageable = pageRequest.toPageable(); Page page; if (StringUtils.hasText(name)) { page = activityRepository.findByPidAndNameContainingOrderByCreateTimeDesc(0L, name, pageable); } else { // 查询所有主活动(pid = 0) page = activityRepository.findByPidOrderByCreateTimeDesc(0L, pageable); } List content = page.getContent().stream() .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()); } /** * 获取比赛详情 */ public ActivityResponse findById(Long id) { Optional activityOpt = activityRepository.findById(id); if (activityOpt.isPresent()) { 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 stages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(id, 1); List stageResponses = stages.stream() .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); } // 加载评委数据 List judges = loadActivityJudges(id); response.setJudges(judges); return response; } return null; } /** * 保存比赛(新增或编辑) */ public ActivityResponse saveActivity(ActivityInput input) { Activity activity; if (input.isNew()) { // 新增比赛 activity = new Activity(); activity.setPid(input.getPid()); activity.setPath(generatePath(input.getPid())); } else { // 编辑比赛 Optional existingOpt = activityRepository.findById(input.getId()); if (!existingOpt.isPresent()) { throw new RuntimeException("比赛不存在"); } activity = existingOpt.get(); } // 设置基本信息 activity.setName(input.getName()); activity.setDescription(input.getDescription()); activity.setSignupDeadline(input.getSignupDeadline()); activity.setMatchTime(input.getMatchTime()); activity.setAddress(input.getAddress()); activity.setRatingSchemeId(input.getRatingSchemeId()); activity.setPlayerMax(input.getPlayerMax()); activity.setState(input.getState()); // 验证评分模板是否存在 if (input.getRatingSchemeId() != null) { Optional schemeOpt = ratingSchemeRepository.findById(input.getRatingSchemeId()); 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()); } // 保存比赛 activity = activityRepository.save(activity); // 如果是比赛且有阶段信息,保存阶段 if (input.isMainActivity() && input.getStages() != null && !input.getStages().isEmpty()) { saveActivityStages(activity.getId(), input.getStages()); } // 如果是比赛且有评委信息,保存评委 if (input.isMainActivity() && input.getJudges() != null && !input.getJudges().isEmpty()) { saveActivityJudges(activity.getId(), input.getJudges()); } // 重新查询完整的数据(包含关联的stages) return findById(activity.getId()); } /** * 保存比赛阶段 */ private void saveActivityStages(Long activityId, List stageInputs) { // 获取现有的所有阶段 List existingStages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(activityId, 1); // 收集传入的阶段ID List inputStageIds = stageInputs.stream() .filter(input -> !input.isNew()) .map(ActivityStageInput::getId) .collect(Collectors.toList()); // 删除不在传入列表中的现有阶段(软删除) for (Activity existingStage : existingStages) { if (!inputStageIds.contains(existingStage.getId())) { existingStage.setState(0); // 软删除 activityRepository.save(existingStage); } } // 获取比赛信息,用于继承报名截止时间和评分模板 Optional activityOpt = activityRepository.findById(activityId); if (!activityOpt.isPresent()) { throw new RuntimeException("比赛不存在"); } Activity activity = activityOpt.get(); // 处理传入的阶段(新增或更新) for (ActivityStageInput stageInput : stageInputs) { Activity stage; if (stageInput.isNew()) { // 新增阶段 stage = new Activity(); stage.setPid(activityId); stage.setPath(generatePath(activityId)); } else { // 编辑阶段 Optional existingOpt = activityRepository.findById(stageInput.getId()); if (!existingOpt.isPresent()) { continue; // 跳过不存在的阶段 } stage = existingOpt.get(); } // 设置阶段信息 stage.setName(stageInput.getName()); stage.setDescription(stageInput.getDescription()); stage.setMatchTime(stageInput.getMatchTime()); stage.setAddress(stageInput.getAddress()); stage.setPlayerMax(stageInput.getPlayerMax()); stage.setSortOrder(stageInput.getSortOrder()); stage.setState(stageInput.getState()); // 阶段继承比赛的报名截止时间 stage.setSignupDeadline(activity.getSignupDeadline()); // 阶段的评分模板:如果指定了则使用指定的,否则继承比赛的评分模板 if (stageInput.getRatingSchemeId() != null) { stage.setRatingSchemeId(stageInput.getRatingSchemeId()); } else { stage.setRatingSchemeId(activity.getRatingSchemeId()); } activityRepository.save(stage); } } /** * 保存比赛评委 */ private void saveActivityJudges(Long activityId, List judgeInputs) { if (judgeInputs == null || judgeInputs.isEmpty()) { return; } // 获取比赛的所有阶段(如果有的话) List stages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(activityId, 1); // 保存评委关联 for (ActivityJudgeInput judgeInput : judgeInputs) { // 先删除该评委的现有关联 activityJudgeRepository.deleteByActivityIdAndJudgeId(activityId, judgeInput.getJudgeId()); if (judgeInput.getStageIds() == null || judgeInput.getStageIds().isEmpty()) { // 如果没有指定阶段,创建关联到所有阶段(如果有阶段)或直接关联到比赛(如果没有阶段) if (stages.isEmpty()) { // 比赛没有阶段,直接关联到比赛(stage_id为null表示所有阶段) ActivityJudge activityJudge = new ActivityJudge(activityId, judgeInput.getJudgeId(), null); activityJudgeRepository.save(activityJudge); } else { // 为每个阶段创建关联 for (Activity stage : stages) { ActivityJudge activityJudge = new ActivityJudge(activityId, judgeInput.getJudgeId(), stage.getId()); activityJudgeRepository.save(activityJudge); } } } else { // 为每个指定的阶段创建关联 for (Long stageId : judgeInput.getStageIds()) { // 如果stageId等于当前比赛ID,表示评委负责整个比赛,stage_id设为null Long actualStageId = stageId.equals(activityId) ? null : stageId; ActivityJudge activityJudge = new ActivityJudge(activityId, judgeInput.getJudgeId(), actualStageId); activityJudgeRepository.save(activityJudge); } } } } /** * 删除比赛 */ public boolean deleteActivity(Long id) { Optional activityOpt = activityRepository.findById(id); if (activityOpt.isPresent()) { Activity activity = activityOpt.get(); // 如果是比赛,先删除其所有阶段 if (activity.isMainActivity()) { List stages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(id, 1); for (Activity stage : stages) { stage.setState(0); // 软删除 activityRepository.save(stage); } } // 软删除比赛 activity.setState(0); activityRepository.save(activity); return true; } return false; } /** * 获取所有有效主比赛(用于下拉选择) */ public List findAllActivitiesForSelection() { // 获取所有状态为1的活动 List allActivities = activityRepository.findByStateOrderByPidAscNameAsc(1); // 过滤:只保留主比赛(pid=0) List filteredActivities = allActivities.stream() .filter(activity -> activity.getPid() == 0) .collect(Collectors.toList()); // 转换为ActivityResponse List 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; } /** * 获取比赛的所有阶段 */ public List findStagesByActivityId(Long activityId) { List stages = activityRepository.findByPidAndStateOrderByCreateTimeAsc(activityId, 1); return stages.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; }) .collect(Collectors.toList()); } /** * 获取所有比赛阶段(用于评审页面下拉选择) * 返回所有状态为1且pid>0的比赛阶段 */ public List findAllStagesForSelection() { // 获取所有状态为1的活动 List allActivities = activityRepository.findByStateOrderByPidAscNameAsc(1); // 分离主比赛和阶段 Map parentActivitiesMap = allActivities.stream() .filter(activity -> activity.getPid() == 0) .collect(Collectors.toMap(Activity::getId, activity -> activity)); // 过滤:只保留比赛阶段(pid>0) List filteredStages = allActivities.stream() .filter(activity -> activity.getPid() > 0) .collect(Collectors.toList()); // 转换为ActivityResponse List 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; } /** * 统计比赛数量 */ public long countActiveActivities() { return activityRepository.countActiveActivities(); } /** * 获取进行中的比赛 */ public List findOngoingActivities() { List activities = activityRepository.findOngoingActivities(); return activities.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; }) .collect(Collectors.toList()); } /** * 生成路径 */ private String generatePath(Long pid) { if (pid == 0) { return "/"; } else { Optional parentOpt = activityRepository.findById(pid); if (parentOpt.isPresent()) { return parentOpt.get().getPath() + pid + "/"; } return "/" + pid + "/"; } } /** * 加载活动的评委数据 */ private List loadActivityJudges(Long activityId) { // 查询活动的评委关联 List activityJudges = activityJudgeRepository.findByActivityId(activityId); // 按评委ID分组,收集每个评委负责的阶段 Map> judgeStageMap = activityJudges.stream() .collect(Collectors.groupingBy( ActivityJudge::getJudgeId, Collectors.mapping( aj -> aj.getStageId() != null ? aj.getStageId() : activityId, // 如果stage_id为null,表示负责整个比赛,使用activityId Collectors.toList() ) )); // 查询评委详细信息并构建响应 List result = new ArrayList<>(); for (Map.Entry> entry : judgeStageMap.entrySet()) { Long judgeId = entry.getKey(); List stageIds = entry.getValue(); Optional judgeOpt = judgeRepository.findById(judgeId); if (judgeOpt.isPresent()) { Judge judge = judgeOpt.get(); ActivityJudgeResponse judgeResponse = new ActivityJudgeResponse( judge.getId(), judge.getName(), judge.getPhone(), judge.getDescription(), stageIds ); result.add(judgeResponse); } } return result; } /** * 验证阶段的sort_order连续性 */ private void validateSortOrderContinuity(List stages) { if (stages == null || stages.isEmpty()) { return; } // 收集所有的sortOrder值 List 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 uniqueSortOrders = new HashSet<>(sortOrders); if (uniqueSortOrders.size() != sortOrders.size()) { throw new RuntimeException("阶段排序不能重复"); } } }