# 作品数据模块优化 — 设计方案 > 所属端:超管端 > 状态:已实现(待验收) > 创建日期:2026-03-27 > 最后更新:2026-03-27 --- ## 1. 背景与问题 超管端"作品数据"菜单目前是两层结构:第一层按活动维度展示活动列表(每行一个活动,显示作品提交数),点击"查看详情"进入第二层查看某活动的具体作品。问题模式与报名数据完全一致。 ### 核心问题 | 问题 | 说明 | |------|------| | 第一层与全部活动列表重复 | Index.vue 是活动列表精简版,全部活动列表已有可点击的作品数列 | | 超管写操作未隔离 | "分配评委"按钮、批量分配、分配抽屉均为机构管理端功能,超管不应有 | | 缺少全局统计 | 没有作品总量、提交率等概览 | | 无跨活动搜索 | 不能跨活动搜索某个作者的作品 | | 第二层围绕"分配评委"设计 | 分配状态列、评委列、分配操作均为管理功能,超管只需查看 | | 样式不一致 | 主色写死 `#1890ff` | --- ## 2. 现状分析 ### 2.1 第一层:作品管理(works/Index.vue) - 个人参与/团队参与 Tab 切换 - 数据来源:`contestsApi.getList()` 按活动类型过滤 - 搜索:仅活动名称 - 表格列:序号/活动名称/主办机构/报名人数/已递交÷应递交/活动时间/操作 - 操作:查看详情(跳转 WorksDetail) ### 2.2 第二层:参赛作品(works/WorksDetail.vue) - 数据来源:`worksApi.getList({ contestId })` - 搜索:选手名/报名账号/作品编号/分配状态/递交时间/机构 - 表格列:序号/作品编号/报名账号/选手名/递交时间/分配状态/评委/操作 - 功能:作品详情弹框(WorkDetailModal)、分配评委抽屉(批量+单个)、行勾选 --- ## 3. 设计方案 ### 3.1 整体思路 与报名数据优化方案一致:**超管端将两层合并为一层**,扁平展示全平台所有作品记录,通过筛选条件切换活动。机构端保持原有两层结构不变。 超管端隐藏所有写操作(分配评委、批量分配),只保留查看能力。 ### 3.2 页面结构 ``` ┌─ 标题卡片 ──────────────────────────────────────────────┐ │ 作品数据 │ └─────────────────────────────────────────────────────────┘ ┌─ 统计卡片 ──────────────────────────────────────────────┐ │ [全部 120] [已提交 85] [评审中 30] [已评完 20] │ └─────────────────────────────────────────────────────────┘ ┌─ 筛选栏 ────────────────────────────────────────────────┐ │ 所属活动:[下拉搜索] 作者/编号:[______] 作品状态:[下拉] │ │ 递交时间:[日期范围] [搜索] [重置] │ └─────────────────────────────────────────────────────────┘ ┌─ 数据表格 ──────────────────────────────────────────────┐ │ 所属活动 | 作品编号 | 提交者 | 报名账号 | 主办机构 | │ │ | 作品状态 | 递交时间 | 操作 │ └─────────────────────────────────────────────────────────┘ ``` ### 3.3 统计卡片 4 张卡片,可点击切换筛选: | 卡片 | 数据 | 颜色 | 说明 | |------|------|------|------| | 全部 | 作品总数 | 主色 | 全平台所有作品 | | 已提交 | submitted 数量 | 蓝色 | 已提交待评审 | | 评审中 | reviewing 数量 | 橙色 | 正在评审(已分配评委) | | 已评完 | reviewed 数量 | 绿色 | 评审完成 | 数据来源:新增 `GET /api/contests/works/stats` 接口。 ### 3.4 筛选栏 | 筛选项 | 组件 | 说明 | |--------|------|------| | 所属活动 | Select(远程搜索) | 按活动名称搜索下拉,选择后按 contestId 过滤 | | 作者/编号 | Input | 搜索作品编号、提交者姓名 | | 作品状态 | Select | 已提交 / 评审中 / 已评完 | | 递交时间 | RangePicker | 时间范围筛选 | **联动逻辑**:从"全部活动"列表点击作品数字跳转时,URL 带 `?contestId=xx`,页面初始化时自动设置"所属活动"筛选。 ### 3.5 表格列 | 列 | 宽度 | 渲染方式 | |----|------|----------| | 所属活动 | 180 | 活动名称,可点击跳转活动详情 | | 作品编号 | 130 | workNo,可点击查看作品详情弹框 | | 提交者 | 130 | 提交者昵称;团队参与时显示队伍名 | | 报名账号 | 120 | username | | 主办机构 | 120 | 提交者所属租户名 | | 作品状态 | 90 | Tag:已提交(蓝)/ 评审中(橙)/ 已评完(绿) | | 递交时间 | 150 | YYYY-MM-DD HH:mm | | 操作 | 80 | 查看详情 | 超管操作列**只有"查看详情"**(打开 WorkDetailModal),不提供分配评委。 ### 3.6 详情交互 点击"查看详情"复用现有的 `WorkDetailModal` 组件,展示作品内容。 点击"作品编号"也打开同一个弹框(与现有行为一致)。 ### 3.7 URL 参数支持 - `/super/contests/works` — 全部作品 - `/super/contests/works?contestId=3` — 筛选某活动的作品(从活动列表跳转) --- ## 4. 后端改动 ### 4.1 新增 GET /api/contests/works/stats 超管调用时返回全平台作品统计: ```json { "total": 120, "submitted": 85, "reviewing": 30, "reviewed": 20 } ``` 支持可选的 `contestId` 参数。 判定逻辑: - submitted:status = 'submitted' 且无评分记录 - reviewing:status = 'submitted' 或 'reviewing',且有评分记录但未全部评完 - reviewed:所有分配的评委都已评分 简化方案:直接按数据库 status 字段统计(submitted / reviewing),reviewed 通过 `reviewedCount` 从活动列表接口已有的逻辑复用。 ### 4.2 扩展 GET /api/contests/works 超管调用时: - `contestId` 变为可选(不传时查全部活动的作品) - 新增 `keyword` 参数:搜索作品编号、提交者姓名 - 新增 `status` 参数:按作品状态筛选 - 返回增加活动名称:`contest: { id, contestName }` - 返回增加提交者租户:`registration.user.tenant.name` 普通租户调用时保持现有逻辑不变。 --- ## 5. 前端改动 | 文件 | 操作 | 说明 | |------|------|------| | `frontend/src/api/contests.ts` | 修改 | 新增 WorksStats 类型和 works.getStats 接口,扩展 works 查询参数 | | `frontend/src/views/contests/works/Index.vue` | 修改 | 超管端改为扁平作品列表(统计卡片+筛选+全平台表格+详情弹框),机构端保持不变 | | `backend/src/contests/works/works.service.ts` | 修改 | 新增 getStats,扩展 findAll 支持跨活动查询 | | `backend/src/contests/works/works.controller.ts` | 修改 | 新增 stats 端点,findAll 增加参数 | --- ## 6. 实施记录 ### 2026-03-27 — 首次实现 **后端改动(3 个文件):** - `backend/src/contests/works/dto/query-work.dto.ts` — 新增 keyword 参数 - `backend/src/contests/works/works.service.ts` — 新增 getStats() 方法(按状态统计);findAll 增加 keyword 搜索(作品编号/提交者姓名/队伍名) - `backend/src/contests/works/works.controller.ts` — 新增 GET /api/contests/works/stats 端点(stats 在 :id 之前) **前端改动(2 个文件):** - `frontend/src/api/contests.ts` — 扩展 QueryWorkParams(keyword),新增 WorksStats 类型和 worksApi.getStats - `frontend/src/views/contests/works/Index.vue` — 超管端改为扁平作品列表(统计卡片+筛选栏+全平台表格+WorkDetailModal),机构端保持原有两层结构;支持 URL 参数联动(?contestId=xx)