diff --git a/backend-java/src/main/java/com/competition/modules/biz/contest/dto/QueryContestDto.java b/backend-java/src/main/java/com/competition/modules/biz/contest/dto/QueryContestDto.java index 7ba9084..80e059a 100644 --- a/backend-java/src/main/java/com/competition/modules/biz/contest/dto/QueryContestDto.java +++ b/backend-java/src/main/java/com/competition/modules/biz/contest/dto/QueryContestDto.java @@ -13,6 +13,9 @@ public class QueryContestDto { @Schema(description = "每页条数", defaultValue = "10") private Long pageSize = 10L; + @Schema(description = "活动ID,精确筛选") + private Long id; + @Schema(description = "活动名称") private String contestName; @@ -31,6 +34,9 @@ public class QueryContestDto { @Schema(description = "活动阶段") private String stage; + @Schema(description = "成果发布状态筛选:published/unpublished") + private String resultState; + @Schema(description = "创建者租户ID") private Long creatorTenantId; diff --git a/backend-java/src/main/java/com/competition/modules/biz/contest/service/impl/ContestRegistrationServiceImpl.java b/backend-java/src/main/java/com/competition/modules/biz/contest/service/impl/ContestRegistrationServiceImpl.java index 4760bc5..3b5a855 100644 --- a/backend-java/src/main/java/com/competition/modules/biz/contest/service/impl/ContestRegistrationServiceImpl.java +++ b/backend-java/src/main/java/com/competition/modules/biz/contest/service/impl/ContestRegistrationServiceImpl.java @@ -18,7 +18,9 @@ import com.competition.modules.biz.contest.mapper.ContestMapper; import com.competition.modules.biz.contest.mapper.ContestRegistrationMapper; import com.competition.modules.biz.contest.mapper.ContestRegistrationTeacherMapper; import com.competition.modules.biz.contest.service.IContestRegistrationService; +import com.competition.modules.sys.entity.SysTenant; import com.competition.modules.sys.entity.SysUser; +import com.competition.modules.sys.mapper.SysTenantMapper; import com.competition.modules.sys.mapper.SysUserMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -39,6 +41,7 @@ public class ContestRegistrationServiceImpl extends ServiceImpl createRegistration(CreateRegistrationDto dto, Long tenantId, Long creatorId) { @@ -119,9 +122,66 @@ public class ContestRegistrationServiceImpl extends ServiceImpl page = new Page<>(dto.getPage(), dto.getPageSize()); Page result = contestRegistrationMapper.selectPage(page, wrapper); - List> voList = result.getRecords().stream() - .map(this::registrationToMap) - .collect(Collectors.toList()); + Set contestIds = result.getRecords().stream() + .map(BizContestRegistration::getContestId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + Map contestMap = new HashMap<>(); + if (!contestIds.isEmpty()) { + contestMap = contestMapper.selectBatchIds(contestIds).stream() + .collect(Collectors.toMap(BizContest::getId, c -> c)); + } + + Set organizerTenantIds = new HashSet<>(); + for (BizContest c : contestMap.values()) { + List ct = c.getContestTenants(); + if (ct != null && !ct.isEmpty()) { + organizerTenantIds.add(ct.get(0).longValue()); + } + } + Map organizerTenantMap = new HashMap<>(); + if (!organizerTenantIds.isEmpty()) { + for (SysTenant t : sysTenantMapper.selectBatchIds(organizerTenantIds)) { + if (t != null && t.getId() != null) { + organizerTenantMap.put(t.getId(), t); + } + } + } + + List> voList = new ArrayList<>(); + for (BizContestRegistration reg : result.getRecords()) { + Map map = registrationToMap(reg); + BizContest contest = contestMap.get(reg.getContestId()); + if (contest != null) { + Map contestVo = new LinkedHashMap<>(); + contestVo.put("id", contest.getId()); + contestVo.put("contestName", contest.getContestName()); + map.put("contest", contestVo); + List ct = contest.getContestTenants(); + if (ct != null && !ct.isEmpty()) { + SysTenant org = organizerTenantMap.get(ct.get(0).longValue()); + if (org != null) { + Map tenantVo = new LinkedHashMap<>(); + tenantVo.put("id", org.getId()); + tenantVo.put("name", org.getName()); + tenantVo.put("code", org.getCode()); + map.put("creatorTenant", tenantVo); + } + } + } + if (reg.getUserId() != null) { + SysUser user = sysUserMapper.selectById(reg.getUserId()); + if (user != null) { + Map userVo = new LinkedHashMap<>(); + userVo.put("id", user.getId()); + userVo.put("username", user.getUsername()); + userVo.put("nickname", user.getNickname()); + userVo.put("phone", user.getPhone()); + map.put("user", userVo); + } + } + voList.add(map); + } return PageResult.from(result, voList); } @@ -191,6 +251,28 @@ public class ContestRegistrationServiceImpl extends ServiceImpl result = registrationToMap(registration); + // 活动与主办机构(前端列表/详情需要 contest、creatorTenant) + if (registration.getContestId() != null) { + BizContest contest = contestMapper.selectById(registration.getContestId()); + if (contest != null) { + Map contestVo = new LinkedHashMap<>(); + contestVo.put("id", contest.getId()); + contestVo.put("contestName", contest.getContestName()); + result.put("contest", contestVo); + List ct = contest.getContestTenants(); + if (ct != null && !ct.isEmpty()) { + SysTenant org = sysTenantMapper.selectById(ct.get(0).longValue()); + if (org != null) { + Map tenantVo = new LinkedHashMap<>(); + tenantVo.put("id", org.getId()); + tenantVo.put("name", org.getName()); + tenantVo.put("code", org.getCode()); + result.put("creatorTenant", tenantVo); + } + } + } + } + // 查询用户详情 if (registration.getUserId() != null) { SysUser user = sysUserMapper.selectById(registration.getUserId()); @@ -203,6 +285,12 @@ public class ContestRegistrationServiceImpl extends ServiceImpl userVo = new LinkedHashMap<>(); + userVo.put("id", user.getId()); + userVo.put("username", user.getUsername()); + userVo.put("nickname", user.getNickname()); + userVo.put("phone", user.getPhone()); + result.put("user", userVo); } } diff --git a/backend-java/src/main/java/com/competition/modules/biz/contest/service/impl/ContestServiceImpl.java b/backend-java/src/main/java/com/competition/modules/biz/contest/service/impl/ContestServiceImpl.java index f077b33..d6c4a92 100644 --- a/backend-java/src/main/java/com/competition/modules/biz/contest/service/impl/ContestServiceImpl.java +++ b/backend-java/src/main/java/com/competition/modules/biz/contest/service/impl/ContestServiceImpl.java @@ -114,6 +114,9 @@ public class ContestServiceImpl extends ServiceImpl i LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(BizContest::getValidState, 1); + if (dto.getId() != null) { + wrapper.eq(BizContest::getId, dto.getId()); + } if (StringUtils.hasText(dto.getContestName())) { wrapper.like(BizContest::getContestName, dto.getContestName()); } @@ -129,6 +132,12 @@ public class ContestServiceImpl extends ServiceImpl i if (StringUtils.hasText(dto.getContestType())) { wrapper.eq(BizContest::getContestType, dto.getContestType()); } + if (StringUtils.hasText(dto.getResultState())) { + wrapper.eq(BizContest::getResultState, dto.getResultState()); + } + if (dto.getCreatorTenantId() != null) { + wrapper.apply("JSON_CONTAINS(contest_tenants, CAST({0} AS JSON))", dto.getCreatorTenantId()); + } // 阶段筛选(与前端活动列表「活动阶段」一致:unpublished/finished/registering/submitting/reviewing) if (StringUtils.hasText(dto.getStage())) { diff --git a/backend-java/src/main/java/com/competition/modules/biz/contest/service/impl/ContestWorkServiceImpl.java b/backend-java/src/main/java/com/competition/modules/biz/contest/service/impl/ContestWorkServiceImpl.java index 438efe7..8bbd085 100644 --- a/backend-java/src/main/java/com/competition/modules/biz/contest/service/impl/ContestWorkServiceImpl.java +++ b/backend-java/src/main/java/com/competition/modules/biz/contest/service/impl/ContestWorkServiceImpl.java @@ -403,11 +403,14 @@ public class ContestWorkServiceImpl extends ServiceImpl ruleMap.put(r.getId(), r)); } - // 批量预加载所有相关活动的评委权重 - LambdaQueryWrapper allJudgesWrapper = new LambdaQueryWrapper<>(); - allJudgesWrapper.in(BizContestJudge::getContestId, contestIds); - allJudgesWrapper.eq(BizContestJudge::getValidState, 1); - List allJudges = contestJudgeMapper.selectList(allJudgesWrapper); + // 批量预加载所有相关活动的评委权重(contestIds 为空时不能拼 IN (),否则 SQL 报错 500) + List allJudges = Collections.emptyList(); + if (!contestIds.isEmpty()) { + LambdaQueryWrapper allJudgesWrapper = new LambdaQueryWrapper<>(); + allJudgesWrapper.in(BizContestJudge::getContestId, contestIds); + allJudgesWrapper.eq(BizContestJudge::getValidState, 1); + allJudges = contestJudgeMapper.selectList(allJudgesWrapper); + } Map> judgesByContestId = allJudges.stream() .collect(Collectors.groupingBy(BizContestJudge::getContestId)); diff --git a/frontend/src/api/contests.ts b/frontend/src/api/contests.ts index f76e51c..b42304e 100644 --- a/frontend/src/api/contests.ts +++ b/frontend/src/api/contests.ts @@ -118,6 +118,8 @@ export interface UpdateContestForm extends Partial { } export interface QueryContestParams extends PaginationParams { + /** 活动 ID,精确筛选(如成果发布「所属活动」) */ + id?: number; contestName?: string; contestState?: "unpublished" | "published"; status?: "ongoing" | "finished"; @@ -131,6 +133,8 @@ export interface QueryContestParams extends PaginationParams { | "finished"; creatorTenantId?: number; role?: "student" | "teacher" | "judge"; + /** 成果发布状态筛选 */ + resultState?: "published" | "unpublished"; } export interface ContestStats { @@ -224,6 +228,8 @@ export interface ContestRegistration { createTime?: string; modifyTime?: string; contest?: Contest; + /** 活动主办机构(与活动 contest_tenants 首个机构一致) */ + creatorTenant?: { id: number; name: string; code?: string }; user?: { id: number; username: string; diff --git a/frontend/src/types/auth.ts b/frontend/src/types/auth.ts index 5edebae..9197022 100644 --- a/frontend/src/types/auth.ts +++ b/frontend/src/types/auth.ts @@ -1,23 +1,23 @@ -export interface User { - id: number; - username: string; - nickname: string; - email: string; - avatar?: string; - tenantId?: number; - tenantCode?: string; - roles: string[]; - permissions: string[]; -} - -export interface LoginForm { - username: string; - password: string; - tenantCode?: string; - captcha?: string; -} - -export interface LoginResponse { - token: string; - user: User; -} +export interface User { + id: number; + username: string; + nickname: string; + email: string; + avatar?: string; + tenantId?: number; + tenantCode?: string; + roles: string[]; + permissions: string[]; +} + +export interface LoginForm { + username: string; + password: string; + tenantCode?: string; + captcha?: string; +} + +export interface LoginResponse { + token: string; + user: User; +} diff --git a/frontend/src/views/contests/registrations/Index.vue b/frontend/src/views/contests/registrations/Index.vue index 543985c..679fd70 100644 --- a/frontend/src/views/contests/registrations/Index.vue +++ b/frontend/src/views/contests/registrations/Index.vue @@ -26,7 +26,7 @@
- +