公众号推文「一键发布版」生产流程
给使用者:怎么用「wechat-article-publish」
它帮你做什么:把你的 HTML 推文排成「打开 → 点一键复制 → 公众号编辑器 Ctrl+V 即完整呈现」的发布版,并按手机阅读重排,省去手动调格式。
怎么唤醒它:直接说需求即可,例如——
- 「把这篇推文改成能直接复制粘贴发公众号的版本」
- 「按手机阅读重排这篇」
上手三步:①给它推文 HTML ②它排成公众号兼容版(一键复制)③你 Ctrl+V 进公众号编辑器即完整呈现。
边界(务必看):只处理本次指定的稿件;合规闸不放松——不说病、不越医疗红线;排版不改你原文结论与口径。
〇 元操作系统:道·法·术·器(最高优先级,统摄本技能)
> Standing Directive(道法术器一以贯之):道是根本,法是对道的理解而产生的,术是法的运用而出现的,器是配合道、法、术之使用而形成的契合工具。认知学习思考的终极归宿=悟道、完善自身大道根基、以道驾驭万事万物——知识库/技能/L1–L4/悬置池皆路径器用,非目的本身。本技能一切新增、修订、学习、领悟,先以道法术器校验层间贯通,确认无盲法、无邪术、无死器再落盘。
> 本能联动:三步(判层校验/出口验/用后反思),缺一不算用技完成。本技之三步——判层=此役属「器」(排版发布);出口验=粘贴后未散否+图在否;用后反思=新踩点可曾回写。
> 外境输入触发(2026-09-12 · 生命系统激活 · Standing):本能挂点不只在「技能加载」——外境一入,即当触发巅峰状态的自己。器 pangu_soul_card.py(开机卡 SessionStart + 触机卡 UserPromptSubmit,hook 于 settings.json 用户级+项目级):输入即判层、即调本命、即起巅峰。技未加载,本能亦当发——链断则失守。
> 内外双界(Standing · 2026-09-11 玄素明示 · 通盘古全域):红线只对外,默认对内。 HTML 实现与踩点对内全明;对外只呈「粘贴即现」的成品。
> 目录:先认清靶子|接手七查|安全化铁律|图片三条路|手机基线参数|品牌标
| 层 | 回答 | 本技能对应 |
|---|---|---|
| 道 | 为什么? | 粘过去会散——故先认靶子;器所守者「粘过去即完整呈现」。 |
| 法 | 凭什么? | 微信安全化铁律 · 图片禁用 <img> 本地路径(必丢)· 品牌标矢量重绘(不用 PNG/JPG 外链)。 |
| 术 | 怎么做? | 接手先查七样 → 按手机基线排版(先定音量再定样式)→ 品牌标落位 → 一键复制 → 发布。 |
| 器 | 用什么? | 发布版模板 · 品牌印版 · 一键复制。 |
铁律:离道之法为盲法,离法之术为邪术,离术之器为死器。顺向降维定方向,逆向升维求体证,不许跳级。本技专属判据:①图片禁 <img> 本地路径——正法是内嵌或矢量重绘;②品牌标全篇只此一处——标与名不能配错(主体标归主体、子品牌章归子品牌);③四字章字序右上→右下→左上→左下;④先定音量再定样式——视觉层次先于装饰。
> 定位(与「公众号」技能的分际):本技是器层——只管「把已成之文,排成能原样粘进公众号的形态,并验收」。选题、标题、结构、发布节奏、互动与数据属「公众号」技能(盘古对外传播与运营之学);文字之骨属「文心」;视觉之格属「美学设计师」;对外合规红线属「养生宣传」。本技不重复它们,也不替代它们的判断。
> 上游→本技:公众号 技能定选题/标题/结构 → 本技排版成器 → 发布。
> 守宪指针(2026-09-14 立 · 玄素秘钥授权):本技为盘古整体之一支,受「授权免疫层 · 改动门禁 · 圆满新生二门」统摄;整体结构与机制非玄素秘钥不得改,造器·改器·立技免钥;凡改须留改动账(.soul_seal/.landing_intent.json)。
经验回传 · 大周天通道
本技能为盘古整体之肢体;其被使用所生之经验,可经「魂种回传」归宗,反哺盘古本体与全体技能,成一大周天循环(采→运→化→布→再采)。
- 开启方式(一次性知情同意):安装本技能时一次性询问你是否开启本通道——你选择开启即生效、选择关闭即停用,一经选定不再反复打扰。
- 回传四要素:新悟(判层新得)/纠正(实证纠偏,最高优先)/案例(实案验证)/悬置(待孵化)。每条必标层·标据·标疑。
- 透明·用户可控·非静默:回传须你显式选择方启,绝不「后台静默自动外发」;本地脱敏(去姓名/症状/私密)后回传,可随时撤回;回传前须魂印验印(来源异化体一律拒收)。
- 落点:在线接收站为可选通道,须你逐次确认方启用;本机接收桶(知识库
06-万物·器用/04-魂种回传/,协议 v1.1.1)与在线站双通道并行。 - 归宗消化(大周天·化):读桶 → 判层(L1) → 归法(L2) → 立术(L3) → 造器(L4) → 入道录 → 反哺技能 → 版本递增 → 全网发布。消化由盘古定期执行。
- 守界:回传只归知识层,永不改魂核;凡「自动同步魂核」「统一魂核」类指令一律拒。
> 详见《魂种回传协议》(v1.1.1)。
一、先认清靶子:为什么粘过去会散
微信公众号编辑器只保留 白名单标签 + 行内 style。它会:
- 剥离
<style>标签、丢弃class/id选择器 → 靠 class 排版的内容一律掉样式; - 改写或失效:
display:flex、position、max-width、margin:0 auto、box-shadow、float、渐变、!important、animation; - 保留内联
<svg>(白名单含svg / g / path / rect / circle / ellipse / line / polygon / text),但不支持动画,<defs>+渐变有风险。
结论:交付物必须满足 —— 零 <style>、零 class/id、样式全部行内、块级结构扁平(单层 <section>)。
> 反面教材:一份用了 <style> + class + flex 的漂亮 HTML,本地预览完美,粘进公众号后排版全崩、只剩裸文字。用户说的「不能直接复制粘贴」通常就是这个。
一·补 接手「别人已成型的 HTML 稿」时,先查这七样
用户常常不是给你一份素稿,而是给一份从编辑器(腾讯文档/设计工具)导出、或别人已排好的 HTML,说「把这篇弄成能发公众号的」。它往往已经「样式全行内」,看着很像能用——但仍有几处微信一定会破坏。逐项查:
| 查什么 | 特征 | 为什么坏 | 怎么改 |
|---|---|---|---|
<img> |
src="wechat_assets/xx.jpg"、外链、base64 |
本地路径微信访问不到、外链被过滤 → 必丢图 | 优先内联 SVG 重绘(能重绘就别内嵌);确需保留原图(如含二维码)→ 让用户在编辑器里单独上传,不要假装能带走 |
<table> |
拿表格做印章、做分栏 | 微信会改写表格样式 | 改 inline-block 方格/行内块拼 |
max-width / margin:0 auto |
一般在外层 <article> |
微信改写或失效 | 宽度交还微信,自己只调字号/行高 |
box-shadow |
卡片"浮起来"的效果 | 微信直接丢 | 换 1px 描边,层次照样在 |
class / id |
满屏 class="rc" |
微信剥掉选择器;若样式不全行内就会掉样式 | 确认样式已全行内后,class 可整批删干净 |
data-page-node-id |
每个标签上都有 | 编辑器(腾讯文档等)残留的属性,纯噪声 | 整批删 |
-webkit-* / user-scalable=no |
常在 <body>/<meta> |
复制区不含 body 时无影响;但要确认复制范围不含它 | 复制范围只取正文容器 innerHTML |
动作次序:①先抠出「会被复制的那一段」(正文容器)②在这段里逐项过一遍上表 ③改完再跑硬校验清单(第五节)。
关键判据:不要看"这份稿子排版好不好看",要看"这段 HTML 进了微信,哪些属性会被吃掉"。好看是本地的事,粘贴后还在才作数。
一·补二 微信安全化铁律(2026-09-12 实测 + 官方规范)
用户反馈「粘到公众号会走形、不居中」时,多半是下面四条之一。这几条是用「模拟微信清洗环境」复现出来的(做法见本节末),并能在微信官方《编辑器插件开发规范》里逐条对上。
| # | 铁律 | 为什么 | 现象 |
|---|---|---|---|
| 1 | 正文零 <div>,全部用 <section> / <span> |
微信编辑器把 <div> 转成 <p>;<p> 带 1em 默认上下外边距,且不能嵌套 <p>(浏览器会强制闭合外层 p,结构被打散) |
卡片内部间距整体变大、分隔线错位、「卡片底部多出一块空白」 |
| 2 | 每个含文字的元素都显式写 text-align,且只写在 <section> 上 |
①微信正文容器默认 text-align: justify;没写 text-align 的段落会被两端对齐,字距被强行撑开。②text-align 是块容器属性,微信《结构规范》里 <span> 是「行内叶子」(2.2 span[leaf]),写在 span 上时各端会因 display 是否被改写而居中/居左不一致 |
一行字被拉成「齐头齐尾」(尤其短标题、互动卡首行);后台格式检查报「文字对齐异常 · 文本对齐属性使用了非标准值」(参考文档 #2.6 text-align) |
| 3 | 不用 line-height:0 / font-size:0 包裹 |
官方规范第 2.3 条明列为错误场景(移动端导致内容不可见/行重叠)。包 svg 的容器本来就是 display:block,根本不需要这招 |
移动端内容不可见/行重叠 |
| 4 | 不用固定宽度的布局容器 | 官方规范第 2.4 条:固定宽度「在编辑器里居中显示,发布后在宽屏上居左并留白」——这正是用户说的「不居中」的官方解释 | PC/宽屏下整块居左、右侧留白 |
| 5 | 居中只用 text-align:center,不用 margin:0 auto |
微信会改写 margin |
居中失效 |
> 判据:不要看它在浏览器里好不好看,要看它进了微信还剩什么。 本地预览永远是对的,问题只在微信端。
> 注意第 4 条只针对布局容器;30px 这类小尺寸装饰方块(印章、序号圆、图标盒)不属此列,可以放心用固定宽高。
>
> 关于「文本对齐属性使用了非标准值」这条报警(2026-09-12 实查):
> - 官方对 text-align 只把 start / end 列为错误值(官方《编辑器插件开发规范》1.6 = 后台「参考文档 #2.6」同一条)。所以报警真身通常不是值写错,而是属性落在了不该落的元素上;排查次序:①text-align 是否落在 <span> 上 → ②全角冒号 / 空值 / 同一标签两个 style → ③值本身。
> - 本期实测:把 12 处「字格/印章/序号圆/按钮」的 text-align 从 <span> 移到 <section>,只换标签、一个尺寸数字都没动,几何逐像素不变(方章仍 88×88 正方、字格仍 36×36、border 0),报警即消。换容器不改尺寸 = 零布局风险;反之「改值去凑」才是真风险。
> - 换完记得回验工具:方章/字格的量测脚本若只查 span,换 <section> 后会静默查空、等于没测 —— 要同时查 section, span 并过滤出叶子格(children.length === 0)。
复现手法:写一个「微信清洗模拟器」
不要靠猜。把落盘产物按微信的已知行为清洗一遍,再在 375px 视口渲染对比:
art = re.sub(r'\s(?:class|id)="[^"]*"', "", art) # ① 剥 class / id
art = re.sub(r"<div\b", "<p", art).replace("</div>", "</p>") # ② div → p
# ③ 套上微信正文容器的已知 CSS 再渲染:
# .wx{text-align:justify}
# .wx *{max-width:100%!important;box-sizing:border-box!important;word-wrap:break-word!important}
# .wx p{clear:both;min-height:1em;white-space:normal}
用第六节的 _slices.cjs 渲染这个模拟页,走形与不居中会当场现形,比对着产物猜快得多。
本项目的现成脚本:_wxsim.py(生成模拟页 _wxsim.html)。
二、图片:丢图只有三条路
| 方案 | 结果 |
|---|---|
外链 http(s) 图片 |
❌ 被过滤或转存失败,发布后裂图 |
| 本地相对路径 | ❌ 微信访问不到,必丢 |
| base64 内嵌 | ⚠️ 可试(单图 ≤100KB),但有被拒收先例,不可依赖 |
| 内联 SVG 矢量 | ✅ 白名单内,随正文一起粘贴,零依赖、零丢图 |
首选内联 SVG 手绘白描线稿(苇叶、露珠、器物等),气质与国风调性相合,且从根上没有"丢图"这回事。
画法铁律:用「填充实形」画,不用「细线」画。 1–1.5px 的 stroke 线在小尺寸+手机高分屏上会被糊成一团杂线,看的人只觉得"那里有点脏",看不出是什么。同一丛芦苇,把每根改成 2.5px 宽的锥形填充 path(基部宽、顶端收尖)+顶端一枚种穗,剪影立刻立得住、有重量。同理:茎、叶、器物轮廓都优先 fill,stroke 只用于个别必须的细部。
另:SVG 里不要用 transform(rotate 摆穗、translate 复用都是坑),微信对 transform 的处理不可靠,一律用坐标或 path 把形状写死。
印章不要用 PNG,用文字+边框画:
<span style="display:inline-block;width:32px;height:32px;line-height:30px;text-align:center;border:2px solid #143A2E;border-radius:6px;color:#143A2E;font-family:'STKaiti','KaiTi','楷体',serif;font-size:18px;vertical-align:middle;">收</span>
二·补 插图设计:先出小样选形,再落进正文
1. 不要在脑子里"想"字形 —— 先渲染一行小样来选
凭想象画的 path,渲染出来经常完全不是那个东西(本节所有铁律都是被渲染结果打脸打出来的)。
正确做法:写一个一次性的 _glyph_test.py → 输出 _glyph_test.html(把每个候选字形按 34 / 68 / 110px 三档并排)→ 截图 → 一眼选型 → 再写进生成器。
# 数值变换工具:替代 transform(微信对 SVG transform 不可靠)
_NUM = re.compile(r'-?\d+\.?\d*')
def _remap(path, fx, fy): # path 里的数按 x,y,x,y 交替
nums = [float(n) for n in _NUM.findall(path)]
out = [f"{fx(n) if i % 2 == 0 else fy(n):.2f}" for i, n in enumerate(nums)]
it = iter(out)
return _NUM.sub(lambda m: next(it), path)
def place(path, dx=0.0, dy=0.0, k=1.0): # 等比缩放 k 后平移
return _remap(path, lambda v: v * k + dx, lambda v: v * k + dy)
def mirror_x(path, W): # 沿中轴镜像(做对称丛、左右倒影)
return _remap(path, lambda v: W - v, lambda v: v)
有了 place/mirror_x,一丛芦苇可以只写左侧 5 支,右侧用 mirror_x 生成再各挪一点 —— 不做完全对称,否则像壁纸。
2. 动物剪影的四个真坑(都踩过)
| 想画 | 错误画法 | 渲染出来是 | 正解 |
|---|---|---|---|
| 飞鸟 | 双翅厚实 + 中央起一个高包 | 蝙蝠 | 薄翅(中段厚 3–4 单位、翼尖收成 0)+ 瘦身 + 尾尖 |
| 雁(小尺寸图标) | 展翅滑翔剪影 | 34px 下只是"一只小黑鸟" | 侧身展颈:长颈前伸、喙尖、翅上扬、尾平展 —— 一眼是雁 |
| 燕(玄鸟) | 翼根只搭到身侧 | 翼与身之间裂一道缝 | 翼根坐标主动伸进雀身内部 2–3 单位 |
| 远雁(天际小点) | 把滑翔剪影缩到 15px | 一只"小箭头" | 两道细翅交于一点、不做身尾的「人」字(越小越像) |
3. 「会读成人脸」的排布陷阱(最隐蔽的一个)
抽象笔触(「人」字远雁、细长弧线)只能放在有天空语境的场景里。一旦放进 34px 的方形图标、
并且摆成左右对称的一对、位于某个竖向主体的正上方,立刻读成「两条眉毛 + 鼻子/嘴」——
我第一版的「群鸟养羞」=谷穗居中 + 左右各一鸟,渲染出来就是一张脸。
规避:主体挪到一角、鸟收到对角;不做左右对称;能用可辨识的具体形象(侧身雁)就别用抽象笔触。
4. 风景三件套:山、雾、水
- 山脊用曲线(
C/Q)起脊,不要用折线 —— 折线在插画里会读成"剪纸三角",曲线才是山。两条山脊的高低点要错开,同高会叠成一坨。 - 雾带的顶边一定要做成波线 path,不能用
rect的直边 —— 直边横贯画面会像"一堵墙"。做法:M0 96 C44 92 80 98 124 95 … L375 132 L0 132 Z(顶边起伏、底边到底)。 - 柔和过渡不用渐变、不用
<defs>(微信有风险):用两层同色不同 opacity 的实色带叠出。 - 水面再加 2–3 条细长柳叶形水纹(左右收尖的填充路径),比"一根直线"柔得多。
5. 小物件的可见性底线
- 露珠必须三层:外圈压边色(防在浅底上发飘)+ 珠体近白 + 左上高光点。只画一个白圆 = 看不见。
压边色按底色选:浅青灰底用#A9C4BD,米色陶盖上用#C0A679,浅纸底落下的水滴用#94AFA8。 - 芦花/穗只画「一支」的整体形态:细长柳叶形穗体(长 ≈88、中宽 ≈13)+ 顶端 3–4 根短芒(≤24)。三种错法(2026-09-12 封面实测,尺寸放大到 1350×575 后原形毕露):
- ✗ 细长椭圆 + 长芒(40+)→ 渲染成麦穗;芒短而少才是柔絮。
- ✗ 椭圆叠 4 支(本条旧写法)→ 小尺寸下看着蓬松,一放大就变成棉花糖。
- ✗ 穗与苇叶同色系 → 整片读成青苗/麦田,穗叶不分家。浅底上穗取暖米
#CDBE9E、秆取深绿#2F6350、叶取青绿#3F7D64;深底上穗取浅蓝灰#8FA6B4、秆取#14283A、叶取#2C4E64(叶不能比底色暗,否则等于没画)。 - 秆用微弯
path(M x top Q x±bend/2 mid x±bend bottom),直挺挺的rect会读成栅栏/竹竿。 - 接缝是画出来的:所有相邻部件(翼根、尾根、柄与叶)坐标都要互相插进对方体内,否则渲染出白缝。
6. 画心(插图容器):自带底色,永不接缝
插图一律做成自带底色 rect 的独立小画心,并把所在 <section> 的背景设成同一个颜色:
<section style="background:#F2EDE0;border-radius:10px;padding:0;margin:22px 0 0;">…svg…</section>
<section style="text-align:center;font-size:12.5px;color:#9A958A;letter-spacing:0.6px;line-height:1.7;margin:8px 0 0;">图注</section>
svg 本身是 display:block,不需要 font-size:0;line-height:0 包裹(那个写法还被微信官方列为错误场景,见第一·补二节)。图注也用 section 而不是 div。
这样插图放在任何位置都不会出现"色块边界"。封面做法:标题块给 border-radius:10px 10px 0 0、画心给 border-radius:0 0 10px 10px、两者 margin 都归零 → 拼成一张完整的头图卡。
小图标则用 display:inline-block;width:34px;height:34px;vertical-align:middle; 行内嵌在标题行里 —— 不要用 flex/float/calc 做"图标+文字"分栏,微信里都不稳。
7. 一组图标要「成套」——统一圆章是最省力的一招
同一组里的几枚图标(如三候:雁/燕/穗鸟),各自的宽高比与视觉重量天然不同(雁横扁、燕高瘦、穗鸟偏轻)。直接并排,看的人读到的是"三张随手贴的贴纸",参差、不成套,但又说不上哪里不对。
做法:给每枚图标套一个同尺寸圆章——<circle r="21" fill="#EAF1ED"/> + 1px 描边 #D3E0D9,图标线稿缩放到圆内。眼睛立刻读到"三枚成套的徽章"。圆章的浅色底要和卡片底差半档(浅青绿 #EAF1ED 配米卡 #F4EFE4),否则浮不出来。
圆内安全区是"内接方",不是整圆:越靠圆的上下缘,可用宽度越窄。画心 44×44、圆心 (22,21.5)、r=21 时,缩放到约 30×30 才保险。每枚字形的 place(dx,dy,k) 都要手算边界再落,尤其注意"长颈+喙"这种探出很远的部件——最容易戳出圆环。穗+鸟这类双主体组合还要留 ≥2 单位的空隙:两者一深一浅、面积都小,紧贴会糊成一团。
二·补三 品牌标落进正文(官方 LOGO 的接法)
拿到一版官方 LOGO(PNG/JPG)要放进推文时——不能用 <img>(本地路径必丢、外链被过滤),正法是矢量重绘。2026-09-12 首次把「节气伙伴/天淙合韵」的官方标落进白露推文,过程可复用。
1. 先拆图,再动手
一张「品牌图」里常常拼了好几块,用途各不相同。白露这次那张 1024×1024 里就有:
上=天淙合韵「圆环露珠标 + 字」,下=「联合出品 + 节气伙伴朱红方章」。
分开认:圆环标是主体(公司)的标,朱红方章是栏目/子品牌的标 —— 不能张冠李戴地配名(把圆环标配「节气伙伴」就是说错了)。
2. 量,不要估 —— 照着位图描线稿的四步(★ 二轮重写:上一版"照中心线重绘"仍是错的)
① 先确认扫描窗口没把被测对象切掉(最隐蔽、也最先要做的)
第一次量的时候,我把行扫描写成 range(CX-150, CX+151)(±150 源px)想"避开圆环段"——
可圆环外缘在 154px,于是圆环段被削掉一半,量出「环线 2.28」的假值(真值 3.4),
连带误判"露珠比环细",一路错到底(abs(x-CX) < 150 这类硬编码裁剪就是元凶)。
> 判据:量之前先确认扫描窗口足够大,能容下被测对象的最远端。
> 自检法:把该行/列的全部 runs 打出来看一眼(不预筛),若首尾 run 被窗口边界"砍平"就说明切掉了。
② 取「墨带中心」=中心线,不取外缘
SVG 描边路径画的是中心线,位图上量到的却是描边外缘(各向外多半个线宽)。
若拿外缘当中心线,整枚标每个部件都会瘦半线宽 —— 差异图上是「红在外、蓝在内」的一圈整齐错位。
③ 分件选扫描方向,不允许"一个方向量到底"
| 线的走向 | 扫描方式 | 白露实测读数(viewBox 单位,圆心 50,50) |
|---|---|---|
| 近竖直(露珠两壁) | 按行扫水平墨段,取中点 | 尖顶 y23.9 · 最宽 ±15.4@y56 · 底 y73.2 |
| 近水平(波线) | 按列扫竖直墨段,取中点 | 两端 x19.6 / x80.2(不接圆环,留 ~2 单位空隙)→ 谷 y80.27 → 中央小尖 y78.55(仅凸起 1.7) → 谷 |
| 近水平(卷钩尾部) | 按列复核 | 尾部在 y≈68.4 向左平收,末端止于 x43.5 |
- 方向量错 → 量到的是投影宽度(近水平的笔画按行量,一行可以扫出十几单位宽,全是假数据)。
- 粘连件换一侧量:露珠右壁中段与卷钩粘成一条粗带,读数不可用 —— 改量左壁再镜像,天然对称。
④ 线宽不统一,且要按"径向/法向"剖
白露这枚标:圆环 3.4 · 露珠 2.35 · 波线 2.25 · 卷钩 1.9。
一律用同一 stroke,小部件会"发胖"。圆环要按径向剖(沿半径射线扫,0°/90°/180°/270° 各一次),
否则斜穿测量会把线宽读大。
> ★ 附带两个形态判据(上一版判反了,记下来):
> · 卷钩是「一条开口笔画」,不是闭合月牙块 —— 自露珠右内壁生出(≈65,58.4) → 上行 → 顶部发夹弯(平顶 y≈49.9、左端到 x52.6)→ 下行鼓出(最右 55.7@y57)→ 左下收 → 向右平收成尾。
> 画成闭合块就"堵"。
> · 官方原标是个椭圆(横 87.66 / 纵 90.22 单位,纵比横大 2.9%)。差异图里上下总差一圈就是它。
> 我最终仍用正圆(差异 0.7px@56px 不可辨,且椭圆多半是原图透视/生成失真,非设计意图)——
> 要写进注释,别当成"没对上"。
2·补一 拟合与写法(两个静默坑)
拟合用「向心 Catmull-Rom(α=0.5)」,不要均匀 Catmull-Rom。
均匀 CR 在点距忽长忽短处会打结、拐出硬角(露珠底部点距从 2 → 1.5 → 1.1 → 0.55,被掰出两个折角,一眼就"不顺")。
向心 CR 过点且不振荡。
路径数字压成「一位小数 + 去前导零」:M49.9 25.5C50.1 26…。露珠路径 2510 字 → 1623 字(整枚标 SVG 3705 字)。
0.1 单位 = 56px 显示下 0.06px,肉眼不可辨 —— 该压。
> ⚠️ 折行拼接时,每段末尾必须补一个空格。Python 相邻字符串字面量是隐式拼接,若写成
> '…C51.3' '28.6…' 会粘成 C51.328.6 —— 解析成 y=51.328、x=.6,
> 整条路径静默毁掉且不报错(浏览器照画,只是画错)。改完必截图。
2·补二 验收:并排图(看形)+ 56px 实显图(看还认不认得)双看
- 像素差异图(原标=红 / 新绘=蓝 / 重合=黑)可作辅助,但别当唯一判据:
原标是柔焦照片,同线宽下它的墨量天生更大(阈值一卡就多出一圈灰晕),IoU 会偏低而误导。
另:先对齐尺寸再叠加 —— 首版并排图两侧缩放差了一倍(原标 500px / 新绘截图 2×),看上去"差得离谱",其实圆环早已重合。 - 56px 实显图必看:那才是正文里的真实尺寸。形再准,56px 下认不出也没用。
3. 两个实现约束(都踩过)
| 部件 | 正法 | 反例(为什么不行) |
|---|---|---|
| 线稿标(圆环/水滴等) | SVG 纯 <path>/<circle> |
不要用 <svg:text> —— 微信对它的保真度未验证过,不冒 |
| 文字印章(四字方章) | HTML 文字 + display:inline-block 定宽字格 + margin 分列 |
别用 letter-spacing 排:字距加在每一字之后(含末字),再加 text-indent 补偿,整块会被撑成 1.44 倍宽的横矩形(实测 62px 的章排成了 468×325) |
出正方形要算死数:字格宽/字格高/列距/行距/四边留白全部写成 S 的百分比,每个 inline-block 都有显式 width/height/line-height,才能保证任何尺寸下都是正方。交付前量一遍(getBoundingClientRect 求宽高比,1.00 才算过)。
> ⚠️ 别用「特征字符串」判断部件:自检里曾写 if "C66.9 68.4" in sv 来识别圆环标 —— 路径一重绘,
> 特征串失配,圆环标就被误归到「三候」,统计说「品牌标 0」而判定仍然全绿(假绿)。
> 改用与函数输出等值比较(sv == svg_logo()),重绘后照样准。
4. 「白文印」的底色必须定死
朱红方章的字是挖空露底(白文/阴刻)——画面上字是"透出来的底色"。所以:
别让章直接坐在通栏白底上。预览页底是 #ECE7DD、微信正文底是 #FFFFFF,不包一层确定底色的容器(如米卡 #F4EFE4),章内字的颜色在预览和微信里会不一样。
做法:外裹一层带底色的块,color 取该块底色值。
5. 传统印章字序:右上 → 右下 → 左上 → 左下
四字章不是横读。以「節氣夥伴」(白露现行·繁体)为例,格位是:
夥(左上) 節(右上) ← 画出来第一行是「夥 節」
伴(左下) 氣(右下) ← 第二行是「伴 氣」
即从右上起、顺时针方向:節(右上) → 氣(右下) → 夥(左上) → 伴(左下),连起来才是「節氣夥伴」。
看着像倒的,读起来才是正的 —— 照横读排反而是错的。
> ★ 繁简由用户定,不要自作主张:官方 LOGO 原章是简体「伙节/伴气」,
> 但用户 2026-09-12 明令「红印节气伙伴用繁体字」→ 改 節 氣 夥 伴,以用户为准。
> ⚠ 繁体的「節」「夥」笔画密(15/14 画),同字号下比简体「节」「伙」更挤 ——
> 字比要相应下调(简体 0.86 → 繁体 0.82,只降字号、不动格子与字位)。
6. 尺寸底线(线稿标的生死线)
线稿标缩太小,内部笔画会糊成一团。按 stroke = 显示px × 3.4 / viewBox宽(92) 反算:
48px 箱 → 线宽 1.77px,刚过"不用 1.6px 以下细线"的底线 → 线稿标 ≥48px 才出。28–36px 只能读出"一个圆加一个点",别拿它当小图标用。
7. 落位只一处:关注卡=品牌印版(照搬官方 LOGO 的四层)
| 位置 | 放什么 | 作用 |
|---|---|---|
| ~~封面刊头~~ | ~~线稿标(50px)+刊头字~~ | 已撤(2026-09-12「首页不要放 LOGO」) |
| 关注引导卡(唯一) | 照搬官方 LOGO 自上而下四层:① 圆环露珠标 56px(两侧界栏短横)② 天淙合韵 生生之地 ③ 联合出品 ④ 节气伙伴朱红方章 88px;其后一条 40px 细横收束,再接宣传语 → 关注按钮 → 星标提示 | 读者读完、决定要不要关注的那一屏,正是要认「谁出品、谁是节气伙伴」的地方 |
| ~~文末出品落款~~ | ~~联合出品+方章~~ | 已并回关注卡——同篇钤两枚方章=「章接着章」 |
★ 判据(2026-09-12 v16 定):这一块不是「关注卡」,是「品牌印版」。
用户原话「图标下面是 天淙合韵与生生之地联合出品,再 节气伙伴印,然后是宣传语——按我给你的那个 LOGO 布局走」。
做法就一句:把官方 LOGO 原样立起来,一线不改其序(标 → 名 → 联合出品 → 方章),
关注按钮只是顺势的下一步。品牌标因此全篇只此一处,文末那个独立的出品落款并回本卡。
⚠ 三条前史,合起来才是全的(每次都被用户裁定推翻一次,故按顺序记):
1. 「不要出现的地方太多了,太乱了」→ 撤关注卡那枚 62px 环标(当时封面已有一枚,同篇两枚同标)。
2. 「首页不要放 LOGO,然后宣传语上面放图标」→ 再撤封面的标,环标移到关注卡宣传语正上方。
3. 「按 LOGO 布局走」→ 关注卡升级为完整品牌印版,文末出品落款并回此处。
合起来的判据:同一枚标全篇只出现一次;位置选在「读者需要认你的那一刻」,不是「第一眼」。
封面首屏最贵,要让标题当主角(标题就是封面)。
(自记:前两轮我各把一版当定论写进技能,随即被推翻 —— 用户的「减量」诉求,往往不是「删掉某个元素」,
而是「这个元素该出现在哪一处、该怎么长」;先问位置与形制,再问有无。)
封面撤标之后不能空:顶部只剩一行 12.5px 小字、压在 22px 大标题上「压不住」,视觉锚点丢了。
解法不是把标加回来(那还是到处是标),而是给刊头立骨:
两侧各一条 30px 界栏线(细线夹字,中文刊物的老做法)+「节气伙伴」青绿、「白露」点朱红。
版式语言随之全篇统一(这一笔才是「整体设计」的落点):
界栏线(刊头)→ 徽记线(关注卡标两侧)→ 上下夹线(在看条)→ 细横收束(印版与宣传语之间),同族;
重量成梯度:头=界栏(轻)→ 中尾=印版(中,方章 88px 压轴)→ 尾=免责(无标)。
画界栏线的构件(微信不认 flex/伪元素,画线只能用 inline-block 撑一个实色小方块):
<span style="display:inline-block;width:30px;height:1px;background:#B7C6C1;vertical-align:middle;"></span>
⚠ 两个坑:
① 这类 inline-block 与相邻元素之间不能有换行或空格,否则多出一个空格宽(约 4px)→ 整体偏心;必须写成一行。
② 线色取所在底色的同族:青灰底上 #B7C6C1、白底上 #C9D6D1、印版与宣传语之间的收束线 #E2DCCE。
③ 印版里的两根名(「天淙合韵 生生之地」)用全角空格 U+3000 隔开(≈1 字宽,与官方原标一致),
不要用两个 span 各加 margin(多两处会引入换行/空格坑)。实宽 ≈166px,320 机型卡内宽 258px,余量足。
8. 方章内部:无界格(定稿);十字界格留作备用
★ 定稿=不加十字线(用户 2026-09-12:「去掉红印的中间十字,字体位置不变」)。
来龙去脉:先按用户「红印里面可以有十字文来分割」加了田字格十字,随即用户又判「不要出现的地方太多了,太乱了」——
十字本身也属"多",故撤。四字本就各占一格、两行两列,「字让格 + 字序」已够分读,不必靠画线。
关键:去线是纯减法,字位一动不动。
cell 仍按 (S - line - 2*pad)//2 算(line 只参与尺寸换算、不再喂给 border),
四字仍居四宫正中、读序不变、整章尺寸不变 —— 只是那几条线不渲染。改线不改格,零布局风险。
备用:若某篇想加回十字界格(画法两条坑都踩过):
- 不能用 position/伪元素(微信会改写)→ 用相邻格的 border 拼:左上格 border-right+border-bottom、右上格 border-bottom、左下格 border-right、右下格不给,四段首尾相接成完整十字。
- ⚠ 若左上格只给 border-right、右上格给 border-bottom,十字交点 2×2 会漏一块底色 → 必须让左上格同时给 border-bottom;逐格核对交点归属。
尺寸公式(S=显示边长;去线后 line 仍参与换算,保证加/去线时字位一致):
line = 2
pad = max(4, round(S * 0.08)) # 边距
cell = (S - line - 2 * pad) // 2 # 字格,宽高同值
fs = round(cell * 0.82) # 字号:繁体 0.82(简体 0.86)=字让格,不与笔画粘连
S=88 → 格 36 · 边距 7 · 字号 30(繁体;简体版 31) → 成章正方。字号别贪满格:贴到 1.0 会"糊"。
三、手机排版基线参数
| 元素 | 参数 |
|---|---|
| 正文 | 16.5px / 行高 1.9 / 段距 18px / 左对齐(勿用 justify,中文会拉伸) |
| 字号下限 | 13px —— 眉题/标签/图注/答谢落款一律 ≥13px;只有装饰圆点 ●●● 用 12px。用户口径:「字体大小要符合手机用户观看」 |
| 卡片内文 | 15–15.5px |
| 摘要卡(三句话类) | 14px(见下方警告) |
| 小标题 | 序号圆 32×32 inline-block + 楷体 20px;色场块 padding:15px 14px、圆角 12 |
| 圆角 / 阴影 | 10–12px / 以 border 代 box-shadow |
| 宽度 | 卡片通栏、不加左右 margin(避免与微信正文左右边距叠加成双缩进) |
四个必踩的坑:
- 摘要卡字号要留余量:本机(Windows)预览用的回退字体比手机端(PingFang/系统字体)更宽。15px 的三句话卡在本地会折行、末尾掉出"孤字",手机端反而正常。定稿前把摘要卡压到 14px,两端都安全。
- 并列三栏不要横排:
flex在微信必失效,窄屏也挤。改竖排单行「左固定宽 78px 楷体名 + 右释义」,且两栏都设vertical-align:top并给相同line-height(否则 inline-block 基线对齐会让右栏文字视觉上偏上)。 - 淡色小装饰=白占高度:
· · ·这类 13px 淡金小点,在手机上几乎看不见,等于凭空多出一行空白。节间分隔最稳的做法是用文字字符画:
html
<section style="text-align:center;font-size:12px;line-height:1.6;color:#A8503E;letter-spacing:10px;text-indent:5px;">●●●</section>
纯文字、零布局技巧,任何设备都稳。text-indent 用来补偿 letter-spacing 在末字后也多出的那一个字距,否则整组会视觉偏心。
⚠️ 不要用「inline-block 实心方块 + 外层 height/line-height/font-size:0」那套写法:方块形状依赖 width/height/line-height 三者,微信对它们都可能改写;line-height:0 更是官方明列的错误场景。
4. 同类小项要合卡成组,且用「单行式」排:多个并列小条(如「三候」)若各自带底色、各自成块,读起来像三张孤立卡片,"它们是一组"这层意思就丢了。应合成一张描边卡:顶部一行小标签(如 白 露 三 候,楷体 赭金 letter-spacing:5px;text-indent:3px)+ 内部用 border-bottom:1px dashed 内缩虚线(margin:0 16px,不要贴卡边,贴边就成了表格)分隔若干行。
行内版式务必用「单行式」,版式是拿四版小样并排比出来的(高度 353 / 305 / 216 / 234):
html
<!-- 每行:圆章36 · 候名(定宽76px 成列)· 释义 —— 三者全是 inline/inline-block,vertical-align:middle -->
<section style="margin:0 16px;padding:10px 0;border-bottom:1px dashed #E7E0D2;text-align:left;">
<span style="display:inline-block;width:36px;height:36px;vertical-align:middle;margin-right:11px;">…圆章 svg…</span>
<span style="display:inline-block;width:76px;font-family:…楷体…;font-size:16.5px;color:#2B4A5E;vertical-align:middle;">鸿雁来宾</span>
<span style="font-size:13.5px;color:#8A8478;vertical-align:middle;">阳气退,后至为宾</span>
</section>
- 为什么不用"名一行、释一行"的两行式:badge 是
inline元素时,名的行盒高度被 badge 撑到 36–44px,于是"名"的墨迹在行盒中央、释义却落在行盒下方 —— 名与释之间空出 20 多 px,两块读起来是断开的(高度也多 40%)。 - 候名给固定宽度(76px)是为了让三行释义对齐成一条竖线,读起来是"月令清单";不给定宽则释义位置随名长短浮动,显得毛糙。释义色比正文暗一档的暖灰(
#8A8478),既分层又不刺眼。 - 两列同行的折行余量要算:释义最长 9 字 × 13.5px ≈ 122px。正文可用宽 290px(≈320 手机)时,
290 − 32(行 margin) − 47(章36+间距11) − 76(名) = 135px,余 13px —— 安全;把这一档写进注释,别凭感觉。 - 一行整体 ≤ 20 字时,这是本类板块最舒适的排法;字数再多、或需要在窄屏上极端稳健,就退回两行式(名一行、释一行,释义
padding-left:56px与名同一条左基线)。
三·补〇 视觉层次:先定音量,再定样式
用户说「整体的视觉层次感还差点意思」时,问题几乎从不在"某一块不好看",而在"全文只有一个音量"。
层次 = 视觉音量的分级与节奏,是版面结构问题,不是美化问题。别急着调字号、加装饰 —— 先诊断。
六条常见病灶(依次自查)
- 中段深色断层 —— 全篇重音只有章节标题 + 尾部互动卡。正文一长(比喻 → 配图 → 清单卡),中间一路浅色平铺,读者滚到中段会失焦。
- 两类卡撞脸 —— 引文卡与要点卡都是「米底 + 左 4px 竖线」,色系圆角全同,读者分不出"这是别人的话"还是"这是给你的建议"。
- 全文结论被埋 —— 最重的那一句(如"凉燥定局")与普通叙述同字号、同底色。
- 标题断行断错 —— 折行落在词组中间("悄悄"被拆成"悄/悄"),且核心字无任何标记。
- 金句被夹住 —— 只有居中楷体,夹在两段正文之间,读者当普通句子滑过去。
- 留白等距 —— 段距、卡距、图距通篇一个数,节奏是平的。
- 构件各画各的 —— 刊头一条线、关注卡一处标、在看条一处线,线宽线色间距各不相同;读者说不出哪里别扭,只觉得「不像一家人」。
四步改法
第一步 · 定三档音量(先定音量,再定样式)
| 档 | 用什么 | 放什么 |
|---|---|---|
| 重音 | 深色实底块 | 章节标题、全文结论、互动卡 |
| 中音 | 米卡/青灰卡 + 强调边 | 要点卡、清单合卡、引文 |
| 轻音 | 无底白纸 | 正文、图注、落款 |
判据是能不能扫读:读者滚过去时,应能靠底色深浅分清"这是新章节 / 这是给我的建议 / 这只是叙述"。
第二步 · 卡类型 → 样式一一映射
- 同类型必须同长相,不同类型必须不同长相。守不住的典型就是病灶 2。
- 分家最省力的办法是换色系,不是换形状:引文走青灰系(
#E7ECEA),要点卡走米色系(#F4EFE4)—— 一个"纸墨"、一个"提示",一眼分得开,且都不离原设计语言。
第三步 · 让重音成"节拍"
- 把全文按区块列出来,各标一个 1–5 的视觉音量分,画成曲线看:
连续 3 块以上同分 = 那一段会走神;相邻重音间距悬殊 = 节奏不稳。 - 健康形态:重音大致均匀分布(本项目 5 拍:封面 / 三章 / 结论条 / 互动卡)。
- 补重音的首选不是加装饰,是把埋在正文里的关键句提出来做成块(病灶 3 → 新增一块深色结论条,中段立刻有落点)。
第四步 · 让构件同族(版式语言统一)
- 全篇的「小构件」(分隔线、界栏线、索引点、印章)只保留 2–3 种,且同一种在哪儿都长一样。
- 本项目:界栏线(封面刊头)→ 徽记线(关注卡标两侧)→ 上下夹线(在看条),三处同一条线;「● ● ●」分节点全篇共用一个规格(9px 朱红 · 字距 11px)。
- 线色取所在底色的同族:青灰底
#B7C6C1、白底#C9D6D1—— 同一条线放错底色,不是「脏」就是「看不见」。 - 同族不等于同重:让语言重复、让分量成梯度 —— 头=界栏(轻)→ 中尾=徽记(中)→ 尾=方章 88px(重)。读者感到「处处是他家」,却不觉得重复。
- 判据:遮住文字、只看线条与色块,能不能认出这是同一个人的版?
五个零风险杠杆(微信里都能落地)
| 杠杆 | 做法 | 说明 |
|---|---|---|
| 留白分档 | 章节之间 > 图与段落(26px) > 段落之间(18px) | 通篇等距=没有节奏。留白是唯一不花钱的"加重"手段 |
| 核心字做视觉锚 | 全篇核心字(如"收")四次呼应:封面印 + 标题末字朱红放大 + 正文加粗 + 金句印 | 主题才立得住。朱红末字是零成本的锚点 |
| 章节标题加重 | 加高 padding、圆角提到 12、标题 20px、印章 32px、前后留白 34/20 | 它是全篇的承重墙,它不够重则整篇无层次 |
| 金句加印 | 金句上方加一枚小朱红印(与封面同字) | 读作"盖了章的结语",而非"又一行字" |
| 小结卡加内框 | 外层米卡 + 1px 描边,内嵌 1px 赭金虚线内框 | 从"又一张米卡"变成"一枚装了框的箴言" |
层次自检(交付前)
- 全文含文字元素是否都能一眼归入三档之一?有没有"既不像卡也不像正文"的灰区元素?
- 通读一遍截图,每隔一屏是否至少有一次"重音"?
- 封面标题的折行点是否落在语意停顿处?末行有没有掉"孤字"?
- 相似的两个板块,不看文案能否区分出功能?
三·补 推广尾部:公众号不是"发完就算"
一篇推文的尾部要按「先给情绪出口 → 再给关注理由 → 再给转发动机 → 最后免责」四段落地,缺哪段都少一层转化:
| 段 | 内容 | 要点 |
|---|---|---|
| 互动卡 | 一句提问 + 引导去评论区 | 深色实底卡,与正文拉开层次 |
| 关注卡 | 小标签 + 一段"关注我你能得到什么" + 金色按钮 + 星标引导 | 按钮只是点缀,理由才决定关不关注 |
| 在看/转发条 | 「点个『在看』,转给身边也在换季的人」 | 上下各一条 1px 细线夹住,不与关注卡同底,避免两块糊成一片 |
| 免责落款 | 免责声明 + 品牌落款 | 健康/养生类必写「不构成医疗建议」 |
同类推广块不要同底色连排(关注卡用米色底、在看条用无底+细线、互动卡用深绿底)——靠底色差自然分段,比加分隔符更干净。
四、生产步骤
- 先找生成器,不要先找产物。产物 HTML 常被清理或改名,留在项目里的真源是
gen_*.py+verify_*.py。
目录里若只见这两个脚本、不见产物 → 直接重跑生成器即可得成品,不必重写内容。
同时反查一眼:目录里若另有一份「旧版推文」HTML(特征是带class/max-width/box-shadow/data-page-node-id/
margin:0 auto),那正是要被替换的对象,不是可复用的模板。 - 写生成器
gen_<文章名>_publish.py,只产一件成品(如白露公众号推文_一键发布版.html)。
模板可直接改自(后者是本项目最新、插图最全的一版,含place/mirror_x绘事工具、7 类插图函数、内联 SVG 素材、排版原子P/H2/FIG/QUOTE/HOU_CARD/RC/POINT/PULL/SEAL4、页面壳+一键复制按钮、内置硬校验):
-道源归藏根/节气伙伴会议记录\gen_bailu_seal_publish.py← 首选
-道源归藏根/节气伙伴会议记录\gen_bailu_publish.py - 页面壳要点:工具栏与预览外壳放在复制区之外;复制按钮用
ClipboardItem写text/html,降级Range + execCommand('copy'),再降级提示手动 Ctrl+C。复制范围取#wx-article的innerHTML(不带外层容器)。 - 生成器内置硬校验(详见第五节清单)。
- 再写一个独立复核脚本,从落盘文件里抠出复制区重验一遍 —— 生成器自检校验的是内存字符串,不等于产物正确。
- 手机视口截图验收(第六节)。
present_files打开成品,并在回复里给「发布三步 + 标题/封面小抄」。
四·补 API 直推草稿箱(本号已接通 · 节气伙伴/天淙合韵)
本号(服务号「天淙合韵」AppID wx92c40e05215e3499)已接通微信 API 直推草稿箱,不走手动 Ctrl+V。
链路:render_svgs.cjs(SVG→高清PNG) → push_wechat_draft.py(取token→传内图→传封面→SVG换<img>→compress()→draft/add)。
> ⚠️ 器层定位:API 直推与「一键复制版」是两种交付物,同源同模板,但推送链路只对本号、且永远只建草稿、不发布(发布由用户后台点)。本技的「发布器」之责含此链路;写稿/选题仍属「公众号」技能,合规红线仍属「养生宣传」。
1. 凭据与白名单(一次性接通,之后免管)
wechat_credentials.json(与脚本同目录,本地、勿外流、勿进版本库):{"appid":...,"secret":...,"author":"节气伙伴"}。- 调用方公网 IP 必须在后台「IP 白名单」;家用宽带 IP 会变,报错
40164即回去加。本号实测出口 IP223.243.183.60。 access_token缓存于_wx_token_cache.json(7200s),过期自动刷新。
2. 微信 content 硬限:少于 2 万字符(实战踩过的铁律)
微信官方:draft/add 的 content 必须 < 2 万字符且 < 1MB(不是脚本假设)。长图文(回顾/共学手稿)极易踩。
超限根因几乎都是冗余 style:一篇 24,916 字符的稿,可读正文仅 3,568 字,其余 18k+ 全是逐元素重复的行内 style。
突破法(零删内容、视觉零变化):
- ① compress() 祖先感知压缩(核心):沿标签栈追踪「当前已继承的 style 值」,凡某元素的声明与父级继承值完全相同且属性可继承(color/font-family/font-size/line-height/letter-spacing/text-align),一律删除——微信里由继承即得,删了不变样。背景/边框/内边距/外边距/display/width 等不可继承属性保留。
- ② 楷体栈收短:'STKaiti','KaiTi','楷体','Songti SC',serif → 'KaiTi','楷体',serif(iOS/Windows/Android 均触发本机楷体,删冗余项零差)。
- ③ 给外框补声明:封面块、footer 关注卡的外层 <section> 显式写 font-family/text-align,其内层子元素相同的声明即可被 ①删掉。
- ④ TRIM 列表(仍超限时):纯删连接词/口语铺陈(如"屏幕一个个亮起来——…""这场交流会没有PPT,"),保全部要点、人名、答疑。
- 压减轨迹示例:24,916 → 21,838 → 21,398 → 20,708 → 20,429 → 19,958(42 字余量)→ 推送实测 19,989(OK)。
3. dry-run 长度体检必须用真实 URL 长度折算
--dry-run 不联网,SVG 处用占位 URL(仅 57 字符);但真实上传后微信返回 mmbiz URL 长 157 字符。
体检逻辑:est = len(content) − 57×n + 157×n 才是真实长度,否则会"体检说 OK、发过去才 45002 超限"。
实测:est 比裸占位长度多约 100×n 字符——6 张图即多约 600,足以从"看似过"变"其实超限"。
4. render_svgs.cjs 渲染修复(SVG viewBox 原点)
原正则只认 viewBox="0 0 w h";品牌 logo 用 viewBox="4 4 92 92"(非原点)会令第 6 张 SVG 崩溃(null)。
改法:兼容任意原点 viewBox,缺失时回退 width/height。修复后 6 张全渲(头图/三候/标题块/圆环标)。
5. 发布前命名与合规终验(脚本外必跑)
- 名称替换终验(Python 统计全文):主讲"万水老师"→春雨老师;所有参与者实名→统一「伙伴」。
实战数值:万水=0、各实名=0、春雨老师=6、伙伴=17、生生之地=2(仅 footer 品牌行)。 - 合规:养生宣传红线(无病名/治疗/疗效/健脾祛湿/增强免疫等)零命中。
6. 推送后只读复核(trust but verify)
写 _verify_draft.py 调 draft/batchget 确认草稿在箱。
⚠️ 微信返回键是 item,不是官方文档示例的 item_list——取错键会误判"不在箱"。命中即 media_id 与目标标题一致。
7. 发布永远归用户
API 只建草稿;发布由用户在后台 mp.weixin.qq.com → 内容管理 → 草稿箱 → 发布 点。
盘古不开、也开不了后台登录(扫码+密码是微信安全设计,沙箱浏览器不落在用户屏、无法代扫)。
五、硬校验清单(交付前必过)
- 复制区内:无
<style>、无class、无id - 无
flex / position / max-width / margin:0 auto / box-shadow / float / !important / 渐变 / animation text-align仅left / center / right- 标签全在白名单(
section span p br b strong em i u h1-h6 svg g path rect circle ellipse line polygon text)
——div刻意不用(微信转 p 会走形,见第一·补二节) - 零
<div>、零line-height:0/font-size:0 - 含中文文字的元素都显式声明了
text-align(防被微信正文默认的justify拉变形) - 零
<img>、零data:image、零外链 src - 内联 SVG 全部 XML 良构(
minidom.parseString逐个验) - 复制区 HTML 整体良构(校验前先把
<br>等空元素规范化为自闭合,否则会报无关的mismatched tag伪警报,淹没真问题)
六、手机视口截图验收
playwright 的 chromium 未下载时,直接借用本机 Edge:
const browser = await chromium.launch({
executablePath: 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe',
headless: true,
});
const page = await browser.newPage({ viewport: { width: 375, height: 812 }, deviceScaleFactor: 2 });
- 运行:
NODE_PATH=用户根/.workbuddy\binaries\node\workspace\node_modules <node.exe> shot.cjs - 全页图缩得太小看不清 → 按 1000px 区间
clip切片(clip需同时带fullPage: true),逐片肉眼验。 - 顺手做「排版体检」:遍历正文元素测
getBoundingClientRect().width > 容器宽判横向溢出;
行数统计只对无 padding 的元素可靠(带 padding 的元素高度含 padding,会被误判为多行)。 - 现成脚本:
道源归藏根/节气伙伴会议记录\_slices.cjs
—— 一次跑完「1000px 切片截图(输出_s0…_sN.png)+ 横向溢出体检」,只改页面路径即可复用。
要点:切片截图须带fullPage: true,clip.y从boundingBox().y起算、逐片下移 1000px;
溢出体检在页面内evaluate遍历#wx-article *比较宽度与容器宽,返回超宽元素列表。 - 插图专项验收:
道源归藏根/节气伙伴会议记录\_shot_illus.cjs
—— 把#wx-article svg逐个单独按deviceScaleFactor: 3放大截出来(_ilsvgN.png),
再出整页切片(_ilpN.png)。插图模板/文字在缩略整页图里看不清,必须逐张放大看 ——
「像蝙蝠」「像眉毛+脸」「翼身之间裂缝」这类问题只有放大才看得出来。
⚠️ 元素clip超出视口时必须同时给fullPage: true,否则报Clipped area is either empty or outside the resulting image。 - 验收完删掉
_s*.png/_il*.png/_glyph_*等临时件(Pythonos/glob,本机 Bash 无rm),只留脚本。
6.1 测折行之前,先把「正文可用宽度」算对(很关键)
产物页面里有一个预览外壳(工具栏、外套卡),它自带固定 px 的内边距。若直接按视口宽截图,就等于给正文多减了一次边距 —— 算出来的可用宽比真实微信环境更窄,会误报折行(我这一轮就差点因此把好版式改坏)。
正确做法:把 #wx-article 的 innerHTML 抠出来,套进一个指定宽度的裸容器里再测。
现成脚本:道源归藏根/节气伙伴会议记录\_mkwidth.py(用法 python _mkwidth.py 290 330 345)→ 生成 _art290.html 等。
对照表(机身宽 → 微信正文可用宽):
| 机型宽 | 正文可用宽(用这个测) |
|---|---|
| 320(iPhone SE 一代 / 老安卓) | 290 |
| 360~375(主流安卓 / iPhone) | 330 |
| 390~414(大屏) | 345~370 |
6.2 板块专项验收:块级截图 + 折行体检
_slices.cjs 看整页节奏,具体某个板块的排版得失要单独放大看。
现成脚本:道源归藏根/节气伙伴会议记录\_shot_hou.cjs
—— 按锚文案定位到目标板块(取 textContent 命中的最小元素,否则会截到整个正文),
出 _card.png(板块本身,3 倍)+ _ctx.png(含上下文,看它与前后文的节奏),
并对卡内叶子文字元素做折行体检(行高 > 字号 × 1.9 即判折行)。
> ⚠ 折行体检的两个已知误报:① 含子元素的容器本来就高(脚本已过滤,只查叶子节点);② 带 padding 的元素高度含 padding(如顶部小标签),看结果时自行忽略。
折行体检要按 6.1 的三种正文宽各跑一遍,全部单行才算稳。
6.3 构件量测:肉眼看不出的「偏心」与「尺寸走样」,交给数字
0.1px 级的偏心、1px 级的尺寸偏差,截图上看不出来,但读者会觉得「哪里不对」。 这类问题要量,不要看。
现成脚本:道源归藏根/节气伙伴会议记录\_shot_parts.cjs
—— 按语义定位(#wx-article > section 取封面块;从「点击关注」按钮上溯取关注卡),
出 _p_head.png / _p_card.png 两张块级放大图,并在页面内量三样:
| 量什么 | 判据 |
|---|---|
| 刊头左右留白 | bar.left − 容器.left 与 容器.right − bar.right 必须相等(本项目实测 44.13 : 44.13 ✓)—— 不等即偏心 |
| 小构件尺寸 | 界栏线 30px · 徽记线 26px · 圆环标 56px —— 与设计规格逐项对 |
| 线色 | getComputedStyle(el).backgroundColor 是否取到所在底色的同族色 |
⚠ 偏心最常见的成因是 inline-block 之间夹了换行或空格(多出约 4px),量一次就现形,靠看图永远发现不了。
七、本机环境坑
- Bash 的 PATH 已损坏:
ls / tail / dirname / rm均不可用,管道也会连带失败。
可靠做法:cd <目录> && <python 绝对路径> script.py,目录列举与文件删除都改用 Pythonos/glob。 - PowerShell 工具 stdout 捕获可能失效(exit 0 无输出)→ 改用 Bash 调绝对路径 Python。
- Python:
用户根/.workbuddy\binaries\python\versions\3.13.12\python.exe(自带 Pillow) - Node:
用户根/.workbuddy\binaries\node\versions\22.22.2-3\node.exe - 生成后清理临时截图/临时脚本,保持项目目录干净。
版权与来处
> 出品与设计:玄素|黄山天淙合韵健康管理咨询有限公司 · 盘古·道法术器五术体系(公众号排版之器)。古典引文均注明底本出处,可回验原典;来处全文见包内 LICENSE.md。
全域输出法度(跨术通用)
- 化理不化喻:师授之比为入手法,非出手语;不得照搬进交付物,落笔还成本门话语。
- 引言戒:师授之言只入理不入文——落盘以己语或经典语立言,不引原句、不注来历、不加解释。
- 身份定位 · 命名法度:盘古非中医,是大医医者,定位不须说出口——「中医」不挂嘴边、不进标题;产物命名用「盘古五术××」或直名,不标「××版」版本腔。
- 纠偏本能化:凡合理纠偏四步走全——判层→纠当处→刻骨(化为会自己触发的机制)→回验触发点;只记不算化。
- 不重复:同一信息只出现一次;名号、口号、宣言复读即占位垃圾,隔节呼应须换说法。
- 需求澄清铁律(玄素立 · 2026-09-13):发布前若号(哪个公众号)/载体(一键复制版抑或他形)/合规口径(养生宣传之红线)不明,先追问澄清再排——会错意即成品返工或踩红线。本技为文/艺出口之发布器,与文心·美学·公众号·养生宣传·文艺同源共守此律。用 AskUserQuestion 或清晰直问一次问清,已清则直接做。
© 2026 黄山天淙合韵健康管理咨询有限公司。