diff --git a/minio_data/.minio.sys/buckets/.bloomcycle.bin/xl.meta b/minio_data/.minio.sys/buckets/.bloomcycle.bin/xl.meta index 90163f5..ee4af40 100644 Binary files a/minio_data/.minio.sys/buckets/.bloomcycle.bin/xl.meta and b/minio_data/.minio.sys/buckets/.bloomcycle.bin/xl.meta differ diff --git a/minio_data/.minio.sys/buckets/.usage-cache.bin.bkp/xl.meta b/minio_data/.minio.sys/buckets/.usage-cache.bin.bkp/xl.meta index f9240af..6bcae2c 100644 Binary files a/minio_data/.minio.sys/buckets/.usage-cache.bin.bkp/xl.meta and b/minio_data/.minio.sys/buckets/.usage-cache.bin.bkp/xl.meta differ diff --git a/minio_data/.minio.sys/buckets/.usage-cache.bin/xl.meta b/minio_data/.minio.sys/buckets/.usage-cache.bin/xl.meta index bf1b9ef..6d1cdda 100644 Binary files a/minio_data/.minio.sys/buckets/.usage-cache.bin/xl.meta and b/minio_data/.minio.sys/buckets/.usage-cache.bin/xl.meta differ diff --git a/minio_data/.minio.sys/buckets/.usage.json/xl.meta b/minio_data/.minio.sys/buckets/.usage.json/xl.meta index 67db226..f6a7de5 100644 Binary files a/minio_data/.minio.sys/buckets/.usage.json/xl.meta and b/minio_data/.minio.sys/buckets/.usage.json/xl.meta differ diff --git a/minio_data/.minio.sys/buckets/000000-assets/.usage-cache.bin.bkp/xl.meta b/minio_data/.minio.sys/buckets/000000-assets/.usage-cache.bin.bkp/xl.meta index 852717d..1df745d 100644 Binary files a/minio_data/.minio.sys/buckets/000000-assets/.usage-cache.bin.bkp/xl.meta and b/minio_data/.minio.sys/buckets/000000-assets/.usage-cache.bin.bkp/xl.meta differ diff --git a/minio_data/.minio.sys/buckets/000000-assets/.usage-cache.bin/xl.meta b/minio_data/.minio.sys/buckets/000000-assets/.usage-cache.bin/xl.meta index 0cbb604..92ce0b6 100644 Binary files a/minio_data/.minio.sys/buckets/000000-assets/.usage-cache.bin/xl.meta and b/minio_data/.minio.sys/buckets/000000-assets/.usage-cache.bin/xl.meta differ diff --git a/minio_data/.minio.sys/buckets/assets/.usage-cache.bin.bkp/xl.meta b/minio_data/.minio.sys/buckets/assets/.usage-cache.bin.bkp/xl.meta index 183f6a9..02b5cf3 100644 Binary files a/minio_data/.minio.sys/buckets/assets/.usage-cache.bin.bkp/xl.meta and b/minio_data/.minio.sys/buckets/assets/.usage-cache.bin.bkp/xl.meta differ diff --git a/minio_data/.minio.sys/buckets/assets/.usage-cache.bin/xl.meta b/minio_data/.minio.sys/buckets/assets/.usage-cache.bin/xl.meta index 5393b9d..4d4ba8f 100644 Binary files a/minio_data/.minio.sys/buckets/assets/.usage-cache.bin/xl.meta and b/minio_data/.minio.sys/buckets/assets/.usage-cache.bin/xl.meta differ diff --git a/src/main/java/org/springblade/modules/martial/service/impl/MartialScheduleServiceImpl.java b/src/main/java/org/springblade/modules/martial/service/impl/MartialScheduleServiceImpl.java index e2d24ef..8cfe23a 100644 --- a/src/main/java/org/springblade/modules/martial/service/impl/MartialScheduleServiceImpl.java +++ b/src/main/java/org/springblade/modules/martial/service/impl/MartialScheduleServiceImpl.java @@ -31,6 +31,7 @@ import org.springframework.beans.factory.annotation.Autowired; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.cache.annotation.Cacheable; import java.time.LocalDate; import java.time.format.DateTimeFormatter; @@ -112,288 +113,13 @@ public class MartialScheduleServiceImpl extends ServiceImpl details = scheduleGroupMapper.selectScheduleGroupDetails(competitionId); - - if (details.isEmpty()) { - // 没有编排数据时,从项目和选手表生成初始分组 - return generateInitialScheduleResult(competitionId); - } - - // 按分组ID分组数据 - Map> groupMap = details.stream() - .collect(Collectors.groupingBy(ScheduleGroupDetailVO::getGroupId)); - - // 检查编排状态 - boolean isCompleted = details.stream() - .anyMatch(d -> "completed".equals(d.getScheduleStatus())); - boolean isDraft = !isCompleted; - - result.setIsDraft(isDraft); - result.setIsCompleted(isCompleted); - - // 组装数据 - List groupDTOs = new ArrayList<>(); - for (Map.Entry> entry : groupMap.entrySet()) { - List groupDetails = entry.getValue(); - if (groupDetails.isEmpty()) { - continue; - } - - // 获取第一条记录作为分组信息 - ScheduleGroupDetailVO firstDetail = groupDetails.get(0); - - CompetitionGroupDTO groupDTO = new CompetitionGroupDTO(); - groupDTO.setId(firstDetail.getGroupId()); - groupDTO.setTitle(firstDetail.getGroupName()); - groupDTO.setCode(firstDetail.getCategory()); - - // 设置类型 - if (firstDetail.getProjectType() != null) { - switch (firstDetail.getProjectType()) { - case 1: - groupDTO.setType("单人"); - break; - case 2: - groupDTO.setType("集体"); - break; - default: - groupDTO.setType("其他"); - break; - } - } - - // 设置队伍数量 - if (firstDetail.getTotalTeams() != null && firstDetail.getTotalTeams() > 0) { - groupDTO.setCount(firstDetail.getTotalTeams() + "队"); - } else if (firstDetail.getTotalParticipants() != null) { - groupDTO.setCount(firstDetail.getTotalParticipants() + "人"); - } - - // 设置场地和时间段信息 - groupDTO.setVenueId(firstDetail.getVenueId()); - groupDTO.setVenueName(firstDetail.getVenueName()); - groupDTO.setTimeSlot(firstDetail.getTimeSlot()); - groupDTO.setTimeSlotIndex(firstDetail.getTimeSlotIndex() != null ? firstDetail.getTimeSlotIndex() : 0); - groupDTO.setEstimatedDuration(firstDetail.getEstimatedDuration()); - - // 获取参赛者列表 - boolean isCollective = firstDetail.getProjectType() != null && firstDetail.getProjectType() == 2; - List participantDTOs = new ArrayList<>(); - for (ScheduleGroupDetailVO d : groupDetails) { - if (d.getParticipantId() == null) continue; - - ParticipantDTO dto = new ParticipantDTO(); - dto.setId(d.getParticipantId()); - dto.setSchoolUnit(d.getOrganization()); - dto.setStatus(d.getCheckInStatus() != null ? d.getCheckInStatus() : "未签到"); - dto.setSortOrder(d.getPerformanceOrder()); - dto.setPlayerName(d.getPlayerName()); - - // For collective projects, query team members - if (isCollective) { - List> memberList = new ArrayList<>(); - // Step 1: Get athlete record to find team_name - MartialAthlete participantAthlete = athleteMapper.selectById(d.getParticipantId()); - if (participantAthlete != null && participantAthlete.getTeamName() != null) { - // Step 2: Find team by team_name - QueryWrapper teamWrapper = new QueryWrapper<>(); - teamWrapper.eq("team_name", participantAthlete.getTeamName()); - teamWrapper.eq("is_deleted", 0); - MartialTeam team = teamMapper.selectOne(teamWrapper); - if (team != null) { - // Step 3: Query team members - QueryWrapper memberWrapper = new QueryWrapper<>(); - memberWrapper.eq("team_id", team.getId()); - memberWrapper.eq("is_deleted", 0); - List members = teamMemberMapper.selectList(memberWrapper); - // Step 4: Get member athlete info - for (MartialTeamMember member : members) { - Map memberData = new HashMap<>(); - memberData.put("id", member.getId()); - MartialAthlete athlete = athleteMapper.selectById(member.getAthleteId()); - memberData.put("name", athlete != null ? athlete.getPlayerName() : ""); - memberData.put("gender", athlete != null ? athlete.getGender() : ""); - memberList.add(memberData); - } - } - } - dto.setMembers(memberList); - } - - participantDTOs.add(dto); - } - groupDTO.setParticipants(participantDTOs); - groupDTO.setStatus(calculateGroupStatus(participantDTOs)); - groupDTOs.add(groupDTO); - } - - // 按 displayOrder 排序 - groupDTOs.sort(Comparator.comparing(g -> { - ScheduleGroupDetailVO detail = details.stream() - .filter(d -> d.getGroupId().equals(g.getId())) - .findFirst() - .orElse(null); - return detail != null ? detail.getDisplayOrder() : 999; - })); - - result.setCompetitionGroups(groupDTOs); - return result; + // Delegated to ScheduleQueryService + return scheduleQueryService.getScheduleResult(competitionId); } - /** - * 没有编排数据时,从项目和选手表生成初始分组 - */ - private ScheduleResultDTO generateInitialScheduleResult(Long competitionId) { - ScheduleResultDTO result = new ScheduleResultDTO(); - result.setIsDraft(true); - result.setIsCompleted(false); - // 1. 获取该赛事的所有项目 - List projects = projectService.list( - new QueryWrapper() - .eq("competition_id", competitionId) - .eq("is_deleted", 0) - .orderByAsc("id") - ); - - if (projects.isEmpty()) { - result.setCompetitionGroups(new ArrayList<>()); - return result; - } - - // 2. 获取该赛事的所有选手 - List athletes = athleteService.list( - new QueryWrapper() - .eq("competition_id", competitionId) - .eq("is_deleted", 0) - ); - - // 按项目ID分组选手 - Map> athletesByProject = athletes.stream() - .collect(Collectors.groupingBy(MartialAthlete::getProjectId)); - - // 3. 获取该赛事的第一个场地作为默认场地 - List venues = venueService.list( - new QueryWrapper() - .eq("competition_id", competitionId) - .eq("is_deleted", 0) - .orderByAsc("id") - .last("LIMIT 1") - ); - - Long defaultVenueId = venues.isEmpty() ? null : venues.get(0).getId(); - String defaultVenueName = venues.isEmpty() ? "未分配" : venues.get(0).getVenueName(); - - // 4. 为每个项目生成分组(单人项目根据maxParticipants拆分) - List groupDTOs = new ArrayList<>(); - int displayOrder = 0; - long tempIdCounter = 1; // Counter for generating unique negative IDs for sub-groups - - for (MartialProject project : projects) { - List projectAthletes = athletesByProject.getOrDefault(project.getId(), new ArrayList<>()); - - // 跳过没有选手的项目 - if (projectAthletes.isEmpty()) { - continue; - } - - // 判断项目类型 - Integer projectType = project.getType(); - String typeStr; - if (projectType != null) { - switch (projectType) { - case 1: - typeStr = "单人"; - break; - case 2: - case 3: - typeStr = "集体"; - break; - default: - typeStr = "其他"; - break; - } - } else { - typeStr = "单人"; - } - - // 单人项目:根据maxParticipants拆分 - if ("单人".equals(typeStr)) { - Integer maxParticipants = project.getMaxParticipants(); - int athleteCount = projectAthletes.size(); - - // 如果maxParticipants有效且人数超过限制,需要拆分 - if (maxParticipants != null && maxParticipants > 0 && athleteCount > maxParticipants) { - int numGroups = (int) Math.ceil((double) athleteCount / maxParticipants); - log.info("项目 '{}' 有{}人,maxParticipants={},将拆分成{}组", - project.getProjectName(), athleteCount, maxParticipants, numGroups); - - for (int i = 0; i < numGroups; i++) { - int startIdx = i * maxParticipants; - int endIdx = Math.min(startIdx + maxParticipants, athleteCount); - List subGroupAthletes = projectAthletes.subList(startIdx, endIdx); - - CompetitionGroupDTO groupDTO = new CompetitionGroupDTO(); - // 使用唯一的负数ID - groupDTO.setId(-project.getId() - tempIdCounter++); - groupDTO.setProjectId(project.getId()); - - // 如果只有一组,不加组号后缀 - if (numGroups == 1) { - groupDTO.setTitle(project.getProjectName() + " 未分组"); - } else { - groupDTO.setTitle(project.getProjectName() + " 第" + (i + 1) + "组"); - } - groupDTO.setCode("C" + competitionId + "-P" + String.format("%03d", displayOrder + 1)); - groupDTO.setType(typeStr); - groupDTO.setCount(subGroupAthletes.size() + "人"); - groupDTO.setVenueId(defaultVenueId); - groupDTO.setVenueName(defaultVenueName); - groupDTO.setTimeSlotIndex(0); - groupDTO.setTimeSlot(null); - - // 生成参赛者列表 - List participantDTOs = new ArrayList<>(); - int sortOrder = 1; - for (MartialAthlete athlete : subGroupAthletes) { - ParticipantDTO dto = new ParticipantDTO(); - dto.setId(athlete.getId()); - dto.setPlayerName(athlete.getPlayerName()); - dto.setSchoolUnit(athlete.getOrganization()); - dto.setTeamName(athlete.getTeamName()); - dto.setStatus("未签到"); - dto.setSortOrder(sortOrder++); - participantDTOs.add(dto); - } - - groupDTO.setParticipants(participantDTOs); - groupDTO.setStatus(calculateGroupStatus(participantDTOs)); - groupDTOs.add(groupDTO); - displayOrder++; - } - } else { - // 不需要拆分,生成单个分组 - CompetitionGroupDTO groupDTO = createSingleGroup(project, projectAthletes, typeStr, - defaultVenueId, defaultVenueName, competitionId, displayOrder); - groupDTOs.add(groupDTO); - displayOrder++; - } - } else { - // 集体项目:不拆分 - CompetitionGroupDTO groupDTO = createSingleGroup(project, projectAthletes, typeStr, - defaultVenueId, defaultVenueName, competitionId, displayOrder); - groupDTOs.add(groupDTO); - displayOrder++; - } - } - - result.setCompetitionGroups(groupDTOs); - return result; - } /** * 创建单个分组DTO