Files
SerpMax/docs/Publishing-功能扩展开发说明.md

131 lines
9.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ProfileMax「发布」(Publishing) 功能扩展开发说明
> 目标:供 Zcode 在现有 SerpMax/ProfileMax 项目中直接扩展。新增一个「发布」一级菜单,页面内部使用 Ant Design Tabs(页签)管理子功能。此处“Tags”按页面 Tabs 理解;站点标签另用 tags 字段,不要混淆。
> 依据:`docs/审计-功能清单与技术栈.md`(2026-10-28),开发前以当前源码为准。
## 1. 定位和边界
- **只扩展现有 ProfileMax**:复用 Bun.serve、PostgreSQL/Bun.sql、React 19 + antd 6、Scripts、Tasks、54 个 MCP 工具、Profile/Proxy/Cookie、Node/Lease、Playwright、Fetch 和 WebDesk。
- **不做独立平台、不集成 LLM/Agent 服务**。Zcode/Codex/OpenCode 通过 MCP + Skills 负责网站学习、文章生成、脚本编写与失败修复。ProfileMax 负责确定性执行、持久化、校验、调度、监控和评分。
- 网站资源由用户 CSV/JSON/API 导入,不实现自动发现/爬取资源引擎;仅支持有授权或允许投稿的网站,遵守站点规则。
- V1 不增加消息队列、微服务、第二套调度器;优先扩展现有 tasks、scripts 和 task_runs。现有脚本/任务功能必须保持兼容。
## 2. UI:一个「发布」菜单 + 内部 Tabs
导航增加 **发布 (Publishing)** 一级菜单,点击后页面顶部用 Ant Design `Tabs` 切换:
| Tab | 最小功能 |
| --- | --- |
| 项目 | 项目 CRUD;官网、产品资料、目标 URL、关键词、内容规则、默认语言 |
| 站点 | CSV/JSON 导入、列表/标签/筛选、站点 URL、平台类型、允许发布的账号/Profile 关联、脚本版本、状态 |
| 文章 | 草稿导入/编辑(Markdown/HTML)、文章版本、审核状态、目标链接/锚文本;内容由外部 Agent 生成后保存 |
| 发布任务 | 创建发布任务、选择文章/站点/Profile、脚本、执行时间/并发、运行日志、失败诊断、手动重试 |
| 质量与评分 | 发布 URL、链接属性、链接存活检查、最近检测时间、站点评分/外链评分和历史结果 |
- 页面沿用当前布局、路由、权限、组件、暗色主题及 API 封装方式;图标使用 lucide-react,不使用 Emoji。
- Tabs 的选择应支持 URL 定位(刷新保留),权限统一使用新增 `publishing` 菜单权限,并校验关联 Profile 的所有权/分享权限。
- “发布”是一级菜单,其下使用 **Tabs 而非再添加五个左侧菜单**。站点本身的业务 `tags` 用于分类筛选,与 UI Tabs 是两种概念。
## 3. 执行流程
1. 用户/Agent 导入站点并与现有 Profile 关联,记录网站可发布权限、平台类型及标签。
2. 外部 Agent 通过已有 MCP/browser tools 学习站点,优先复用已有 `schema` 脚本,复杂页面才使用 `code`;第一次或少量测试后保存稳定脚本并绑定站点(或平台)。
3. 外部 Agent 根据项目资料生成有实际价值的文章,通过 MCP/REST 写入「文章」,标记 `draft/review/ready`。
4. Publishing 生成发布作业并交给**现有任务系统**执行。文章正文、标题、图片、链接作为每次运行的输入参数;不为每篇文章复制脚本。执行时使用已有 Profile Lease。
5. 将结构化输出(发布 URL、状态、错误码)与 task_run 关联,提交超时标记 `unknown`,先查是否已发布再重试,避免重复提交。
6. 失败时保存**脱敏**错误、失败步骤、截图/DOM 摘要;将修复状态标记 `needs_repair`,外部 Agent 通过 MCP 查询、测试并提交新脚本版本。V1 允许 Agent 主动轮询,不要求 ProfileMax 自动启动 Agent。
7. 发布后由后台定时进行 HTTP/HTML 检查;需要登录/JS 渲染才回退现有 Profile Fetch/Browser。定期计算评分,供站点筛选使用。
### 标准脚本 I/O(新增适配层,不破坏现有脚本 API)
```typescript
interface PublishInput {
siteId: string;
article: {
title: string;
html: string;
markdown?: string;
images?: string[];
};
targetLinks: Array<{ url: string; anchor: string }>;
mode: "draft" | "publish";
}
interface PublishResult {
status: "draft" | "published" | "failed" | "unknown";
articleUrl?: string;
externalId?: string;
errorCode?: string;
message?: string;
}
```
任务需要 `idempotencyKey`、脚本版本快照和稳定的 run ID;不能因重试发布重复文章。
## 4. 数据模型(尽量少表,沿用现有数据库)
新增前先检查已有数据结构,避免重复:
| 表 | 核心字段 |
| --- | --- |
| `publishing_projects` | id, owner_user_id, name, website, config(jsonb), created_at |
| `publishing_sites` | id, project_id, url, platform, tags(text[]), profile_id(nullable), script_id(nullable), status, metadata(jsonb) |
| `publishing_articles` | id, project_id, title, markdown, html, target_links(jsonb), version, status, metadata(jsonb) |
| `publishing_jobs` | id, project_id, site_id, article_id, profile_id, task_id(nullable), script_version, idempotency_key, status, result(jsonb) |
| `publishing_checks` | id, job_id, checked_at, page_status, link_status, rel(jsonb), detail(jsonb) |
- 与现有 `profiles`/`scripts`/`tasks`/`task_runs` 使用关联 ID,不复制 Cookie、Proxy 或完整执行日志。
- V1 脚本版本可增加 `script_versions` 通用表及稳定版本指针;禁止直接覆盖正在运行的版本。版本表应是通用 Scripts 能力,不放在 Publishing 业务表中。
- 评分先用查询/视图或定期计算,不必新建评分历史表;Site Score 建议结合主题相关性、成功率、链接保留率、成本;Backlink Score 包含链接存活、属性、内容相关性及可获得的引荐效果。未知数据标记 unknown,不编造指标。
- 迁移延续现有 PostgreSQL 迁移惯例;新增索引(owner/project/site/job/status/idempotency_key);新写接口校验访问权限、输入及关联实体归属。
## 5. REST / MCP / Skills
REST API 建议统一前缀 `/api/publishing`:
- `GET/POST /projects`、`GET/PATCH/DELETE /projects/:id`
- `GET/POST /sites`、`POST /sites/import`、`PATCH /sites/:id`
- `GET/POST /articles`、`PATCH /articles/:id`
- `GET/POST /jobs`、`GET /jobs/:id`、`POST /jobs/:id/retry`
- `POST /jobs/:id/verify`、`GET /jobs/:id/checks`、`GET /scores`
MCP **复用** `admin/src/api/mcp.ts` 的认证与工具框架;V1 只补充少量组合工具:
- `publishing_import_sites`
- `publishing_save_article`
- `publishing_create_job`
- `publishing_get_job`
- `publishing_verify_job`
- `publishing_get_repair_context`
脚本 CRUD/运行尽量调用现有 MCP,不重复暴露同名能力。新增 `skills/profilemax-publishing/SKILL.md` 及 references,写明:导入站点、学习站点、复用/生成脚本、测试、生成内容、创建任务、查询失败、修复测试、验证链接。Skills 是外部 Agent 的操作说明,不在服务端执行大模型。
## 6. 代码落点与实现要求
- 前端:`admin/frontend/pages/Publishing.tsx`;接入现有路由/导航;内部 Tabs 使用独立子组件,避免一个超大文件。
- API:`admin/src/api/routes/publishing.ts`;保持现有 `Bun.serve` 路由模式、身份与权限中间件。
- DB:`admin/src/repos/publishing*.ts` 与现有迁移文件。
- 业务:`admin/src/runtime/publishing/` 负责作业映射、定时监控和评分;**复用** `admin/src/runtime/taskScheduler.ts`,不要写第二套 scheduler。
- Node:优先不改节点;只有在脚本 I/O 或故障证据无法通过现有 Schema 执行器实现时,才最小修改 `node/src/core/schema/`。
- MCP:`admin/src/api/mcp.ts` 增加工具,继续使用同一 Bearer 认证与权限校验。
- 现有 `code` 脚本通过 `new Function` 在节点进程执行、没有沙箱:**不得**让 Agent 新生成的任意代码直接进入该运行通道。V1 优先 Schema;如果必须支持 Agent 生成 JS/TS,需先实现真正的低权限独立进程/容器隔离(不是 `node:vm`),并限制敏感文件、进程、网络及密钥访问。Agent 输出和网页 DOM 一律视为不可信。
- 站点/脚本修复只提交候选版本,经测试和审查再发布 stable;不能在生产中直接修改热脚本。
## 7. 开发顺序与验收
**阶段 A(最小可用)**:发布菜单+Tabs;项目/站点/文章 CRUD;导入站点/关联 Profile;MCP 读写;复用现有稳定脚本创建任务并显示结果。
**阶段 B(脚本复用)**:参数化脚本 I/O、通用版本管理、失败证据、待修复状态、外部 Agent 的学习/测试/修复 Skill。完成代码执行隔离前,不允许自动运行不可信 Agent 生成的 code 脚本。
**阶段 C(质量)**:定时外链验证、历史检查、站点评分及汇总报表。
必须验证:
1. 发布菜单仅一个一级入口,内部五个 Tabs 切换和刷新定位正常;多用户权限正确。
2. CSV/JSON 批量导入可去重,同项目站点可筛选、打标签、关联获授权的 Profile。
3. 已有 Schema/脚本可复用,文章不同但不复制脚本;运行成功返回文章 URL。
4. 失败、取消、超时、重复投递安全处理,重复任务不会导致重复发布。
5. Agent 离线时正常任务与质量监控照常运行;失败待修复可通过 MCP 领取和诊断。
6. HTTP 检测正常,动态/认证页面有回退方案;评分无数据时展示未知或样本数。
7. 原有 Profiles、Scripts、Tasks、SERP、MCP、WebDesk 功能均通过回归测试。
**Zcode 开发原则:先检查现有源码/接口与表结构,再最小增量改造;禁止重复造已有模块。本文是实施目标,不代表接口或表已经存在。**