PPT 排版优化技能
> 方法论根基:
> - 许岑《征服世界的美学暴力:「电影级」幻灯片设计方法论》——每个元素服务于表达。
> - 佐藤可士和「超整理术」——「不是元素删减,而是剥离冗余、保留核心本质」。
> 剥离是举证判断(先证明「对沟通零贡献」),删减是审美偏好;本技能只做前者。
> 定位:排版优化,不是内容编辑。 默认轨道下,内容一字不改,只做规范处理。
运行前提(先读,否则会失败)
本技能的三个脚本是零第三方依赖的(只用 Python 标准库),但必须与 rules/ 目录同处:
ppt-optimization/
├── SKILL.md
├── rules/
│ ├── rules.json # 41 条规则(规则即数据)
│ ├── aesthetic.json # 六维审美评分的分档与权重
│ └── type-scale.json # 字号阶梯(L1 统一层的唯一真相来源)
└── scripts/
├── check_layout.py # 检查器(只读,产出 report.md/json)
├── fix_layout.py # 整改器(产出 *_fixed.pptx)
└── aesthetic.py # 审美评分器
- 脚本按
../rules/*.json相对路径查找规则文件。目录被拆散则规则全部退化为默认值,
不会报错但结果不可信(这是刻意设计:宁降级不崩溃)。 - 运行示例:
python scripts/check_layout.py 我的课.pptx --out 报告/ - 所有脚本支持
--help。
能力分级(如实声明,避免过度承诺)
| 能力 | 状态 | 说明 |
|---|---|---|
| 几何合规检查(41 条) | 可自动 | 确定性判定,机械可复现 |
| 字号/颜色统一(L1) | 可自动 | 由 type-scale.json 与 deck 色板驱动 |
| 对比度修正 | 可自动 | 吸附到既有色板的最小位移 |
| 审美六维评分 | 量化但非绝对 | 只保证排序方向正确(更好的版式分更高), |
| 绝对值不可跨 deck 比较 | ||
| 行距/段距(R-34) | 仅提示 | XML 可读但渲染行高需人工确认 |
| 动画、母版、SmartArt | 不处理 | 超出纯排版范围 |
| 需要"好不好看"的最终判断 | 人工 | 脚本给量化依据,不替人下结论 |
版本与迭代纪律
- 版本号唯一来源:
VERSION.txt文件,必须与本文档 frontmatter 的version一致
(不一致时pack.py打包自检会报错并拒绝打包)。 - 每次改动必须同步做三件事:① 升
VERSION.txt;② 在CHANGELOG.md追加一条
(含"改了什么 / 依据 / 实测数值影响");③ 重新打包 → 产出
ppt-optimization.zip与ppt排版优化技能_v<版本>.zip。 - 自动落地的门槛(每日研究任务把研究提案变成真实代码时必须全过才能发版):
1.python tests/run_tests.py全部通过(当前 23 项);
2. 文字内容零改动(56 页逐页比对<a:t>);
3. 门禁不放松(P0 FAIL 不得被"改判"成 PASS,只能被真实修复);
4. 行为变化必须是可解释的暴露真相(如 D1/D2 让 FAIL 从 162→179),
而非无据的回归——每一处增量都要能在CHANGELOG.md里说清来源。 - 风险分级:新规则 / 阈值方向变更 / 度量基准变更,一律先只出 WARN观察一轮,
人工看过新增报项无误后再升 FAIL。
第 0 步:启动确认(声明默认,可一句话覆盖)
不要抛问卷让用户逐项拍板。 先声明默认假设并直接开工,用户不满意一句话即可改。
只有用户主观取舍(风险偏好、审美取向、时间投入)才需要问。
默认假设(未说明时一律采用):
| 项 | 默认 | 覆盖方式 |
|---|---|---|
| 轨道 | 纯排版(不改一字一字一个标点) | 说"可以改内容"即切内容轨道 |
| 配色 | 沿用原稿既有色板(不引入新色) | 给出主色/强调色即切换 |
| 场景 | 线上分享(正文字号下限 20pt) | 说"会议室"→23pt;说"发布会大屏"→36pt |
| 不可动元素 | Logo、客户名、法定文字、数据 | 明确点名即加入保护 |
只在以下情况才必须问(因为无法从文件推断且后果不可逆):
- 用户明确要求"必须统一到某个品牌色/字体",但没给色值或字体名;
- 稿件含法定文字(如药品说明书、金融披露)而用户没说明哪些不能动。
★ 逐页铁律:一页一循环,不许跳页、不许合并
为什么强制逐页。 整份报告 = 页数 × 41 条:56 页就是 2296 条。
一次读完再动手,越靠后的页越容易被跳过,实测表现就是"前面的页改到位,
后面的页像完全没看过、没改过"。
这不是脚本的锅。 已实测:引擎对每页是对称处理的——修复器只吃本页几何,
色板/字阶/槽位这三个全局锚点在开工前一次性算好、全程不变,不存在"被前几页污染"。
把 deck 三等分后,三段修复率完全一致(无页序偏差)。
所以根因是处理者面对超长报告时的注意力衰减,只能靠流程强制解决。
因此:禁止一次性读全量报告,禁止一次性整改整份 PPT。 必须一页一循环:
for 每一页 N in 1..总页数:
1. python scripts/check_layout.py 稿.pptx --page N --out 报告/
→ 只吐这一页的 41 条,逐条过目(FAIL / WARN / NEEDS_REVIEW 都要判,不跳条)
→ 报告自动落到 报告/page-0NN/,不会覆盖上一页
2. 该页 NEEDS_REVIEW 逐条人工裁决 → 写入 resolutions.json
3. python scripts/fix_layout.py 稿.pptx --pages N --out 输出/
→ 只改这一页,其余页语义内容不变(已实测:非目标页 55/56 个 slide part 零改动)
4. python scripts/check_layout.py 输出稿.pptx --page N --out 报告/
→ 复核该页,确认是变好而不是变差
5. 在下方「逐页进度表」登记该页 → 登记完才允许进入 N+1
全局锚点必须冻结(防"越改越漂"):
- 色板、字号基准、结构槽位是全稿统计量。若每页都从"当前稿"重算,
前一页的改动会改变后一页的锚点,同一语义颜色会被分批归一到不同结果。
- 整改器首次运行会生成 analysis_manifest.json(记录源文件哈希 + 色板 + 字号基准,
不可变);后续逐页整改只要哈希匹配就复用该清单,绝不重算。
- 该清单在输出目录。整份 PPT 的逐页流程必须全程指向同一份清单;
换稿(哈希不匹配)时脚本会拒绝复用并重新生成,避免张冠李戴。
硬性要求(违反即视为该页未处理):
- 一次只读一页、只改一页,绝不批量跨页;
- 每页 41 条逐条过目,不能只扫 FAIL;
- 每页处理完必须登记,未登记的页 = 没做过;
- 页号参数写错必须报错,绝不静默改成全稿:--page / --pages 解析失败、
含 0/负数、或超出总页数时,脚本会报错退出(退出码 2),不会退化成全量整改。
- 全部页处理完后,必须再跑一次全量 check 做交叉校验(见第 4 步)。
逐页进度表(必须产出,防遗漏的兜底)
| 页 | 页面类型 | 处理前 FAIL | 处理后 FAIL | NEEDS_REVIEW 闭环 | 未改项及原因 | 状态 |
|---|---|---|---|---|---|---|
| 1 | 封面 | 1 | 0 | 3/3 | 无 | ✅ 完成 |
| 2 | 正文 | 4 | 1 | 2/2 | R-16 改了会压坏内边距,交人工 | ⚠️ 完成但有未改项 |
状态只有三种:✅ 完成 / ⚠️ 完成但有未改项 / ❌ 待人工。
任何一页为 ❌,整份不得交付。
第 1 步:检查(先看清楚,再动手)
# 全量:只用于最后交叉校验,不作为逐页工作的依据
python scripts/check_layout.py 输入.pptx --out 报告/
# 逐页:日常工作用这个,一次只看一页的 41 条
python scripts/check_layout.py 输入.pptx --page 12 --out 报告/
产出 报告/report.md 与 报告/report.json。
--page 支持逗号与区间,如 --page 1,3-5,12;逐页模式下门禁只针对该页。
必读校验(不通过则报告不可信):
- 报告的记录总数必须 = 页数 × 41。少于这个数说明有规则被跳过(漏检)。
- 状态分布中 NEEDS_REVIEW 不为 0 时,门禁不会通过,必须先闭环。
六态判定:
| 状态 | 含义 | 处理 |
|---|---|---|
| PASS | 通过 | — |
| FAIL | 违反规则 | 交整改器或人工修 |
| WARN | 接近阈值 | 建议复核 |
| NA | 该页不适用(如无文字页跑图文规则) | — |
| NEEDS_REVIEW | 脚本无法判定(需视觉确认) | 必须人工闭环 |
| CLOSED | NEEDS_REVIEW 已闭环 | — |
NEEDS_REVIEW 闭环:谁来写、怎么写
由使用者(或调用本技能的 AI)在看过报告后填写,不是脚本自动生成。
- 检查器会在
--out目录查找resolutions.json;找不到再查 pptx 同级目录。
没有任何文件时,在控制台提示"P0 待复核 N 处"。 - 打开
报告/report.md,搜NEEDS_REVIEW,逐条人工过目(报告里附了坐标,
可在 PPT 里按坐标定位)。 - 填写
resolutions.json(放在 pptx 同级或--out目录)。
唯一合法格式是「对象」(每条必须有result与非空note):
{
"1|R-34": {
"result": "CONFIRMED_OK",
"by": "复核人",
"note": "检查了渲染效果,行距层次清楚,没有裁切",
"at": "2026-10-11"
},
"7|R-13": {
"result": "CONFIRMED_BAD",
"by": "复核人",
"note": "确认是有意重叠,需人工调整",
"at": "2026-10-11"
}
}
- 键格式
"页码|规则ID";页码用*表示全 deck 一律。 result三个合法取值:CONFIRMED_OK(看过,没问题)、CONFIRMED_BAD(确认要改)、
EXEMPT(该情况合理,豁免)。note必须非空——没有说明的复核不算复核。- ⚠️ 旧版字符串写法(如
"1|R-34": "CONFIRMED_OK")已废弃,代码会拒绝并告警。
照抄旧格式会导致复核全部不生效,务必用上面的对象格式。 - 填完重跑检查器,
NEEDS_REVIEW会变成CLOSED。
4. 门禁同时卡两件事:P0 级 FAIL 必须为 0,且P0 级 NEEDS_REVIEW 必须全部闭环。
第 2 步:整改(带护栏)
# 逐页:日常工作用这个,只改这一页,其余页字节不动
python scripts/fix_layout.py 输入.pptx --pages 12 --out 输出目录/
# 全量:仅当所有页都已逐页处理完、需要整体收敛时用
python scripts/fix_layout.py 输入.pptx --out 输出目录/
产出 <原名>_fixed.pptx 与 <原名>_fixed.typescale-meta.json
(后者记录判定基准,检查器下次会复用它,避免"整改后基准漂移")。
--pages 支持逗号与区间,如 --pages 1-5,12。
三道铁律(违反即中止,不产出文件):
1. 文字内容一字不改 —— 整改前后逐个 run 的文本必须完全一致;
2. 不引入外来色 —— 对比度修正只在既有色板内做最小位移;
3. 不劣化无序度 —— 字号/颜色/字重/对齐的取值种类数不得增加。
修复顺序及其理由:
字号统一(定标) → 跨页位置统一 → 色板归一 → 配色 → 对齐微调 → 容器 → 收尾
- 必须"先定标再对齐":对齐会移动元素纵向位置,而角色判定依赖位置,
位置一动角色就漂移,字号永远统一不了(实测:顺序反了 R-33 只采纳 5/56 页)。 - 字号统一与色板归一是原子操作(全 deck 一次性应用,只允许整轮回退)。
部分统一会让同一语义并存两个值,字号种类反而更多(实测 9→13)。
第 3 步:审美评分(第二目标)
python scripts/aesthetic.py 输入.pptx --out 报告/
六维评分:层级 / 构图 / 平衡 / 密度 / 焦点 / 收敛。
读分注意:
- 评分含短板封顶 —— 任何一维掉到 40 分以下,总分被压到该维附近。
这是刻意的:读者最先感知的是缺陷,不是优点,不能用"居中对称"补偿"没有层级"。
- 只保证排序方向(更好的版式分更高,有回归测试保证),
绝对值不可跨 deck 比较。
- 审美分下滑时整改器会回退该页(容差 3 分),但可用性底线规则不受此约束
(字号下限、对比度 —— "看得清"优先于"好看")。
第 4 步:交付
- 逐页进度表全部登记完毕 —— 无一页遗漏、无一页为 ❌;
- 全量交叉校验(必做):
python scripts/check_layout.py 输出稿.pptx --out 报告/
核对「逐页进度表各页 FAIL 之和 == 全量报告的 FAIL 总数」。
不等 = 有页被漏处理或被重复计数,必须回查,不允许带疑点交付。 - 检查器门禁通过(无 P0 FAIL、无未闭环 P0 NEEDS_REVIEW);
*_fixed.pptx与原始稿对比,文字内容一致;- 报告附行动摘要(哪些页要人工处理)。
只有三种交付状态:
- 绿灯 —— 全页 ✅,原样交付;
- 黄灯 —— 存在 ⚠️ 页:可交付,但必须附「未改项交接清单」;
- 红灯 —— 存在 ❌ 页或红线被破:停止交付,回炉重做。
机器可读最终状态与退出码(供上层自动化判定)
检查器会把最终状态与退出码一一对应输出。绝不能只看退出码 0 就当成"成品已通过验收":
| 最终状态 | 退出码 | 含义 | 能否交付 |
|---|---|---|---|
PASS |
0 | 三态门禁全绿 | ✅ 可交付 |
BLOCKED |
1 | 有 P0 FAIL 或未闭环 P0 复核 | ❌ 不可交付 |
PENDING_SIGN |
3 | 自动门禁过,但有 P0 manual 项待真人签署 | ⚠️ 未完成签署前不可交付 |
PENDING_RENDER |
4 | 无渲染引擎,视觉未验收(当前默认即此态) | ⚠️ 仅"程序整改完成,待渲染验收" |
| (用法错误) | 2 | 参数非法、文件不存在等 | — |
> 关键区分:「程序执行完成」≠「自动检查通过」≠「成品可交付」,三者是独立的三件事。
> 当前版本无渲染引擎,故最终状态正常情况是 PENDING_RENDER(退出码 4),而不是 0。
附录:规则与设计系统
- 规则清单(41 条):见
rules/rules.json。每条含 id / 名称 / 层级 / 优先级 /
选择器 / 度量 / 参数 / 修复动作 / 豁免条件。 - 字号阶梯:见
rules/type-scale.json。这是 L1「统一」层的唯一真相来源,
字号修复与检查都从它取值,不各自造数。 - 审美分档:见
rules/aesthetic.json。六维的分档区间与权重,
以及短板惩罚参数。
⚠️ 设计系统描述「层级比例」,不是「绝对字号」(必读)
type-scale.json 里的 page_title=54 / body=20 是基准稿的绝对 pt,
不是每份稿子都必须达到的目标值。整套阶梯是比例关系
(标题 ≈ 正文的 2.7 倍、副标题 ≈ 1.9 倍、页脚 ≈ 0.85 倍)。
落地时必须按本稿自身的尺度等比缩放:
scale = 本稿正文主字号 / 基准正文(20)
- 紧凑商务报告稿(正文 11pt,占页高 2.0%)→
scale = 0.55
→ 54→30、38→21、28→15.5、20→11、17→9.5,原稿层级被完整保留。 - 投影演示稿(正文 20~24pt)→
scale ≈ 1.0~1.2,接近基准。
若不缩放(强行把 11pt 正文拉到 20pt、把 30pt 页标题按 54pt 标准判定):
正文被放大 1.8 倍、30pt 页标题被压到 17pt,四级层级被抹平成两级——
整份精致的稿件被改成"又大又平"的大字报。这就是用户反馈的「傻大粗」。
该缩放由 _derive_scale() 统一完成,修复器(fix_layout)与检查器
(check_layout)共用同一套缩放后的 target,禁止各自推算。
函数带幂等守卫(ts['_scaled']),重复调用不会二次缩放。
两种字号模式(P0-3,防"下限被悄悄缩小")
缩放只保留层级比例,但"场景字号下限"是否跟着缩放,由 fix_layout.py 的
--readable 开关决定,两种模式显式分离(不再混进一个公式):
| 模式 | 触发 | 场景字号下限 | 适用 |
|---|---|---|---|
| 保留原稿尺度(默认) | 不加参数 | 下限 × ts_scale(随原稿正文比例缩放) |
紧凑报告稿,保层级、不放"傻大粗" |
| 可读性优先 | --readable |
场景绝对下限(不被 ts_scale 缩小) | 投影/演示,宁可溢出报告也不留小字 |
> 关键修正:旧版把"下限"也乘了 ts_scale,小字号原稿下 20pt 场景下限会被
> 缩成 11pt,名义上"合规"实则远低于可读要求。现默认仍保留原稿尺度(保守),
> 但显式提供 --readable 让使用者按需切到"下限不缩放";两种模式只读同一份
> rules.json 的 body_size_min_*,不再各写一套数。
⚠️ 角色判据:字号档位定大类,长度只在同档内细分
role_of_run() / _role_guess() 的最终判据(第 5 代):
- 先给整份 deck 建立实测字号梯队(
_deck_sizes,去重升序),
由 deck 自己报出"它用了哪几档"——比拿绝对尺子量更可靠。 - 页眉带:以正文为标尺分档
≥2.2×正文 → 页标题、≥1.5×正文 → 副标题、
≥0.9×正文 → 引言(按正文级)、其余 → 眉标/页码。 - 正文区:算"该字号比正文大几档"(delta)
delta≥2 → 小标题、delta==1 → 次级标签(长文本则为小标题)、
delta==0 → 正文、delta<0 → 图注。
关键原则:字号一旦大于正文,就不再因"文本短"降级。
早期判据把"短文本"等同于"小角色",导致 30pt 页标题(8 字)被判成
label 并被压到 12.7pt——判据自己在制造字号分裂,这是层级被抹平的
另一台机器。长度只用于同一字号档内部区分正文与标签。
> 反面教材(已实测复现,勿回退):
> 用绝对阈值 subtitle(54)×0.85 判页标题 → 30pt 页标题被误判成 running;
> 用"y 坐标相近"当"同级罗列" → 同行的页标题与引言被互相拉平;
> 双重缩放(_derive_scale 后又乘一次 scale)→ 29.7×0.55=16.3 吸附成 15.4。
第 1 部分 · 底层哲学(动手前内化)
- ★ 第 0 原则:存在性先于排版质量。
在问「这个元素排得好不好」之前,先问「它凭什么存在」。
一个与页面目标无关的装饰件,即使排得再整齐,也是负资产——
它占版面、抢注意力、稀释信息密度。
不需要任何「为了存在而存在」的东西:每个元素都必须对本页的目标
有可指认的作用(承载信息 / 建立层级 / 引导视线 / 呼应内容)。
评判用「存在性四问」(见 R-41):任一为「是」即保留,
四问全否即冗余。举证责任在元素一方——说不出服务什么,就该移除。
(机器判据见 R-41;删除属需授权操作,脚本只标记)
这一原则源于 许岑(元素服务于表达)与 佐藤可士和(剥离冗余、保留核心本质)——
注意佐藤的原意是「剥离」而非「删减」:剥离是举证判断,删减是审美偏好。 - 幻灯片是利他的:做给听众看,后排观众能不能瞬间 get。
- 一页一个主张:排版上要突出唯一主角,但默认轨道下不拆页。
- 先有演讲,再有幻灯片:幻灯片是辅助,不是讲稿誊写板。
- 克制是最高级的用心:堆元素 = 业余。每个元素都要有存在的理由。
- 敢于留白:页面不必填满。
- 参考线与对齐是底线:不允许"差不多对齐"。
- 整套是一个作品:字号、颜色、间距、位置跨页一致。
- 内容决定容器大小:先有内容,再根据内容量定色块尺寸,不是反过来。
第 2 部分 · 规范层(Static Rules)
2.1 配色 Token
- 一页内文字颜色 ≤ 3 种(背景色不计入)。
- ⚠️ 这个"3"是症状指标,不是修法。 遇到超标的正确处置顺序:
1. 先查是不是"同一语义被写成多个值" —— 如#141414与#1E1E1E
(明度差 ≈2%,肉眼不可分)应合并;#E60012与#FF6B78
若是同一品牌色的深浅两档,应归一为频次更高的那个。
2. 再判断剩下的差是不是"真实层级" —— 5 级灰阶
(#141414/#4D4D4D/#6E6E6E/#8F8F8F/#A0A0A0)+ 反白 + 1 品牌红
是设计意图明确的层级系统,砍到 3 种等于取消层级,
会与 R-26(字号层级拉开)一样把审美推向反面。
3. 只有确认是"无意义的碎色"时才继续合并。 - 判断依据:合并后页内色种数是否下降。若不降(如 5 种→5 种,只是成分变了),
说明这 5 种都是真实层级,不动。 - 强调色只服务"本页主角"(一个数字 / 一个关键词 / 一句结论),不撒胡椒面。
- 文字与背景对比度 ≥ 4.5:1(WCAG 标准)。
- 禁止:渐变填充、阴影发光特效、默认 Office 配色、彩虹色图表。
2.2 字体阶梯
- 一套 PPT 最多 2 个字体族(标题 1 个,正文 1 个)。
- 字号阶梯(按场景定下限):
| 层级 | 会议室投影 | 线上分享 | 发布会大屏 |
|---|---|---|---|
| 大标题 / 金句 | 44–60pt | 36–48pt | 60–80pt |
| 页面标题 | 28–32pt | 24–28pt | 36–44pt |
| 正文 | ≥ 20pt | ≥ 18pt | ≥ 32pt |
| 注释 / 页码 | 10–12pt | 10–12pt | 12–14pt |
| 超大数字(数据页专用) | 60–80pt | 48–72pt | 80–120pt |
- 字重对比:标题 Bold/Heavy,正文 Regular/Light。
- 行距 1.2–1.5 倍;段间距 ≥ 行距的 1.5 倍。
2.3 间距栅格(8pt 基线)
所有 margin / padding / 元素间距 ∈ {4, 8, 12, 16, 24, 32, 48, 64}。
- 页面左右安全边距 = 页面宽度 × 5%(动态计算,不写死)。
- 正文区与页眉/页脚带之间留 ≥ 24pt 呼吸。
2.4 固定件(母版锁死)
- 页头带:章节名 / 项目名,左对齐,全套位置不动。
- 页脚带:Logo / 公司名,位置固定。
- 页码:右下,10–12pt 灰色。
- 正文页严禁修改这三件套的位置和格式。
2.5 版式骨架库(选模具,不从零画)
| 内容类型 | 推荐骨架 |
|---|---|
| 封面 | 大标题 + 副标题 + 日期/汇报人,大片留白 |
| 目录 | 编号 + 章节名,纵向排列 |
| 章节分隔 | 超大数字 + 章节名,整页深色或整页留白 |
| 观点陈述 | 一句金句居中,其余全空 |
| 左右对比 | 中间一条竖线,两侧对称 |
| 三栏并列 | 等宽三列,每列一个标题 + 说明 |
| 流程 / 时间线 | 横向节点,节点之间细线连接 |
第 3 部分 · 审查总表(共 41 条)
> 粒度说明:规则分两级跑。
> - 页内规则(R-01 ~ R-26、R-33 ~ R-40):每一页都要跑一遍。当页不存在这个问题 → NA-PASS 通过,不允许跳过检查项。
> - 跨页规则(R-27 ~ R-32、R-41):整套 PPT 扫一次,不是每页跑一遍。检查全套是否一致。
>
> 三态判定:
> - PASS:适用且没问题
> - FAIL:适用且有问题,按"整改动作"修
> - NA-PASS:不适用(比如这页没有色块),自动通过
>
> 不允许"以为不用跑"就跳过。识别不出是否适用时,先做判断,不能整组跳过。
>
> 完整性校验:report.md 的逐页完整审查清单必须列出全部 41 条 × 页数 行
> (含 PASS)。行数不足即为漏跑,交付前必须核对。
哪些规则会被自动修改(务必先看清)
41 条里只有 14 条有自动修复器,其余 26 条只检查、只报告,不会自动改。
| 可自动修复(14 条) | 只报告不改(26 条) |
|---|---|
R-33 字号下限与统一<br>R-23 同级同字号<br>R-27 页眉页脚跨页位置<br>R-35 页内近色合并<br>R-17 对比度修正<br>R-05 对齐一致性<br>R-06 基线对齐<br>R-07 安全边距<br>R-11 文字重叠<br>R-12 文字压色块<br>R-16 色块内边距<br>R-19 容器内文字间距<br>R-22/R-24 色块内边距对称 |
R-01/R-02 页面类型与骨架(需视觉判断)<br>R-03 背景统一(涉及整页设计)<br>R-04 母版一致性<br>R-08/R-09 间距与栅格(需定基准)<br>R-10 页眉页脚对母版<br>R-13 形状重叠<br>R-14/R-15 图文溢出与裁切<br>R-18 内容分布(涉及主观布局意图)<br>R-20/R-21 列表与编号<br>R-25 多行均分<br>R-26 字号层级拉开(需定义层级斜率)<br>R-28~R-32 跨页一致性<br>R-34 行距(需渲染确认)<br>R-36~R-40 其余<br>R-41 装饰件冗余(只标记不删除,删除元素属需授权操作) |
这意味着:整改器跑完不等于全达标。剩下的 FAIL 需要人工处理或明确豁免,
具体见报告"行动摘要"里的"卡住的规则"表。
页面类型豁免矩阵
审查前先判断页面类型,有些规则对特定类型豁免:
| 规则 | 封面页 | 目录页 | 章节分隔页 | 内容页 |
|---|---|---|---|---|
| R-03 背景统一 | 豁免(允许特殊设计) | 按标准 | 豁免(允许整页深色) | 按标准 |
| R-04 主角突出 | 豁免(标题就是主角) | 按标准 | 豁免(大数字就是主角) | 按标准 |
| R-18 内容分布≥60% | 豁免(大片留白是设计) | 按标准 | 豁免(居中大数字) | 按标准 |
| R-24 内容垂直居中 | 按标准 | 按标准 | 按标准 | 按标准 |
| R-25 多行均分 | 豁免 | 按标准 | 豁免 | 按标准 |
> 豁免不是"不用检查",是"这页这样设计是对的,不算 FAIL"。
> 比如封面页大片留白是设计意图,不能判 R-18 FAIL。
A 组 · 页面类型与骨架(R-01 ~ R-04)
R-01 页面类型识别
- 适用范围:所有页
- 判定方式:视觉判断
- PASS:能说清这页是封面/目录/过渡/内容页,内容页能细分观点型/数据型/流程型/对比型/清单型
- FAIL整改:识别不清 → 先确认页面定位,再检查布局是否匹配
- 优先级:P1
R-02 版式骨架匹配
- 适用范围:所有内容页
- 判定方式:视觉判断
- PASS:选的骨架和内容类型匹配(观点→金句居中、数据→大数字、流程→时间线、对比→左右分栏)
- FAIL整改:换匹配的骨架布局
- 优先级:P1
R-03 整页背景统一
- 适用范围:所有页
- 判定方式:脚本算(读slide背景填充色)
- PASS:全套PPT背景色一致(白底全套白,黑底全套黑)。章节分隔页可以单独深色,但要有明确的"过渡页"身份。
- FAIL整改:统一背景色,或把不统一的页标记为"章节分隔页"
- 优先级:P0
- 已修复冲突:原"背景二选一套统一" vs "章节分隔页整页深色" → 统一为"章节分隔页允许深色,但其他页必须统一"
R-04 主角突出
- 适用范围:所有内容页
- 判定方式:视觉判断
- PASS:本页唯一主角一眼能认出来(最大面积 / 最强对比 / 最亮颜色)
- FAIL整改:把配角降级(变灰、缩小、移到次要位置)
- 优先级:P1
- 轨道说明:纯排版轨道下只调视觉权重,不删内容
B 组 · 对齐与间距(R-05 ~ R-10)
R-05 横向对齐一致
- 适用范围:所有页
- 判定方式:脚本算(比较同组元素x坐标)
- PASS:同一组元素左对齐/居中/右对齐,方式一致。不能这个左那个居中。
- FAIL整改:统一对齐方式
- 优先级:P0
R-06 竖向基线对齐
- 适用范围:有列表/卡片的页
- 判定方式:脚本算(比较同组元素y坐标)
- PASS:同类元素基线在一条线上
- FAIL整改:对齐y坐标
- 优先级:P0
R-07 安全边距
- 适用范围:所有页
- 判定方式:脚本算
- PASS:所有文字元素的x ≥ 页面宽度×5%,x+宽度 ≤ 页面宽度×95%。不允许被页面边缘截断。
- FAIL整改:元素内移,或调整宽度
- 优先级:P0
- 已修复bug:原写死72pt/888pt → 改成动态计算
R-08 同类元素间距一致
- 适用范围:有多列/多行的页
- 判定方式:脚本算(比较相邻元素间距)
- PASS:三列卡片间距相等,列表行距相等
- FAIL整改:统一间距
- 优先级:P1
R-09 间距落在8pt栅格
- 适用范围:所有页
- 判定方式:脚本算
- PASS:元素间距 ∈ {4, 8, 12, 16, 24, 32, 48, 64}
- FAIL整改:调整到最近的栅格值
- 优先级:P2
R-10 页眉页脚对齐母版
- 适用范围:所有内容页
- 判定方式:脚本算
- PASS:页头、页脚、页码的位置和全套其他页一致
- FAIL整改:对齐母版位置
- 优先级:P0
- 已修复冲突:原"严禁修改页眉" vs "必须对齐参考线" → 统一为"页眉位置以母版为准,不对齐就改到母版位置"
C 组 · 重叠检查(R-11 ~ R-14)
R-11 文字与文字重叠
- 适用范围:所有页
- 判定方式:脚本算(比较相邻文字元素边界框)
- PASS:同列相邻文字元素之间不重叠。上一项说明底 ≤ 下一项标题顶 - 6pt。
- FAIL整改:拉开间距
- 优先级:P0
R-12 文字与色块重叠
- 适用范围:有色块的页
- 判定方式:脚本算
- PASS:文字不被色块遮挡,文字在色块内或色块外明确分开
- FAIL整改:移动文字或调整色块层级
- 优先级:P0
R-13 形状与形状重叠
- 适用范围:有多个形状的页
- 判定方式:脚本算
- PASS:形状之间不重叠,除非是设计意图(如叠加装饰)
- FAIL整改:分开重叠的形状
- 优先级:P1
R-14 线条闭合连接
- 适用范围:有边框线的页
- 判定方式:视觉判断
- PASS:所有边框线(横线+竖线)在四个角精确交汇,不断层、不错位
- FAIL整改:调整线条位置让它们接上
- 优先级:P1
D 组 · 容器与内容关系(R-15 ~ R-22)
> 色块识别口径(先判断这页有没有色块,再决定跑不跑这组):
> 满足以下任一条件就算"有色块":
> 1. 有填充色的矩形/圆角矩形(不是纯白/纯透明背景)
> 2. 卡片式容器(多个并列的、带底色的内容块)
> 3. 侧边栏/标签条(竖条或横条底色,上面有文字)
>
> 识别不出时 → 逐元素检查:这个形状有没有填充色?填充色是不是白/透明?
> 不能因为"感觉这页没色块"就整组 NA-PASS。
R-15 内容决定容器大小
- 适用范围:有色块的页
- 判定方式:脚本算
- PASS:先算内容包围盒的宽和高,再定色块尺寸。色块宽 = 内容宽 + 左右内边距(各≥12pt)。色块高 = 内容高 + 上下内边距(各≥12pt)。
- FAIL整改:调整色块尺寸适配内容,而不是把内容塞进去
- 优先级:P0
R-16 文字包围盒不超出色块(四边距)
- 适用范围:有色块的页
- 判定方式:脚本算
- PASS:文字包围盒的最左x ≥ 色块左边 + 12pt。最右x ≤ 色块右边 - 12pt。最上y ≥ 色块顶边 + 12pt。最下y ≤ 色块底边 - 12pt。
- FAIL整改:优先加大色块,不是收窄文字
- 优先级:P0
R-17 配色对比度
- 适用范围:有色块的页
- 判定方式:脚本算(WCAG 相对亮度对比度,非简单亮度差)
- PASS:投影后对比度 CR_p ≥ 4.5(正文);≥ 3.0(大字:≥18pt 或 ≥14pt 粗,依 WCAG 1.4.3)。
CR_p = (L_hi + flare) / (L_lo + flare),其中 flare = 1/(C−1),C = 该场景的系统对比度
(--scene 决定:screen/online=21、meeting=15、stage=7,取自 ANSI/INFOCOMM 3M-2011)。
默认 screen/online 时 flare = 0.05,与 WCAG 原式等价。
- FAIL整改:换文字颜色或底色(只在本 deck 既有色板内做最小位移,不引入外来色)
- 优先级:P0
- 说明:审美评分固定 flare=0.05,不随场景变(否则历史审美基线失去可比性)。
R-18 内容分布合理
- 适用范围:有色块的页
- 判定方式:脚本算
- PASS:文字包围盒高度 ≥ 色块高度的 60%。文字包围盒宽度 ≥ 色块宽度的 70%。不允许内容只占色块上部1/3、下面空2/3。
- FAIL整改:调整内容位置(垂直居中),或调整色块高度
- 优先级:P1
R-19 容器内文字间距
- 适用范围:有色块的页
- 判定方式:脚本算
- PASS:容器内相邻两段文字间距 ≥ 8pt。序号/标签与后面的标题间距 ≥ 6pt。
- FAIL整改:拉开间距
- 优先级:P1
R-20 同类容器统一
- 适用范围:有多组同类色块的PPT
- 判定方式:脚本算
- PASS:同类容器(同结构、同用途)的内边距一致、内容垂直位置一致、标题与说明的间距一致。
- FAIL整改:统一为同一套参数
- 优先级:P1
R-21 同类页面模板统一
- 适用范围:有系列详情页的PPT
- 判定方式:视觉判断
- PASS:同类页面模板该有的横线分隔,每页都有;不该有的,每页都没有。不允许这页有那页没有。
- FAIL整改:统一模板
- 优先级:P1
R-22 色块上下边距对称
- 适用范围:有色块的页
- 判定方式:脚本算
- PASS:色块内第一个元素到顶边距 ≈ 最后一个元素到底边距(差 ≤ 8pt)。
- FAIL整改:调整内容位置居中
- 优先级:P1
E 组 · 视觉细节(R-23 ~ R-26)
R-23 同级罗列同字号
- 适用范围:有并列清单的页
- 判定方式:脚本算(比较并列项字号)
- PASS:云图/并列清单/词云式罗列,所有项同字号同字重同色。不允许用字号递减暗示重要性层级。
- FAIL整改:统一字号字重
- 优先级:P1
R-24 内容垂直居中
- 适用范围:上下有边界线的内容区
- 判定方式:脚本算
- PASS:上下两条边界线之间的内容块,垂直居中或中心略偏上。不允许全部挤在一侧。
- FAIL整改:调整内容y坐标居中
- 优先级:P1
R-25 多行列表均分
- 适用范围:有多行列表的页
- 判定方式:脚本算
- PASS:多行列表在上下边界之间均匀分布。不允许挤成一团、下面大空。
- FAIL整改:均匀分布行距
- 优先级:P1
R-26 字号层级拉开
- 适用范围:所有内容页
- 判定方式:脚本算
- PASS:标题 vs 正文 vs 注释,层级拉开(大小/颜色/字重三者至少两项有明显差异)。
- FAIL整改:调整字号/字重/颜色拉开层级
- 优先级:P1
- 已修复冲突:原"一页字号≥5种打回" vs "数据页有超大数字" → 统一为"一页字号不超过5种,超大数字算在里面,超了就精简"
F 组 · 跨页一致性(R-27 ~ R-32)
R-27 标题位置跨页一致
- 适用范围:所有内容页
- 判定方式:脚本算(比较各页标题y坐标)
- PASS:全套内容页的标题y坐标一致
- FAIL整改:对齐标题位置
- 优先级:P1
R-28 正文字号跨页一致
- 适用范围:所有内容页
- 判定方式:脚本算
- PASS:全套正文用同一个字号
- FAIL整改:统一字号
- 优先级:P1
R-29 页边距跨页一致
- 适用范围:所有页
- 判定方式:脚本算
- PASS:全套PPT的内容区左右边距一致
- FAIL整改:统一边距
- 优先级:P1
R-30 配色跨页一致
- 适用范围:所有页
- 判定方式:脚本算
- PASS:全套PPT用同一套配色(主色/辅助色/强调色色值一致)
- FAIL整改:统一色值
- 优先级:P1
R-31 字体跨页一致
- 适用范围:所有页
- 判定方式:脚本算
- PASS:全套PPT用同一套字体(标题字体、正文字体一致)
- FAIL整改:统一字体
- 优先级:P1
- 已修复冲突:原"最多2个字体族" vs "金句可用书法体" → 统一为"全套最多2个字体族,金句页可以用书法体作为第3族,但仅限金句页,其他页统一"
R-32 整套风格统一
- 适用范围:全套PPT
- 判定方式:视觉判断
- PASS:翻页时感觉是同一个作品,不是拼拼凑凑的
- FAIL整改:找出风格不一致的页,统一调整
- 优先级:P2
G 组 · 排版质量与能力边界(R-33 ~ R-40)
> 本组的特殊性:R-33~R-36 的度量可由脚本算出(status: auto),
> R-34/R-37~R-40 需要渲染或视觉判断(status: needs_review)。
> needs_review 不等于"不用查"——脚本必须输出 NEEDS_REVIEW 并进入待复核清单,
> 由人工给出结论后写进 resolutions.json 才算闭环(见第 4.6 节)。
R-33 字号不低于场景下限
- 适用范围:每页正文类文字
- 判定方式:脚本可算。下限由观看几何给出,不再取自被缩放的 roles.body.target:
floor_pt = page_h × R / (200 × cap_ratio)(DISCAS = ANSI/INFOCOMM V202.01:2016 §4.3.4)。
R = 该场景的观看比(constants.viewing_ratio:screen 3.4 / online 5.2 / meeting 6.0 / stage 9.2)。
screen 档按 DISCAS §1.4(明文排除单用户显示器)回落 constants.body_size_min_screen(12pt)。
- 输出:本版先只出 WARN(阶段 1);同时打印整本能力陈述
本稿正文参照 X pt → 可支撑观看比 R_max=Y(场景需 R=W)。
- 不适用:params.shrink_roles 内的角色(caption 图注 / running 页眉页脚页码)
——它们本该比正文小,把它们的字号顶到正文下限等于取消层级
- 整改:修复器 f_font_size_min 只在本稿自身尺度内统一(floor × ts_scale),
严禁把 DISCAS 绝对下限接进修复器——那会把紧凑稿改成大字报("傻大粗")。
「本稿尺度不足以支撑该场景」是排版整改解决不了的问题(需换稿/换场景/换屏)。
- 优先级:P0(可用性底线,不受审美护栏约束)
- 让位:R-16 色块内边距、R-11 文字重叠
R-34 行距与段距
- 适用范围:每页多行文本
- 判定方式:<a:lnSpc> 在 XML 里可读(spcPct = 相对单倍行距的百分比),
但 m_line_spacing 目前是空壳(直接返回 NEEDS_REVIEW)→ 待接通
- PASS(现行 params):行距在 1.2 ~ 1.5 倍之间
- ⚠ 已知参数方向错误(待修):max = 1.5 把 WCAG SC 1.4.12 的"用户覆盖容忍度下限"
当成了"舒适度上限"(原文 Note 1:"Content is not required to use these text spacing values")。
实测舒适区应为 1.2 – 1.7 em,≥2.0 才开始损害(Rello 2016,104 人眼动)。
按现参数本测试稿 1078/1078 个文本全部 FAIL —— 这本身就是方向错的反证。
- 优先级:P1
R-35 页内颜色≤3种
- 适用范围:每页文字颜色(背景色不计入)
- 判定方式:脚本可算。统计该页所有 run 的 srgbClr 去重
- FAIL整改:合并相近色值
- 优先级:P1
R-36 页内字号≤5种
- 适用范围:每页
- 判定方式:脚本可算。统计该页所有 run 的 sz 去重(超大装饰数字算在内)
- FAIL整改:精简字号档位——优先归到 type-scale.json 的合法档位
- 优先级:P1
R-37 动画克制
- 适用范围:每页
- 判定方式:XML 可检测 <p:timing> 节点存在性,动画类型需人工判 → NEEDS_REVIEW
- FAIL整改:删除飞入/旋转/弹跳动画
- 不适用:镜头推进 / 关系揭示类动画
- 优先级:P2
R-38 项目符号样式
- 适用范围:含项目符号的文本
- 判定方式:XML 可读 buChar,是否美观需人工判 → NEEDS_REVIEW
- FAIL整改:替换默认圆点为自定义符号
- 不适用:条目少于 5 条
- 优先级:P2
R-39 表格规范
- 适用范围:graphicFrame 内的表格
- 判定方式:表格结构与样式(列宽/行高/单元格内边距)需人工确认 → NEEDS_REVIEW
- FAIL整改:统一列宽行高与单元格内边距
- 优先级:P1
R-40 图片不变形
- 适用范围:pic 图片
- 判定方式:XML 难取原图尺寸,需视觉确认 → NEEDS_REVIEW
- FAIL整改:恢复原始宽高比
- 不适用:有意为之的裁切
- 优先级:P1
H 组 · 存在性审查(R-41)
> 本组是「元规则」——前面 40 条全部只回答「这个元素排得好不好看」,
> 本组回答的是「这个元素该不该存在」。
> 一个与页面目标毫无关系的装饰件,只要排得整齐,就能在其余 40 条下拿满分。
> 这是规则体系的结构性盲区:排版规则无法识别冗余,只会把冗余排得更整齐。
> 判据根源(两位设计者的共识)
> - 许岑《征服世界的美学暴力》:每个元素服务于本页表达;
> 说不出服务什么,就是冗余——举证责任在元素一方。
> - 佐藤可士和「超整理术」:「不是元素删减,而是剥离冗余、保留核心本质」。
> 剥离 ≠ 删减:删减是审美偏好,剥离是举证判断——
> 必须先证明它「对沟通零贡献」,而不是「我不喜欢它」。
> → 故本机制不做主观删减,而是让元素逐项举证其对本业表达的作用。
R-41 装饰件须服务页面目标 —— 「存在性四问」评判链
- 核心原则:不需要任何「为了存在而存在」的东西。
每一个元素都必须对本页的目标起作用,否则移除。 - 适用范围:
deck(跨页扫描全部纯图形元素) - 评判机制——四问,任一为「是」即保留(服务于表达):
| # | 问题 | 判据(机械化) | 为「是」的含义 |
|---|---|---|---|
| Q1 | 承载信息? | 有文字 / 命中正向语义命名约定(如 _rule_*/_icon_*/divider_*;中英文工具默认名如「矩形 1」「Rectangle 1」除外) |
它在「说话」,含信息 |
| Q2 | 建立层级? | 作者以正向语义约定命名声明用途(如 _rule_h_*) |
它标记了主次或章节边界 |
| Q3 | 引导视线? | 与更重的文本元素几何邻近(<8pt / <40pt)且同色呼应 | 它指向主角或划分区域 |
| Q4 | 全站一致? | 跨页出现率 ≥ 80% | 它是全站全局件(页眉条 / logo / 底纹),作者有意,保留不误报 |
保留条件:Q2(语义声明)或 Q3(服务内容)或 Q4(全站一致)任一为真 → 保留。
冗余条件:默认命名(中英文)且非全站一致且不与内容呼应 → 四问全否 → NEEDS_REVIEW。
> Q2 的范围约束:仅认正向语义约定(含 _rule_/_icon_/_divider_/... 等前缀),
> 纯占位名(decor/shape/temp/未命名 等)不计数——否则攻击者把装饰件
> 任意改名即可绕过本规则(第 3 轮红队发现的绕过路径)。
- 四问全为「否」→ 判定冗余 →
NEEDS_REVIEW。
报告附同义多色值作为佐证强度(种数 / 色值 / 是否明度分层)。 - ★ 为什么 Q1~Q4 能机械化:四问全部可归约为元素自身属性(文字/命名)
与元素间几何关系(邻近/同色/跨页分布)——不需要理解页面语义。
实测(第 3 轮回归):匿名小长条(默认名「Rectangle 1」)被点名;语义命名的
_rule_h_*规则线 Q1/Q2 为真,零误杀。规则因此有区分力,不是「见装饰就杀」。 - 为什么只标记不删除:删除元素属于技能定位中的「需显式授权」灰色区。
脚本给出证据链,由使用者裁决——这才符合「不改内容、只做克制处理」的边界。 - 报告呈现:跨页同类问题在「待人工复核清单」中合并为一条并注明影响页数
(避免同一问题被重复报 50 次);逐页矩阵仍保留每页一行,确保不漏。 - 优先级:P1
> ⚠️ 反面教训(判据设计):Q2 初期曾用「位于页眉带且与标题垂直邻接」作几何判据,
> 实测把「压叠在页眉文字上」的装饰件全部误判为合格——页眉带里任何小件都会邻接标题,
> 该判据没有区分力。「标记作用」是语义属性,只能由作者的命名声明来举证。
> 教训:判据必须有区分力,能同时通过正例与反例,否则等于没有。
>
> 第 3 轮再次修正的三处硬伤(此前 R-41 在真实稿上召回率 0%、误报率 100%):
> 1. 中文默认名失明——旧版 DEFAULT_NAME 仅匹配英文,中文稿「矩形 1」等 100% 失明;
> 现补中文默认名全集。
> 2. Q4 逻辑倒置——旧版「跨页率 < 80% → 随内容变化 → 放行」,使真正孤立的匿名装饰
> (只出现 1~3 页)被一律放行,而跨页 80%+ 的页眉固定条反而被误报;现改为
> ≥ 80% 视为全站件保留,< 80% 的匿名件才进入冗余判定。
> 3. 任意改名绕过——旧版「非默认名即放行」,攻击者把装饰件改名成任意字符串即可豁免;
> 现 Q2 仅认正向语义约定,纯占位名不计数。
第 4 部分 · 红线清单(一眼否决,P0优先级)
出现以下任何一条,直接打回:
- [ ] 文字被页面边缘截断(R-07 FAIL)
- [ ] 文字之间明显重叠(R-11 FAIL)
- [ ] 色块内文字溢出四边(R-16 FAIL)
- [ ] 配色对比度太低看不清(R-17 FAIL)
- [ ] 页头/页脚/页码跨页位置不一致(R-10 FAIL)
- [ ] 文字铺满页面,四周无呼吸边距
- [ ] 出现默认 Office 剪贴画 / 艺术字 / 3D 特效
- [ ] 数据图表带多余网格线、3D 柱、渐变填充
- [ ] 存在「为了存在而存在」的装饰件——无文字、无命名、不随内容变化,
对页面目标无贡献(R-41 命中后必须人工裁决)
第 4.5 部分 · 约束冲突与修复顺序
> 排版本质是多条约束同时作用于同一个元素。逐条顺序整改必然互相破坏——
> 修 R-16(色块加高)可能破坏 R-05(对齐一致),这不是"某条规则错了",是没按顺序修。
修复顺序(必须按这个顺序,不能乱)
- 母版层:先改母版/layout,一次性统一页头页脚页码位置
- 栅格对齐层:横纵对齐、安全边距、同类元素间距
- 字号字重层:统一字号阶梯、拉开层级
- 配色层:统一色值、修对比度
- 容器布局层:色块大小、内边距、内容居中
- 微调整层:最后才动细节间距
约束冲突仲裁
遇到两条规则打架时,按以下原则决策:
| 冲突 | 谁让位 | 原因 |
|---|---|---|
| R-15(内容决定容器大小) vs R-05(横向对齐一致) | R-15 让位 | 三列等宽布局时,卡片尺寸由版面对齐决定,不能逐卡按内容缩宽窄不一 |
| R-16(内边距≥12pt) vs R-18(内容占色块≥60%) | R-18 让位 | 等宽等高多列布局天然不满足"内容占60%",这是设计意图 |
| R-09(间距落在8pt栅格) vs R-25(多行均分) | R-25 让位 | 均分出来的行距不一定刚好是8的倍数,视觉均匀比栅格精确重要 |
| R-03(背景全套统一) vs R-01(章节分隔页) | R-03 让位 | 章节页是设计意图,允许单独深色 |
> 遇到冲突不要硬修。先标记"约束冲突",再按上表决策。
> 批量脚本自动修时,每修一轮必须重跑全量检查,确认没有引入新问题。
上表已下沉为可执行数据:rules/rules.json 中每条规则的 yields_to 字段。
整改引擎据此自动生成护栏集,无需人肉记忆。新增冲突时改 JSON,不改脚本。
第 4.6 部分 · 检查引擎(强制执行,不得用肉眼代替)
第 3 部分的总表由 scripts/check_layout.py 执行,规则数据在 rules/rules.json。
改规则改 JSON,不要改脚本。
用法
python scripts/check_layout.py <pptx路径> --out <报告目录> --scene online|meeting|stage \
[--resolutions 人工复核结论.json]
- 零依赖:仅用 Python 标准库,任何环境可直接运行(豆包环境同样适用)
- 产物:
report.json(全量矩阵,机器可读)+report.md(逐页全 41 条,人读) --scene会覆盖规则内的场景设定(历史 bug:rules.json 里写死 online 会吃掉命令行传参)
四态含义(关键)
| 状态 | 含义 | 怎么处理 |
|---|---|---|
| PASS | 规则适用且达标 | 无需处理 |
| FAIL | 违规 | 按该规则"整改动作"修 |
| WARN | 提示级偏离 | 视情况修 |
| NA | 本页不适用,附明确原因 | 无需处理,但原因必须成立 |
| NEEDS_REVIEW | 脚本能力不足,需人工/视觉判断 | 必须人工过一遍,禁止当作 PASS |
| CLOSED | 已有明确人工复核结论 | 已闭环,可交付 |
> NA 和 NEEDS_REVIEW 的区别:NA 是"这页确实没有这个对象",NEEDS_REVIEW 是"有这个对象但我算不准"。
> 把 NEEDS_REVIEW 当 PASS 交付,等同于漏检。
NEEDS_REVIEW 必须闭环(否则等于没查)
NEEDS_REVIEW 不是最终状态,它代表"检查尚未完成"。
复核完成后必须把结论写入 resolutions.json,该项才会变成 CLOSED:
{
"第12页|R-02": {"result": "CONFIRMED_OK", "by": "张三", "note": "骨架匹配封面版式", "at": "2026-10-10"},
"*|R-01": {"result": "EXEMPT", "by": "张三", "note": "本套不适用页面类型判定", "at": "2026-10-10"}
}
"页码|规则ID"精确定位一条;"*|规则ID"表示该规则全套通过result取值:CONFIRMED_OK/CONFIRMED_BAD/EXEMPT- 查找顺序:
--resolutions指定 →--out目录 → pptx 同级目录
门禁同时卡住两类:P0 级 FAIL 与 P0 级未闭环 NEEDS_REVIEW。
只卡 FAIL 会让"没查出来"混进交付。
覆盖保证
引擎对「每一页 × 每一条规则」都产出一条记录,
报告总行数必须 = 页数 × 规则数。对不上就是漏跑了,必须排查后重跑。
report.md 的「逐页完整审查清单」列出全部 41 条(含 PASS),
便于人工逐条核验"确实每条都跑过",而不是只看到有问题的那些。
NEEDS_REVIEW 真空行分类(G3)
NEEDS_REVIEW 不是均质的"算不准"。每条 NEEDS_REVIEW 行附加 vacuum_reason 字段,
标明"为什么算不准",分 4 类:
| 分类 | 含义 | 处置方式 |
|---|---|---|
visual_only |
纯视觉判断——机器无法量化(如"主角是否突出"、"风格是否统一") | 必须人眼看,无法快速闭环 |
engine_limit |
引擎能力限制——XML 可读但算不准(如"文字实际渲染高度") | 需渲染引擎,人工复核 |
data_missing |
输入数据缺失——对象存在但关键属性不可得(如"图片原图尺寸") | 补数据后可重算 |
structural_na |
结构性不适用——该页确实没有该对象 | 可直接填 EXEMPT 快速闭环 |
> structural_na 的条目逻辑上可视为 NA(该页确实没有该对象),但因覆盖保证要求
> 每页每规则各一行,仍标记为 NEEDS_REVIEW。人工复核时可将此类直接填 EXEMPT 快速闭环。
> 报告中「七、NEEDS_REVIEW 真空行分类」段落会列出各分类的条数与涉及规则,
> 让使用者一拿到报告就知道哪些是"机器永远算不出"、哪些是"这页没有该对象"。
能力矩阵(脚本算不了的要人工补)
| 能力 | 状态 |
|---|---|
| 坐标 / 尺寸 / 字号 / 颜色 / 间距 / 重叠 / 对比度 | 可精确计算 |
| 跨页一致性(标题位置 / 字号 / 配色 / 字体 / 背景) | 可精确计算 |
| 文字实际渲染高度(估算:段落数 × 字号 × 1.25,并按框宽估折行) | 估算值,非精确;已用于重叠/内边距判定以降低假阳性 |
| 是否溢出文本框、多行精确行距 | 算不准 → NEEDS_REVIEW |
| 表格 / 图表 / SmartArt / 艺术字内部结构 | 读不到 → NEEDS_REVIEW |
| 主角是否突出、骨架是否匹配、风格是否统一 | 需视觉判断 → NEEDS_REVIEW |
交付门禁
存在以下任一情况,脚本 exit 1,不得交付:
- P0 级 FAIL(明确的违规)
- P0 级 NEEDS_REVIEW 未闭环(查不准且没人看过)
只卡 FAIL 是不够的——那会让"没查出来"混进交付。
第 4.7 部分 · 整改引擎(自动修,不得凭感觉手动挪)
第 4.6 只负责"查出问题"。要自动修,用 scripts/fix_layout.py。
python scripts/fix_layout.py <pptx路径> [--out 输出.pptx] [--scene online] [--rounds 3]
三条铁律(脚本强制执行,不是建议)
- 绝不修改任何文字内容。
修复前后逐条比对所有<a:t>,只要有一个字符不一致 →exit 3,不输出文件。
本技能是纯排版轨道:只调位置 / 尺寸 / 对齐 / 间距 / 字号 / 字重 / 行距 / 颜色 / 容器。 - 分层修复 + 双重护栏(合规 + 审美)。
修复顺序即 4.5 的 6 层顺序。每一层的每一页改完立即重算:
- 若破坏了更高优先级约束 → 该整页回退
- 若该页审美分下滑超过容差(默认 3 分) → 该整页回退
- 若本条规则没改善却产生了位移 → 也回退(克制原则,不做无收益扰动) - 迭代收敛。默认 3 轮,每轮输出改善/恶化明细,整轮无改善即停。
为什么要有"审美护栏"(实测结论,不是设计洁癖)
合规整改会把页面改丑,这不是理论风险。实测:
| 维度 | 原始稿 | 只做合规整改 | 结论 |
|---|---|---|---|
| hierarchy 层级 | 88.3 | 84.2 | 字号被统一后阶梯压平 |
| emphasis 焦点 | 68.7 | 64.3 | 抬正文后标题占比被稀释 |
| density 比例 | 68.2 | 76.3 | 字号抬升,此项改善 |
R-33 修法的三代演进(勿回退)
| 版本 | 做法 | 实测结果 |
|---|---|---|
| v1 | 把每个 < 下限的 run 一律顶成下限(11/13/15.5 → 18pt) | hierarchy -4.1、emphasis -4.4,阶梯被压平 |
| v2 | 按页内比例抬升 s × (floor / s_min) |
有害:放大系数逐页不同(第5页 1.636、第12页 1.895),同一角色在不同页取值不同,产出 20.8 / 24.6 这类无设计含义的算术残渣。字号种类 9 → 12 种(劣化) |
| v3(现行) | 按角色统一:由 type-scale.json 定出「角色 → 目标字号」(全 deck 唯一),再按角色双向归位(低于目标抬上来、高于目标拉下来) |
见第 4.9 节 |
v2 的错误必须记住:它把「下限」当成了「缩放尺」。
R-33 的语义是「不许小于 X」,不是「按比例放大」。只看"每页最小正文"决定系数,
就必然产生逐页漂移——这是"字体规则不一致"的根源。
为什么 v3 必须"按角色"而不是"按页"
- 规则说的对象是「正文这一类」(角色),修复器却在「这一页内」做 → 粒度错配。
- 统一是全局性质:逐页 accept/reject 会让 A 页统一了、B 页没统一,字号种类反而更多
(实测 9 → 15 种)。所以字号统一被独立为「阶段 0」,不参与逐页回退。 - 角色判定必须位置优先:若用"当前字号"判角色,改完字号角色就漂移
(页脚 9.5pt 抬到 17pt 后被判成 label,又违反 label 下限)→ 循环依赖。
正确语义:元素在哪个槽位,就扮演什么角色;字号是角色的属性,不是角色的定义。 - 判定基准必须固化:
body_ref若每次重算会自我漂移(整改后 23pt 成最高频,
body_ref从 11 漂到 23,正文 20pt 反被判成图注)。
现由整改器写入<输出>.typescale-meta.json,检查器优先读它。
★ R-33 保守门禁:证据不足时拒绝自动统一字号(拒绝自动统一字号)
> 改错比不改更糟。 R-33 是"锦上添花"的层级规则,不是红线(R-07 溢出等)。
> 当"从稿件反推字号基准"的证据不足时,宁可不动,把差异留给 NEEDS_REVIEW 人工裁决,
> 也绝不能用 1 页样本猜一个基准、再按错误基准改写全稿的字阶。
为什么必须加这道门禁(实测教训):R-33 的一切判断都建立在"从整份稿子反推基准与角色"之上,
但反推只在样本足够时可靠。构造稿(单页 32pt 引号装饰 / 27pt 主标题 / 12.5pt 卡片说明 / 11pt 正文)实测:
| 实现 | 结果 | 病灶 |
|---|---|---|
| 修门禁前 | 32→23.8 / 27→11.2 / 12.5→11.2 / 11→9.4 | 27pt 主标题被压到与卡片说明同级,设计层级被抹平 |
| 只修"平票取大档" | 主标题仍被压到 11.2pt | 换了个方向的破坏——1 页样本本就无法反推基准 |
| 加保守门禁(现行) | 四个设计性字号全部原样保留 | 拒绝改写,交人工复核 |
三道门禁(任一不满足即 return 0,不改任何字号):
| 门 | 阈值 | 常量名(fix_layout.py) |
理由 |
|---|---|---|---|
| 有效页数 | ≥ 3 | MIN_PAGES_FOR_UNIFY |
页数太少,全稿统计无意义 |
| 实测字号档位 | ≥ 4 | MIN_BANDS_FOR_UNIFY |
档位太少,delta 分档失去分辨力(装饰大字与标题会挤进同一档) |
| 参与统计的 run 数 | ≥ 30 | MIN_RUNS_FOR_UNIFY |
样本太少,众数不稳,body_ref 易被偶发字号带偏 |
留痕不许静默:拒绝时写 ts['_unify_declined'],经 save_meta 落盘到
<输出>.typescale-meta.json,check_layout 在控制台与 report.md 顶部双重提示
"字号统一已被主动放弃(P1-2 保守门禁)"。否则用户看到字号没被统一却不知为何,
会误以为'检查过了、没问题' —— 这与"程序跑了=检查过了"是同一类误解。
不影响正常稿:真实 56 页稿(56 页 / 7 档 / 大样本)门禁不触发,body_ref 仍 11.0,
R-33 行为与门禁前完全一致(改动 0 处、FAIL +0)。逐页模式 --pages 12 同样不触发——
fx.pages() 始终是整稿页数,--pages 只做目标页过滤、不截断。
可用性底线不受审美护栏约束
R-33(字号下限)、R-17(对比度)、R-07(安全边距)、R-11/R-12(重叠)属看得清问题,
不是审美问题。为了"好看"去否决可读性修复是本末倒置 → 见脚本 AESTH_EXEMPT。
实测对比:不加豁免时,审美护栏会拦掉 9 页 R-33 和 4 页 R-17,P0 从 29 涨到 41;
加上豁免后 P0 回到 29,同时仍拦住了 R-23 那 5+3 页真正会拉低审美的改动。
护栏集怎么来的(不靠硬编码)
引擎从 rules.json 已有的两个字段自动推导,不给任何单条规则写特例:
| 被修规则 | 护栏集(不得破坏的约束) |
|---|---|
| P0 规则 | 其余全部 P0(同级互斥,谁也不许踩谁) |
| P1 规则 | 全部 P0 |
| P2 规则 | 全部 P0 + P1 |
| 任意规则 | 额外并入自身的 yields_to(承载 4.5 仲裁表里优先级推不出的例外,如 R-25 让位 R-09) |
实测意义:R-19(P1,容器内间距)曾被整层采纳,代价是踩坏 R-16(P0,内边距)。
护栏上线后变为「32 处采纳 / 3 页回退」,不再出现"P1 换 P0"的倒挂。
修复器覆盖现状(必须显式,不得让人误以为全部会改)
引擎启动时会打印"可自动修复的规则"清单,并对无修复器却在顺序中的规则告警。
(历史上 R-18 曾在修复顺序里空跑——已修。)
| 规则 | 状态 | 说明 |
|---|---|---|
| R-05 R-06 R-07 R-11 R-12 R-16 R-17 R-19 R-22 R-23 R-24 R-33 | 已实现 | 见脚本 FIXERS |
| R-08 R-09 R-13 R-18 R-25 R-26 R-35 R-36 | 只查不改 | 涉及栅格/分组/语义分组,硬改风险大于收益 |
| R-03 R-10 R-27~R-31(跨页) | 只查不改 | 需先定"以哪页为准",属设计决策 |
| R-01 R-02 R-04 R-14 R-15 R-21 R-32(语义) | 不实现 | 需视觉判断 |
脚本拒绝修的,必须人工决策,不要硬改
护栏全回退 = 引擎判定"这页没有既安全又有效的改法"。
这时正确动作是如实上报给用户决策,不是强行挪动。
典型例子:R-03(整页背景统一)报 21 页深色 #141414 vs 全套白色 #FFFFFF。
这不是排版瑕疵,是深色章节页 vs 浅色内容页的设计选择。
规则自带豁免条件(章节分隔页可豁免),脚本一律不自动统一,
必须由用户决定「统一为浅色」还是「保留深色章节页」。
(同类:R-12 文字压色块时是"把文字收进块内"还是"把色块放大",取决于设计意图。)
内容不变量:不止"文字没变"
文字完整性校验只能证明文本数据没变,不能证明文字仍然完整可见。
R-07 缩小文本框宽度后,文字可能重新换行、增加行数甚至被裁切。
因此交付前除文字比对外,必须人工确认:
- 没有文字因框变窄而被裁切、遮挡或溢出页面
- 字号抬升后没有撞到相邻元素或容器边界
第 4.8 部分 · 审美质量层(与合规层并列,不是附属)
合规层回答"有没有犯规",审美层回答"好不好看"。两者是两个独立目标,
不存在"合规了自然就好看"——实测中合规整改一度把审美改差。
python scripts/aesthetic.py <pptx路径> [--out 目录]
核心模型:视觉重量 = 面积 × 可见度
可见度 = clamp(|ΔL*_元素 - ΔL*_背景| / 40, 0.15, 1.0)
一个 156pt 的 #1E1E1E 巨型数字压在 #141414 深色底上,
面积巨大但几乎看不见——它不是视觉重心,也不是主角。
用纯面积算重心,会把这个隐形元素误判成页面上最重的东西。
(实测:章节页 02~07 因此被误判为"层级倒挂、重心偏上",修正后 A 级 7 页 → 21 页。)
同类地,超大字号 + 极低对比(≥2.5×中位字号 且 ΔL*<20)判为装饰性元素,
不参与信息层级判定,也不计入"标题/正文字号"统计。
六个维度(全部可计算,不靠感觉)
| 维度 | 回答的问题 | 关键度量 |
|---|---|---|
| hierarchy 层级 | 深浅是否服务于主次? | 层级倒挂率、标题正文明度差、明度档位数 |
| composition 构图 | 视觉重心是否恰当? | 面积加权重心、重心到理想位置的偏移量 |
| balance 平衡 | 画面是否偏重一侧? | 以页面中心为支点的左右/上下力矩差 |
| density 比例 | 字在页面里的比例是否合适? | 文字墨量占版率、字号/页高、版面覆盖率 |
| emphasis 焦点 | 第一眼能否辨认主角? | 主角视觉重量占比、主角到三分法焦点距离 |
| alignment 收敛 | 元素是否收敛到少数对齐轴? | 左对齐轴命中率、水平行轴数/元素数 |
输出与定位(关键:不判对错)
产出 0~100 分 + 等级(A/B/C/D/E)+ 每个维度的可执行诊断(含具体数值和改动量)。
- 不设硬门禁:审美没有绝对对错,低于建议线只标记「必须人工过目」
- 但绝不静默:分数、偏移量、明暗差全部量化输出,人只需判断"这个建议对不对"
- 诊断必须可执行:不说"重心不佳",而说"视觉重心偏上 11.8% → 内容整体下移约 64pt"
页面类型差异(不可用同一把尺子)
章节页允许大面积留白,数据页可以高信息密度,观点页需要一句话占据视觉中心。
因此审美区间是参考范围而非绝对标准,且低分页必须结合页面类型人工判断。
report.md 会把低分页单列,但不自动扣分降级。
第 5 部分 · 内容轨道(用户显式授权后才执行)
> 以下规则默认不执行。只有用户明确说"你可以帮我删冗余、合并重复页、提炼文字"时,才进入内容轨道。
- [ ] 一页一个主张:一页讲≥2个主张 → 拆页(需用户确认)
- [ ] 正文>6行 → 提炼(需用户确认)
- [ ] 删掉装饰性、不服务信息的元素
- [ ] 演讲稿内容贴页面 → 移入演讲者注释
- [ ] 填不出唯一主张的页 → 考虑删除或合并(需用户确认)
第 6 部分 · 交付要求
- 改完后输出:
1. 改好的 PPT 文件。
2. 合规报告(report.md):逐页全 41 条、PASS/FAIL/WARN/NA/NEEDS_REVIEW/CLOSED 分布、改了什么。
3. 审美报告(aesthetic.md):总分与六维分、最需人工过目的页面、每页可执行诊断。 - 不编造数据:涉及数据、客户案例时,保留原值或标注"【原案例资料待补】"。
- 用户标记的"不可动内容",原样保留。
交付前必过的七道检查(缺一不可)
| # | 检查 | 通过标准 |
|---|---|---|
| 1 | 覆盖完整 | 报告总行数 = 页数 × 41(逐页模式下本次页数 × 41) |
| 2 | P0 无 FAIL | 0 处 |
| 3 | P0 复核已闭环 | 0 处未闭环 NEEDS_REVIEW |
| 4 | 文字内容未变 | <a:t> 逐条比对一致 |
| 5 | 文字仍完整可见 | 无因框变窄/字号变大而裁切、遮挡、溢出(须人工确认) |
| 6 | 审美未退化 | 审美总分不低于整改前;若下降须说明原因并经用户确认 |
| 7 | 逐页无遗漏 | 逐页进度表已登记全部页,且各页 FAIL 之和 == 全量报告 FAIL 总数 |
> 第 2 条和第 3 条是不同的两件事:一个是"发现了问题没修",一个是"没查清楚也没人看"。
> 第 5 条是提醒:文字完整性校验只能证明文本数据没变,不能证明文字仍然看得见。