library-picturebook-activity/docs/design/super-admin/activity-list-optimization.md

349 lines
16 KiB
Markdown
Raw Normal View History

# 全部活动模块优化 — 设计方案
> 所属端:超管端
> 状态:已实现(待验收)
> 创建日期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/statsfindAll 增加查询参数 |
| `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 超管详情路由