feat: 评委替换接口与作品评分列表按分配返回(含未评分行与 canReplaceJudge)
Made-with: Cursor
This commit is contained in:
parent
4d0b13524c
commit
4ba2af18f6
@ -20,7 +20,7 @@
|
||||
| 评审状态筛选无效 | 第一层评审状态下拉选了不生效(前端计算但未传后端) |
|
||||
| 缺少全局统计 | 没有全平台评审总进度概览 |
|
||||
| 无跨活动维度 | 不能跨活动查看所有作品的评审状态 |
|
||||
| TODO 未实现 | 未提交作品列表、评委替换 API 均为空实现 |
|
||||
| ~~TODO~~ 部分已补 | 未提交作品列表仍为 TODO;**评委替换**已由 `POST /api/contests/reviews/replace-judge` 实现(分配 ID + 新评委用户 ID,未评分前可换) |
|
||||
| 样式不一致 | 主色 `#1890ff` |
|
||||
|
||||
---
|
||||
@ -133,10 +133,11 @@
|
||||
|
||||
## 4. 后端改动
|
||||
|
||||
无新增接口。复用已有能力:
|
||||
- 统计:复用 `GET /api/contests/works/stats`(已有 submitted/reviewing/reviewed)
|
||||
- 列表:复用 `GET /api/contests/works`(已返回 reviewedCount/totalJudgesCount/averageScore/assignments)
|
||||
- 评分详情:复用 `GET /api/contests/reviews/works/:workId/scores`(已有)
|
||||
- **评委替换**:`POST /api/contests/reviews/replace-judge`(权限 `review:assign`),请求体 `{ "assignmentId": long, "newJudgeId": long }`;该分配下若已有有效评分则不允许替换。
|
||||
- 其余复用已有能力:
|
||||
- 统计:复用 `GET /api/contests/works/stats`(已有 submitted/reviewing/reviewed)
|
||||
- 列表:复用 `GET /api/contests/works`(已返回 reviewedCount/totalJudgesCount/averageScore/assignments)
|
||||
- 评分详情:复用 `GET /api/contests/reviews/work/{workId}/scores`(已有)
|
||||
|
||||
### 4.1 评审进度前端过滤
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ import com.lesingle.modules.biz.review.dto.AssignWorkDto;
|
||||
import com.lesingle.modules.biz.review.dto.BatchAssignDto;
|
||||
import com.lesingle.modules.biz.review.dto.CreateScoreDto;
|
||||
import com.lesingle.modules.biz.review.dto.MarkContestWorkViolationDto;
|
||||
import com.lesingle.modules.biz.review.dto.ReplaceJudgeDto;
|
||||
import com.lesingle.modules.biz.review.service.IContestReviewService;
|
||||
import com.lesingle.security.annotation.RequirePermission;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@ -36,6 +37,15 @@ public class ContestReviewController {
|
||||
return Result.success(contestReviewService.assignWork(contestId, dto.getWorkId(), dto.getJudgeIds(), creatorId));
|
||||
}
|
||||
|
||||
@PostMapping("/replace-judge")
|
||||
@RequirePermission("review:assign")
|
||||
@Operation(summary = "替换评委", description = "将某条作品-评委分配改为另一名评委;该分配下若已有有效评分则不允许替换")
|
||||
public Result<Map<String, Object>> replaceJudge(@Valid @RequestBody ReplaceJudgeDto dto) {
|
||||
Long operatorId = SecurityUtil.getCurrentUserId();
|
||||
return Result.success(contestReviewService.replaceJudge(
|
||||
dto.getAssignmentId(), dto.getNewJudgeId(), operatorId));
|
||||
}
|
||||
|
||||
@PostMapping("/batch-assign")
|
||||
@RequirePermission("review:assign")
|
||||
@Operation(summary = "批量分配作品给评委")
|
||||
@ -129,7 +139,7 @@ public class ContestReviewController {
|
||||
|
||||
@GetMapping("/work/{workId}/scores")
|
||||
@RequirePermission("review:read")
|
||||
@Operation(summary = "查询作品评分记录")
|
||||
@Operation(summary = "查询作品评委与评分", description = "按作品评委分配逐行返回;未评分行仍可替换评委(canReplaceJudge=true);已评分为 false")
|
||||
public Result<List<Map<String, Object>>> getWorkScores(@PathVariable Long workId) {
|
||||
return Result.success(contestReviewService.getWorkScores(workId));
|
||||
}
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
package com.lesingle.modules.biz.review.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Schema(description = "替换作品评委分配(仅未提交评分时可替换)")
|
||||
public class ReplaceJudgeDto {
|
||||
|
||||
@NotNull(message = "分配记录ID不能为空")
|
||||
@Schema(description = "作品评委分配表主键 t_biz_contest_work_judge_assignment.id")
|
||||
private Long assignmentId;
|
||||
|
||||
@NotNull(message = "新评委用户ID不能为空")
|
||||
@Schema(description = "新评委用户ID(须已加入本活动评委)")
|
||||
private Long newJudgeId;
|
||||
}
|
||||
@ -36,4 +36,9 @@ public interface IContestReviewService {
|
||||
Map<String, Object> calculateFinalScore(Long workId);
|
||||
|
||||
Map<String, Object> getJudgeContestDetail(Long judgeId, Long contestId);
|
||||
|
||||
/**
|
||||
* 将某条作品评委分配替换为另一名评委(该分配下尚无有效评分记录时才允许)。
|
||||
*/
|
||||
Map<String, Object> replaceJudge(Long assignmentId, Long newJudgeId, Long operatorId);
|
||||
}
|
||||
|
||||
@ -23,7 +23,9 @@ import com.lesingle.modules.biz.review.mapper.ContestReviewRuleMapper;
|
||||
import com.lesingle.modules.biz.review.mapper.ContestWorkJudgeAssignmentMapper;
|
||||
import com.lesingle.modules.biz.review.mapper.ContestWorkScoreMapper;
|
||||
import com.lesingle.modules.biz.review.service.IContestReviewService;
|
||||
import com.lesingle.modules.sys.entity.SysTenant;
|
||||
import com.lesingle.modules.sys.entity.SysUser;
|
||||
import com.lesingle.modules.sys.mapper.SysTenantMapper;
|
||||
import com.lesingle.modules.sys.mapper.SysUserMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -34,7 +36,18 @@ import org.springframework.util.StringUtils;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@ -50,6 +63,7 @@ public class ContestReviewServiceImpl implements IContestReviewService {
|
||||
private final ContestRegistrationMapper registrationMapper;
|
||||
private final ContestReviewRuleMapper reviewRuleMapper;
|
||||
private final SysUserMapper sysUserMapper;
|
||||
private final SysTenantMapper sysTenantMapper;
|
||||
|
||||
/**
|
||||
* 仅允许将「已在本活动评委表 t_biz_contest_judge 中显式配置」的评委新分配到作品。
|
||||
@ -692,27 +706,179 @@ public class ContestReviewServiceImpl implements IContestReviewService {
|
||||
|
||||
@Override
|
||||
public List<Map<String, Object>> getWorkScores(Long workId) {
|
||||
log.info("查询作品评分列表,作品ID:{}", workId);
|
||||
log.info("查询作品评分列表(按评委分配),作品ID:{}", workId);
|
||||
|
||||
BizContestWork work = workMapper.selectById(workId);
|
||||
if (work == null) {
|
||||
throw BusinessException.of(ErrorCode.NOT_FOUND, "作品不存在");
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<BizContestWorkJudgeAssignment> aw = new LambdaQueryWrapper<>();
|
||||
aw.eq(BizContestWorkJudgeAssignment::getWorkId, workId);
|
||||
aw.orderByAsc(BizContestWorkJudgeAssignment::getId);
|
||||
List<BizContestWorkJudgeAssignment> assignments = assignmentMapper.selectList(aw);
|
||||
|
||||
if (assignments.isEmpty()) {
|
||||
return listWorkScoresFallbackByScoresOnly(workId);
|
||||
}
|
||||
|
||||
Set<Long> judgeIds = assignments.stream()
|
||||
.map(BizContestWorkJudgeAssignment::getJudgeId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
Map<Long, SysUser> judgeUserById = loadUsersByIds(judgeIds);
|
||||
Map<Long, String> tenantNameById = loadTenantNames(judgeUserById.values());
|
||||
|
||||
List<Map<String, Object>> rows = new ArrayList<>();
|
||||
for (BizContestWorkJudgeAssignment a : assignments) {
|
||||
Long assignmentId = a.getId();
|
||||
Long judgeId = a.getJudgeId();
|
||||
|
||||
BizContestWorkScore s = findValidScoreForAssignment(workId, assignmentId, judgeId);
|
||||
|
||||
boolean scored = s != null;
|
||||
boolean canReplaceJudge = !scored;
|
||||
|
||||
SysUser judgeUser = judgeId != null ? judgeUserById.get(judgeId) : null;
|
||||
String judgeName = scored && StringUtils.hasText(s.getJudgeName())
|
||||
? s.getJudgeName()
|
||||
: null;
|
||||
if (!StringUtils.hasText(judgeName) && judgeUser != null) {
|
||||
judgeName = StringUtils.hasText(judgeUser.getNickname())
|
||||
? judgeUser.getNickname()
|
||||
: judgeUser.getUsername();
|
||||
}
|
||||
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("assignmentId", assignmentId);
|
||||
map.put("judgeId", judgeId);
|
||||
map.put("judgeName", judgeName);
|
||||
map.put("canReplaceJudge", canReplaceJudge);
|
||||
map.put("scored", scored);
|
||||
|
||||
if (judgeUser != null) {
|
||||
map.put("judge", buildJudgeDetailMap(judgeUser, tenantNameById));
|
||||
}
|
||||
|
||||
if (s != null) {
|
||||
map.put("id", s.getId());
|
||||
map.put("scoreId", s.getId());
|
||||
map.put("tenantId", s.getTenantId());
|
||||
map.put("contestId", s.getContestId());
|
||||
map.put("workId", s.getWorkId());
|
||||
map.put("dimensionScores", s.getDimensionScores());
|
||||
map.put("totalScore", s.getTotalScore());
|
||||
map.put("comments", s.getComments());
|
||||
map.put("scoreTime", s.getScoreTime());
|
||||
} else {
|
||||
map.put("id", assignmentId);
|
||||
map.put("scoreId", null);
|
||||
map.put("tenantId", judgeUser != null ? judgeUser.getTenantId() : null);
|
||||
map.put("contestId", work.getContestId());
|
||||
map.put("workId", workId);
|
||||
map.put("dimensionScores", null);
|
||||
map.put("totalScore", null);
|
||||
map.put("comments", null);
|
||||
map.put("scoreTime", null);
|
||||
}
|
||||
rows.add(map);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
private Map<Long, SysUser> loadUsersByIds(Set<Long> judgeIds) {
|
||||
Map<Long, SysUser> judgeUserById = new HashMap<>();
|
||||
if (judgeIds == null || judgeIds.isEmpty()) {
|
||||
return judgeUserById;
|
||||
}
|
||||
for (SysUser u : sysUserMapper.selectBatchIds(judgeIds)) {
|
||||
if (u != null && u.getId() != null) {
|
||||
judgeUserById.put(u.getId(), u);
|
||||
}
|
||||
}
|
||||
return judgeUserById;
|
||||
}
|
||||
|
||||
private Map<Long, String> loadTenantNames(Collection<SysUser> users) {
|
||||
Set<Long> tenantIds = users.stream()
|
||||
.map(SysUser::getTenantId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
Map<Long, String> tenantNameById = new HashMap<>();
|
||||
for (Long tid : tenantIds) {
|
||||
SysTenant t = sysTenantMapper.selectById(tid);
|
||||
if (t != null && StringUtils.hasText(t.getName())) {
|
||||
tenantNameById.put(tid, t.getName());
|
||||
}
|
||||
}
|
||||
return tenantNameById;
|
||||
}
|
||||
|
||||
private Map<String, Object> buildJudgeDetailMap(SysUser judgeUser, Map<Long, String> tenantNameById) {
|
||||
Map<String, Object> judge = new LinkedHashMap<>();
|
||||
judge.put("id", judgeUser.getId());
|
||||
judge.put("username", judgeUser.getUsername());
|
||||
judge.put("nickname", judgeUser.getNickname());
|
||||
judge.put("phone", judgeUser.getPhone());
|
||||
if (judgeUser.getTenantId() != null) {
|
||||
String tn = tenantNameById.get(judgeUser.getTenantId());
|
||||
if (StringUtils.hasText(tn)) {
|
||||
Map<String, Object> tenant = new LinkedHashMap<>();
|
||||
tenant.put("name", tn);
|
||||
judge.put("tenant", tenant);
|
||||
}
|
||||
}
|
||||
return judge;
|
||||
}
|
||||
|
||||
/**
|
||||
* 优先按分配 ID 关联评分;若无则按作品+评委兜底(历史数据 assignment_id 为空)。
|
||||
*/
|
||||
private BizContestWorkScore findValidScoreForAssignment(Long workId, Long assignmentId, Long judgeId) {
|
||||
LambdaQueryWrapper<BizContestWorkScore> sw = new LambdaQueryWrapper<>();
|
||||
sw.eq(BizContestWorkScore::getAssignmentId, assignmentId);
|
||||
sw.eq(BizContestWorkScore::getValidState, 1);
|
||||
List<BizContestWorkScore> byAssign = scoreMapper.selectList(sw);
|
||||
if (!byAssign.isEmpty()) {
|
||||
return pickLatestScore(byAssign);
|
||||
}
|
||||
if (judgeId == null) {
|
||||
return null;
|
||||
}
|
||||
LambdaQueryWrapper<BizContestWorkScore> legacy = new LambdaQueryWrapper<>();
|
||||
legacy.eq(BizContestWorkScore::getWorkId, workId);
|
||||
legacy.eq(BizContestWorkScore::getJudgeId, judgeId);
|
||||
legacy.eq(BizContestWorkScore::getValidState, 1);
|
||||
legacy.and(w -> w.isNull(BizContestWorkScore::getAssignmentId)
|
||||
.or()
|
||||
.eq(BizContestWorkScore::getAssignmentId, assignmentId));
|
||||
List<BizContestWorkScore> list = scoreMapper.selectList(legacy);
|
||||
return list.isEmpty() ? null : pickLatestScore(list);
|
||||
}
|
||||
|
||||
private static BizContestWorkScore pickLatestScore(List<BizContestWorkScore> list) {
|
||||
return list.stream()
|
||||
.max(Comparator.comparing(BizContestWorkScore::getScoreTime, Comparator.nullsLast(LocalDateTime::compareTo))
|
||||
.thenComparing(BizContestWorkScore::getId, Comparator.nullsLast(Long::compareTo)))
|
||||
.orElse(list.get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* 无分配记录时仍返回历史评分行(无 assignment 则不可替换评委)。
|
||||
*/
|
||||
private List<Map<String, Object>> listWorkScoresFallbackByScoresOnly(Long workId) {
|
||||
LambdaQueryWrapper<BizContestWorkScore> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(BizContestWorkScore::getWorkId, workId);
|
||||
wrapper.eq(BizContestWorkScore::getValidState, 1);
|
||||
wrapper.orderByAsc(BizContestWorkScore::getScoreTime);
|
||||
|
||||
List<BizContestWorkScore> scores = scoreMapper.selectList(wrapper);
|
||||
|
||||
Set<Long> judgeIds = scores.stream()
|
||||
.map(BizContestWorkScore::getJudgeId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
Map<Long, SysUser> judgeUserById = new HashMap<>();
|
||||
if (!judgeIds.isEmpty()) {
|
||||
for (SysUser u : sysUserMapper.selectBatchIds(judgeIds)) {
|
||||
if (u != null && u.getId() != null) {
|
||||
judgeUserById.put(u.getId(), u);
|
||||
}
|
||||
}
|
||||
}
|
||||
Map<Long, SysUser> judgeUserById = loadUsersByIds(judgeIds);
|
||||
Map<Long, String> tenantNameById = loadTenantNames(judgeUserById.values());
|
||||
|
||||
return scores.stream().map(s -> {
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
@ -720,6 +886,8 @@ public class ContestReviewServiceImpl implements IContestReviewService {
|
||||
map.put("scoreId", s.getId());
|
||||
map.put("assignmentId", s.getAssignmentId());
|
||||
map.put("judgeId", s.getJudgeId());
|
||||
map.put("canReplaceJudge", false);
|
||||
map.put("scored", true);
|
||||
SysUser judgeUser = s.getJudgeId() != null ? judgeUserById.get(s.getJudgeId()) : null;
|
||||
String judgeName = s.getJudgeName();
|
||||
if (!StringUtils.hasText(judgeName) && judgeUser != null) {
|
||||
@ -729,12 +897,11 @@ public class ContestReviewServiceImpl implements IContestReviewService {
|
||||
}
|
||||
map.put("judgeName", judgeName);
|
||||
if (judgeUser != null) {
|
||||
Map<String, Object> judge = new LinkedHashMap<>();
|
||||
judge.put("id", judgeUser.getId());
|
||||
judge.put("username", judgeUser.getUsername());
|
||||
judge.put("nickname", judgeUser.getNickname());
|
||||
map.put("judge", judge);
|
||||
map.put("judge", buildJudgeDetailMap(judgeUser, tenantNameById));
|
||||
}
|
||||
map.put("tenantId", s.getTenantId());
|
||||
map.put("contestId", s.getContestId());
|
||||
map.put("workId", s.getWorkId());
|
||||
map.put("dimensionScores", s.getDimensionScores());
|
||||
map.put("totalScore", s.getTotalScore());
|
||||
map.put("comments", s.getComments());
|
||||
@ -900,4 +1067,59 @@ public class ContestReviewServiceImpl implements IContestReviewService {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ====== 替换评委 ======
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Map<String, Object> replaceJudge(Long assignmentId, Long newJudgeId, Long operatorId) {
|
||||
log.info("替换评委分配,assignmentId:{},newJudgeId:{}", assignmentId, newJudgeId);
|
||||
|
||||
BizContestWorkJudgeAssignment assignment = assignmentMapper.selectById(assignmentId);
|
||||
if (assignment == null) {
|
||||
throw BusinessException.of(ErrorCode.NOT_FOUND, "分配记录不存在");
|
||||
}
|
||||
Long contestId = assignment.getContestId();
|
||||
Long workId = assignment.getWorkId();
|
||||
Long oldJudgeId = assignment.getJudgeId();
|
||||
|
||||
if (newJudgeId != null && newJudgeId.equals(oldJudgeId)) {
|
||||
Map<String, Object> noop = new LinkedHashMap<>();
|
||||
noop.put("assignmentId", assignmentId);
|
||||
noop.put("changed", false);
|
||||
return noop;
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<BizContestWorkScore> scoreWrapper = new LambdaQueryWrapper<>();
|
||||
scoreWrapper.eq(BizContestWorkScore::getAssignmentId, assignmentId);
|
||||
scoreWrapper.eq(BizContestWorkScore::getValidState, 1);
|
||||
if (scoreMapper.selectCount(scoreWrapper) > 0) {
|
||||
throw BusinessException.of(ErrorCode.BAD_REQUEST, "该评委已提交评分,无法替换");
|
||||
}
|
||||
|
||||
assertJudgeAssignedToContest(contestId, newJudgeId);
|
||||
|
||||
LambdaQueryWrapper<BizContestWorkJudgeAssignment> dupWrapper = new LambdaQueryWrapper<>();
|
||||
dupWrapper.eq(BizContestWorkJudgeAssignment::getContestId, contestId);
|
||||
dupWrapper.eq(BizContestWorkJudgeAssignment::getWorkId, workId);
|
||||
dupWrapper.eq(BizContestWorkJudgeAssignment::getJudgeId, newJudgeId);
|
||||
dupWrapper.ne(BizContestWorkJudgeAssignment::getId, assignmentId);
|
||||
if (assignmentMapper.selectCount(dupWrapper) > 0) {
|
||||
throw BusinessException.of(ErrorCode.BAD_REQUEST, "该评委已负责本作品,无需重复分配");
|
||||
}
|
||||
|
||||
assignment.setJudgeId(newJudgeId);
|
||||
assignment.setModifier(operatorId != null ? operatorId.intValue() : null);
|
||||
assignment.setModifyTime(LocalDateTime.now());
|
||||
assignmentMapper.updateById(assignment);
|
||||
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
result.put("assignmentId", assignmentId);
|
||||
result.put("workId", workId);
|
||||
result.put("contestId", contestId);
|
||||
result.put("oldJudgeId", oldJudgeId);
|
||||
result.put("newJudgeId", newJudgeId);
|
||||
result.put("changed", true);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -504,17 +504,18 @@ export interface ContestWorkJudgeAssignment {
|
||||
export interface ContestWorkScore {
|
||||
/** 与 id 同源,评分列表扁平接口常用 scoreId */
|
||||
scoreId?: number;
|
||||
/** 有评分记录时为评分表 id;仅有分配未评分时与 assignmentId 相同 */
|
||||
id: number;
|
||||
tenantId: number;
|
||||
tenantId?: number;
|
||||
contestId: number;
|
||||
workId: number;
|
||||
assignmentId: number;
|
||||
assignmentId?: number;
|
||||
judgeId: number;
|
||||
judgeName: string;
|
||||
dimensionScores: any;
|
||||
totalScore: number;
|
||||
totalScore: number | null;
|
||||
comments?: string;
|
||||
scoreTime: string;
|
||||
scoreTime: string | null;
|
||||
creator?: number;
|
||||
modifier?: number;
|
||||
createTime?: string;
|
||||
@ -525,7 +526,12 @@ export interface ContestWorkScore {
|
||||
id: number;
|
||||
username: string;
|
||||
nickname: string;
|
||||
phone?: string;
|
||||
tenant?: { name?: string };
|
||||
};
|
||||
/** 后端按分配返回:未提交有效评分前为 true,已评分则为 false(仅可读的评审详情可隐藏「替换评委」) */
|
||||
canReplaceJudge?: boolean;
|
||||
scored?: boolean;
|
||||
}
|
||||
|
||||
export interface AssignWorkForm {
|
||||
|
||||
@ -96,7 +96,7 @@
|
||||
<!-- 评审详情抽屉 -->
|
||||
<a-drawer v-model:open="scoreDrawerVisible" title="评审详情" placement="right" width="700">
|
||||
<a-table :columns="scoreColumns" :data-source="scoreList" :loading="scoreLoading" :pagination="false"
|
||||
row-key="scoreId" size="small">
|
||||
:row-key="(r: any) => (r.assignmentId != null ? r.assignmentId : r.scoreId ?? r.id)" size="small">
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'judgeName'">
|
||||
{{
|
||||
@ -122,9 +122,15 @@
|
||||
{{ formatDate(record.scoreTime) }}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'action'">
|
||||
<a-button type="link" size="small" @click="handleReplaceJudge(record)">
|
||||
<a-button
|
||||
v-if="record.canReplaceJudge === true"
|
||||
type="link"
|
||||
size="small"
|
||||
@click="handleReplaceJudge(record)"
|
||||
>
|
||||
替换评委
|
||||
</a-button>
|
||||
<span v-else class="text-gray">—</span>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user