diff --git a/minio_data/.minio.sys/buckets/.bloomcycle.bin/xl.meta b/minio_data/.minio.sys/buckets/.bloomcycle.bin/xl.meta index 4aaaa7a..70509f4 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 b49d39c..d4290e0 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 b1fa1db..c8e19a8 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 88ea48d..5caf38f 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 8d2bbf0..e0dadbb 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 ad35cde..2e13a90 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 94dce67..21ece1f 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 0a0e25e..c1a0dee 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/MartialScheduleArrangeServiceImpl.java b/src/main/java/org/springblade/modules/martial/service/impl/MartialScheduleArrangeServiceImpl.java index 52a983b..debbfa5 100644 --- a/src/main/java/org/springblade/modules/martial/service/impl/MartialScheduleArrangeServiceImpl.java +++ b/src/main/java/org/springblade/modules/martial/service/impl/MartialScheduleArrangeServiceImpl.java @@ -28,6 +28,7 @@ import org.springblade.modules.martial.service.IMartialScheduleArrangeService; import org.springblade.modules.martial.service.schedule.generator.TimeSlotGenerator; import org.springblade.modules.martial.service.schedule.grouping.ParticipantGroupingService; import org.springblade.modules.martial.service.schedule.allocation.VenueAllocationService; +import org.springblade.modules.martial.service.schedule.query.ScheduleQueryService; import org.springframework.stereotype.Service; import org.springblade.modules.martial.service.schedule.model.ScheduleGroupData; import org.springblade.modules.martial.service.schedule.model.TimeSlot; @@ -65,19 +66,13 @@ public class MartialScheduleArrangeServiceImpl implements IMartialScheduleArrang private final ParticipantGroupingService participantGroupingService; private final VenueAllocationService venueAllocationService; + private final ScheduleQueryService scheduleQueryService; @Override public List getUnlockedCompetitions() { - // 查询所有未锁定的赛事(schedule_status != 2) - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.ne(MartialScheduleStatus::getScheduleStatus, 2) - .eq(MartialScheduleStatus::getIsDeleted, 0); - - List statusList = scheduleStatusMapper.selectList(wrapper); - return statusList.stream() - .map(MartialScheduleStatus::getCompetitionId) - .collect(Collectors.toList()); + return scheduleQueryService.getUnlockedCompetitions(); } + @Override @Transactional(rollbackFor = Exception.class) public void autoArrange(Long competitionId) { @@ -165,165 +160,10 @@ public class MartialScheduleArrangeServiceImpl implements IMartialScheduleArrang @Override public Map getScheduleResult(Long competitionId) { - // 获取编排状态 - MartialScheduleStatus status = getOrCreateScheduleStatus(competitionId); - - // 获取分组列表 - LambdaQueryWrapper groupWrapper = new LambdaQueryWrapper<>(); - groupWrapper.eq(MartialScheduleGroup::getCompetitionId, competitionId) - .eq(MartialScheduleGroup::getIsDeleted, 0) - .orderByAsc(MartialScheduleGroup::getDisplayOrder); - - List groups = scheduleGroupMapper.selectList(groupWrapper); - - // 构建前端需要的数据结构 - List> scheduleGroups = new ArrayList<>(); - - for (MartialScheduleGroup group : groups) { - Map groupData = new HashMap<>(); - groupData.put("id", group.getId()); - groupData.put("groupName", group.getGroupName()); - groupData.put("projectType", group.getProjectType()); - groupData.put("displayOrder", group.getDisplayOrder()); - groupData.put("totalParticipants", group.getTotalParticipants()); - groupData.put("totalTeams", group.getTotalTeams()); - groupData.put("estimatedDuration", group.getEstimatedDuration()); - groupData.put("projectId", group.getProjectId()); - - // 获取该分组的场地时间段详情 - LambdaQueryWrapper detailWrapper = new LambdaQueryWrapper<>(); - detailWrapper.eq(MartialScheduleDetail::getScheduleGroupId, group.getId()) - .eq(MartialScheduleDetail::getIsDeleted, 0); - List details = scheduleDetailMapper.selectList(detailWrapper); - - List> scheduleDetails = new ArrayList<>(); - for (MartialScheduleDetail detail : details) { - Map detailData = new HashMap<>(); - detailData.put("venueId", detail.getVenueId()); - detailData.put("venueName", detail.getVenueName()); - detailData.put("scheduleDate", detail.getScheduleDate()); - detailData.put("timeSlot", detail.getTimeSlot()); - detailData.put("timePeriod", detail.getTimePeriod()); - detailData.put("timeSlotIndex", detail.getTimeSlotIndex()); - scheduleDetails.add(detailData); - } - groupData.put("scheduleDetails", scheduleDetails); - // 提取第一个detail的场地和时间段信息到group级别 - if (!details.isEmpty()) { - MartialScheduleDetail firstDetail = details.get(0); - groupData.put("venueId", firstDetail.getVenueId()); - groupData.put("venueName", firstDetail.getVenueName()); - groupData.put("timeSlot", firstDetail.getTimeSlot()); - groupData.put("timeSlotIndex", firstDetail.getTimeSlotIndex()); - } - - // 获取该分组的参赛者 - LambdaQueryWrapper participantWrapper = new LambdaQueryWrapper<>(); - participantWrapper.eq(MartialScheduleParticipant::getScheduleGroupId, group.getId()) - .eq(MartialScheduleParticipant::getIsDeleted, 0); - List participants = scheduleParticipantMapper.selectList(participantWrapper); - - if (group.getProjectType() == 2) { - // 集体项目:按单位分组,并获取队员列表 - Map> orgGroupMap = participants.stream() - .collect(Collectors.groupingBy(MartialScheduleParticipant::getOrganization)); - - List> organizationGroups = new ArrayList<>(); - for (Map.Entry> entry : orgGroupMap.entrySet()) { - Map orgGroup = new HashMap<>(); - orgGroup.put("organization", entry.getKey()); - - List> orgParticipants = new ArrayList<>(); - for (MartialScheduleParticipant p : entry.getValue()) { - Map pData = new HashMap<>(); - pData.put("id", p.getParticipantId()); - pData.put("playerName", p.getPlayerName()); - pData.put("schoolUnit", p.getOrganization()); - - // 查询队伍信息和队员列表 - String teamName = p.getPlayerName(); - LambdaQueryWrapper teamWrapper = new LambdaQueryWrapper<>(); - teamWrapper.eq(MartialTeam::getTeamName, teamName) - .eq(MartialTeam::getIsDeleted, 0) - .last("LIMIT 1"); - MartialTeam team = teamMapper.selectOne(teamWrapper); - - List> memberList = new ArrayList<>(); - if (team != null) { - // 获取队员列表 - LambdaQueryWrapper memberWrapper = new LambdaQueryWrapper<>(); - memberWrapper.eq(MartialTeamMember::getTeamId, team.getId()) - .eq(MartialTeamMember::getIsDeleted, 0); - List members = teamMemberMapper.selectList(memberWrapper); - - for (MartialTeamMember member : members) { - // 获取队员详情 - MartialAthlete athlete = athleteMapper.selectById(member.getAthleteId()); - if (athlete != null) { - Map memberData = new HashMap<>(); - memberData.put("id", athlete.getId()); - memberData.put("playerName", athlete.getPlayerName()); - memberData.put("organization", athlete.getOrganization()); - memberList.add(memberData); - } - } - } - pData.put("members", memberList); - orgParticipants.add(pData); - } - orgGroup.put("participants", orgParticipants); - - // 获取该单位的场地时间段 - orgGroup.put("scheduleDetails", scheduleDetails); - - organizationGroups.add(orgGroup); - } - groupData.put("organizationGroups", organizationGroups); - - } else { - // 个人项目:直接列出参赛者 - List> individualParticipants = new ArrayList<>(); - for (MartialScheduleParticipant p : participants) { - Map pData = new HashMap<>(); - pData.put("id", p.getParticipantId()); - pData.put("organization", p.getOrganization()); - pData.put("playerName", p.getPlayerName()); - - // 获取该参赛者的场地时间段 - LambdaQueryWrapper pDetailWrapper = new LambdaQueryWrapper<>(); - pDetailWrapper.eq(MartialScheduleDetail::getId, p.getScheduleDetailId()) - .eq(MartialScheduleDetail::getIsDeleted, 0) - .last("LIMIT 1"); - MartialScheduleDetail pDetail = scheduleDetailMapper.selectOne(pDetailWrapper); - - if (pDetail != null) { - Map scheduleDetail = new HashMap<>(); - scheduleDetail.put("venueId", pDetail.getVenueId()); - scheduleDetail.put("venueName", pDetail.getVenueName()); - scheduleDetail.put("scheduleDate", pDetail.getScheduleDate()); - scheduleDetail.put("timeSlot", pDetail.getTimeSlot()); - pData.put("scheduleDetail", scheduleDetail); - } - - individualParticipants.add(pData); - } - groupData.put("participants", individualParticipants); - } - - scheduleGroups.add(groupData); - } - - // 构建返回结果 - Map result = new HashMap<>(); - result.put("scheduleStatus", status.getScheduleStatus()); - result.put("lastAutoScheduleTime", status.getLastAutoScheduleTime()); - result.put("totalGroups", status.getTotalGroups()); - result.put("totalParticipants", status.getTotalParticipants()); - result.put("competitionGroups", scheduleGroups); - - return result; + return scheduleQueryService.getScheduleResult(competitionId); } + // ==================== 私有辅助方法 ==================== private MartialScheduleStatus getOrCreateScheduleStatus(Long competitionId) { diff --git a/src/main/java/org/springblade/modules/martial/service/schedule/query/ScheduleQueryService.java b/src/main/java/org/springblade/modules/martial/service/schedule/query/ScheduleQueryService.java new file mode 100644 index 0000000..fb1375a --- /dev/null +++ b/src/main/java/org/springblade/modules/martial/service/schedule/query/ScheduleQueryService.java @@ -0,0 +1,253 @@ +package org.springblade.modules.martial.service.schedule.query; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springblade.modules.martial.mapper.*; +import org.springblade.modules.martial.pojo.entity.*; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * Schedule query service + * Handles schedule result queries + * + * @author Refactored from MartialScheduleArrangeServiceImpl + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class ScheduleQueryService { + + private final MartialScheduleStatusMapper scheduleStatusMapper; + private final MartialScheduleGroupMapper scheduleGroupMapper; + private final MartialScheduleDetailMapper scheduleDetailMapper; + private final MartialScheduleParticipantMapper scheduleParticipantMapper; + private final MartialAthleteMapper athleteMapper; + private final MartialTeamMapper teamMapper; + private final MartialTeamMemberMapper teamMemberMapper; + + /** + * Get unlocked competition IDs + */ + public List getUnlockedCompetitions() { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.ne(MartialScheduleStatus::getScheduleStatus, 2) + .eq(MartialScheduleStatus::getIsDeleted, 0); + + List statusList = scheduleStatusMapper.selectList(wrapper); + return statusList.stream() + .map(MartialScheduleStatus::getCompetitionId) + .collect(Collectors.toList()); + } + + /** + * Get schedule result for a competition + */ + public Map getScheduleResult(Long competitionId) { + MartialScheduleStatus status = getOrCreateScheduleStatus(competitionId); + List groups = loadScheduleGroups(competitionId); + List> scheduleGroups = buildScheduleGroupsData(groups); + + Map result = new HashMap<>(); + result.put("scheduleStatus", status.getScheduleStatus()); + result.put("lastAutoScheduleTime", status.getLastAutoScheduleTime()); + result.put("totalGroups", status.getTotalGroups()); + result.put("totalParticipants", status.getTotalParticipants()); + result.put("competitionGroups", scheduleGroups); + + return result; + } + + public MartialScheduleStatus getOrCreateScheduleStatus(Long competitionId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(MartialScheduleStatus::getCompetitionId, competitionId) + .eq(MartialScheduleStatus::getIsDeleted, 0) + .last("LIMIT 1"); + + MartialScheduleStatus status = scheduleStatusMapper.selectOne(wrapper); + + if (status == null) { + status = new MartialScheduleStatus(); + status.setCompetitionId(competitionId); + status.setScheduleStatus(0); + status.setTotalGroups(0); + status.setTotalParticipants(0); + status.setCreateTime(new Date()); + scheduleStatusMapper.insert(status); + } + + return status; + } + + private List loadScheduleGroups(Long competitionId) { + LambdaQueryWrapper groupWrapper = new LambdaQueryWrapper<>(); + groupWrapper.eq(MartialScheduleGroup::getCompetitionId, competitionId) + .eq(MartialScheduleGroup::getIsDeleted, 0) + .orderByAsc(MartialScheduleGroup::getDisplayOrder); + return scheduleGroupMapper.selectList(groupWrapper); + } + + private List> buildScheduleGroupsData(List groups) { + List> scheduleGroups = new ArrayList<>(); + + for (MartialScheduleGroup group : groups) { + Map groupData = buildGroupData(group); + List details = loadScheduleDetails(group.getId()); + List> scheduleDetails = buildScheduleDetails(details); + + groupData.put("scheduleDetails", scheduleDetails); + if (!details.isEmpty()) { + MartialScheduleDetail firstDetail = details.get(0); + groupData.put("venueId", firstDetail.getVenueId()); + groupData.put("venueName", firstDetail.getVenueName()); + groupData.put("timeSlot", firstDetail.getTimeSlot()); + groupData.put("timeSlotIndex", firstDetail.getTimeSlotIndex()); + } + + List participants = loadParticipants(group.getId()); + + if (group.getProjectType() == 2) { + groupData.put("organizationGroups", buildOrganizationGroups(participants, scheduleDetails)); + } else { + groupData.put("participants", buildIndividualParticipants(participants)); + } + + scheduleGroups.add(groupData); + } + + return scheduleGroups; + } + + private Map buildGroupData(MartialScheduleGroup group) { + Map groupData = new HashMap<>(); + groupData.put("id", group.getId()); + groupData.put("groupName", group.getGroupName()); + groupData.put("projectType", group.getProjectType()); + groupData.put("displayOrder", group.getDisplayOrder()); + groupData.put("totalParticipants", group.getTotalParticipants()); + groupData.put("totalTeams", group.getTotalTeams()); + groupData.put("estimatedDuration", group.getEstimatedDuration()); + groupData.put("projectId", group.getProjectId()); + return groupData; + } + + private List loadScheduleDetails(Long groupId) { + LambdaQueryWrapper detailWrapper = new LambdaQueryWrapper<>(); + detailWrapper.eq(MartialScheduleDetail::getScheduleGroupId, groupId) + .eq(MartialScheduleDetail::getIsDeleted, 0); + return scheduleDetailMapper.selectList(detailWrapper); + } + + private List> buildScheduleDetails(List details) { + List> scheduleDetails = new ArrayList<>(); + for (MartialScheduleDetail detail : details) { + Map detailData = new HashMap<>(); + detailData.put("venueId", detail.getVenueId()); + detailData.put("venueName", detail.getVenueName()); + detailData.put("scheduleDate", detail.getScheduleDate()); + detailData.put("timeSlot", detail.getTimeSlot()); + detailData.put("timePeriod", detail.getTimePeriod()); + detailData.put("timeSlotIndex", detail.getTimeSlotIndex()); + scheduleDetails.add(detailData); + } + return scheduleDetails; + } + + private List loadParticipants(Long groupId) { + LambdaQueryWrapper participantWrapper = new LambdaQueryWrapper<>(); + participantWrapper.eq(MartialScheduleParticipant::getScheduleGroupId, groupId) + .eq(MartialScheduleParticipant::getIsDeleted, 0); + return scheduleParticipantMapper.selectList(participantWrapper); + } + + private List> buildOrganizationGroups(List participants, + List> scheduleDetails) { + Map> orgGroupMap = participants.stream() + .collect(Collectors.groupingBy(MartialScheduleParticipant::getOrganization)); + + List> organizationGroups = new ArrayList<>(); + for (Map.Entry> entry : orgGroupMap.entrySet()) { + Map orgGroup = new HashMap<>(); + orgGroup.put("organization", entry.getKey()); + orgGroup.put("participants", buildTeamParticipants(entry.getValue())); + orgGroup.put("scheduleDetails", scheduleDetails); + organizationGroups.add(orgGroup); + } + return organizationGroups; + } + + private List> buildTeamParticipants(List participants) { + List> result = new ArrayList<>(); + for (MartialScheduleParticipant p : participants) { + Map pData = new HashMap<>(); + pData.put("id", p.getParticipantId()); + pData.put("playerName", p.getPlayerName()); + pData.put("schoolUnit", p.getOrganization()); + pData.put("members", loadTeamMembers(p.getPlayerName())); + result.add(pData); + } + return result; + } + + private List> loadTeamMembers(String teamName) { + List> memberList = new ArrayList<>(); + LambdaQueryWrapper teamWrapper = new LambdaQueryWrapper<>(); + teamWrapper.eq(MartialTeam::getTeamName, teamName) + .eq(MartialTeam::getIsDeleted, 0) + .last("LIMIT 1"); + MartialTeam team = teamMapper.selectOne(teamWrapper); + + if (team != null) { + LambdaQueryWrapper memberWrapper = new LambdaQueryWrapper<>(); + memberWrapper.eq(MartialTeamMember::getTeamId, team.getId()) + .eq(MartialTeamMember::getIsDeleted, 0); + List members = teamMemberMapper.selectList(memberWrapper); + + for (MartialTeamMember member : members) { + MartialAthlete athlete = athleteMapper.selectById(member.getAthleteId()); + if (athlete != null) { + Map memberData = new HashMap<>(); + memberData.put("id", athlete.getId()); + memberData.put("playerName", athlete.getPlayerName()); + memberData.put("organization", athlete.getOrganization()); + memberList.add(memberData); + } + } + } + return memberList; + } + + private List> buildIndividualParticipants(List participants) { + List> result = new ArrayList<>(); + for (MartialScheduleParticipant p : participants) { + Map pData = new HashMap<>(); + pData.put("id", p.getParticipantId()); + pData.put("organization", p.getOrganization()); + pData.put("playerName", p.getPlayerName()); + pData.put("scheduleDetail", loadParticipantScheduleDetail(p.getScheduleDetailId())); + result.add(pData); + } + return result; + } + + private Map loadParticipantScheduleDetail(Long detailId) { + LambdaQueryWrapper pDetailWrapper = new LambdaQueryWrapper<>(); + pDetailWrapper.eq(MartialScheduleDetail::getId, detailId) + .eq(MartialScheduleDetail::getIsDeleted, 0) + .last("LIMIT 1"); + MartialScheduleDetail pDetail = scheduleDetailMapper.selectOne(pDetailWrapper); + + if (pDetail != null) { + Map scheduleDetail = new HashMap<>(); + scheduleDetail.put("venueId", pDetail.getVenueId()); + scheduleDetail.put("venueName", pDetail.getVenueName()); + scheduleDetail.put("scheduleDate", pDetail.getScheduleDate()); + scheduleDetail.put("timeSlot", pDetail.getTimeSlot()); + return scheduleDetail; + } + return null; + } +}