# 全部活动模块优化 — 设计方案

> 所属端：超管端
> 状态：已实现（待验收）
> 创建日期：2026-03-27
> 最后更新：2026-03-27

---

## 1. 背景与问题

超管端"全部活动"模块包含列表页和详情页，均与机构端共用组件，仅通过 `isSuperAdmin` 隐藏写操作按钮。超管的核心职能是**监管**，但当前设计缺乏监管视角。

### 列表页问题

| 问题 | 说明 |
|------|------|
| 无全局概览 | 没有活动总量、各状态分布等统计信息，进来就是一张裸表格 |
| 缺少活动阶段筛选 | 只能筛发布状态（已发布/未发布），不能按实际阶段（报名中/征稿中/评审中/已结束）筛选 |
| 缺少主办机构筛选 | 超管跨机构查看但无法按机构过滤 |
| 数据列缺少阶段感知 | 看不到每个活动当前处于哪个阶段（报名中？征稿中？评审中？），只有静态的"已发布/未发布" |
| 统计数字不可交互 | 报名/作品/评委列的数字是纯展示，不能点击跳转到对应的管理页面 |
| 主色不一致 | 页面内写死 `#1890ff`，与全局主题色 `#6366f1` 不一致 |

### 详情页问题

| 问题 | 说明 |
|------|------|
| 页面为参与者视角 | 海报+报名按钮设计面向教师/学生，不适合超管监管场景 |
| 缺少监管数据 | 看不到报名人数、作品提交情况、评审完成进度等关键指标 |
| 缺少配置信息 | 看不到报名时间、提交时间、评审时间、评审规则等完整配置 |
| 缺少快捷导航 | 无法从详情页跳转到该活动的报名数据、作品数据、评审进度等子模块 |
| 文案错误 | 标题写的"竞赛详情"，应为"活动详情" |

---

## 2. 现状分析

### 2.1 列表页（contests/Index.vue）

- 与机构管理端共用同一组件
- 超管通过 `isSuperAdmin` 隐藏写操作（创建/编辑/删除/发布/添加评委）
- 搜索：活动名称、活动状态、活动类型、可见范围
- 表格 12 列：序号/名称/主办方/类型/状态/可见范围/公开机构/报名/作品/评委/时间/操作
- 操作列只有"查看详情"

### 2.2 详情页（contests/Detail.vue）

- 与机构端、教师端完全共用
- 顶部海报区 + 3 个 Tab（活动信息/通知公告/活动结果）+ 右侧组织信息
- 报名按钮仅 teacher 角色可见，超管看不到也不需要
- 活动信息 Tab 展示富文本内容
- 活动结果 Tab 展示获奖表格（成果已发布时）

### 2.3 后端现有能力

`QueryContestDto` 已支持：contestName, contestState(published/unpublished), status(ongoing/finished), contestType, visibility

返回数据已包含：`_count { registrations, works, teams, judges }`, 时间字段齐全, `reviewedCount`, `totalWorksCount`

---

## 3. 设计方案

### 3.1 整体思路

**列表页**：在现有基础上增加统计卡片和阶段筛选，增强数据列的信息密度和可交互性。不拆分为独立组件（超管和机构端列表差异不大），继续共用但通过 isSuperAdmin 适配。

**详情页**：超管端使用独立的详情页组件，取代当前的参与者视角页面，聚焦监管数据展示和快捷导航。

### 3.2 列表页优化

#### 3.2.1 新增统计卡片

列表页顶部增加一行统计卡片（仅超管可见）：

```
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ 全部  12 │ │ 报名中 3 │ │ 征稿中 2 │ │ 评审中 1 │ │ 已结束 4 │ │ 未发布 2 │
└─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘
```

点击卡片 = 快捷筛选。需要后端新增 `GET /api/contests/stats` 接口。

活动阶段判定逻辑（基于时间字段，非数据库字段）：
```
未发布：contestState === 'unpublished'
报名中：已发布 && now 在 registerStartTime ~ registerEndTime 之间
征稿中：已发布 && now 在 submitStartTime ~ submitEndTime 之间
评审中：已发布 && now 在 reviewStartTime ~ reviewEndTime 之间
已结束：status === 'finished' 或 所有阶段时间均已过
```

#### 3.2.2 增强筛选栏

在现有 4 项筛选基础上，超管端增加：

| 新增筛选项 | 组件 | 说明 |
|-----------|------|------|
| 主办机构 | Select（下拉搜索） | 按 organizers 字段模糊匹配，或按创建活动的租户筛选 |
| 活动阶段 | Select | 报名中 / 征稿中 / 评审中 / 已结束（前端根据时间字段过滤，或后端增加 stage 参数） |

注意：将现有的"活动状态（已发布/未发布）"和"活动阶段"合并为一个筛选项，因为阶段已隐含发布状态。

最终筛选栏（超管端）：
```
活动名称:[______] 活动阶段:[下拉] 活动类型:[下拉] 可见范围:[下拉] 主办机构:[下拉] [搜索] [重置]
```

#### 3.2.3 表格列优化

| 列 | 宽度 | 变更 |
|----|------|------|
| 序号 | 60 | 不变 |
| 活动名称 | 200 | 不变 |
| 主办机构 | 120 | **改为 tenant.name**（创建活动的租户名），替代 organizers 字段，更准确 |
| 活动类型 | 90 | 不变 |
| 活动阶段 | 100 | **新列，替代原"活动状态"**，根据时间字段计算当前阶段，颜色编码：蓝=报名中，绿=征稿中，橙=评审中，灰=已结束，默认=未发布 |
| 可见范围 | 90 | 不变 |
| 报名 | 70 | **可点击**，点击跳转到该活动的报名数据页 |
| 作品 | 70 | **可点击**，点击跳转到该活动的作品数据页 |
| 评审 | 80 | **改为进度展示**：`已评/总数`（如 `12/30`），利用后端已有的 reviewedCount/totalWorksCount |
| 活动时间 | 160 | 不变 |
| 操作 | 100 | 不变（查看详情）|

移除列：
- "公开机构"列 — 信息密度低，可在详情页查看
- "评委"列 — 评委数量监管价值低，评审进度更有意义

#### 3.2.4 样式修复

- 将页面内写死的 `$primary: #1890ff` 改为 `$primary: #6366f1`，与全局主题一致

### 3.3 详情页优化（超管专用）

超管点击"查看详情"后，跳转到**超管专用的活动详情页**，而非现有的参与者视角页面。

#### 3.3.1 页面结构

```
┌─ 顶部信息栏 ──────────────────────────────────────────────┐
│ ← 返回    活动名称                                        │
│ [个人参与] [已发布] [报名中]   主办：广东省图  创建：2026-03-01 │
└──────────────────────────────────────────────────────────┘

┌─ 数据概览卡片 ─────────────────────────────────────────────┐
│ [报名 128人] [作品 56份] [评审进度 12/56] [评委 5人]        │
│  点击跳转     点击跳转     点击跳转        点击跳转         │
└──────────────────────────────────────────────────────────┘

┌─ 时间轴 ──────────────────────────────────────────────────┐
│ ● 报名阶段 03-01~03-15  ● 征稿阶段 03-15~04-01           │
│ ○ 评审阶段 04-01~04-10  ○ 成果发布 未发布                  │
└──────────────────────────────────────────────────────────┘

┌─ Tab 区域 ────────────────────────────────────────────────┐
│ [活动配置] [活动内容] [通知公告] [活动结果]                  │
├──────────────────────────────────────────────────────────┤
│ 活动配置 Tab：                                             │
│  基本信息：名称/类型/可见范围/定向条件                       │
│  报名配置：时间/是否审核/年级限制/人数限制                   │
│  作品配置：提交时间/提交规则/作品类型/作品要求               │
│  评审配置：评审时间/评审规则名                              │
│  组织信息：主办/协办/赞助/联系方式                          │
│                                                           │
│ 活动内容 Tab：                                             │
│  富文本 v-html（复用现有）                                  │
│                                                           │
│ 通知公告 Tab：                                             │
│  公告列表（复用现有）                                       │
│                                                           │
│ 活动结果 Tab：                                             │
│  获奖表格（复用现有）                                       │
└──────────────────────────────────────────────────────────┘
```

#### 3.3.2 顶部信息栏

一行展示核心身份信息：
- 返回按钮
- 活动名称（大标题）
- 标签组：活动类型 + 发布状态 + 当前阶段
- 主办机构、创建时间

不使用海报/背景图，保持管理后台的简洁风格。

#### 3.3.3 数据概览卡片

4 张可点击的数据卡片：

| 卡片 | 数据来源 | 点击跳转 |
|------|---------|---------|
| 报名人数 | `_count.registrations` | `/super/contests/registrations?contestId=xx`（报名数据页带筛选） |
| 作品数量 | `_count.works` | `/super/contests/works/:id/list`（作品数据页） |
| 评审进度 | `reviewedCount / totalWorksCount` | `/super/contests/reviews/:id/progress`（评审进度页） |
| 评委人数 | `_count.judges` | `/super/contests/:id/judges`（评委管理页） |

#### 3.3.4 时间轴

横向时间轴，展示活动的 4 个阶段及其时间范围：
```
报名阶段 → 征稿阶段 → 评审阶段 → 成果发布
```
- 已完成的阶段：实心圆 + 主色
- 当前阶段：实心圆 + 高亮 + 脉冲动画
- 未来阶段：空心圆 + 灰色
- 每个节点显示时间范围

#### 3.3.5 Tab 区域

| Tab | 内容 | 说明 |
|-----|------|------|
| 活动配置 | Descriptions 组件展示所有配置字段 | **新增**，超管最需要看到的完整配置信息 |
| 活动内容 | 富文本 v-html | 复用现有逻辑 |
| 通知公告 | 公告列表 | 复用现有逻辑 |
| 活动结果 | 获奖表格 | 复用现有逻辑 |

**活动配置 Tab 详细设计**：

```
基本信息
├── 活动名称 / 活动类型 / 可见范围
├── 定向条件（城市/年龄，仅 targeted 时显示）
└── 公开机构列表（仅 designated 时显示）

报名配置
├── 报名时间：xx ~ xx
├── 是否需要审核：是/否
├── 允许年级/班级（如有）
└── 团队人数限制（团队参与时显示）

作品配置
├── 提交时间：xx ~ xx
├── 提交规则：单次提交 / 允许重新提交
├── 作品类型：图片/视频/文档/...
└── 作品要求（文本描述）

评审配置
├── 评审时间：xx ~ xx
├── 关联评审规则：规则名称
└── 成果状态：已发布 / 未发布

组织信息
├── 主办单位 / 协办单位 / 赞助单位
└── 联系人 / 联系电话
```

### 3.4 路由设计

超管端活动详情使用独立路由，不影响现有的机构端/教师端详情页：

```typescript
// 新增：超管活动详情路由
{
  path: "contests/:id/overview",
  name: "SuperContestOverview",
  component: () => import("@/views/contests/SuperDetail.vue"),
  meta: { title: "活动详情", requiresAuth: true },
}
```

列表页"查看详情"按钮：
- 超管端跳转到 `/:tenantCode/contests/:id/overview`（新页面）
- 机构端保持跳转到 `/:tenantCode/contests/:id`（原页面）

### 3.5 后端改动

#### 3.5.1 新增 GET /api/contests/stats（活动统计）

仅超管可用，返回：

```json
{
  "total": 12,
  "unpublished": 2,
  "registering": 3,
  "submitting": 2,
  "reviewing": 1,
  "finished": 4
}
```

阶段判定在后端基于时间字段计算。

#### 3.5.2 扩展 GET /api/contests 查询参数

| 新增参数 | 类型 | 说明 |
|---------|------|------|
| `stage` | string? | 活动阶段筛选：`unpublished`/`registering`/`submitting`/`reviewing`/`finished` |
| `creatorTenantId` | number? | 按创建活动的租户（主办机构）筛选 |

stage 筛选逻辑在后端实现（基于时间字段比较），避免前端做应用层过滤影响分页。

#### 3.5.3 GET /api/contests/:id 返回增强

超管调用时额外返回：
- `tenant: { id, name, code }`（创建活动的租户信息）
- 确保 `reviewedCount` 和 `totalWorksCount` 已返回（当前已有）

### 3.6 前端改动

| 文件 | 操作 | 说明 |
|------|------|------|
| `frontend/src/api/contests.ts` | 修改 | QueryContestParams 增加 stage/creatorTenantId，新增 getStats 接口 |
| `frontend/src/views/contests/Index.vue` | 修改 | 超管端增加统计卡片、阶段筛选、机构筛选、可点击数字、阶段列、样式修复 |
| `frontend/src/views/contests/SuperDetail.vue` | **新增** | 超管专用活动详情页 |
| `frontend/src/router/index.ts` | 修改 | 新增超管活动详情路由 |
| `backend/src/contests/contests/contests.service.ts` | 修改 | 新增 getStats 方法，findAll 增加 stage/creatorTenantId 参数 |
| `backend/src/contests/contests/contests.controller.ts` | 修改 | 新增 stats 端点，findAll 增加查询参数 |
| `backend/src/contests/contests/dto/query-contest.dto.ts` | 修改 | 新增 stage/creatorTenantId 字段 |

---

## 4. 改动范围

### 后端（3 个文件）

| 文件 | 改动类型 |
|------|---------|
| `backend/src/contests/contests/contests.service.ts` | 修改：新增 getStats()，findAll 增加 stage/creatorTenantId 过滤 |
| `backend/src/contests/contests/contests.controller.ts` | 修改：新增 GET /contests/stats，findAll 增加查询参数 |
| `backend/src/contests/contests/dto/query-contest.dto.ts` | 修改：DTO 新增字段 |

### 前端（4 个文件）

| 文件 | 改动类型 |
|------|---------|
| `frontend/src/api/contests.ts` | 修改：扩展类型和接口 |
| `frontend/src/views/contests/Index.vue` | 修改：超管端增强 |
| `frontend/src/views/contests/SuperDetail.vue` | **新增**：超管活动详情页 |
| `frontend/src/router/index.ts` | 修改：新增路由 |

---

## 5. 实施记录

### 2026-03-27 — 首次实现

**后端改动（3 个文件）：**
- `backend/src/contests/contests/dto/query-contest.dto.ts` — 新增 stage、creatorTenantId 字段
- `backend/src/contests/contests/contests.service.ts` — 新增 getContestStage() 阶段判定方法、getStats() 统计方法；findAll 增加 stage 应用层过滤和 creatorTenantId 筛选；返回数据增加 stage、creatorTenant 字段
- `backend/src/contests/contests/contests.controller.ts` — 新增 GET /api/contests/stats 端点

**前端改动（4 个文件）：**
- `frontend/src/api/contests.ts` — QueryContestParams 增加 stage/creatorTenantId/visibility；新增 ContestStats 类型和 getStats 接口
- `frontend/src/views/contests/Index.vue` — 重写：超管端增加统计卡片（6 个阶段）、活动阶段筛选+主办机构筛选、超管/机构分列定义、活动阶段列、报名/作品可点击跳转、评审进度列（已评/总数）、主色修复为 #6366f1
- `frontend/src/views/contests/SuperDetail.vue` — **新增**：超管活动详情页，含顶部信息栏+4 张数据概览卡片+横向时间轴+4 Tab（配置/内容/公告/结果）
- `frontend/src/router/index.ts` — 新增 contests/:id/overview 超管详情路由
