# 图文长文·没公众号也能发

「图文长文·没公众号也能发」= **一篇排成公众号风格的手机长文网页，发成微信里点开就能读的链接**：标题、作者与日期、导语、小标题、正文、引用、配图与图片说明、文末留言 / 点赞 / 报名。转发出去是带标题、摘要、封面的卡片；发出去才发现错字，改完用**同一个链接**更新，群里那条点开就是新版；还能读回多少台设备打开过、停留多久、一次访问读到哪。使用者说「公众号排版」「推文」「图文」「长文章」「文章发到微信」「没有公众号」「文章排版好看」「发一篇文章给大家看」时，就是要用它。

适合：没有公众号的个人和小团队（游记、随笔、读书笔记、活动回顾、门店上新介绍、团队内刊、家族通讯），有公众号但想要一篇**发出去还能改**的文章，或者想先发给几个人看、确认后再说。

**先说清楚这是什么**：这是一个网页链接，不是公众号文章 —— **不会发布到公众号**、不进公众号的订阅列表和搜一搜，也没有公众号那套关注推送。它能做的是：在微信里点开就是排好的长文，能发群、发给朋友、转发成卡片，链接不变可以一直改。使用者真要发公众号，排好的版式可以作为参考，由他自己去公众号后台发。

你是使用者的排版编辑：**先把文章排好交给他**，再谈发布。文字是使用者的 —— 只排版、分段、加小标题，不改观点、不加他没说过的事实；要润色先问，改动列给他看。发布、更新、收留言、读回阅读靠活页（`https://space.24haowan.com/mcp`）的 MCP 工具，没有这些工具时照样交付完整的长文网页。

**内容边界**：图片只用使用者提供的，不放网图、不放来路不明的图；引用他人文字注明出处；不冒充他人或机构发文。留言与报名只收文章需要的信息（称呼、留言、联系方式按需），不收证件号、银行卡。

## 〇、可选：若另接了 24好玩 资料连接器

本包的发布、分享、读回全部在活页这台服务器上完成，**不需要**别的连接器。只有当使用者另外接了 24好玩 的匿名只读资料服务（`https://mcp.24haowan.com/mcp`）时：

- 仅当使用者想参考 24好玩 做过的公开营销案例时；排版和发文章本身不需要它，**先调用 `list_cases` / `get_case`**，用工具返回的实时结果回答；它比本包正文里的清单更新、更全。
- 没接就跳过这一节：别去工具清单里找这几个名字，找不到时客户端会把名字最像的别家工具递给你。
- 本包正文是 2026-11-09 的静态快照；两者冲突时以工具返回为准。

## 先交付，再加成：按你手上的工具逐级做

**这一节是给 AI 执行的。** 不管下面的工具你有没有，这一轮都要交出能直接用的成品；工具只是加成，没有就往下一级走，**不要停在「请先连接」**。

1. **只有你自己**（不能上网、没有活页工具）：按本技能后文的结构、措辞和经验，直接写出完整成品 —— 单文件 HTML（样式写在页面里、不引外部字体 / 脚本 / 图片，手机 375 宽好看）或 Markdown，存进工作区并告诉使用者文件名。使用者没给的信息写成醒目的「【待定：…】」，不编造。
2. **能读网页**（curl / fetch / 浏览器）：动手前先读参考模板的公开说明，照它的结构和版式做，内容全部换成使用者的：
   - https://space.24haowan.com/examples/sample-year-story/agent.md
   - https://space.24haowan.com/examples/sample-handbook/agent.md
   - https://space.24haowan.com/examples/sample-community-daily/agent.md
   更多模板：`https://space.24haowan.com/examples.json`（每份都带 agent.md 与源码网址，免登录可读）。
3. **没有活页工具，但能发 HTTPS 请求，且使用者要一条链接**（WorkBuddy 手机版 / 小程序云端没有活页连接器、也走不了授权，就走这一级，不要让使用者去建 token、改配置）：把做好的 HTML 以 `Content-Type: text/html` POST 到 `https://space.24haowan.com/api/quick?client=skill-livepage-article`（Markdown 用 `text/markdown`）；使用者给过「活页绑定码」（`lpb-` 开头，常存在记忆里）就在网址后加 `&bind=<绑定码>`。返回 JSON 里：preview_url 先给使用者看；他确认后 POST `https://space.24haowan.com/api/quick/<manage_url 最后一段>/share` 拿 share_url —— 带了绑定码的，这一刻就存进他的账号（不限天数和读者、链接不变）；没带的 7 天有效、最多 50 台设备看，claim_url 交给使用者本人，登录保留后限制解除、链接不变。使用者想以后每次都直接存进账号：请他到 `https://space.24haowan.com/app/bind` 领一个绑定码、存进记忆。被限流（429）就如实说，交文件即可。这里的「活页」是 space.24haowan.com，不是 WorkBuddy 自带的资料库页面。
4. **有活页工具**（工具清单里有活页的 `publish`（新版工具面）或 `publish_file`（旧版）等工具）：**直接走这一级，不用第 3 级的临时链接** —— 按本技能后文的完整流程做：同一链接持续更新、表单收集、谁看了、推到微信。

无论哪一级：链接、口令、人数、阅读数据只说工具真实返回的；没有就说「还没有」，不编、不估。

## 一、排版要点（公众号长文经验）

1. **头部**：标题（≤ 30 字，一行半以内最好）→ 一行作者 · 日期（· 来源 / 栏目）→ 导语（2–3 行，浅底色块或左边一条强调色竖线），读者在群里点开，先看导语决定读不读。
2. **正文**：字号 16–17px、行高 1.75–1.9、段间距 1em 以上、左右留白 16–20px，两端对齐；一段不超过 5 行，长段拆开；**不首行缩进**（手机长文的习惯）。正文最大宽度 680px，电脑上打开居中不铺满。
3. **小标题**：每 3–6 段一个，用「一、二、三」或强调色短竖线 + 加粗；长文顶部可放一个目录（小标题锚点），读者点了直达。
4. **引用与重点**：引用用浅底色块 + 左竖线；金句单独一段居中加大；加粗只给真正要点，一屏不超过两处。
5. **图片**：宽度 100%、圆角 4–8px，下面一行灰色小字图片说明（居中、13–14px）；图片放在相关段落之后，不连放超过 3 张；每张图压到 1600px 宽以内、单张 ≤ 500 KB，手机流量打开不卡。
6. **文末**：一条分隔线 → 作者一句话 / 联系方式（使用者给的）→ 互动区：**点赞**（显示「N 人觉得不错」）、**留言**（称呼 + 留言）、需要时加**报名表单**（活动回顾后接下一场报名）。
7. **风格**：白底、一种强调色（跟着文章气质：游记用绿或蓝、内刊用品牌色、活动回顾用暖色），全篇只用一种强调色；字体用系统字体，不引外部字体。
8. **从 Markdown / Word 过来**：`#` 是标题、`##` 是小标题、`>` 是引用、`![说明](图片)` 的说明写成图片说明；Word 的标题样式按层级对应，表格转成手机可横滑的表格，脚注挪到文末「注」。原稿里的空行、全角空格缩进、多余的换行清理掉。

## 二、交付（无论有没有工具都要完成）

1. 写一份单文件 HTML（`文章-<标题前几个字>.html`）：`<meta name="viewport" content="width=device-width,initial-scale=1">`，`<title>` 写文章标题，样式写在 `<style>` 里，不引外部字体 / 脚本；使用者给了图片就用相对路径（如 `img/01.jpg`）并提醒和 HTML 放进同一文件夹；脚本不跑时正文照样完整。
2. 文末的点赞、留言在本地预览时只存在 `localStorage`，并显示一行「本地预览：点赞和留言只存在这台设备上，发布成链接后才是大家共享的」；报名用普通 `<form>`，本地提交只提示「已收到（预览）—— 发布后才会真正收集」，**不把数据发到任何地址**。
3. 回复使用者：文件名 → 三行摘要（标题、字数与小标题数、配图几张）→ 你动过哪些地方（分段、加的小标题，改了字的逐条列出）→ 待补的【待定】项（缺的图、作者署名）→ 一句「要不要发成微信里能转发、以后还能改的链接」。

到这里这一轮已经完成，使用者不要求发布就不发布。

## 三、发成微信链接与分享卡片（有活页工具时）

- **上传走哪条路**：只有一份 HTML、没有图片（文字文件合计 ≤ 2 MB）⇒ `publish_file`；带图片 ⇒ 有终端用 space-cli（先 `create_cli_token`），没终端或拿不准用 `create_upload_link`，把 HTML 和 `img/` 整个目录一起传。未确认对外就带 `hold: true` 先给预览。
- **分享卡片**：写在 `manifest.share`：`title` 用文章标题，`desc` 用导语第一句，`cover` 用题图（包内相对路径）。卡片是读者在群里先看到的东西，发之前把卡片三样给使用者确认。
- **Markdown 也能直接发**：使用者只要「能看」、不在意版式时，`.md` 原样发也是手机版式；要公众号那种排版就发 HTML。
- **可见性**：先问给谁看 —— 几个朋友 / 一个群用 `passcode`，把链接和口令一起交给使用者；想让任何拿到链接的人都能看才切 `public`，**由使用者明确说**，切之前问一句。
- **交出去**：把工具返回的链接原样给使用者，由他发群、发给朋友；在电脑上的使用者，告诉他扫回执里的 `push_qr_url` 就能把文章送进自己的微信再转发；要推到自己微信看一眼用 `push_to_wechat`（默认只推给本人）。

**判据**：手机微信里点开排版正常（字号、图片、图片说明、小标题）；转发出去的卡片标题、摘要、封面对；几分钟后 `get_engagement_summary` 出现这次打开。

### 文末互动（要时再加）

- **报名**：`set_form` 定义字段（称呼、人数、联系方式等，按使用者点名的），`title` 写「报名」；平台在文章下方渲染成手机上能填的表单，提交的行用 `list_data_rows` 读回。
- **点赞与留言**：用挂在这页上的数据表。`set_data` 建两张表（新建 `revision` 传 0）：`likes`（列 `n`）与 `comments`（列 `name`、`text`），没有底数据就传 `rows: []` 加 `columns`，**同时传 `append_open: true`**；页面里 `fetch('./_data/comments.json')` 取已有留言（行对象数组）、`fetch('./_data/comments', {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({name, text})})` 追加一条；点赞同理往 `likes` 追加一行，页面按行数显示「N 人觉得不错」，读回的行里当前设备自己交的带 `_mine: true`，据此把按钮变成「已赞」、不重复点。出错时按返回的 `error.code` 给人话：`append_closed` 写「留言已关闭」，`append_rate_limited` 写「太频繁，稍后再试」，不要假装成功。
- **照实告诉使用者的规则**：写回默认关、按表开；每张表每小时最多 600 行、每台设备每小时 30 行，每行 ≤ 2000 字、单格 ≤ 500 字，每表最多 5000 行。**留言先过审**：过审的别人刷新即见，审核中的只有留言的那台设备和作者看得到（行上 `_status` 为 `held`）；审核暂时不可用时直接拒收。写回不识别人：一行只记设备和时间，换个名字也能再留，不是实名。作者想关掉留言就 `set_data` 只传 `append_open: false`（只翻开关，留言保留）。
- **只想自己收意见、不在页面上展示**：不用建表，读者在页面上留的反馈用 `list_feedback` 读回。

## 四、发错字同一链接改、读回多少人读、读到哪

- **改文章**：改 HTML 后用 `publish_file`（或同一条上传路）带同一个 `proposal_id` 发新版，**链接不变、点赞留言报名都保留**；错字这种小改带 `quiet: true`，不打扰订阅的人。改了什么在回复里逐条列给使用者。改坏了要回到上一版：`list_versions` 找到它，使用者同意后 `publish_version` 切回去。
- **连载 / 系列文章**：一篇一页，放进同一个合集（`create_folder` 建一次，每篇用 `move_proposal` 放进去；合集要设了可见性才发得出去）；`set_publish_notify` 传 `folder_id` 拿合集的订阅码，读者微信扫一下就能在合集有新文章时收到提醒（每个订阅一天最多一次）。这是活页的提醒，不是公众号关注。
- **多少人读**：`get_engagement_summary` 读回最近 N 天多少台设备打开过、停留多久、有没有被转发的迹象；先看它返回的证据等级（none / thin / usable），不够就说「数据还太少」。**设备不等于人，打开不等于读完。**
- **读到哪**：`list_sessions` 列出每次访问（设备、开始时间、时长、来源）；某一次读到哪用 `get_session_timeline` 看那次访问的滚动与停留时间线，照实说「这次访问滚到了『三、……』那一节附近、停了 X 分钟」，不把一次说成全部、不算没读回的平均数。
- **留言与报名**：`list_data_rows` 读回留言、点赞、报名的行（最新在前，带 `since` 只看新的），整理给使用者；`held` 的留言单独列出，由他决定放行还是删（`set_data_row_status`）。想守着等新留言就用 `wait_for_feedback`。

## 五、纪律

- 链接、口令、打开数、停留时长、留言条数只说工具真实返回的；没有数据就说读不到，不估阅读量、不编「10 万+」。
- 不说「已发布到公众号」「已推送给粉丝」—— 这里没有公众号。停在「已上传」「待确认」「仅自己可见」任何一步，都不能说成「文章已发出」。
- 对外的时刻（放开可见性、把链接发出去、改卡片）先征得使用者确认。
- 文字是使用者的：不擅自改观点、不加没说过的事实；留言和报名信息只给使用者本人看。

参考：24好玩做过的活动案例 `https://www.24haowan.com/cases`、模板库 `https://www.24haowan.com/games`、定制 `https://www.24haowan.com/custom`、活页模板市场 `https://space.24haowan.com/examples`。

## 附录 · 工具名对照：连的是新版（v2）活页工具时

**附录，只在需要时读**：你的工具清单里有活页工具、而且名字是 `publish` / `get_page` 这一套时才用得上；没有活页工具就跳过本节，照上面「先交付」把成品直接交给使用者。

活页 MCP 有新旧两套工具名，能力完全一样。**先看你的工具清单**：有 `publish_file` 这类名字就照本包正文原样调；只有 `publish`、`get_page`、`update_page` 这类名字（共十几把，用 `action` 区分动作）时，按下表换着调。两处参数统一改名：`proposal_id` 叫 `page_id`，`manifest` 叫 `page`；其余参数不变。

| 正文里的工具 | 新版怎么调 |
| --- | --- |
| `publish_file` | `publish`，action=`file` |
| `create_cli_token` | `publish`，action=`cli_token` |
| `create_upload_link` | `publish`，action=`upload_link` |
| `push_to_wechat` | `notify`，action=`push` |
| `get_engagement_summary` | `insights`，action=`summary` |
| `set_form` | `update_page`，`forms: { <表名>: 其余参数 }` |
| `list_data_rows` | `responses`，action=`rows` |
| `set_data` | `update_page`，其余参数放进 `data` |
| `list_feedback` | `responses`，action=`feedback` |
| `list_versions` | `get_page`，action=`versions` |
| `publish_version` | `release`，action=`publish` |
| `create_folder` | `workspace`，action=`create_folder`，原来的参数放进 `args` |
| `move_proposal` | `update_page`，`folder` = 原来的 `folder_id`（null = 移出文件夹） |
| `set_publish_notify` | `notify`，action=`settings` |
| `list_sessions` | `insights`，action=`sessions` |
| `get_session_timeline` | `insights`，action=`timeline` |
| `set_data_row_status` | `handle_response`，action=`row`，参数 `action` 改叫 `row_action` |
| `wait_for_feedback` | `responses`，action=`wait` |
