Merge remote-tracking branch 'origin/master_develop' into master_develop
This commit is contained in:
commit
9b5c24c49c
@ -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()) {
|
||||
|
||||
@ -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")
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -607,13 +607,23 @@ const handleViewWork = (record: ContestWork) => {
|
||||
}
|
||||
|
||||
// 单个分配评委
|
||||
const handleAssignJudge = (record: ContestWork) => {
|
||||
const handleAssignJudge = async (record: ContestWork) => {
|
||||
currentAssignWork.value = record
|
||||
isBatchAssign.value = false
|
||||
selectedJudgeKeys.value = []
|
||||
selectedJudgeRows.value = []
|
||||
assignModalVisible.value = true
|
||||
fetchJudgeList()
|
||||
await fetchJudgeList()
|
||||
|
||||
// 回显已分配的评委
|
||||
if (record.assignments && record.assignments.length > 0) {
|
||||
const assignedJudgeUserIds = record.assignments.map((a) => a.judgeId)
|
||||
const matchedJudges = judgeList.value.filter((judge) =>
|
||||
assignedJudgeUserIds.includes(judge.judgeId)
|
||||
)
|
||||
selectedJudgeKeys.value = matchedJudges.map((j) => j.id)
|
||||
selectedJudgeRows.value = matchedJudges
|
||||
}
|
||||
}
|
||||
|
||||
// 批量分配评委
|
||||
|
||||
Loading…
Reference in New Issue
Block a user