# 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 开发原则:先检查现有源码/接口与表结构,再最小增量改造;禁止重复造已有模块。本文是实施目标,不代表接口或表已经存在。**