diff --git a/docs/design/judge-portal/review-tasks.md b/docs/design/judge-portal/review-tasks.md index 394b1fc..1c1356b 100644 --- a/docs/design/judge-portal/review-tasks.md +++ b/docs/design/judge-portal/review-tasks.md @@ -47,6 +47,31 @@ 避免「列表能进、详情 403」与隐式评委场景不一致。 +## 标记作品违规(活动参赛作品) + +**接口**:`POST /contests/reviews/work/{workId}/violation` + +**权限**:`review:score`(与提交评分一致) + +**请求体(JSON)**: + +| 字段 | 必填 | 说明 | +|------|------|------| +| `assignmentId` | 是 | 当前评委在该作品上的分配记录 ID(`t_biz_contest_work_judge_assignment.id`),与打分接口一致 | +| `reason` | 否 | 违规说明,写入 `t_biz_contest_work.violation_reason` | + +**行为**: + +- 将 `t_biz_contest_work.status` 置为 `violation`,并写入 `violation_mark_time`、`violation_judge_id`(及可选 `violation_reason`)。 +- 将该评委对应的分配记录 `status` 置为 `completed`,与「已处理该评审任务」一致,避免长期占用「待评审」。 +- 若作品已是 `violation`,幂等返回成功。 + +**列表字段**:`GET .../works` 响应中增加 `workStatus`(作品表 `status`),便于前端展示「违规」等状态;与分配维度上的 `status`(`assignment` 是否 completed)区分。 + +**说明**:此为**活动赛事投稿作品**(`t_biz_contest_work`)的违规标记,与 UGC 绘本广场超管审核(`/content-review/...`)不同。 + +**公众端**:`GET /public/activities/{id}/my-registration` 返回最新参赛作品 `latestWorkStatus`、`violationReason` 等;若最新作品为 `violation`,参赛者在活动提交期内可重新从作品库提交(`submitRule=once` 时亦允许覆盖违规版本)。 + --- ## 与租户端「评审进度」的口径对齐 diff --git a/lesingle-creation-backend/src/main/java/com/lesingle/common/enums/WorkStatus.java b/lesingle-creation-backend/src/main/java/com/lesingle/common/enums/WorkStatus.java index e9cc7f0..3999e45 100644 --- a/lesingle-creation-backend/src/main/java/com/lesingle/common/enums/WorkStatus.java +++ b/lesingle-creation-backend/src/main/java/com/lesingle/common/enums/WorkStatus.java @@ -16,7 +16,8 @@ public enum WorkStatus { REJECTED("rejected", "已拒绝"), ACCEPTED("accepted", "已采纳"), AWARDED("awarded", "已获奖"), - TAKEN_DOWN("taken_down", "已下架"); + TAKEN_DOWN("taken_down", "已下架"), + VIOLATION("violation", "违规"); private final String value; private final String description; diff --git a/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/contest/entity/BizContestWork.java b/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/contest/entity/BizContestWork.java index 3ff3ccf..7706a8c 100644 --- a/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/contest/entity/BizContestWork.java +++ b/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/contest/entity/BizContestWork.java @@ -51,9 +51,21 @@ public class BizContestWork extends BaseEntity { @TableField("is_latest") private Boolean isLatest; - @Schema(description = "作品状态", allowableValues = {"submitted", "locked", "reviewing", "rejected", "accepted", "awarded", "taken_down"}) + @Schema(description = "作品状态", allowableValues = {"submitted", "locked", "reviewing", "rejected", "accepted", "awarded", "taken_down", "violation"}) private String status; + @Schema(description = "评委标记违规原因") + @TableField("violation_reason") + private String violationReason; + + @Schema(description = "违规标记时间") + @TableField("violation_mark_time") + private LocalDateTime violationMarkTime; + + @Schema(description = "标记违规的评委用户ID") + @TableField("violation_judge_id") + private Long violationJudgeId; + @Schema(description = "提交时间") @TableField("submit_time") private LocalDateTime submitTime; diff --git a/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/contest/service/impl/ContestWorkServiceImpl.java b/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/contest/service/impl/ContestWorkServiceImpl.java index 95f35b8..eb55857 100644 --- a/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/contest/service/impl/ContestWorkServiceImpl.java +++ b/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/contest/service/impl/ContestWorkServiceImpl.java @@ -729,6 +729,9 @@ public class ContestWorkServiceImpl extends ServiceImpl> markViolation( + @PathVariable Long workId, + @Valid @RequestBody MarkContestWorkViolationDto dto) { + Long judgeId = SecurityUtil.getCurrentUserId(); + return Result.success(contestReviewService.markViolation(workId, dto, judgeId)); + } + @PatchMapping("/score/{id}") @RequirePermission("review:score") @Operation(summary = "修改评分") diff --git a/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/review/dto/MarkContestWorkViolationDto.java b/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/review/dto/MarkContestWorkViolationDto.java new file mode 100644 index 0000000..beb91f0 --- /dev/null +++ b/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/review/dto/MarkContestWorkViolationDto.java @@ -0,0 +1,17 @@ +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 MarkContestWorkViolationDto { + + @NotNull + @Schema(description = "评委分配记录 ID(与打分接口一致)") + private Long assignmentId; + + @Schema(description = "违规说明(可选)") + private String reason; +} diff --git a/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/review/service/IContestReviewService.java b/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/review/service/IContestReviewService.java index 41795c2..b01f843 100644 --- a/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/review/service/IContestReviewService.java +++ b/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/review/service/IContestReviewService.java @@ -2,6 +2,7 @@ package com.lesingle.modules.biz.review.service; import com.lesingle.common.result.PageResult; import com.lesingle.modules.biz.review.dto.CreateScoreDto; +import com.lesingle.modules.biz.review.dto.MarkContestWorkViolationDto; import java.util.List; import java.util.Map; @@ -16,6 +17,8 @@ public interface IContestReviewService { Map score(CreateScoreDto dto, Long judgeId, Long tenantId); + Map markViolation(Long workId, MarkContestWorkViolationDto dto, Long judgeId); + Map updateScore(Long scoreId, CreateScoreDto dto, Long judgeId); List> getAssignedWorks(Long judgeId, Long contestId); diff --git a/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/review/service/impl/ContestResultServiceImpl.java b/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/review/service/impl/ContestResultServiceImpl.java index da58646..de78f91 100644 --- a/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/review/service/impl/ContestResultServiceImpl.java +++ b/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/review/service/impl/ContestResultServiceImpl.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.lesingle.common.enums.ErrorCode; import com.lesingle.common.enums.PublishStatus; import com.lesingle.common.enums.Visibility; +import com.lesingle.common.enums.WorkStatus; import com.lesingle.common.exception.BusinessException; import com.lesingle.common.result.PageResult; import com.lesingle.modules.biz.contest.entity.BizContest; @@ -387,6 +388,9 @@ public class ContestResultServiceImpl implements IContestResultService { wrapper.eq(BizContestWork::getIsLatest, true); wrapper.eq(BizContestWork::getValidState, 1); wrapper.isNotNull(BizContestWork::getFinalScore); + // 评委标记违规或下架的作品不参与公示 + wrapper.notIn(BizContestWork::getStatus, + List.of(WorkStatus.VIOLATION.getValue(), WorkStatus.TAKEN_DOWN.getValue())); wrapper.orderByDesc(BizContestWork::getFinalScore); Page pageObj = new Page<>(page, pageSize); diff --git a/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/review/service/impl/ContestReviewServiceImpl.java b/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/review/service/impl/ContestReviewServiceImpl.java index 08e5ce5..6768aaf 100644 --- a/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/review/service/impl/ContestReviewServiceImpl.java +++ b/lesingle-creation-backend/src/main/java/com/lesingle/modules/biz/review/service/impl/ContestReviewServiceImpl.java @@ -13,6 +13,7 @@ import com.lesingle.modules.biz.contest.mapper.ContestMapper; import com.lesingle.modules.biz.contest.mapper.ContestRegistrationMapper; import com.lesingle.modules.biz.contest.mapper.ContestWorkMapper; import com.lesingle.modules.biz.review.dto.CreateScoreDto; +import com.lesingle.modules.biz.review.dto.MarkContestWorkViolationDto; import com.lesingle.modules.biz.review.entity.BizContestJudge; import com.lesingle.modules.biz.review.entity.BizContestReviewRule; import com.lesingle.modules.biz.review.entity.BizContestWorkJudgeAssignment; @@ -284,6 +285,60 @@ public class ContestReviewServiceImpl implements IContestReviewService { return result; } + @Override + @Transactional(rollbackFor = Exception.class) + public Map markViolation(Long workId, MarkContestWorkViolationDto dto, Long judgeId) { + log.info("评委标记违规,评委ID:{},作品ID:{},分配ID:{}", judgeId, workId, dto.getAssignmentId()); + + BizContestWorkJudgeAssignment assignment = assignmentMapper.selectById(dto.getAssignmentId()); + if (assignment == null) { + throw BusinessException.of(ErrorCode.NOT_FOUND, "分配记录不存在"); + } + if (!assignment.getJudgeId().equals(judgeId)) { + throw BusinessException.of(ErrorCode.FORBIDDEN, "无权标记该作品违规"); + } + if (!assignment.getWorkId().equals(workId)) { + throw BusinessException.of(ErrorCode.BAD_REQUEST, "作品ID与分配记录不匹配"); + } + + BizContestWork work = workMapper.selectById(workId); + if (work == null) { + throw BusinessException.of(ErrorCode.NOT_FOUND, "作品不存在"); + } + if (work.getValidState() != null && work.getValidState() != 1) { + throw BusinessException.of(ErrorCode.NOT_FOUND, "作品不存在"); + } + if (!work.getContestId().equals(assignment.getContestId())) { + throw BusinessException.of(ErrorCode.BAD_REQUEST, "活动与作品不匹配"); + } + + if (WorkStatus.VIOLATION.getValue().equals(work.getStatus())) { + Map done = new LinkedHashMap<>(); + done.put("workId", workId); + done.put("status", work.getStatus()); + return done; + } + + work.setStatus(WorkStatus.VIOLATION.getValue()); + if (StringUtils.hasText(dto.getReason())) { + work.setViolationReason(dto.getReason().trim()); + } + work.setViolationMarkTime(LocalDateTime.now()); + work.setViolationJudgeId(judgeId); + work.setModifyTime(LocalDateTime.now()); + workMapper.updateById(work); + + assignment.setStatus("completed"); + assignment.setModifyTime(LocalDateTime.now()); + assignmentMapper.updateById(assignment); + + log.info("作品已标记违规,作品ID:{},评委ID:{}", workId, judgeId); + Map result = new LinkedHashMap<>(); + result.put("workId", workId); + result.put("status", WorkStatus.VIOLATION.getValue()); + return result; + } + @Override public Map updateScore(Long scoreId, CreateScoreDto dto, Long judgeId) { log.info("更新评分,评分ID:{},评委ID:{}", scoreId, judgeId); @@ -514,6 +569,7 @@ public class ContestReviewServiceImpl implements IContestReviewService { map.put("previewUrl", work.getPreviewUrl()); map.put("previewUrls", work.getPreviewUrls()); map.put("submitterAccountNo", submitterAcc); + map.put("workStatus", work.getStatus()); BizContestWorkScore scoreRecord = scoreMap.get(a.getId()); if (scoreRecord != null) { @@ -616,7 +672,8 @@ public class ContestReviewServiceImpl implements IContestReviewService { WorkStatus.LOCKED.getValue(), WorkStatus.REVIEWING.getValue(), WorkStatus.REJECTED.getValue(), - WorkStatus.ACCEPTED.getValue() + WorkStatus.ACCEPTED.getValue(), + WorkStatus.VIOLATION.getValue() }; Map result = new LinkedHashMap<>(); result.put("total", total); diff --git a/lesingle-creation-backend/src/main/java/com/lesingle/modules/pub/controller/PublicActivityController.java b/lesingle-creation-backend/src/main/java/com/lesingle/modules/pub/controller/PublicActivityController.java index 5567bff..946ad99 100644 --- a/lesingle-creation-backend/src/main/java/com/lesingle/modules/pub/controller/PublicActivityController.java +++ b/lesingle-creation-backend/src/main/java/com/lesingle/modules/pub/controller/PublicActivityController.java @@ -54,6 +54,16 @@ public class PublicActivityController { return Result.success(contestResultService.getPublicResults(id, page, pageSize)); } + @Public + @GetMapping("/{id}/works") + @Operation(summary = "参赛作品列表(公开活动已发布,无需登录)") + public Result>> listPublicWorks( + @PathVariable Long id, + @RequestParam(defaultValue = "1") int page, + @RequestParam(defaultValue = "10") int pageSize) { + return Result.success(publicActivityService.listPublicContestWorks(id, page, pageSize)); + } + @GetMapping("/{id}/my-registration") @Operation(summary = "查询我的报名信息") public Result> getMyRegistration(@PathVariable Long id) { diff --git a/lesingle-creation-backend/src/main/java/com/lesingle/modules/pub/service/PublicActivityService.java b/lesingle-creation-backend/src/main/java/com/lesingle/modules/pub/service/PublicActivityService.java index 4de99fd..f073149 100644 --- a/lesingle-creation-backend/src/main/java/com/lesingle/modules/pub/service/PublicActivityService.java +++ b/lesingle-creation-backend/src/main/java/com/lesingle/modules/pub/service/PublicActivityService.java @@ -35,6 +35,7 @@ import org.springframework.util.StringUtils; import java.time.LocalDateTime; import java.util.*; +import java.util.stream.Collectors; @Slf4j @Service @@ -195,6 +196,18 @@ public class PublicActivityService { result.put("hasSubmittedWork", workCount > 0); result.put("workCount", workCount); + BizContestWork latest = contestWorkMapper.selectOne( + new LambdaQueryWrapper() + .eq(BizContestWork::getRegistrationId, reg.getId()) + .eq(BizContestWork::getIsLatest, true) + .last("LIMIT 1")); + if (latest != null) { + result.put("latestWorkId", latest.getId()); + result.put("latestWorkStatus", latest.getStatus()); + result.put("violationReason", latest.getViolationReason()); + result.put("violationMarkTime", latest.getViolationMarkTime()); + } + return result; } @@ -429,10 +442,12 @@ public class PublicActivityService { .last("LIMIT 1")); if (existingWork != null) { - if ("once".equals(submitRule)) { + boolean allowReplace = "resubmit".equals(submitRule) + || WorkStatus.VIOLATION.getValue().equals(existingWork.getStatus()); + if (!allowReplace) { throw new BusinessException(400, "该活动仅允许提交一次作品"); } - // resubmit 模式:将旧作品标记为非最新 + // resubmit 或评委标记违规后重提:将旧作品标记为非最新 existingWork.setIsLatest(false); contestWorkMapper.updateById(existingWork); } @@ -509,4 +524,105 @@ public class PublicActivityService { contestWorkMapper.insert(work); return work; } + + /** + * 公开活动参赛作品列表:本活动下各报名记录的最新版本(排除违规、下架等不宜公开展示的状态) + */ + public PageResult> listPublicContestWorks(Long contestId, int page, int pageSize) { + BizContest contest = contestMapper.selectById(contestId); + if (contest == null) { + throw new BusinessException(404, "活动不存在"); + } + if (!Visibility.PUBLIC.getValue().equals(contest.getVisibility())) { + throw new BusinessException(403, "活动不可公开访问"); + } + if (!PublishStatus.PUBLISHED.getValue().equals(contest.getContestState())) { + throw new BusinessException(400, "活动未发布"); + } + + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(BizContestWork::getContestId, contestId) + .eq(BizContestWork::getIsLatest, true) + .eq(BizContestWork::getValidState, 1) + .notIn(BizContestWork::getStatus, + List.of(WorkStatus.VIOLATION.getValue(), WorkStatus.TAKEN_DOWN.getValue())) + .orderByDesc(BizContestWork::getSubmitTime) + .orderByDesc(BizContestWork::getId); + + IPage workPage = contestWorkMapper.selectPage(new Page<>(page, pageSize), wrapper); + List records = workPage.getRecords(); + if (records.isEmpty()) { + return PageResult.from(workPage, Collections.emptyList()); + } + + Set ugcIds = records.stream() + .map(BizContestWork::getUserWorkId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + Map ugcMap = new HashMap<>(); + if (!ugcIds.isEmpty()) { + List ugcList = ugcWorkMapper.selectBatchIds(ugcIds); + for (UgcWork uw : ugcList) { + if (uw != null && (uw.getIsDeleted() == null || uw.getIsDeleted() == 0)) { + ugcMap.put(uw.getId(), uw); + } + } + } + + Set submitterIds = records.stream() + .map(BizContestWork::getSubmitterUserId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + Map userMap = new HashMap<>(); + if (!submitterIds.isEmpty()) { + List users = sysUserMapper.selectBatchIds(submitterIds); + for (SysUser u : users) { + userMap.put(u.getId(), u); + } + } + + List> list = new ArrayList<>(); + for (BizContestWork work : records) { + Map row = new LinkedHashMap<>(); + Long userWorkId = work.getUserWorkId(); + UgcWork ugc = userWorkId != null ? ugcMap.get(userWorkId) : null; + + String coverUrl = work.getPreviewUrl(); + String originalImageUrl = null; + int likeCount = 0; + int viewCount = 0; + if (ugc != null) { + if (StringUtils.hasText(ugc.getCoverUrl())) { + coverUrl = ugc.getCoverUrl(); + } + originalImageUrl = ugc.getOriginalImageUrl(); + likeCount = ugc.getLikeCount() != null ? ugc.getLikeCount() : 0; + viewCount = ugc.getViewCount() != null ? ugc.getViewCount() : 0; + } + + // 前端与作品广场一致:id 为 UGC 作品 ID(点赞、跳转 /p/works/:id) + row.put("id", userWorkId); + row.put("contestWorkId", work.getId()); + row.put("title", work.getTitle()); + row.put("coverUrl", coverUrl); + row.put("originalImageUrl", originalImageUrl); + row.put("likeCount", likeCount); + row.put("viewCount", viewCount); + + Map creator = new LinkedHashMap<>(); + SysUser su = work.getSubmitterUserId() != null ? userMap.get(work.getSubmitterUserId()) : null; + if (su != null) { + creator.put("nickname", StringUtils.hasText(su.getNickname()) ? su.getNickname() : su.getUsername()); + creator.put("avatar", su.getAvatar()); + } else { + creator.put("nickname", StringUtils.hasText(work.getSubmitterAccountNo()) ? work.getSubmitterAccountNo() : "用户"); + creator.put("avatar", null); + } + row.put("creator", creator); + + list.add(row); + } + + return PageResult.from(workPage, list); + } } diff --git a/lesingle-creation-backend/src/main/resources/db/migration/V19__contest_work_violation.sql b/lesingle-creation-backend/src/main/resources/db/migration/V19__contest_work_violation.sql new file mode 100644 index 0000000..d4b42c4 --- /dev/null +++ b/lesingle-creation-backend/src/main/resources/db/migration/V19__contest_work_violation.sql @@ -0,0 +1,5 @@ +-- 评委标记活动作品违规:原因、时间、操作评委 +ALTER TABLE t_biz_contest_work + ADD COLUMN violation_reason VARCHAR(500) NULL COMMENT '评委标记违规原因' AFTER status, + ADD COLUMN violation_mark_time DATETIME NULL COMMENT '违规标记时间' AFTER violation_reason, + ADD COLUMN violation_judge_id BIGINT NULL COMMENT '标记违规的评委用户ID' AFTER violation_mark_time; diff --git a/lesingle-creation-frontend/src/api/contests.ts b/lesingle-creation-frontend/src/api/contests.ts index b42304e..5701d57 100644 --- a/lesingle-creation-frontend/src/api/contests.ts +++ b/lesingle-creation-frontend/src/api/contests.ts @@ -366,7 +366,19 @@ export interface ContestWork { files?: string[] | Record[] | string; version: number; isLatest: boolean; - status: "submitted" | "locked" | "reviewing" | "rejected" | "accepted"; + status: + | "submitted" + | "locked" + | "reviewing" + | "rejected" + | "accepted" + | "awarded" + | "taken_down" + | "violation"; + /** 评委标记违规原因(status=violation 时可能有值) */ + violationReason?: string | null; + violationMarkTime?: string | null; + violationJudgeId?: number | null; submitTime: string; submitterUserId?: number; submitterAccountNo?: string; @@ -1210,6 +1222,18 @@ export const reviewsApi = { return response; }, + /** 评委标记作品违规(作品 status=violation,分配任务 completed) */ + markViolation: async ( + workId: number, + data: { assignmentId: number; reason?: string }, + ): Promise<{ workId: number; status: string }> => { + const response = await request.post( + `/contests/reviews/work/${workId}/violation`, + data, + ); + return response; + }, + // 更新评分 updateScore: async ( scoreId: number, diff --git a/lesingle-creation-frontend/src/api/public.ts b/lesingle-creation-frontend/src/api/public.ts index ae17057..872a337 100644 --- a/lesingle-creation-frontend/src/api/public.ts +++ b/lesingle-creation-frontend/src/api/public.ts @@ -318,6 +318,23 @@ export interface PublicActivityDetail extends PublicActivity { targetCities?: string[]; } +/** 当前用户在某活动的报名 + 最新参赛作品状态(GET my-registration) */ +export interface PublicActivityMyRegistration { + id: number; + contestId: number; + userId: number; + registrationType: string; + registrationState: string; + registrationTime: string; + hasSubmittedWork: boolean; + workCount: number; + latestWorkId?: number; + /** 与 BizContestWork.status 一致,含 violation */ + latestWorkStatus?: string; + violationReason?: string | null; + violationMarkTime?: string | null; +} + /** 公众端公示成果行(无报名账号等敏感字段) */ export interface PublicActivityResultItem { id: number; @@ -329,6 +346,21 @@ export interface PublicActivityResultItem { participantName: string; } +/** 活动详情「参赛作品」Tab(id 为 UGC 作品 ID,无关联作品库时为 null) */ +export interface PublicActivityContestWorkItem { + id: number | null; + contestWorkId: number; + title: string | null; + coverUrl: string | null; + originalImageUrl: string | null; + likeCount: number; + viewCount: number; + creator?: { + nickname: string; + avatar: string | null; + }; +} + export const publicActivitiesApi = { list: (params?: { page?: number; @@ -347,16 +379,9 @@ export const publicActivitiesApi = { ) => publicApi.post(`/public/activities/${id}/register`, data), getMyRegistration: (id: number) => - publicApi.get<{ - id: number; - contestId: number; - userId: number; - registrationType: string; - registrationState: string; - registrationTime: string; - hasSubmittedWork: boolean; - workCount: number; - } | null>(`/public/activities/${id}/my-registration`), + publicApi.get( + `/public/activities/${id}/my-registration`, + ), submitWork: ( id: number, @@ -386,6 +411,17 @@ export const publicActivitiesApi = { page: number; pageSize: number; }> => publicApi.get(`/public/activities/${id}/results`, { params }), + + /** 参赛作品分页(公开且已发布的活动;无需登录) */ + getActivityWorks: ( + id: number, + params?: { page?: number; pageSize?: number }, + ): Promise<{ + list: PublicActivityContestWorkItem[]; + total: number; + page: number; + pageSize: number; + }> => publicApi.get(`/public/activities/${id}/works`, { params }), }; // ==================== 我的报名 ==================== diff --git a/lesingle-creation-frontend/src/views/activities/components/ReviewWorkModal.vue b/lesingle-creation-frontend/src/views/activities/components/ReviewWorkModal.vue index 98d38bb..8eee4d8 100644 --- a/lesingle-creation-frontend/src/views/activities/components/ReviewWorkModal.vue +++ b/lesingle-creation-frontend/src/views/activities/components/ReviewWorkModal.vue @@ -108,6 +108,15 @@
作品打分
+ +
+ 该作品已标记为违规 +
+ {{ workDetail.violationReason }} +
+
+ +
+ + +

+ 确定标记后,作品状态将变为「违规」,并结束您在本作品上的评审任务。 +

+ +