---
type: pointer
title: 编辑来源配置页面需求
summary: 从 /editorial-sources 当前展示和操作推导字段、数量、存储与取舍
updated: 2026-10-08
---

# 编辑来源配置

路由：`/editorial-sources`。角色：独立运营人员。范围：**现有辅助入口**。依据：当前页面和调用组件（代码基线 `67df5ab1`，本轮仅修复根元素 hydration 并移除无调用旧 header 插槽）。以下数量是现有读取策略，不是实际业务记录数，也不是容量或服务承诺。

源码入口：[page.tsx](../../../../frontend/src/app/editorial-sources/page.tsx) · [content-presenters.ts](../../../../frontend/src/app/content/components/content-presenters.ts) · [editorial-external-ingress.tsx](../../../../frontend/src/app/editorial-sources/components/editorial-external-ingress.tsx) · [editorial-local-approval.tsx](../../../../frontend/src/app/editorial-sources/components/editorial-local-approval.tsx) · [editorial-source-manager.tsx](../../../../frontend/src/app/editorial-sources/components/editorial-source-manager.tsx)。

## 用户任务与当前操作

作为独立运营人员，我需要管理可公开阅读的合规取数来源。当前操作围绕下表的数据完成；不从旧表和旧接口的存在反推新增产品需求。页面存在不等于来源、模型、送达或长期运行已通过真实验收。

## 页面需要的数据

| 区域／操作 | 实际展示或输入字段 | 展示数量／读取方式 | 是否持久化及最小存储 |
|---|---|---|---|
| 编辑来源配置 | profile id/name/kind/mode/tier、revision/configuration/policy、interval、config、health | 现有运营列表和表单 | editorial_source_profiles/versions |
| 预览/材料/运行 | 样本数、title/url/excerpt、请求数、job/status、reason、content_id/version、收据 | 材料20条/页；运行最多100条；先选来源 | source_runs/material_receipts；内容仍共用content |
| 准入与图标 | 允许连接版本、审批原因、icon状态/时间 | 显式维护动作；令牌仅内存 | 现有策略/图标；不新增供应商平台 |

## 接口与业务落点

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

| 页面调用 | 方法和路径 | 请求 → 响应合同 | 实现依据 |
|---|---|---|---|
| `approveEditorialBodyExtraction` | `POST /api/editorial-sources/{profile_id}/body-approval` | `approveEditorialBodyExtractionParams, EditorialBodyApprovalInput` → `EditorialBodyApprovalView` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |
| `approveEditorialRsshubSource` | `POST /api/editorial-sources/{profile_id}/rsshub-approval` | `approveEditorialRsshubSourceParams, EditorialRsshubApprovalInput` → `EditorialRsshubApprovalView` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |
| `createEditorialSourceProfile` | `POST /api/editorial-sources` | `EditorialProfileInput` → `EditorialProfileView` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |
| `getEditorialSourceIcon` | `GET /api/editorial-sources/{profile_id}/icon` | `getEditorialSourceIconParams` → `SourceIconView` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |
| `getEditorialSourcePreview` | `GET /api/editorial-sources/previews/{job_id}` | `getEditorialSourcePreviewParams` → `EditorialPreviewJobView` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |
| `getExternalEditorialIngressReceipt` | `GET /api/editorial-sources/{profile_id}/ingest/{run_id}` | `getExternalEditorialIngressReceiptParams` → `ExternalIngressReceipt` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |
| `ingestExternalEditorialSource` | `POST /api/editorial-sources/{profile_id}/ingest` | `ingestExternalEditorialSourceParams, ExternalEditorialInput` → `ExternalIngressReceipt` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |
| `listContentRecords` | `GET /api/contents` | `listContentRecordsParams` → `PageViewContentRecordSummaryView_` | [客户端](../../../../frontend/src/api/zuopinziliao.ts) · [后端](../../../../backend/app/api/routers/content_records.py) |
| `listEditorialSourceGroupBacklogs` | `GET /api/editorial-sources/groups/backlogs` | `无业务入参` → `EditorialGroupBacklogView[]` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |
| `listEditorialSourceProfiles` | `GET /api/editorial-sources` | `无业务入参` → `EditorialProfileView[]` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |
| `listEditorialSourceRuns` | `GET /api/editorial-sources/{profile_id}/runs` | `listEditorialSourceRunsParams` → `EditorialRunResult[]` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |
| `pollEditorialSource` | `POST /api/editorial-sources/{profile_id}/runs` | `pollEditorialSourceParams, EditorialPollInput` → `JobView` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |
| `previewEditorialSourceSample` | `POST /api/editorial-sources/preview/sample` | `EditorialSamplePreviewInput` → `EditorialSourcePreviewView` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |
| `previewStoredEditorialSource` | `POST /api/editorial-sources/{profile_id}/previews` | `previewStoredEditorialSourceParams, EditorialRemotePreviewInput` → `JobView` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |
| `refreshEditorialSourceIcon` | `POST /api/editorial-sources/{profile_id}/icon/refresh` | `refreshEditorialSourceIconParams, SourceIconRefreshInput` → `JobView` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |
| `reviewEditorialSourceGroupBacklog` | `POST /api/editorial-sources/groups/backlogs/review` | `EditorialGroupBacklogReviewInput` → `EditorialGroupBacklogReviewResult` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |
| `reviewEditorialSourcePreview` | `POST /api/editorial-sources/previews/{job_id}/review` | `reviewEditorialSourcePreviewParams, EditorialPreviewReviewInput` → `EditorialPreviewReviewView` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |
| `reviewEditorialSourceRun` | `POST /api/editorial-sources/{profile_id}/runs/{run_id}/review` | `reviewEditorialSourceRunParams, EditorialRunReviewInput` → `EditorialRunResult` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |
| `updateEditorialSourceProfile` | `PUT /api/editorial-sources/{profile_id}` | `updateEditorialSourceProfileParams, EditorialProfileInput` → `EditorialProfileView` | [客户端](../../../../frontend/src/api/bianjilaiyuan.ts) · [后端](../../../../backend/app/api/routers/editorial_sources.py) |

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

## 收敛与替换

维护既有来源，停止扩展通用采集编排器；旧免费候选清单不代表接入任务。

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

## 验收与非功能要求

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

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