fix(registration): 修复我的报名列表信息显示不全问题

- 修改list接口返回VO而非Entity
- 添加getListWithRelations方法批量加载关联数据
- 返回赛事名称、地点、时间、项目名称、选手名称等完整信息
- 优化批量查询减少数据库访问次数
This commit is contained in:
2025-12-30 17:43:45 +08:00
parent b7ad819a29
commit 87a05df04f
12 changed files with 174 additions and 42 deletions

View File

@@ -16,6 +16,7 @@ import org.springblade.core.tool.utils.Func;
import org.springblade.modules.martial.pojo.entity.MartialAthlete; import org.springblade.modules.martial.pojo.entity.MartialAthlete;
import org.springblade.modules.martial.pojo.entity.MartialRegistrationOrder; import org.springblade.modules.martial.pojo.entity.MartialRegistrationOrder;
import org.springblade.modules.martial.pojo.dto.RegistrationSubmitDTO; import org.springblade.modules.martial.pojo.dto.RegistrationSubmitDTO;
import org.springblade.modules.martial.pojo.vo.MartialRegistrationOrderVO;
import org.springblade.modules.martial.service.IMartialAthleteService; import org.springblade.modules.martial.service.IMartialAthleteService;
import org.springblade.modules.martial.service.IMartialRegistrationOrderService; import org.springblade.modules.martial.service.IMartialRegistrationOrderService;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -44,41 +45,26 @@ public class MartialRegistrationOrderController extends BladeController {
@GetMapping("/detail") @GetMapping("/detail")
@Operation(summary = "详情", description = "传入ID") @Operation(summary = "详情", description = "传入ID")
public R detail(@RequestParam Long id) { public R detail(@RequestParam Long id) {
// 返回包含关联数据的完整详情
return R.data(registrationOrderService.getDetailWithRelations(id)); return R.data(registrationOrderService.getDetailWithRelations(id));
} }
/** /**
* 分页列表 - 只返回当前用户的报名记录 * 分页列表 - 只返回当前用户的报名记录(包含关联数据)
*/ */
@GetMapping("/list") @GetMapping("/list")
@Operation(summary = "分页列表", description = "分页查询当前用户的报名记录") @Operation(summary = "分页列表", description = "分页查询当前用户的报名记录")
public R<IPage<MartialRegistrationOrder>> list(MartialRegistrationOrder registrationOrder, Query query) { public R<IPage<MartialRegistrationOrderVO>> list(MartialRegistrationOrder registrationOrder, Query query) {
// 获取当前登录用户ID
Long userId = AuthUtil.getUserId(); Long userId = AuthUtil.getUserId();
Integer status = registrationOrder.getStatus();
// 构建查询条件 - 只查询当前用户的订单 IPage<MartialRegistrationOrderVO> pages = registrationOrderService.getListWithRelations(
LambdaQueryWrapper<MartialRegistrationOrder> queryWrapper = new LambdaQueryWrapper<>(); userId, status, query.getCurrent(), query.getSize());
queryWrapper.eq(MartialRegistrationOrder::getUserId, userId);
// 如果传入了状态参数,添加状态过滤
if (registrationOrder.getStatus() != null) {
queryWrapper.eq(MartialRegistrationOrder::getStatus, registrationOrder.getStatus());
}
// 按创建时间倒序
queryWrapper.orderByDesc(MartialRegistrationOrder::getCreateTime);
// 分页查询
IPage<MartialRegistrationOrder> page = new Page<>(query.getCurrent(), query.getSize());
IPage<MartialRegistrationOrder> pages = registrationOrderService.page(page, queryWrapper);
return R.data(pages); return R.data(pages);
} }
/** /**
* 提交报名订单 * 提交报名订单
* 接收前端传来的 athleteIds 和 projectIds更新选手的 orderId
*/ */
@PostMapping("/submit") @PostMapping("/submit")
@Operation(summary = "提交报名", description = "提交报名订单并关联选手") @Operation(summary = "提交报名", description = "提交报名订单并关联选手")
@@ -92,7 +78,7 @@ public class MartialRegistrationOrderController extends BladeController {
log.info("联系电话: {}", dto.getContactPhone()); log.info("联系电话: {}", dto.getContactPhone());
log.info("总金额: {}", dto.getTotalAmount()); log.info("总金额: {}", dto.getTotalAmount());
// 1. 创建订单实体 // Create order entity
MartialRegistrationOrder order = new MartialRegistrationOrder(); MartialRegistrationOrder order = new MartialRegistrationOrder();
order.setOrderNo(dto.getOrderNo()); order.setOrderNo(dto.getOrderNo());
order.setCompetitionId(dto.getCompetitionId()); order.setCompetitionId(dto.getCompetitionId());
@@ -101,11 +87,11 @@ public class MartialRegistrationOrderController extends BladeController {
order.setUserId(AuthUtil.getUserId()); order.setUserId(AuthUtil.getUserId());
order.setUserName(AuthUtil.getUserName()); order.setUserName(AuthUtil.getUserName());
// 解析选手ID列表 // Parse athlete IDs
List<Long> athleteIds = Func.toLongList(dto.getAthleteIds()); List<Long> athleteIds = Func.toLongList(dto.getAthleteIds());
order.setTotalParticipants(athleteIds.size()); order.setTotalParticipants(athleteIds.size());
// 2. 保存订单 // Save order
boolean saved = registrationOrderService.save(order); boolean saved = registrationOrderService.save(order);
if (!saved) { if (!saved) {
return R.fail("创建订单失败"); return R.fail("创建订单失败");
@@ -114,18 +100,17 @@ public class MartialRegistrationOrderController extends BladeController {
Long orderId = order.getId(); Long orderId = order.getId();
log.info("订单创建成功订单ID: {}", orderId); log.info("订单创建成功订单ID: {}", orderId);
// 3. 解析项目ID列表 // Parse project IDs
List<Long> projectIds = Func.toLongList(dto.getProjectIds()); List<Long> projectIds = Func.toLongList(dto.getProjectIds());
Long firstProjectId = projectIds.isEmpty() ? null : projectIds.get(0); Long firstProjectId = projectIds.isEmpty() ? null : projectIds.get(0);
// 4. 更新选手的 orderIdcompetitionId projectId // Update athletes with orderId, competitionId and projectId
if (!athleteIds.isEmpty()) { if (!athleteIds.isEmpty()) {
LambdaUpdateWrapper<MartialAthlete> updateWrapper = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<MartialAthlete> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.in(MartialAthlete::getId, athleteIds) updateWrapper.in(MartialAthlete::getId, athleteIds)
.set(MartialAthlete::getOrderId, orderId) .set(MartialAthlete::getOrderId, orderId)
.set(MartialAthlete::getCompetitionId, dto.getCompetitionId()); .set(MartialAthlete::getCompetitionId, dto.getCompetitionId());
// 如果只有一个项目设置项目ID
if (firstProjectId != null) { if (firstProjectId != null) {
updateWrapper.set(MartialAthlete::getProjectId, firstProjectId); updateWrapper.set(MartialAthlete::getProjectId, firstProjectId);
} }
@@ -134,7 +119,6 @@ public class MartialRegistrationOrderController extends BladeController {
log.info("更新选手关联,选手数量: {}, 更新结果: {}", athleteIds.size(), updated); log.info("更新选手关联,选手数量: {}, 更新结果: {}", athleteIds.size(), updated);
} }
// 5. 返回订单信息
return R.data(order); return R.data(order);
} }

View File

@@ -1,5 +1,6 @@
package org.springblade.modules.martial.service; package org.springblade.modules.martial.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import org.springblade.modules.martial.pojo.entity.MartialRegistrationOrder; import org.springblade.modules.martial.pojo.entity.MartialRegistrationOrder;
import org.springblade.modules.martial.pojo.vo.MartialRegistrationOrderVO; import org.springblade.modules.martial.pojo.vo.MartialRegistrationOrderVO;
@@ -19,4 +20,15 @@ public interface IMartialRegistrationOrderService extends IService<MartialRegist
*/ */
MartialRegistrationOrderVO getDetailWithRelations(Long id); MartialRegistrationOrderVO getDetailWithRelations(Long id);
/**
* 获取报名订单列表(包含关联数据)
*
* @param userId 用户ID
* @param status 状态
* @param current 当前页
* @param size 每页大小
* @return 订单列表VO
*/
IPage<MartialRegistrationOrderVO> getListWithRelations(Long userId, Integer status, Integer current, Integer size);
} }

View File

@@ -1,6 +1,8 @@
package org.springblade.modules.martial.service.impl; package org.springblade.modules.martial.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springblade.modules.martial.pojo.entity.MartialAthlete; import org.springblade.modules.martial.pojo.entity.MartialAthlete;
@@ -16,7 +18,9 @@ import org.springblade.modules.martial.service.IMartialRegistrationOrderService;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@@ -34,40 +38,96 @@ public class MartialRegistrationOrderServiceImpl extends ServiceImpl<MartialRegi
@Override @Override
public MartialRegistrationOrderVO getDetailWithRelations(Long id) { public MartialRegistrationOrderVO getDetailWithRelations(Long id) {
// 获取订单基本信息
MartialRegistrationOrder order = this.getById(id); MartialRegistrationOrder order = this.getById(id);
if (order == null) { if (order == null) {
return null; return null;
} }
return convertToVO(order);
}
// 创建VO对象 @Override
public IPage<MartialRegistrationOrderVO> getListWithRelations(Long userId, Integer status, Integer current, Integer size) {
// Build query
LambdaQueryWrapper<MartialRegistrationOrder> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(MartialRegistrationOrder::getUserId, userId);
if (status != null) {
queryWrapper.eq(MartialRegistrationOrder::getStatus, status);
}
queryWrapper.orderByDesc(MartialRegistrationOrder::getCreateTime);
// Paginate
IPage<MartialRegistrationOrder> page = new Page<>(current, size);
IPage<MartialRegistrationOrder> orderPage = this.page(page, queryWrapper);
// Convert to VO page
IPage<MartialRegistrationOrderVO> voPage = new Page<>(current, size, orderPage.getTotal());
if (orderPage.getRecords().isEmpty()) {
voPage.setRecords(new ArrayList<>());
return voPage;
}
// Batch load competition info
List<Long> competitionIds = orderPage.getRecords().stream()
.map(MartialRegistrationOrder::getCompetitionId)
.filter(id -> id != null)
.distinct()
.collect(Collectors.toList());
Map<Long, MartialCompetition> competitionMap = competitionIds.isEmpty() ?
Map.of() :
competitionService.listByIds(competitionIds).stream()
.collect(Collectors.toMap(MartialCompetition::getId, c -> c));
// Batch load athletes by order IDs
List<Long> orderIds = orderPage.getRecords().stream()
.map(MartialRegistrationOrder::getId)
.collect(Collectors.toList());
LambdaQueryWrapper<MartialAthlete> athleteWrapper = new LambdaQueryWrapper<>();
athleteWrapper.in(MartialAthlete::getOrderId, orderIds);
List<MartialAthlete> allAthletes = athleteService.list(athleteWrapper);
Map<Long, List<MartialAthlete>> athletesByOrder = allAthletes.stream()
.collect(Collectors.groupingBy(MartialAthlete::getOrderId));
// Batch load projects
List<Long> projectIds = allAthletes.stream()
.map(MartialAthlete::getProjectId)
.filter(id -> id != null)
.distinct()
.collect(Collectors.toList());
Map<Long, MartialProject> projectMap = projectIds.isEmpty() ?
Map.of() :
projectService.listByIds(projectIds).stream()
.collect(Collectors.toMap(MartialProject::getId, p -> p));
// Convert each order to VO
List<MartialRegistrationOrderVO> voList = orderPage.getRecords().stream()
.map(order -> {
MartialRegistrationOrderVO vo = new MartialRegistrationOrderVO(); MartialRegistrationOrderVO vo = new MartialRegistrationOrderVO();
BeanUtils.copyProperties(order, vo); BeanUtils.copyProperties(order, vo);
// 获取赛事信息 // Set competition info
if (order.getCompetitionId() != null) { MartialCompetition competition = competitionMap.get(order.getCompetitionId());
MartialCompetition competition = competitionService.getById(order.getCompetitionId());
if (competition != null) { if (competition != null) {
vo.setCompetitionName(competition.getCompetitionName()); vo.setCompetitionName(competition.getCompetitionName());
vo.setLocation(competition.getLocation()); vo.setLocation(competition.getLocation());
vo.setStartTime(competition.getCompetitionStartTime() != null ? competition.getCompetitionStartTime().toString() : null); vo.setStartTime(competition.getCompetitionStartTime() != null ?
vo.setEndTime(competition.getCompetitionEndTime() != null ? competition.getCompetitionEndTime().toString() : null); competition.getCompetitionStartTime().toString() : null);
} vo.setEndTime(competition.getCompetitionEndTime() != null ?
competition.getCompetitionEndTime().toString() : null);
} }
// 获取该订单的所有选手 // Set athlete info
LambdaQueryWrapper<MartialAthlete> athleteWrapper = new LambdaQueryWrapper<>(); List<MartialAthlete> athletes = athletesByOrder.getOrDefault(order.getId(), new ArrayList<>());
athleteWrapper.eq(MartialAthlete::getOrderId, id);
List<MartialAthlete> athletes = athleteService.list(athleteWrapper);
if (!athletes.isEmpty()) { if (!athletes.isEmpty()) {
// 设置选手名称列表
String athleteNames = athletes.stream() String athleteNames = athletes.stream()
.map(MartialAthlete::getPlayerName) .map(MartialAthlete::getPlayerName)
.collect(Collectors.joining("")); .collect(Collectors.joining(""));
vo.setAthleteNames(athleteNames); vo.setAthleteNames(athleteNames);
// 设置选手详细列表
List<MartialRegistrationOrderVO.AthleteInfo> athleteList = athletes.stream() List<MartialRegistrationOrderVO.AthleteInfo> athleteList = athletes.stream()
.map(athlete -> { .map(athlete -> {
MartialRegistrationOrderVO.AthleteInfo info = new MartialRegistrationOrderVO.AthleteInfo(); MartialRegistrationOrderVO.AthleteInfo info = new MartialRegistrationOrderVO.AthleteInfo();
@@ -80,7 +140,87 @@ public class MartialRegistrationOrderServiceImpl extends ServiceImpl<MartialRegi
.collect(Collectors.toList()); .collect(Collectors.toList());
vo.setAthleteList(athleteList); vo.setAthleteList(athleteList);
// 获取项目信息从选手的项目ID中去重 // Set project info
List<Long> orderProjectIds = athletes.stream()
.map(MartialAthlete::getProjectId)
.filter(id -> id != null)
.distinct()
.collect(Collectors.toList());
if (!orderProjectIds.isEmpty()) {
List<MartialProject> projects = orderProjectIds.stream()
.map(projectMap::get)
.filter(p -> p != null)
.collect(Collectors.toList());
String projectNames = projects.stream()
.map(MartialProject::getProjectName)
.collect(Collectors.joining(""));
vo.setProjectNames(projectNames);
List<MartialRegistrationOrderVO.ProjectInfo> projectList = projects.stream()
.map(project -> {
MartialRegistrationOrderVO.ProjectInfo info = new MartialRegistrationOrderVO.ProjectInfo();
info.setId(project.getId());
info.setProjectName(project.getProjectName());
Integer type = project.getType();
info.setProjectType(type == 1 ? "个人" : "集体");
return info;
})
.collect(Collectors.toList());
vo.setProjectList(projectList);
}
}
return vo;
})
.collect(Collectors.toList());
voPage.setRecords(voList);
return voPage;
}
private MartialRegistrationOrderVO convertToVO(MartialRegistrationOrder order) {
MartialRegistrationOrderVO vo = new MartialRegistrationOrderVO();
BeanUtils.copyProperties(order, vo);
// Get competition info
if (order.getCompetitionId() != null) {
MartialCompetition competition = competitionService.getById(order.getCompetitionId());
if (competition != null) {
vo.setCompetitionName(competition.getCompetitionName());
vo.setLocation(competition.getLocation());
vo.setStartTime(competition.getCompetitionStartTime() != null ?
competition.getCompetitionStartTime().toString() : null);
vo.setEndTime(competition.getCompetitionEndTime() != null ?
competition.getCompetitionEndTime().toString() : null);
}
}
// Get athletes for this order
LambdaQueryWrapper<MartialAthlete> athleteWrapper = new LambdaQueryWrapper<>();
athleteWrapper.eq(MartialAthlete::getOrderId, order.getId());
List<MartialAthlete> athletes = athleteService.list(athleteWrapper);
if (!athletes.isEmpty()) {
String athleteNames = athletes.stream()
.map(MartialAthlete::getPlayerName)
.collect(Collectors.joining(""));
vo.setAthleteNames(athleteNames);
List<MartialRegistrationOrderVO.AthleteInfo> athleteList = athletes.stream()
.map(athlete -> {
MartialRegistrationOrderVO.AthleteInfo info = new MartialRegistrationOrderVO.AthleteInfo();
info.setId(athlete.getId());
info.setPlayerName(athlete.getPlayerName());
info.setGender(athlete.getGender());
info.setIdCard(athlete.getIdCard());
return info;
})
.collect(Collectors.toList());
vo.setAthleteList(athleteList);
// Get project info
List<Long> projectIds = athletes.stream() List<Long> projectIds = athletes.stream()
.map(MartialAthlete::getProjectId) .map(MartialAthlete::getProjectId)
.filter(projectId -> projectId != null) .filter(projectId -> projectId != null)
@@ -90,22 +230,18 @@ public class MartialRegistrationOrderServiceImpl extends ServiceImpl<MartialRegi
if (!projectIds.isEmpty()) { if (!projectIds.isEmpty()) {
List<MartialProject> projects = projectService.listByIds(projectIds); List<MartialProject> projects = projectService.listByIds(projectIds);
// 设置项目名称列表
String projectNames = projects.stream() String projectNames = projects.stream()
.map(MartialProject::getProjectName) .map(MartialProject::getProjectName)
.collect(Collectors.joining("")); .collect(Collectors.joining(""));
vo.setProjectNames(projectNames); vo.setProjectNames(projectNames);
// 设置项目详细列表
List<MartialRegistrationOrderVO.ProjectInfo> projectList = projects.stream() List<MartialRegistrationOrderVO.ProjectInfo> projectList = projects.stream()
.map(project -> { .map(project -> {
MartialRegistrationOrderVO.ProjectInfo info = new MartialRegistrationOrderVO.ProjectInfo(); MartialRegistrationOrderVO.ProjectInfo info = new MartialRegistrationOrderVO.ProjectInfo();
info.setId(project.getId()); info.setId(project.getId());
info.setProjectName(project.getProjectName()); info.setProjectName(project.getProjectName());
//类型(1-个人,2-双人,3-集体)
Integer type = project.getType(); Integer type = project.getType();
String strType = type == 1 ? "个人":"集体"; info.setProjectType(type == 1 ? "个人" : "集体");
info.setProjectType(strType);
return info; return info;
}) })
.collect(Collectors.toList()); .collect(Collectors.toList());