fix:分配评委时应该查询租户下的+平台的评委

This commit is contained in:
zhonghua 2026-04-07 19:16:13 +08:00
parent 1d43501983
commit 7a039e8403
5 changed files with 150 additions and 22 deletions

View File

@ -173,8 +173,37 @@ public class JudgesManagementServiceImpl implements IJudgesManagementService {
Long currentTenantId = SecurityUtil.getCurrentTenantId();
Long judgeTenantId = getJudgeTenantId();
// 查询当前租户和平台评委租户的 judge 角色 ID
Set<Long> judgeRoleIds = new HashSet<>();
for (Long tid : List.of(currentTenantId, judgeTenantId)) {
if (tid == null) continue;
LambdaQueryWrapper<SysRole> roleWrapper = new LambdaQueryWrapper<>();
roleWrapper.eq(SysRole::getCode, "judge");
roleWrapper.eq(SysRole::getTenantId, tid);
SysRole role = sysRoleMapper.selectOne(roleWrapper);
if (role != null) {
judgeRoleIds.add(role.getId());
}
}
// 查询拥有 judge 角色的用户 ID
Set<Long> judgeUserIds = new HashSet<>();
if (!judgeRoleIds.isEmpty()) {
LambdaQueryWrapper<SysUserRole> urWrapper = new LambdaQueryWrapper<>();
urWrapper.in(SysUserRole::getRoleId, judgeRoleIds);
List<SysUserRole> userRoles = sysUserRoleMapper.selectList(urWrapper);
for (SysUserRole ur : userRoles) {
judgeUserIds.add(ur.getUserId());
}
}
if (judgeUserIds.isEmpty()) {
return new PageResult<>(Collections.emptyList(), 0L, page, pageSize);
}
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
// 查询当前租户评委 + 平台评委
// 只查询拥有 judge 角色且属于当前租户或平台评委租户的用户
wrapper.in(SysUser::getId, judgeUserIds);
wrapper.in(SysUser::getTenantId, List.of(currentTenantId, judgeTenantId));
if (keyword != null && !keyword.isBlank()) {

View File

@ -3,6 +3,7 @@ package com.competition.modules.biz.review.controller;
import com.competition.common.result.Result;
import com.competition.common.util.SecurityUtil;
import com.competition.modules.biz.review.dto.CreatePresetCommentDto;
import com.competition.modules.biz.review.dto.SyncPresetCommentsDto;
import com.competition.modules.biz.review.entity.BizPresetComment;
import com.competition.modules.biz.review.service.IPresetCommentService;
import io.swagger.v3.oas.annotations.Operation;
@ -65,11 +66,10 @@ public class PresetCommentController {
return Result.success();
}
@SuppressWarnings("unchecked")
@PostMapping("/batch-delete")
@Operation(summary = "批量删除预设评语")
public Result<Void> batchDelete(@RequestBody Map<String, Object> body) {
List<Long> ids = (List<Long>) body.get("ids");
public Result<Void> batchDelete(@RequestBody Map<String, List<Long>> body) {
List<Long> ids = body.get("ids");
Long judgeId = SecurityUtil.getCurrentUserId();
presetCommentService.batchDelete(ids, judgeId);
return Result.success();
@ -77,12 +77,9 @@ public class PresetCommentController {
@PostMapping("/sync")
@Operation(summary = "同步评语到其他赛事")
public Result<Map<String, Object>> syncComments(@RequestBody Map<String, Object> body) {
Long sourceContestId = Long.valueOf(body.get("sourceContestId").toString());
@SuppressWarnings("unchecked")
List<Long> targetContestIds = (List<Long>) body.get("targetContestIds");
public Result<Map<String, Object>> syncComments(@Valid @RequestBody SyncPresetCommentsDto dto) {
Long judgeId = SecurityUtil.getCurrentUserId();
return Result.success(presetCommentService.syncComments(sourceContestId, targetContestIds, judgeId));
return Result.success(presetCommentService.syncComments(dto.getSourceContestId(), dto.getTargetContestIds(), judgeId));
}
@PostMapping("/{id}/use")

View File

@ -0,0 +1,21 @@
package com.competition.modules.biz.review.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.List;
@Data
@Schema(description = "同步预设评语DTO")
public class SyncPresetCommentsDto {
@NotNull(message = "源赛事ID不能为空")
@Schema(description = "源赛事ID")
private Long sourceContestId;
@NotEmpty(message = "目标赛事列表不能为空")
@Schema(description = "目标赛事ID列表")
private List<Long> targetContestIds;
}

View File

@ -9,7 +9,9 @@ import com.competition.modules.biz.review.entity.BizContestWorkJudgeAssignment;
import com.competition.modules.biz.review.mapper.ContestJudgeMapper;
import com.competition.modules.biz.review.mapper.ContestWorkJudgeAssignmentMapper;
import com.competition.modules.biz.review.service.IContestJudgeService;
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;
@ -27,6 +29,7 @@ public class ContestJudgeServiceImpl extends ServiceImpl<ContestJudgeMapper, Biz
private final ContestJudgeMapper contestJudgeMapper;
private final ContestWorkJudgeAssignmentMapper assignmentMapper;
private final SysUserMapper sysUserMapper;
private final SysTenantMapper sysTenantMapper;
@Override
public BizContestJudge createJudge(Long contestId, Long judgeId, String specialty, BigDecimal weight, String description) {
@ -57,6 +60,10 @@ public class ContestJudgeServiceImpl extends ServiceImpl<ContestJudgeMapper, Biz
public List<Map<String, Object>> findByContest(Long contestId) {
log.info("查询赛事评委列表赛事ID{}", contestId);
// 获取平台评委租户 ID
Long judgeTenantId = getJudgeTenantId();
// 1. 查询已显式分配的评委
LambdaQueryWrapper<BizContestJudge> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(BizContestJudge::getContestId, contestId);
wrapper.eq(BizContestJudge::getValidState, 1);
@ -64,11 +71,32 @@ public class ContestJudgeServiceImpl extends ServiceImpl<ContestJudgeMapper, Biz
List<BizContestJudge> judges = contestJudgeMapper.selectList(wrapper);
// 收集所有需要查询的用户 ID已分配评委
Set<Long> assignedJudgeIds = judges.stream().map(BizContestJudge::getJudgeId).collect(Collectors.toSet());
// 2. 查询平台评委自动对所有赛事可用
List<SysUser> platformJudges = new ArrayList<>();
if (judgeTenantId != null) {
LambdaQueryWrapper<SysUser> platformWrapper = new LambdaQueryWrapper<>();
platformWrapper.eq(SysUser::getTenantId, judgeTenantId);
platformWrapper.eq(SysUser::getStatus, "enabled");
platformJudges = sysUserMapper.selectList(platformWrapper);
}
// 平台评委中去掉已显式分配的避免重复
Set<Long> platformOnlyIds = platformJudges.stream()
.map(SysUser::getId)
.filter(id -> !assignedJudgeIds.contains(id))
.collect(Collectors.toSet());
// 合并所有需要查询的用户 ID
Set<Long> allUserIds = new HashSet<>(assignedJudgeIds);
allUserIds.addAll(platformOnlyIds);
// 批量查询用户信息
Set<Long> userIds = judges.stream().map(BizContestJudge::getJudgeId).collect(Collectors.toSet());
Map<Long, SysUser> userMap = new HashMap<>();
if (!userIds.isEmpty()) {
List<SysUser> users = sysUserMapper.selectBatchIds(userIds);
if (!allUserIds.isEmpty()) {
List<SysUser> users = sysUserMapper.selectBatchIds(allUserIds);
for (SysUser user : users) {
userMap.put(user.getId(), user);
}
@ -76,14 +104,17 @@ public class ContestJudgeServiceImpl extends ServiceImpl<ContestJudgeMapper, Biz
// 批量查询每个评委在该赛事下的已分配作品数
Map<Long, Long> assignedCountMap = new HashMap<>();
for (BizContestJudge j : judges) {
for (Long judgeId : allUserIds) {
LambdaQueryWrapper<BizContestWorkJudgeAssignment> assignWrapper = new LambdaQueryWrapper<>();
assignWrapper.eq(BizContestWorkJudgeAssignment::getContestId, contestId);
assignWrapper.eq(BizContestWorkJudgeAssignment::getJudgeId, j.getJudgeId());
assignedCountMap.put(j.getJudgeId(), assignmentMapper.selectCount(assignWrapper));
assignWrapper.eq(BizContestWorkJudgeAssignment::getJudgeId, judgeId);
assignedCountMap.put(judgeId, assignmentMapper.selectCount(assignWrapper));
}
return judges.stream().map(j -> {
List<Map<String, Object>> result = new ArrayList<>();
// 构建已显式分配的评委数据
for (BizContestJudge j : judges) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("id", j.getId());
map.put("contestId", j.getContestId());
@ -98,9 +129,50 @@ public class ContestJudgeServiceImpl extends ServiceImpl<ContestJudgeMapper, Biz
if (user != null) {
map.put("judgeName", user.getNickname());
map.put("judgeUsername", user.getUsername());
map.put("tenantId", user.getTenantId());
map.put("status", user.getStatus());
map.put("organization", user.getOrganization());
map.put("isPlatform", judgeTenantId != null && judgeTenantId.equals(user.getTenantId()));
} else {
map.put("isPlatform", false);
}
return map;
}).collect(Collectors.toList());
result.add(map);
}
// 追加未显式分配的平台评委
for (SysUser platformJudge : platformJudges) {
if (assignedJudgeIds.contains(platformJudge.getId())) {
continue; // 已在显式分配列表中跳过
}
Map<String, Object> map = new LinkedHashMap<>();
map.put("id", null);
map.put("contestId", contestId);
map.put("judgeId", platformJudge.getId());
map.put("specialty", null);
map.put("weight", null);
map.put("description", null);
map.put("createTime", null);
map.put("assignedCount", assignedCountMap.getOrDefault(platformJudge.getId(), 0L));
map.put("judgeName", platformJudge.getNickname());
map.put("judgeUsername", platformJudge.getUsername());
map.put("tenantId", platformJudge.getTenantId());
map.put("status", platformJudge.getStatus());
map.put("organization", platformJudge.getOrganization());
map.put("isPlatform", true);
result.add(map);
}
return result;
}
/**
* 获取平台评委租户 ID
*/
private Long getJudgeTenantId() {
LambdaQueryWrapper<SysTenant> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SysTenant::getCode, "judge");
SysTenant tenant = sysTenantMapper.selectOne(wrapper);
return tenant != null ? tenant.getId() : null;
}
@Override

View File

@ -6,6 +6,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.competition.common.enums.ErrorCode;
import com.competition.common.exception.BusinessException;
import com.competition.modules.biz.review.dto.CreatePresetCommentDto;
import com.competition.modules.biz.contest.entity.BizContest;
import com.competition.modules.biz.contest.mapper.ContestMapper;
import com.competition.modules.biz.review.entity.BizContestJudge;
import com.competition.modules.biz.review.entity.BizPresetComment;
import com.competition.modules.biz.review.mapper.ContestJudgeMapper;
@ -25,6 +27,7 @@ public class PresetCommentServiceImpl extends ServiceImpl<PresetCommentMapper, B
private final PresetCommentMapper presetCommentMapper;
private final ContestJudgeMapper contestJudgeMapper;
private final ContestMapper contestMapper;
@Override
public BizPresetComment createComment(CreatePresetCommentDto dto, Long judgeId) {
@ -162,7 +165,14 @@ public class PresetCommentServiceImpl extends ServiceImpl<PresetCommentMapper, B
return judgeRecords.stream().map(j -> {
Map<String, Object> map = new LinkedHashMap<>();
map.put("contestId", j.getContestId());
map.put("id", j.getContestId());
// 查询赛事详情获取名称和状态
BizContest contest = contestMapper.selectById(j.getContestId());
if (contest != null) {
map.put("contestName", contest.getContestName());
map.put("contestState", contest.getContestState());
map.put("status", contest.getStatus());
}
return map;
}).collect(Collectors.toList());
}
@ -201,9 +211,8 @@ public class PresetCommentServiceImpl extends ServiceImpl<PresetCommentMapper, B
log.info("预设评语同步完成,新建数量:{}", created);
Map<String, Object> result = new LinkedHashMap<>();
result.put("sourceCount", sourceComments.size());
result.put("targetContests", targetContestIds.size());
result.put("createdCount", created);
result.put("message", "同步成功");
result.put("count", created);
return result;
}