---
type: pointer
title: 私有资料与评论页面需求
summary: 从 /content/[contentId] 当前展示和操作推导字段、数量、存储与取舍
updated: 2026-10-08
---

# 私有资料与评论

路由：`/content/[contentId]`。角色：所属用户。范围：**当前主流程**。依据：当前页面和调用组件（代码基线 `67df5ab1`，本轮仅修复根元素 hydration 并移除无调用旧 header 插槽）。以下数量是现有读取策略，不是实际业务记录数，也不是容量或服务承诺。

源码入口：[page.tsx](../../../../frontend/src/app/content/[contentId]/page.tsx) · [annotation-panel.tsx](../../../../frontend/src/app/content/[contentId]/components/annotation-panel.tsx) · [comment-refresh-action.tsx](../../../../frontend/src/app/content/[contentId]/components/comment-refresh-action.tsx) · [comment-thread-list.tsx](../../../../frontend/src/app/content/[contentId]/components/comment-thread-list.tsx) · [content-detail.tsx](../../../../frontend/src/app/content/[contentId]/components/content-detail.tsx)。

## 用户任务与当前操作

作为所属用户，我需要读取原帖与评论上下文并核对采集证据。当前操作围绕下表的数据完成；不从旧表和旧接口的存在反推新增产品需求。页面存在不等于来源、模型、送达或长期运行已通过真实验收。

## 页面需要的数据

| 区域／操作 | 实际展示或输入字段 | 展示数量／读取方式 | 是否持久化及最小存储 |
|---|---|---|---|
| 资料正文与出处 | id/object_type/source/external_id；版本title/body/text_origin；观察时间/互动计数/可见性/获取记录 | 单身份及当前可读版本历史 | content_records/versions/observations与visibility |
| 评论树 | post/root/parent/reply_target、作者/正文/时间、父缺失状态 | 根评论20条/页，回复另按20条加载 | 评论也是content，threads仅保存关系 |
| 分析及刷新 | topic_rule_version/prompt_version、relevant/sentiment/reason/summary；comment readiness/job_id | 切主题/版本读取；刷新评论明确点击 | content_annotations及原jobs；不新增评论正文表 |

## 接口与业务落点

下列为本页业务读取/提交入口。全局会话、头像、站点元信息和共享组件中未在本页触发的导出函数不算新增页面能力。请求类型、响应与错误以生成客户端和后端为准。

| 页面调用 | 方法和路径 | 请求 → 响应合同 | 实现依据 |
|---|---|---|---|
| `cancelCollectionJob` | `POST /api/jobs/{job_id}/cancel` | `cancelCollectionJobParams` → `JobStatusView` | [客户端](../../../../frontend/src/api/caijirenwu.ts) · [后端](../../../../backend/app/api/routers/collection_jobs.py) |
| `createContentExport` | `POST /api/content-exports` | `ContentExportInput` → `ExportView` | [客户端](../../../../frontend/src/api/siyoudaochu.ts) · [后端](../../../../backend/app/api/routers/private_exports.py) |
| `createReportExport` | `POST /api/reports/{report_id}/exports` | `createReportExportParams, ReportExportInput` → `ExportView` | [客户端](../../../../frontend/src/api/siyoudaochu.ts) · [后端](../../../../backend/app/api/routers/private_exports.py) |
| `downloadContentExport` | `GET /api/content-exports/{export_id}/download` | `downloadContentExportParams` → `string` | [客户端](../../../../frontend/src/api/siyoudaochu.ts) · [后端](../../../../backend/app/api/routers/private_exports.py) |
| `downloadReportExport` | `GET /api/report-exports/{export_id}/download` | `downloadReportExportParams` → `string` | [客户端](../../../../frontend/src/api/siyoudaochu.ts) · [后端](../../../../backend/app/api/routers/private_exports.py) |
| `getContentCommentRunReadiness` | `GET /api/contents/{content_id}/comment-run-readiness` | `getContentCommentRunReadinessParams` → `CommentRunReadinessView` | [客户端](../../../../frontend/src/api/zuopinziliao.ts) · [后端](../../../../backend/app/api/routers/content_records.py) |
| `getContentExport` | `GET /api/content-exports/{export_id}` | `getContentExportParams` → `ExportView` | [客户端](../../../../frontend/src/api/siyoudaochu.ts) · [后端](../../../../backend/app/api/routers/private_exports.py) |
| `getContentRecord` | `GET /api/contents/{content_id}` | `getContentRecordParams` → `ContentRecordDetailView` | [客户端](../../../../frontend/src/api/zuopinziliao.ts) · [后端](../../../../backend/app/api/routers/content_records.py) |
| `getReportExport` | `GET /api/report-exports/{export_id}` | `getReportExportParams` → `ExportView` | [客户端](../../../../frontend/src/api/siyoudaochu.ts) · [后端](../../../../backend/app/api/routers/private_exports.py) |
| `listContentComments` | `GET /api/contents/{content_id}/comments` | `listContentCommentsParams` → `PageViewContentCommentView_` | [客户端](../../../../frontend/src/api/zuopinziliao.ts) · [后端](../../../../backend/app/api/routers/content_records.py) |
| `retryCollectionJob` | `POST /api/jobs/{job_id}/retry` | `retryCollectionJobParams` → `JobStatusView` | [客户端](../../../../frontend/src/api/caijirenwu.ts) · [后端](../../../../backend/app/api/routers/collection_jobs.py) |
| `runContentComments` | `POST /api/contents/{content_id}/comment-runs` | `runContentCommentsParams, CommentManualRunInput` → `JobAcceptedView` | [客户端](../../../../frontend/src/api/zuopinziliao.ts) · [后端](../../../../backend/app/api/routers/content_records.py) |

数据落点：[content_records](../reference/13-现有数据库字典.md#content_records)、[content_versions](../reference/13-现有数据库字典.md#content_versions)、[content_observations](../reference/13-现有数据库字典.md#content_observations)、[content_threads](../reference/13-现有数据库字典.md#content_threads)、[content_visibility_observations](../reference/13-现有数据库字典.md#content_visibility_observations)、[content_annotations](../reference/13-现有数据库字典.md#content_annotations)、[jobs](../reference/13-现有数据库字典.md#jobs)、[content_export_requests](../reference/13-现有数据库字典.md#content_export_requests)。这是当前依赖定位，不代表这些表均为重新设计时必须新建；详细字段/键/关系及保留原因见[页面数据库设计](../reference/09-全站页面数据库设计.md)。

## 收敛与替换

撤掉四档相关性新结构作为当前前置；当前bool/null不能虚构direct/indirect；导出复用现有服务。

实现时先复用上述合同。确有缺口须描述具体控件、输入、输出、当前失败和最小修复，不能直接把历史扩展方案列为前置。公开分发、付费供应商、海外新来源与 Flutter 继续受[冻结范围](../../decisions/11-冻结范围.md)和其他生效决策约束。

## 验收与非功能要求

- 主路径：父评论不存在可读其余上下文；详情失败不标为删除；第二轮去重不吞新增评论。
- 数据边界：上表数量、字段和统计范围要能从响应核对；未知、未分析、无权限和真实零值不同。筛选、页签与选择不创建持久业务副本。
- 状态：有远程读取的区域分别验证正常、零数据、加载、失败和撤权；静态说明的业务空态/无权限写不适用，不伪造验收。
- 写入：有保存/运行/发布时保留可恢复输入，版本冲突先重读；请求结果未知按现有接口查询或复用原幂等键，不新增全局操作账本。
- 交互：1440px与390px下主动作可见；Tab/Enter/Escape和适用的方向键可操作，弹层关闭返回触发点。凭据只按现有认证流程传递，不进入日志/URL/本机持久存储。

测量和跨页场景统一见[非功能要求](../reference/10-全站非功能需求.md)、[验收场景](../reference/11-全站验收场景.md)。这里只定义判据，执行进度仍只在 BACKLOG。

### 本轮权限状态补查

首次作品读取401/403分别按无权限展示，不继续显示旧正文；503保留可重试错误。
