# 评审进度模块优化 — 设计方案 > 所属端:超管端 > 状态:已实现(待验收) > 创建日期:2026-03-27 > 最后更新:2026-03-27 --- ## 1. 背景与问题 超管端"评审进度"菜单是两层结构,问题模式与报名数据、作品数据一致:第一层是活动列表精简版(冗余),第二层围绕管理操作设计(开始评审/结束评审/替换评委),不符合超管只读监管定位。 ### 核心问题 | 问题 | 说明 | |------|------| | 第一层与全部活动列表重复 | 活动列表已有评审进度列(已评/总数),两个入口功能重叠 | | 写操作未隔离 | "开始评审""结束评审""替换评委"均为机构管理端操作 | | 评审状态筛选无效 | 第一层评审状态下拉选了不生效(前端计算但未传后端) | | 缺少全局统计 | 没有全平台评审总进度概览 | | 无跨活动维度 | 不能跨活动查看所有作品的评审状态 | | ~~TODO~~ 部分已补 | 未提交作品列表仍为 TODO;**评委替换**已由 `POST /api/contests/reviews/replace-judge` 实现(分配 ID + 新评委用户 ID,未评分前可换) | | 样式不一致 | 主色 `#1890ff` | --- ## 2. 现状分析 ### 2.1 第一层:评审进度(reviews/Progress.vue) - 个人参与/团队参与 Tab - 数据来源:`contestsApi.getList()` 按活动类型过滤 - 搜索:活动名称 + 评审状态(无效) - 表格列:序号/活动名称/主办机构/评审状态/已评审÷作品数/评审时间/操作 - 操作:查看详情 → 跳转 ProgressDetail ### 2.2 第二层:评审进度详情(reviews/ProgressDetail.vue) - 数据来源:`worksApi.getList({ contestId })` - 搜索:作品编号/报名账号/评审进度 - 表格列:序号/作品编号/报名账号/评委评分/评审进度/操作 - 操作按钮:开始评审、结束评审、未提交作品、导出 - 评审详情 Drawer:每个评委评分 + 替换评委 - 评委替换 Drawer:选择新评委 --- ## 3. 设计方案 ### 3.1 整体思路 与报名/作品模块一致:**超管端两层合一为扁平作品评审列表**,展示全平台所有作品的评审状态和评分情况。隐藏所有写操作,只保留查看能力。机构端保持不变。 ### 3.2 页面结构 ``` ┌─ 标题卡片 ──────────────────────────────────────────────┐ │ 评审进度 │ └─────────────────────────────────────────────────────────┘ ┌─ 统计卡片 ──────────────────────────────────────────────┐ │ [全部 120] [未评审 60] [评审中 40] [已完成 20] │ └─────────────────────────────────────────────────────────┘ ┌─ 筛选栏 ────────────────────────────────────────────────┐ │ 所属活动:[下拉搜索] 作品/作者:[______] 评审进度:[下拉] │ │ [搜索] [重置] │ └─────────────────────────────────────────────────────────┘ ┌─ 数据表格 ──────────────────────────────────────────────┐ │ 所属活动 | 作品编号 | 提交者 | 报名账号 | │ │ 评审进度 | 平均分 | 递交时间 | 操作 │ └─────────────────────────────────────────────────────────┘ ``` ### 3.3 统计卡片 4 张卡片,可点击筛选: | 卡片 | 数据 | 颜色 | 说明 | |------|------|------|------| | 全部 | 作品总数 | 主色 | validState=1 且 isLatest=true | | 未评审 | 无评分记录的作品 | 灰色 | assignments 为空或 scores 为空 | | 评审中 | 部分评委已评的作品 | 橙色 | 有评分但未全部评完 | | 已完成 | 所有评委评完的作品 | 绿色 | reviewedCount >= totalJudgesCount | 复用作品 stats 接口数据即可(submitted≈未评审,reviewing≈评审中,reviewed≈已完成)。 ### 3.4 筛选栏 | 筛选项 | 组件 | 说明 | |--------|------|------| | 所属活动 | Select(远程搜索) | 按活动名称搜索下拉 | | 作品/作者 | Input | 搜索作品编号、提交者姓名 | | 评审进度 | Select | 未评审 / 评审中 / 已完成 | ### 3.5 表格列 | 列 | 宽度 | 渲染方式 | |----|------|----------| | 所属活动 | 180 | 活动名称,可点击跳转活动详情 | | 作品编号 | 130 | workNo,可点击查看作品详情 | | 提交者 | 130 | 昵称 / 队伍名 | | 报名账号 | 120 | username | | 评审进度 | 100 | Tag:未评审(灰)/ 评审中 x/y(橙)/ 已完成(绿) | | 平均分 | 80 | averageScore,已完成时显示分数,否则"-" | | 递交时间 | 150 | YYYY-MM-DD HH:mm | | 操作 | 100 | 查看详情 | ### 3.6 详情 Drawer 点击"查看详情"打开 Drawer,展示该作品的评审明细: ``` 作品信息 ├── 所属活动 / 作品编号 ├── 提交者 / 报名账号 ├── 平均分 / 评审进度(x/y) 评委评分列表(表格) ├── 评委姓名 / 所属单位 / 评分 / 评分时间 ``` 不提供"替换评委"操作。 ### 3.7 URL 参数支持 - `/super/contests/reviews/progress` — 全部作品评审进度 - `/super/contests/reviews/progress?contestId=3` — 从活动列表跳转,筛选某活动 --- ## 4. 后端改动 - **评委替换**:`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 评审进度前端过滤 "评审进度"筛选(未评审/评审中/已完成)基于返回数据的 `reviewedCount` 和 `totalJudgesCount` 在前端过滤,或后端 works 接口增加 `reviewProgress` 参数。 简化方案:前端直接利用作品 status 字段 + scores 数据判定,不改后端。 --- ## 5. 前端改动 | 文件 | 操作 | 说明 | |------|------|------| | `frontend/src/views/contests/reviews/Progress.vue` | 修改 | 超管端改为扁平评审进度列表(统计卡片+筛选+表格+评分Drawer),机构端保持不变 | 后端无需改动,完全复用已有的 works 接口和 stats 接口。 --- ## 6. 实施记录 ### 2026-03-27 — 首次实现 **后端改动:无**(完全复用 works 接口和 reviews/scores 接口) **前端改动(1 个文件):** - `frontend/src/views/contests/reviews/Progress.vue` — 完全重写:超管端为扁平评审进度列表(统计卡片复用 worksApi.getStats + 筛选栏 + 全平台作品表格含评审进度/平均分 + 评分详情 Drawer 含评委评分明细),机构端保持原有两层结构;评审进度筛选为前端过滤(基于 reviewedCount/totalJudgesCount);支持 URL 参数联动(?contestId=xx)