# 公众端活动详情 —「活动成果」Tab 设计方案

> 所属端：用户端（公众端 `/p/`）  
> 状态：需求已补充，待开发实现  
> 创建日期：2026-04-08  
> 关联需求：[总需求 US-105](../../project/01-requirements.md)、[开发计划 P1 成果查看详情](../../project/05-development-plan.md)

---

## 1. 背景与目标

### 1.1 问题

机构在管理端「成果发布」中发布活动成果后，参与者与公众需要在**公众端活动详情页**查看评审结果。当前实现仅在「活动成果」Tab 内展示奖杯图标与提示语「活动成果已发布，敬请查看！」，**未展示具体获奖名单与得分**，与总需求中「查看活动成果和评审结果」不一致。

### 1.2 目标

- 在**不降低隐私安全**的前提下，使公众端 Tab 内容与管理端已发布成果的**业务口径一致**（排名、奖项、分数来源同一套计算与数据）。
- 将「活动成果已发布，敬请查看！」定位为**辅助提示**（如副标题或加载态提示），**主内容**为可浏览的成果列表及必要元信息。

### 1.3 关联文档

| 文档 | 说明 |
|------|------|
| [成果发布优化（超管）](../super-admin/results-publish-optimization.md) | 活动维度发布状态、列表筛选 |
| [租户端全面优化 — 成果发布 Detail](../org-admin/tenant-portal-optimization.md) | 统计摘要、排名、设奖、发布流程 |
| [UGC 社区升级](./ugc-platform-upgrade.md) | 公众端整体信息架构，本设计细化「活动」模块下成果 Tab |

---

## 2. 入口与可见性

### 2.1 Tab 显示条件

- 仅当活动 **`resultState === 'published'`** 时显示「活动成果」Tab。  
- 未发布：不展示该 Tab（与当前 [ActivityDetail.vue](../../../frontend/src/views/public/ActivityDetail.vue) 逻辑一致）。

### 2.2 主操作区「查看成果」

- 活动阶段为「已结束」时，主按钮「查看成果」将 **`activeTab` 切换为 `results`**，用户在同一页查看「活动成果」Tab 内容。  
- 文档约定：**默认不跳转独立路由**；若未来产品改为「成果专页」，需单独迭代路由与返回行为。

### 2.3 是否需要登录

| 策略 | 说明 |
|------|------|
| **默认（推荐）** | **无需登录**即可查看已发布活动的成果列表，与公开浏览活动信息一致。 |
| 可选 | 若合规或机构要求「仅报名用户可见」，可在活动级增加配置，此时未登录用户看到引导登录或模糊提示；**需在实现阶段单独评审**，本文档以默认策略为验收基线。 |

---

## 3. Tab 内信息架构

### 3.1 文案「活动成果已发布，敬请查看！」的定位

- **不作为唯一内容**：数据加载完成后，主区域应为成果列表。  
- 可用作：**副文案**、**骨架屏/加载中的简短说明**，或列表上方的温和提示。

### 3.2 主内容：成果列表

与管理端活动详情「活动结果」Tab（[contests/Detail.vue](../../../frontend/src/views/contests/Detail.vue)）**同一业务数据口径**，公众端字段可裁剪如下：

| 字段 | 是否展示（默认） | 说明 |
|------|------------------|------|
| 名次（排名） | 是 | 与管理端排名一致 |
| 作品编号 | 是 | 若有业务编号则展示，便于用户核对 |
| 奖项 | 是 | 如一等奖、二等奖等 |
| 最终得分 | 是 | 与机构发布策略一致；若机构侧不公开分数，后端可不返回或由配置控制 |
| 姓名/展示名 | 是 | 个人：用户昵称；团队：队名 |
| 报名账号 | **否** | 见第 4 节 |

### 3.3 元信息

- **成果发布时间**：展示活动级 **`resultPublishTime`**（公众活动详情接口已返回该字段，见前端 `PublicActivity` 类型）。

### 3.4 空状态

- 当 `resultState === 'published'` 但公示列表为空时：展示明确空状态文案，例如「暂无公示信息」，避免长时间加载无反馈。

---

## 4. 隐私与脱敏

- **默认不展示**：登录账号、手机号、邮箱等可直接识别身份或联系方式的字段。  
- **展示名**：优先使用昵称、队名等已在业务中用于对外的名称。  
- **少儿场景**：不展示精确联系方式；仅展示机构允许公示的字段。  
- 若需展示账号类信息，须为**脱敏**形式（如仅保留前后若干位），且需产品/合规确认。

---

## 5. 交互与体验

### 5.1 列表与分页

- 移动端优先：采用 **分页** 或 **加载更多** 之一，避免单次加载数据量过大。  
- 列表项在窄屏下可用卡片式排布，保证名次、奖项、得分可读。

### 5.2 行内「查看详情」（分期）

| 阶段 | 范围 |
|------|------|
| **P1** | 完成公示**列表**（排名、奖项、得分、展示名、作品编号等）。 |
| **P2（可选）** | 点击行进入参赛作品/绘本预览详情，依赖作品公开范围与权限策略。 |

### 5.3 数据一致性

- 排名、奖项、最终得分的**计算与更新**与租户端「成果发布」模块一致，避免公众端与后台两套数据。参见 [租户端成果发布 Detail](../org-admin/tenant-portal-optimization.md)。

---

## 6. 后端与接口（需求说明）

### 6.1 现状

- 管理端使用 `GET /contests/results/{contestId}`（需 **`contest:read`**），**不适合**匿名公众直接调用。

### 6.2 建议新增（实现时）

- 提供公众专用只读接口，例如：  
  **`GET /public/activities/{id}/results`**  
  - 查询参数：分页（`page` / `pageSize`），可选关键词（若需按作品编号搜索可后续扩展）。  
  - **仅当**该活动 `resultState === 'published'` 时返回公示字段；否则返回空列表或 **404**，具体策略在实现时二选一并写清（推荐与详情接口状态一致：未发布则列表接口返回空列表 + 前端不展示 Tab，减少歧义）。

### 6.3 多租户与安全

- 服务端必须按活动 **`tenant_id`** 与 **`contest_id`** 限定查询，仅返回该活动下已发布结果数据，防止跨租户泄露。  
- 不依赖前端传 `tenantId` 作为信任来源。

---

## 7. 验收标准

| 编号 | 场景 | 预期 |
|------|------|------|
| AC-1 | 成果已发布 | 公众端「活动成果」Tab 展示与文档一致的列表字段，不含未授权敏感信息 |
| AC-2 | 成果未发布 | 不展示「活动成果」Tab |
| AC-3 | 机构撤回发布 | 活动 `resultState` 非 `published` 后，公众端不再展示该 Tab 或列表内容 |
| AC-4 | 匿名用户 | 默认策略下，无需登录即可查看已发布列表 |
| AC-5 | 发布时间 | 可看到与活动一致的成果发布时间（若接口与 UI 已接通） |

---

## 8. 前端实现参考（待开发）

| 位置 | 说明 |
|------|------|
| [frontend/src/views/public/ActivityDetail.vue](../../../frontend/src/views/public/ActivityDetail.vue) | 替换纯占位为列表 + 加载/空状态；接入公众成果 API |
| [frontend/src/api/public.ts](../../../frontend/src/api/public.ts) | 新增 `publicActivitiesApi.getPublishedResults(contestId, params)` 等 |

---

## 9. 修订记录

| 日期 | 说明 |
|------|------|
| 2026-04-08 | 初稿：入口、字段、隐私、接口、验收与分期 |
