@topmindspace/tms-skills 0.3.6 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +74 -0
- package/README.en.md +4 -4
- package/README.md +4 -4
- package/bin/tms-skills.js +9 -1
- package/package.json +1 -1
- package/top-ppt-html/README.en.md +2 -2
- package/top-ppt-html/README.md +1 -1
- package/top-ppt-html/assets/examples/2026-09-09-architecture-graphite-dark.html +43 -14
- package/top-ppt-html/assets/examples/2026-09-09-presentation-business-blue.html +43 -14
- package/top-ppt-html/assets/examples/2026-09-09-research-mckinsey.html +43 -14
- package/top-ppt-html/assets/examples/2026-09-26-topmind-tms-skills-showcase.html +43 -14
- package/top-ppt-html/assets/pptx-export.js +42 -13
- package/top-ppt-html/assets/style-gallery.html +1 -1
- package/top-ppt-html/assets/templates/architecture.html +45 -15
- package/top-ppt-html/assets/templates/presentation.html +45 -15
- package/top-ppt-html/assets/templates/research.html +45 -15
- package/top-ppt-html/scripts/audit_css.py +1 -1
- package/top-ppt-html/scripts/build_pptx.js +136 -25
- package/top-ppt-html/scripts/layout-constants.json +1 -1
- package/top-ppt-html/scripts/regression.py +3 -3
- package/top-ppt-html/scripts/render_compare.py +1 -1
- package/top-ppt-html/scripts/scaffold_report.py +1 -1
- package/top-ppt-html/scripts/sync_runtime.py +14 -14
- package/top-ppt-html/scripts/validate_report.py +4 -0
- package/topmind-cover/README.en.md +1 -1
- package/topmind-cover/README.md +1 -1
- package/topmind-cover/SKILL.md +3 -1
- package/topmind-cover/assets/examples/big-type-wechat.png +0 -0
- package/topmind-cover/assets/examples/big-type.png +0 -0
- package/topmind-cover/assets/examples/brand-launch-wechat.png +0 -0
- package/topmind-cover/assets/examples/brand-launch.png +0 -0
- package/topmind-cover/assets/examples/gan-huo-wechat.png +0 -0
- package/topmind-cover/assets/examples/gan-huo.png +0 -0
- package/topmind-cover/assets/examples/ip-fun-wechat.png +0 -0
- package/topmind-cover/assets/examples/ip-fun.png +0 -0
- package/topmind-cover/assets/examples/magazine-wechat.png +0 -0
- package/topmind-cover/assets/examples/magazine.png +0 -0
- package/topmind-cover/assets/examples/minimal-wechat.png +0 -0
- package/topmind-cover/assets/examples/minimal.png +0 -0
- package/topmind-cover/assets/examples/news-flash-wechat.png +0 -0
- package/topmind-cover/assets/examples/news-flash.png +0 -0
- package/topmind-cover/assets/examples/overview.png +0 -0
- package/topmind-cover/assets/examples/tutorial-steps-wechat.png +0 -0
- package/topmind-cover/assets/examples/tutorial-steps.png +0 -0
- package/topmind-cover/references/cover-styles.md +65 -22
- package/topmind-cover/references/impact-language.md +38 -0
- package/topmind-cover/scripts/crop-cover.py +19 -13
- package/topmind-wechat-post/README.en.md +2 -2
- package/topmind-wechat-post/README.md +2 -2
- package/topmind-wechat-post/SKILL.md +1 -1
- package/topmind-wechat-post/scripts/md2wechat.py +12 -3
- package/topmind-x-article/README.en.md +1 -1
- package/topmind-x-article/README.md +1 -1
- package/topmind-x-article/scripts/md2x.py +7 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,79 @@
|
|
|
1
|
+
## [0.3.9] - 2026-09-29
|
|
2
|
+
|
|
3
|
+
> **本版备发**(tag v0.3.9 待打;npm 待发布;commit = 本轮审计报告落盘时的 `git log` 首条)。
|
|
4
|
+
> 注:0.3.7、0.3.8 未发布,全部内容已并入本版。
|
|
5
|
+
> 根包 0.3.8 → **0.3.9**(patch);4 个技能 `version` 保持不动(top-ppt-html 0.1.19,其余 0.1.0)。
|
|
6
|
+
> 本轮是"新鲜眼睛"横扫(第十一轮):只找前十轮没覆盖的盲区,改动最小。
|
|
7
|
+
|
|
8
|
+
### 代码异味横扫(第十一轮 Worker A)
|
|
9
|
+
|
|
10
|
+
- TODO 注释 6 命中 → 0 真遗留(均为有意为之:文档纪律说明/scaffold 指导注释/校验正则/示例代称)
|
|
11
|
+
- 死代码:全仓 Python + top-ppt-html JS 逐函数交叉 grep,零死函数;12 个 CLI 参数逐个验证全部在用
|
|
12
|
+
- 跨技能一致性修复:19 处错误信息半角冒号 `错误:` → 全角 `错误:`(多数派 47 处);`validate_report.py` 加 `-h/--help` 早退(exit 0),与其他 argparse CLI 一致
|
|
13
|
+
- 重复逻辑(仅记录,不重构):`esc()` HTML 转义三处逐字相同、`read_frontmatter()` 跨技能同构、`load_constants()` 各自实现——均为四技能同构门禁的有意设计
|
|
14
|
+
|
|
15
|
+
### 对抗输入测试(第十一轮 Worker B:5 真崩溃全部修复)
|
|
16
|
+
|
|
17
|
+
- `bin/tms-skills.js`:`--to` 指向已存在文件时 `mkdirSync` 抛未捕获堆栈 → try/catch 干净报错 exit 1
|
|
18
|
+
- `md2wechat.py`:`resolve_image` 的 `shutil.copy2`/`os.makedirs` 未捕获 OSError(磁盘满/目录当图片)→ 干净报错 exit 1
|
|
19
|
+
- `md2x.py`:输出写入 `mkdir`+`write_text` 未捕获 OSError → 干净报错 exit 1;目录当输入的报错文案修正("找不到输入文件"→"输入是目录不是文件")
|
|
20
|
+
- `crop-cover.py`:`out_dir.mkdir` 与渲染循环 `out.save` 未捕获 OSError(磁盘满→截断 PNG)→ 干净报错 exit 1
|
|
21
|
+
- 对抗矩阵:100KB 单行/emoji+零宽+混合换行/非法 UTF-8/空文件/纯标题/48MB 图片,其余全部干净通过
|
|
22
|
+
|
|
23
|
+
### 文档一致性(第十一轮 Worker C)
|
|
24
|
+
|
|
25
|
+
- 审计结论抽查 5 处全部为真(architecture 归一化/SKILL.md 13KB 预算/cover 触发词/ip-fun 原位垫色块补丁/footer 移出 content 标记)
|
|
26
|
+
- SKILL.md vs --help 漂移修复 1 处:wechat-post SKILL.md 注释声称 `--workspace` 参数,全仓无此参数 → 改为 `--base`
|
|
27
|
+
- README 示例 10/10 实跑通过(/tmp 干净目录,本地包安装)
|
|
28
|
+
|
|
29
|
+
## [0.3.8] - 2026-09-29
|
|
30
|
+
|
|
31
|
+
> **本版未发布**(未打 tag、未推 npm;0.3.8 全部内容已并入 0.3.9)。
|
|
32
|
+
> 根包 0.3.6 → **0.3.8**(patch);4 个技能 `version` 保持不动(top-ppt-html 0.1.19,其余 0.1.0)。
|
|
33
|
+
> 本轮只动 top-ppt-html + 文档:渲染产出目检修复(A)+ PPTX 双引擎保真修复 11 bug(B)+ 文档修正(C)。
|
|
34
|
+
|
|
35
|
+
### 模板 footer 修复(第十轮 Worker A:渲染产出目检)
|
|
36
|
+
|
|
37
|
+
- `top-ppt-html/assets/templates/{presentation,research,architecture}.html`:`<footer>` 移出 `__TOPPPT_CONTENT_START__`/`__TOPPPT_CONTENT_END__` 标记之外——此前自动渲染取 content 区间时会连带删除页脚,目检确认已修复。
|
|
38
|
+
|
|
39
|
+
### PPTX 双引擎保真修复(第十轮 Worker B:PPTX 实检,11 bug 全部像素复验)
|
|
40
|
+
|
|
41
|
+
- `top-ppt-html/scripts/build_pptx.js` + `assets/pptx-export.js`(双端同规则):
|
|
42
|
+
- 图表数据标签小数位:按模型数值实际小数位(上限 2 位)生成 format code,修复小数标签被截断
|
|
43
|
+
- hbar 条形图:类目轴自下而上绘制,反转数据使首项居顶;单系列颜色按数据点分配(跟随数据归属,与 A 通道一致)
|
|
44
|
+
- streamgraph 退化:相邻 ribbon quad 沿走向微叠 0.02in,消除拼接处抗锯齿发丝缝
|
|
45
|
+
- boxplot:min 标签默认移到须线帽下方,不再被组标签带压住叠印
|
|
46
|
+
- marimekko:单元格归一化兼容裸数值或 `[标签,数值]` 对(裸数值沿用旧行为),修复 NaN 崩坏
|
|
47
|
+
- pyramid:标题列宽按层内宽比例(labelFrac≈0.3)分配,顶层窄时改单框混排,修复窄层标题/说明叠印
|
|
48
|
+
- KPI:第 4 个起的支撑指标不再静默截断——容量按最小允许行高计算、行高按全部指标自适应压缩,超容显式告警
|
|
49
|
+
- donut 图例:百分比列 x(`donut.legendPctX` 5.3 → 10.8)右移,修复图例数值被圆环覆盖
|
|
50
|
+
- table:内容高度逐格预估、超高全表收字号,字号触底仍装不下则显式告警(不再撑高行压脚注)
|
|
51
|
+
- exhibit 徽标:纯编号自动补 `Exhibit ` 前缀(与 HTML 视觉一致),已带前缀的不重复
|
|
52
|
+
- sankey/streamgraph note:note 与 footnote 均参与 `chartBottom` 结算,修复 note 重叠
|
|
53
|
+
- `top-ppt-html/scripts/layout-constants.json`:`donut.legendPctX` 5.3 → 10.8(单源),已由 `sync_runtime.py` 同步至 `pptx-export.js`、画廊、`templates/*.html`、示例的内联副本与 `__TOPPPT_RUNTIME_SHA__` 戳
|
|
54
|
+
|
|
55
|
+
### 文档修正(第十轮 Worker C)
|
|
56
|
+
|
|
57
|
+
- 根 README(中英):当前线 0.2.x → 0.3.x;`topmind-cover` "17 张双尺寸" → "16 张双尺寸 + 1 张风格总览图"
|
|
58
|
+
- `docs/PUBLISHING.md`:`latest` 指向 0.3.1 → 0.3.6
|
|
59
|
+
- `topmind-wechat-post/README`(中英):二级标题编号示例 `01` → `1`
|
|
60
|
+
|
|
61
|
+
## [0.3.7] - 2026-09-29
|
|
62
|
+
|
|
63
|
+
> **本版未发布**(未打 tag、未推 npm;0.3.7 全部内容已并入 0.3.8)。
|
|
64
|
+
> 根包 0.3.6 → **0.3.7**(patch);4 个技能 `version` 保持不动(top-ppt-html 0.1.19,其余 0.1.0)。
|
|
65
|
+
> 本轮只动 topmind-cover:文字排印与装饰系统(第九轮)。
|
|
66
|
+
|
|
67
|
+
### 文字排印与装饰系统(第九轮)
|
|
68
|
+
|
|
69
|
+
- `topmind-cover/references/impact-language.md`:新增第七节"文字装饰系统"(+38 行):6 种可靠装饰(关键词变色/字号对比/色块衬底/轻微阴影立体/手绘划线圈注箭头/小元素旋转≤8°)各给效果/风险/适用风格/提示词写法四列 + 8 风格各 2~3 种必用装饰指定 + 7 条装饰禁令(禁大标题透视/一句话超 3 色/三重叠加/竖排+旋转/色块吞字/装饰压笔画/装饰超量)
|
|
70
|
+
- `topmind-cover/references/cover-styles.md`(316→359 行):8 风格提示词新增"文字特效"段(中英双语,全部含色号与量化参数,如"钩子词放大 1.5 倍""色块高 1.2 倍字高""投影偏移 1/10 字高");各风格"绝不"清单追加装饰禁令;news-flash 单色铁律放宽为"纯黑打底+爆点词朱红点睛"(仍 ≤3 色,与参考图布局/配色/文字结构全错开);brand-launch 品牌词发光描边改为荧光绿块衬底
|
|
71
|
+
- `topmind-cover/SKILL.md`(114→116 行):冲击力自检清单追加第 9/10 条——中文逐字正确(装饰未导致错字/乱码/笔画粘连)、装饰手法 ≤ 该风格指定数量(minimal 只许 1 种);"必过 8 项"同步为"必过 10 项"
|
|
72
|
+
- 16 张样张全部重生成(标题沿用第八轮):三重目检通过——中文逐字正确(装饰是错字重灾区,逐字核对)、每张 ≥2 种装饰生效且不乱(minimal 仅 1 种)、与 7 张参考图无实质相似;返工 1 次(magazine 首版比例错误)
|
|
73
|
+
|
|
1
74
|
## [0.3.6] - 2026-09-29
|
|
2
75
|
|
|
76
|
+
> **本版已发布**(commit 5dc0bb8,tag v0.3.6,GitHub Release + npm @0.3.6,latest 已切换)。
|
|
3
77
|
> 根包 0.3.5 → **0.3.6**(patch);4 个技能 `version` 保持不动(top-ppt-html 0.1.19,其余 0.1.0)。
|
|
4
78
|
> 本轮只动 topmind-cover:冲击力升级(第八轮)。
|
|
5
79
|
|
package/README.en.md
CHANGED
|
@@ -55,7 +55,7 @@ npx @topmindspace/tms-skills install topmind-cover
|
|
|
55
55
|
<img src="docs/assets/tms-skills-banner.png" alt="tms-skills · top-ppt-html — formal business presentations" width="960" />
|
|
56
56
|
</p>
|
|
57
57
|
|
|
58
|
-
> **Warning**: do not install `@topmindspace/tms-skills@^2` (2.0.0–2.1.1 deprecated). Current line is **0.
|
|
58
|
+
> **Warning**: do not install `@topmindspace/tms-skills@^2` (2.0.0–2.1.1 deprecated). Current line is **0.3.x** (`latest`).
|
|
59
59
|
|
|
60
60
|
## Skills
|
|
61
61
|
|
|
@@ -64,9 +64,9 @@ npx @topmindspace/tms-skills install topmind-cover
|
|
|
64
64
|
| [`top-ppt-html`](./top-ppt-html/) | **0.1.19** | Formal business decks: paginated HTML + editable 16:9 PPTX; dual delivery · MD3-inspired density; 3 modes × 9 styles; strict 0/0 |
|
|
65
65
|
| [`topmind-wechat-post`](./topmind-wechat-post/) | **0.1.0** | WeChat article lifecycle: package, review, 3 quality gates, inline typography & publish checklist |
|
|
66
66
|
| [`topmind-x-article`](./topmind-x-article/) | **0.1.0** | X long-form one-click publish: Markdown → paste-ready plain text + cover + checklist |
|
|
67
|
-
| [`topmind-cover`](./topmind-cover/) | **0.1.0** | Cover art for X / WeChat: striking, theme-focused; 8-style cover style library +
|
|
67
|
+
| [`topmind-cover`](./topmind-cover/) | **0.1.0** | Cover art for X / WeChat: striking, theme-focused; 8-style cover style library + 16 dual-size example images + 1 style overview |
|
|
68
68
|
|
|
69
|
-
Installer [`@topmindspace/tms-skills`](https://www.npmjs.com/package/@topmindspace/tms-skills) is **0.3.
|
|
69
|
+
Installer [`@topmindspace/tms-skills`](https://www.npmjs.com/package/@topmindspace/tms-skills) is **0.3.9** (whole-repo same-tag releases).
|
|
70
70
|
|
|
71
71
|
## Install
|
|
72
72
|
|
|
@@ -76,7 +76,7 @@ Installer [`@topmindspace/tms-skills`](https://www.npmjs.com/package/@topmindspa
|
|
|
76
76
|
npx @topmindspace/tms-skills list
|
|
77
77
|
npx @topmindspace/tms-skills install top-ppt-html
|
|
78
78
|
npx @topmindspace/tms-skills install top-ppt-html --to ./.claude/skills
|
|
79
|
-
npx @topmindspace/tms-skills@0.3.
|
|
79
|
+
npx @topmindspace/tms-skills@0.3.9 install top-ppt-html # pin
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
```bash
|
package/README.md
CHANGED
|
@@ -53,7 +53,7 @@ npx @topmindspace/tms-skills install topmind-cover
|
|
|
53
53
|
<img src="docs/assets/tms-skills-banner.png" alt="tms-skills · top-ppt-html — formal business presentations" width="960" />
|
|
54
54
|
</p>
|
|
55
55
|
|
|
56
|
-
> **警告**:不要安装 `@topmindspace/tms-skills@^2`(2.0.0–2.1.1 已弃用)。当前线 **0.
|
|
56
|
+
> **警告**:不要安装 `@topmindspace/tms-skills@^2`(2.0.0–2.1.1 已弃用)。当前线 **0.3.x**(`latest`)。
|
|
57
57
|
|
|
58
58
|
## 技能一览
|
|
59
59
|
|
|
@@ -62,9 +62,9 @@ npx @topmindspace/tms-skills install topmind-cover
|
|
|
62
62
|
| [`top-ppt-html`](./top-ppt-html/) | **0.1.19** | 正式商务演示:HTML 可翻页 + 16:9 可编辑 PPTX;双交付 · MD3 密度克制;三模式 × 九风格;strict 0/0 |
|
|
63
63
|
| [`topmind-wechat-post`](./topmind-wechat-post/) | **0.1.0** | 公众号文章全生命周期:交付包、审校改写、质量三关、微信内联排版与发布清单 |
|
|
64
64
|
| [`topmind-x-article`](./topmind-x-article/) | **0.1.0** | X 长文一键发布:Markdown 原稿转可直接粘贴的纯文本 + 封面图 + 发布清单 |
|
|
65
|
-
| [`topmind-cover`](./topmind-cover/) | **0.1.0** | 文章封面配图(X / 公众号共用):震撼醒目主题突出;8 风格封面风格库 +
|
|
65
|
+
| [`topmind-cover`](./topmind-cover/) | **0.1.0** | 文章封面配图(X / 公众号共用):震撼醒目主题突出;8 风格封面风格库 + 16 张双尺寸示例图 + 1 张风格总览图 |
|
|
66
66
|
|
|
67
|
-
安装器 [`@topmindspace/tms-skills`](https://www.npmjs.com/package/@topmindspace/tms-skills) 为 **0.3.
|
|
67
|
+
安装器 [`@topmindspace/tms-skills`](https://www.npmjs.com/package/@topmindspace/tms-skills) 为 **0.3.9**(整仓同 tag 发版)。
|
|
68
68
|
|
|
69
69
|
> SKILL.md frontmatter 除标准 `name`/`description` 外,本仓库扩展了 `action_category` / `triggers` / `triggers_cn` / `updated` 字段供安装器与路由使用。
|
|
70
70
|
|
|
@@ -76,7 +76,7 @@ npx @topmindspace/tms-skills install topmind-cover
|
|
|
76
76
|
npx @topmindspace/tms-skills list
|
|
77
77
|
npx @topmindspace/tms-skills install top-ppt-html
|
|
78
78
|
npx @topmindspace/tms-skills install top-ppt-html --to ./.claude/skills
|
|
79
|
-
npx @topmindspace/tms-skills@0.3.
|
|
79
|
+
npx @topmindspace/tms-skills@0.3.9 install top-ppt-html # 钉版本
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
```bash
|
package/bin/tms-skills.js
CHANGED
|
@@ -140,7 +140,15 @@ function install(skillId, targetRoot, { force = false } = {}) {
|
|
|
140
140
|
}
|
|
141
141
|
const dest = path.join(targetRoot, skillId);
|
|
142
142
|
assertDestOutsideSource(src, dest);
|
|
143
|
-
|
|
143
|
+
try {
|
|
144
|
+
fs.mkdirSync(targetRoot, { recursive: true });
|
|
145
|
+
} catch (e) {
|
|
146
|
+
die(
|
|
147
|
+
`Cannot create install directory: ${targetRoot}\n` +
|
|
148
|
+
` reason: ${e.message}\n` +
|
|
149
|
+
'Choose a --to directory that can be created (not a file, not unwritable).'
|
|
150
|
+
);
|
|
151
|
+
}
|
|
144
152
|
if (fs.existsSync(dest)) {
|
|
145
153
|
if (!force) {
|
|
146
154
|
die(
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
**Let ideas fly — make good thinking visible.** A high-craft skill for **demo reports / formal business presentations**: **HTML + PPT dual delivery** — day-to-day, present with paginated HTML like slides; export **layout-faithful editable PPTX** when needed. **MD3-inspired**: fitting information density, restrained type / shapes / color. Core craft is layout, typography, color, and content structure — not gadget soup.
|
|
11
11
|
|
|
12
12
|
- Skill id: `top-ppt-html`; brand: **TopPPT HTML**
|
|
13
|
-
- Version: **v0.1.19** (same tag as `@topmindspace/tms-skills@0.3.
|
|
13
|
+
- Version: **v0.1.19** (same tag as `@topmindspace/tms-skills@0.3.9`)
|
|
14
14
|
- **Agent entry**: `SKILL.md` → `references/playbook.md` (L1) → L2 on demand
|
|
15
15
|
- **Human maintainers**: this README (install / commands / layout); do not treat it as the generation spec
|
|
16
16
|
|
|
@@ -55,7 +55,7 @@ Also: arrow-key paging; **Esc** closes modals. After style/theme change, re-run
|
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
57
|
npx @topmindspace/tms-skills install top-ppt-html
|
|
58
|
-
npx @topmindspace/tms-skills@0.3.
|
|
58
|
+
npx @topmindspace/tms-skills@0.3.9 install top-ppt-html
|
|
59
59
|
npx github:topmindspace/tms-skills install top-ppt-html
|
|
60
60
|
```
|
|
61
61
|
|
package/top-ppt-html/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
**让 idea 飞,好想法被看见。** 为**演示报告 / 正式商务演示**而生的高品质演示文稿技能:**HTML + PPT 双交付**——日常用可翻页 HTML 等同幻灯片;需要时再导出**版式保真可编辑 PPTX**。参考 **MD3**:合适信息密度、克制文字/图形/颜色。核心工艺是版式、排版、色彩与内容组织——不是 gadget 堆砌。
|
|
11
11
|
|
|
12
12
|
- 技能标识:`top-ppt-html`;品牌名:**TopPPT HTML**
|
|
13
|
-
- 版本:**v0.1.19**(与 `@topmindspace/tms-skills@0.3.
|
|
13
|
+
- 版本:**v0.1.19**(与 `@topmindspace/tms-skills@0.3.9` 同 tag)
|
|
14
14
|
- **智能体入口**:`SKILL.md` → `references/playbook.md`(L1)→ L2 按需
|
|
15
15
|
- **人类维护者**:本 README(安装 / 命令 / 目录);勿把本文件当生成规范
|
|
16
16
|
|
|
@@ -2005,7 +2005,7 @@ window.REPORT_MODEL = {
|
|
|
2005
2005
|
|
|
2006
2006
|
/* __TOPPPT_RUNTIME_START__ */
|
|
2007
2007
|
/* ══ PPTX 导出运行时(assets/pptx-export.js 的内联副本 · 由 scripts/sync_runtime.py 注入,禁止手改) ══ */
|
|
2008
|
-
/* __TOPPPT_RUNTIME_SHA__:
|
|
2008
|
+
/* __TOPPPT_RUNTIME_SHA__:a4c909346759fe9c */
|
|
2009
2009
|
/* ═══════════════════════════════════════════════════════════════════════════
|
|
2010
2010
|
* TopPPT HTML· 浏览器端 PPTX 预览运行时
|
|
2011
2011
|
* 零依赖、随报告单文件分发;OOXML 序列化器(仅供预览,页面不导出文件)。
|
|
@@ -2060,7 +2060,7 @@ function isRec(v) { return !!v && typeof v === 'object' && !Array.isArray(v); }
|
|
|
2060
2060
|
var PW = 13.333, PH = 7.5, MX = 0.6, CW = PW - 2 * MX, EMU = 914400;
|
|
2061
2061
|
var TS_BASE = {"coverTitle":44,"coverSub":18,"h1":30,"h2":17,"lead":14,"body":13,"caption":11,"micro":10};
|
|
2062
2062
|
var MTS = {"presentation":{"coverTitle":44,"coverSub":18,"h1":30,"h2":17,"lead":14,"body":13,"caption":11,"micro":10},"research":{"coverTitle":36,"coverSub":14,"h1":22,"h2":13.5,"lead":11.5,"body":10.5,"caption":9,"micro":8.5},"architecture":{"coverTitle":44,"coverSub":19,"h1":30,"h2":17,"lead":14,"body":13,"caption":11,"micro":10}};
|
|
2063
|
-
var PT = {"layout":{"contentTop":2.35,"contentBottom":6.9,"contentBottomWithNote":6.4,"pageNumY":7.0},"common":{"headEyebrowY":0.48,"headTitleY":0.82,"headRuleY":1.72,"leadY":1.88,"bodyY":2.35,"bodyYWithLead":2.55,"pagerY":7.0},"cover":{"metaY":0.7,"titleY":2.4,"titleH":2.0,"subtitleY":4.5,"subtitleH":0.8},"closing":{"eyebrowY":0.7,"titleY":1.2,"titleH":1.2,"pointsY":3.0,"pointTitleH":0.6,"pointBodyH":1.2},"points":{"listY":2.5,"rowH":0.72,"rowHMin":0.5,"markSize":0.14,"metricY":4.7,"metricW":2.6,"metricValH":0.9,"metricCapY":5.6},"metrics":{"bandY":3.1,"cardH":2.3,"valY":3.45,"valH":1.1,"capY":4.55,"capH":0.7,"gap":0.3,"maxW":2.9},"table":{"y":2.5,"rowH":0.55,"rowHMin":0.32,"headRowH":0.5},"bar":{"hbarY0":2.6,"hbarY1":6.25,"chartX":0.6,"chartY":2.95,"chartW":1.2,"chartH":3.35,"noteY":6.55},"note":{"y":6.55,"h":0.4},"exhibit":{"badgeY":2.35,"chartY":2.75,"chartH":3.25,"soWhatY":6.05,"footnoteY":6.72},"twocol":{"colGap":0.5,"bodyH":3.6,"rowHMin":0.5},"hbar":{"labelW":1.9,"valW":1.0,"rowH":0.55,"barRatio":0.5},"diagram":{"layerBarW":1.35,"layerGap":0.15,"nodeGap":0.15,"bodyStartY":2.9,"maxLayerH":1.15,"nodeMaxW":2.2},"split":{"leftW":0.55,"rightW":0.415,"rightX":0.585,"pointsY":2.7,"rowH":0.78,"capY":2.55,"chartY":3.0,"chartH":3.7,"tableY":2.7,"tableRowH":0.5},"cards":{"startY":3.0,"gap":0.25,"maxH":2.0,"titleH":0.4},"timeline":{"labelY":2.95,"axisY":3.58,"dotY":3.51,"dotR":0.18,"nameY":3.9,"descY":4.45,"descH":1.2},"research":{"col3Gap":0.38,"matrixLabelW":1.5,"matrixCellH":0.85,"matrixY":2.2,"denseTableY":2.2,"denseRowH":0.42,"halfTableW":0.52,"halfChartX":0.57,"halfChartW":0.43},"arch":{"fullStartY":2.1,"fullEndY":6.9,"laneH":0.72,"laneHMin":0.5,"laneGap":0.14,"laneHeadW":1.3,"stepGap":0.12,"stepMaxW":1.9},"kpi":{"heroY":2.9,"heroW":0.52,"heroH":1.6,"dividerX":0.56,"metricY0":2.95,"metricRowH":0.85},"comparison":{"panelGap":0.4,"panelY":2.55,"panelH":3.4,"titleH":0.45,"rowH":0.62},"quote":{"markY":1.75,"textY":2.7,"textH":2.3,"authorY":5.25,"contextY":5.8},"donut":{"centerX":3.05,"centerY":4.6,"r":1.6,"holeR":0.95,"legendX":5.6,"legendRowH":0.55,"legendLabelW":3.4,"legendValW":1.3,"legendPctX":
|
|
2063
|
+
var PT = {"layout":{"contentTop":2.35,"contentBottom":6.9,"contentBottomWithNote":6.4,"pageNumY":7.0},"common":{"headEyebrowY":0.48,"headTitleY":0.82,"headRuleY":1.72,"leadY":1.88,"bodyY":2.35,"bodyYWithLead":2.55,"pagerY":7.0},"cover":{"metaY":0.7,"titleY":2.4,"titleH":2.0,"subtitleY":4.5,"subtitleH":0.8},"closing":{"eyebrowY":0.7,"titleY":1.2,"titleH":1.2,"pointsY":3.0,"pointTitleH":0.6,"pointBodyH":1.2},"points":{"listY":2.5,"rowH":0.72,"rowHMin":0.5,"markSize":0.14,"metricY":4.7,"metricW":2.6,"metricValH":0.9,"metricCapY":5.6},"metrics":{"bandY":3.1,"cardH":2.3,"valY":3.45,"valH":1.1,"capY":4.55,"capH":0.7,"gap":0.3,"maxW":2.9},"table":{"y":2.5,"rowH":0.55,"rowHMin":0.32,"headRowH":0.5},"bar":{"hbarY0":2.6,"hbarY1":6.25,"chartX":0.6,"chartY":2.95,"chartW":1.2,"chartH":3.35,"noteY":6.55},"note":{"y":6.55,"h":0.4},"exhibit":{"badgeY":2.35,"chartY":2.75,"chartH":3.25,"soWhatY":6.05,"footnoteY":6.72},"twocol":{"colGap":0.5,"bodyH":3.6,"rowHMin":0.5},"hbar":{"labelW":1.9,"valW":1.0,"rowH":0.55,"barRatio":0.5},"diagram":{"layerBarW":1.35,"layerGap":0.15,"nodeGap":0.15,"bodyStartY":2.9,"maxLayerH":1.15,"nodeMaxW":2.2},"split":{"leftW":0.55,"rightW":0.415,"rightX":0.585,"pointsY":2.7,"rowH":0.78,"capY":2.55,"chartY":3.0,"chartH":3.7,"tableY":2.7,"tableRowH":0.5},"cards":{"startY":3.0,"gap":0.25,"maxH":2.0,"titleH":0.4},"timeline":{"labelY":2.95,"axisY":3.58,"dotY":3.51,"dotR":0.18,"nameY":3.9,"descY":4.45,"descH":1.2},"research":{"col3Gap":0.38,"matrixLabelW":1.5,"matrixCellH":0.85,"matrixY":2.2,"denseTableY":2.2,"denseRowH":0.42,"halfTableW":0.52,"halfChartX":0.57,"halfChartW":0.43},"arch":{"fullStartY":2.1,"fullEndY":6.9,"laneH":0.72,"laneHMin":0.5,"laneGap":0.14,"laneHeadW":1.3,"stepGap":0.12,"stepMaxW":1.9},"kpi":{"heroY":2.9,"heroW":0.52,"heroH":1.6,"dividerX":0.56,"metricY0":2.95,"metricRowH":0.85},"comparison":{"panelGap":0.4,"panelY":2.55,"panelH":3.4,"titleH":0.45,"rowH":0.62},"quote":{"markY":1.75,"textY":2.7,"textH":2.3,"authorY":5.25,"contextY":5.8},"donut":{"centerX":3.05,"centerY":4.6,"r":1.6,"holeR":0.95,"legendX":5.6,"legendRowH":0.55,"legendLabelW":3.4,"legendValW":1.3,"legendPctX":10.8,"legendPctW":1.3},"steps":{"y":3.05,"barH":1.35,"gap":0.12,"arrowW":0.3,"numH":0.3,"titleH":0.34,"pad":0.08,"maxPerRow":6},"heatmap":{"y":2.6,"labelW":1.7,"headH":0.42,"cellH":0.6,"cellGap":0.06,"legendW":1.6},"pyramid":{"y":2.35,"rowH":0.72,"gap":0.08,"minW":0.34,"labelW":3.2},"bullet":{"y":2.6,"rowH":0.8,"labelW":2.4,"valW":1.7,"barH":0.26},"image":{"y":2.3,"h":4.2,"halfW":0.56,"halfGap":0.06,"capY":6.6,"capH":0.3,"radius":0.09,"noteRowH":0.62,"gridGap":0.16,"gridCols":{"2":2,"3":3,"4":4,"6":3},"gridCapH":0.28,"compareGap":0.3,"compareTagH":0.26,"wallCellH":0.92,"wallGap":0.18,"wallMaxRows":2},"flagbar":{"hdH":0.26,"rowH":0.24,"maxRows":3,"gap":0.12},"sankey":{"y":2.45,"h":4.1,"nodeW":0.32,"nodeGap":0.14,"labelW":1.55,"minBandH":0.22,"maxNodes":12,"maxFlows":24},"treemap":{"y":2.45,"h":4.1,"gap":0.05,"labelMinH":0.34,"maxLeaves":16,"maxDepth":3},"boxplot":{"y":2.7,"h":3.7,"labelW":1.5,"groupGap":0.3,"boxMaxW":0.9,"whiskerCapW":0.34,"maxGroups":8},"network":{"y":2.4,"h":4.2,"nodeR":0.28,"nodeRMin":0.18,"labelMaxW":1.4,"maxNodes":18,"maxEdges":30},"marimekko":{"y":2.6,"h":3.75,"labelW":1.55,"colGap":0.06,"legendH":0.42,"maxCols":6,"maxSegs":4},"streamgraph":{"y":2.6,"h":3.75,"labelW":1.4,"bandMinH":0.12,"maxSeries":6}};
|
|
2064
2064
|
var PRESETS = {
|
|
2065
2065
|
'business-blue': { accent:'1A73E8', ink:'202124', body:'5F6368', faint:'80868B', bg:'FFFFFF', surface:'F8F9FA', line:'DADCE0', soft:'E8F0FE', onAccent:'FFFFFF', font:'Microsoft YaHei', fontDisplay:'Microsoft YaHei' },
|
|
2066
2066
|
'apple-mono': { accent:'1D1D1F', ink:'1D1D1F', body:'6E6E73', faint:'86868B', bg:'FFFFFF', surface:'F5F5F7', line:'D2D2D7', soft:'F5F5F7', onAccent:'FFFFFF', font:'Microsoft YaHei', fontDisplay:'Microsoft YaHei' },
|
|
@@ -3001,7 +3001,9 @@ function infoTableRows(sec) {
|
|
|
3001
3001
|
if (t === 'marimekko') {
|
|
3002
3002
|
var head = ['列', '总量' + u].concat((sec.legend || []).map(String));
|
|
3003
3003
|
return [head].concat((sec.cols || []).map(function (c, i) {
|
|
3004
|
-
return [String(c[0]), String(c[1])].concat(((sec.cells || [])[i] || []).map(
|
|
3004
|
+
return [String(c[0]), String(c[1])].concat((((sec.cells || [])[i] || []).map(function (el) {
|
|
3005
|
+
return Array.isArray(el) ? String(el[0]) + ' ' + el[1] : String(el);
|
|
3006
|
+
})));
|
|
3005
3007
|
}));
|
|
3006
3008
|
}
|
|
3007
3009
|
if (t === 'streamgraph') {
|
|
@@ -3149,7 +3151,11 @@ function infoApprox(sh, sec, S, y0, y1) {
|
|
|
3149
3151
|
var cx1 = MX;
|
|
3150
3152
|
cols.forEach(function (c, i) {
|
|
3151
3153
|
var cw = Math.max(0.2, (Number(c[1]) || 0) / total * availW);
|
|
3152
|
-
|
|
3154
|
+
/* 单元格兼容 [标签,数值] 对(与 B 通道 marimekkoSegs 同规则);非数值 → 0 */
|
|
3155
|
+
var shares = ((sec.cells || [])[i] || []).map(function (el) {
|
|
3156
|
+
var v = Number(Array.isArray(el) ? el[1] : el);
|
|
3157
|
+
return isFinite(v) ? v : 0;
|
|
3158
|
+
});
|
|
3153
3159
|
var sum = shares.reduce(function (a, b) { return a + b; }, 0) || 1;
|
|
3154
3160
|
var cy = P.y0;
|
|
3155
3161
|
shares.forEach(function (v, k) {
|
|
@@ -3299,13 +3305,20 @@ function slidesOf(model, S) {
|
|
|
3299
3305
|
});
|
|
3300
3306
|
}
|
|
3301
3307
|
|
|
3302
|
-
/*
|
|
3308
|
+
/* Exhibit 徽标文本:纯编号补 "Exhibit " 前缀(HTML 为 `Exhibit {no}` + CSS uppercase);
|
|
3309
|
+
调用方已带前缀的不重复(与 B 通道 exhibitBadge 同规则) */
|
|
3310
|
+
function exhibitBadge(no) {
|
|
3311
|
+
var t = String(no == null ? '' : no).trim();
|
|
3312
|
+
if (!t) return t;
|
|
3313
|
+
return /^exhibit[\s\-:]*/i.test(t) ? t.toUpperCase() : ('EXHIBIT ' + t.toUpperCase());
|
|
3314
|
+
}
|
|
3315
|
+
/* 章节页 */
|
|
3303
3316
|
(model.sections || []).forEach(function (sec) {
|
|
3304
3317
|
var type = sec.type || 'points';
|
|
3305
3318
|
var sh = [];
|
|
3306
3319
|
if (type !== 'quote') head(sh, sec.eyebrow, sec.title, sec.lead);
|
|
3307
3320
|
/* 非 exhibit 页型也可带 Exhibit 编号(帧头徽标;正文区下移让位,与 B 通道同规则) */
|
|
3308
|
-
var exBadge = (type !== 'exhibit' && sec.exhibitNo) ?
|
|
3321
|
+
var exBadge = (type !== 'exhibit' && sec.exhibitNo) ? exhibitBadge(sec.exhibitNo) : null;
|
|
3309
3322
|
var bodyY0 = sec.lead ? PT.common.bodyYWithLead : CONTENT_TOP;
|
|
3310
3323
|
var bodyY = exBadge ? bodyY0 + 0.42 : bodyY0;
|
|
3311
3324
|
if (exBadge) {
|
|
@@ -3316,7 +3329,7 @@ function slidesOf(model, S) {
|
|
|
3316
3329
|
var _F = PT.flagbar || { hdH: 0.26, rowH: 0.24, maxRows: 3, gap: 0.12 };
|
|
3317
3330
|
var flagH = flagItems.length
|
|
3318
3331
|
? (_F.hdH + Math.min(_F.maxRows, flagItems.length) * _F.rowH + 0.06) : 0;
|
|
3319
|
-
var bodyBottom = chartBottom(!!sec.soWhat, !!sec.footnote);
|
|
3332
|
+
var bodyBottom = chartBottom(!!sec.soWhat, !!(sec.footnote || sec.note));
|
|
3320
3333
|
var flagY = 0;
|
|
3321
3334
|
if (flagH) {
|
|
3322
3335
|
flagY = CONTENT_BOTTOM - flagH;
|
|
@@ -3350,9 +3363,14 @@ function slidesOf(model, S) {
|
|
|
3350
3363
|
sh.push(shape('rect', kdivX, K.heroY + 0.15, 0.025, 3.1, S.line));
|
|
3351
3364
|
var mRegK = regOf('kpi', 'metrics') || { x: kdivX + 0.35, y: K.metricY0, w: CW * (1 - K.dividerX) - 0.5 };
|
|
3352
3365
|
var kmets = sec.metrics || [];
|
|
3353
|
-
|
|
3366
|
+
/* 容量按最小允许行高判断,行高按全部指标自适应压缩 —— 禁静默丢数据(与 B 通道同规则) */
|
|
3367
|
+
var kAvailA = CONTENT_BOTTOM - mRegK.y;
|
|
3368
|
+
var kCap = Math.max(1, Math.floor(kAvailA / 0.42));
|
|
3354
3369
|
var kRows = Math.min(kmets.length, kCap);
|
|
3355
|
-
|
|
3370
|
+
if (kRows < kmets.length && typeof console !== 'undefined')
|
|
3371
|
+
console.warn('[pptx-export] KPI 页「' + (sec.title || '') + '」支撑指标 ' + kmets.length +
|
|
3372
|
+
' 个超出容量,仅渲染前 ' + kRows + ' 个 —— 建议拆页');
|
|
3373
|
+
var kRowH = fitRowH(kAvailA, kRows, K.metricRowH, 0.42);
|
|
3356
3374
|
var kTopH = Math.min(0.55, kRowH * 0.62);
|
|
3357
3375
|
kmets.slice(0, kRows).forEach(function (m, i) {
|
|
3358
3376
|
var ky = mRegK.y + i * kRowH;
|
|
@@ -3503,9 +3521,20 @@ function slidesOf(model, S) {
|
|
|
3503
3521
|
var lt = isRec(l) ? (l.t || '') : String(l[0] || '');
|
|
3504
3522
|
var ld = isRec(l) ? (l.d || '') : String(l[1] || '');
|
|
3505
3523
|
sh.push(shape('roundRect', x2, y2, w2, rowHP, acc ? S.soft : S.surface, { adj: 5000, line: acc ? undefined : S.line }));
|
|
3506
|
-
var lwP = Math.min(P.labelW, w2 - 0.44);
|
|
3507
|
-
|
|
3508
|
-
|
|
3524
|
+
var lwP = Math.min(P.labelW, (w2 - 0.44) * (P.labelFrac == null ? 0.32 : P.labelFrac));
|
|
3525
|
+
var descW = w2 - 0.44 - lwP;
|
|
3526
|
+
/* 窄层判定:说明列 < 1.2in,或标题在标题列内放不下单行 → 单框混排(与 B 通道同规则) */
|
|
3527
|
+
var narrowP = descW < 1.2 || (ld && estLines(lt, lwP, 13.5) > 1) || (!ld && estLines(lt, w2 - 0.44, 13.5) > 1);
|
|
3528
|
+
if (narrowP) {
|
|
3529
|
+
/* 顶层窄 → 标题上、说明下单框混排(HTML 窄屏 .pyr__lvl 即单列,与 B 通道同规则) */
|
|
3530
|
+
sh.push(txSp(x2 + 0.22, y2 + 0.03, w2 - 0.44, 0.30,
|
|
3531
|
+
[[{ t: lt, sz: 12.5, b: 1, col: acc ? S.accent : S.ink, font: S.font }]]));
|
|
3532
|
+
sh.push(txSp(x2 + 0.22, y2 + 0.33, w2 - 0.44, Math.max(0.2, rowHP - 0.36),
|
|
3533
|
+
[[{ t: ld, sz: 10.5, col: S.faint, font: S.font }]]));
|
|
3534
|
+
} else {
|
|
3535
|
+
sh.push(txSp(x2 + 0.22, y2, lwP, rowHP, [[{ t: lt, sz: 13.5, b: 1, col: acc ? S.accent : S.ink, font: S.font }]], { anchor: 'ctr' }));
|
|
3536
|
+
if (ld) sh.push(txSp(x2 + 0.22 + lwP, y2, descW, rowHP, [[{ t: ld, sz: 11, col: S.faint, font: S.font }]], { anchor: 'ctr' }));
|
|
3537
|
+
}
|
|
3509
3538
|
});
|
|
3510
3539
|
} else if (type === 'steps') {
|
|
3511
3540
|
var S2 = PT.steps, st = sec.steps || [], maxPer = S2.maxPerRow || 6, groups = sec.groups || [];
|
|
@@ -3854,12 +3883,12 @@ function slidesOf(model, S) {
|
|
|
3854
3883
|
var eReg = regOf('exhibit', 'primary')
|
|
3855
3884
|
|| { x: MX, y: PT.exhibit.chartY, w: CW, badgeY: PT.exhibit.badgeY };
|
|
3856
3885
|
if (sec.exhibitNo) {
|
|
3857
|
-
sh.push(txSp(MX, eReg.badgeY != null ? eReg.badgeY : PT.exhibit.badgeY, CW, 0.35, [[{ t:
|
|
3886
|
+
sh.push(txSp(MX, eReg.badgeY != null ? eReg.badgeY : PT.exhibit.badgeY, CW, 0.35, [[{ t: exhibitBadge(sec.exhibitNo), sz: 11.5, b: 1, col: S.accent, font: S.font, spc: 200 }]]));
|
|
3858
3887
|
}
|
|
3859
3888
|
var ec2 = sec.chart || {};
|
|
3860
3889
|
if (ec2.labels && ec2.values) {
|
|
3861
3890
|
var edcols2 = (ec2.colors || dataColors(model.style, model.theme));
|
|
3862
|
-
var hh2 = Math.max(1.2, chartBottom(!!sec.soWhat, !!sec.footnote) - eReg.y - 0.05);
|
|
3891
|
+
var hh2 = Math.max(1.2, chartBottom(!!sec.soWhat, !!(sec.footnote || sec.note)) - eReg.y - 0.05);
|
|
3863
3892
|
if (ec2.type === 'hbar') {
|
|
3864
3893
|
chartBlockShapes(sh, ec2, S, eReg.x, eReg.y, eReg.w, hh2, edcols2);
|
|
3865
3894
|
} else {
|
|
@@ -2403,7 +2403,7 @@ window.REPORT_MODEL = {
|
|
|
2403
2403
|
|
|
2404
2404
|
/* __TOPPPT_RUNTIME_START__ */
|
|
2405
2405
|
/* ══ PPTX 导出运行时(assets/pptx-export.js 的内联副本 · 由 scripts/sync_runtime.py 注入,禁止手改) ══ */
|
|
2406
|
-
/* __TOPPPT_RUNTIME_SHA__:
|
|
2406
|
+
/* __TOPPPT_RUNTIME_SHA__:a4c909346759fe9c */
|
|
2407
2407
|
/* ═══════════════════════════════════════════════════════════════════════════
|
|
2408
2408
|
* TopPPT HTML· 浏览器端 PPTX 预览运行时
|
|
2409
2409
|
* 零依赖、随报告单文件分发;OOXML 序列化器(仅供预览,页面不导出文件)。
|
|
@@ -2458,7 +2458,7 @@ function isRec(v) { return !!v && typeof v === 'object' && !Array.isArray(v); }
|
|
|
2458
2458
|
var PW = 13.333, PH = 7.5, MX = 0.6, CW = PW - 2 * MX, EMU = 914400;
|
|
2459
2459
|
var TS_BASE = {"coverTitle":44,"coverSub":18,"h1":30,"h2":17,"lead":14,"body":13,"caption":11,"micro":10};
|
|
2460
2460
|
var MTS = {"presentation":{"coverTitle":44,"coverSub":18,"h1":30,"h2":17,"lead":14,"body":13,"caption":11,"micro":10},"research":{"coverTitle":36,"coverSub":14,"h1":22,"h2":13.5,"lead":11.5,"body":10.5,"caption":9,"micro":8.5},"architecture":{"coverTitle":44,"coverSub":19,"h1":30,"h2":17,"lead":14,"body":13,"caption":11,"micro":10}};
|
|
2461
|
-
var PT = {"layout":{"contentTop":2.35,"contentBottom":6.9,"contentBottomWithNote":6.4,"pageNumY":7.0},"common":{"headEyebrowY":0.48,"headTitleY":0.82,"headRuleY":1.72,"leadY":1.88,"bodyY":2.35,"bodyYWithLead":2.55,"pagerY":7.0},"cover":{"metaY":0.7,"titleY":2.4,"titleH":2.0,"subtitleY":4.5,"subtitleH":0.8},"closing":{"eyebrowY":0.7,"titleY":1.2,"titleH":1.2,"pointsY":3.0,"pointTitleH":0.6,"pointBodyH":1.2},"points":{"listY":2.5,"rowH":0.72,"rowHMin":0.5,"markSize":0.14,"metricY":4.7,"metricW":2.6,"metricValH":0.9,"metricCapY":5.6},"metrics":{"bandY":3.1,"cardH":2.3,"valY":3.45,"valH":1.1,"capY":4.55,"capH":0.7,"gap":0.3,"maxW":2.9},"table":{"y":2.5,"rowH":0.55,"rowHMin":0.32,"headRowH":0.5},"bar":{"hbarY0":2.6,"hbarY1":6.25,"chartX":0.6,"chartY":2.95,"chartW":1.2,"chartH":3.35,"noteY":6.55},"note":{"y":6.55,"h":0.4},"exhibit":{"badgeY":2.35,"chartY":2.75,"chartH":3.25,"soWhatY":6.05,"footnoteY":6.72},"twocol":{"colGap":0.5,"bodyH":3.6,"rowHMin":0.5},"hbar":{"labelW":1.9,"valW":1.0,"rowH":0.55,"barRatio":0.5},"diagram":{"layerBarW":1.35,"layerGap":0.15,"nodeGap":0.15,"bodyStartY":2.9,"maxLayerH":1.15,"nodeMaxW":2.2},"split":{"leftW":0.55,"rightW":0.415,"rightX":0.585,"pointsY":2.7,"rowH":0.78,"capY":2.55,"chartY":3.0,"chartH":3.7,"tableY":2.7,"tableRowH":0.5},"cards":{"startY":3.0,"gap":0.25,"maxH":2.0,"titleH":0.4},"timeline":{"labelY":2.95,"axisY":3.58,"dotY":3.51,"dotR":0.18,"nameY":3.9,"descY":4.45,"descH":1.2},"research":{"col3Gap":0.38,"matrixLabelW":1.5,"matrixCellH":0.85,"matrixY":2.2,"denseTableY":2.2,"denseRowH":0.42,"halfTableW":0.52,"halfChartX":0.57,"halfChartW":0.43},"arch":{"fullStartY":2.1,"fullEndY":6.9,"laneH":0.72,"laneHMin":0.5,"laneGap":0.14,"laneHeadW":1.3,"stepGap":0.12,"stepMaxW":1.9},"kpi":{"heroY":2.9,"heroW":0.52,"heroH":1.6,"dividerX":0.56,"metricY0":2.95,"metricRowH":0.85},"comparison":{"panelGap":0.4,"panelY":2.55,"panelH":3.4,"titleH":0.45,"rowH":0.62},"quote":{"markY":1.75,"textY":2.7,"textH":2.3,"authorY":5.25,"contextY":5.8},"donut":{"centerX":3.05,"centerY":4.6,"r":1.6,"holeR":0.95,"legendX":5.6,"legendRowH":0.55,"legendLabelW":3.4,"legendValW":1.3,"legendPctX":
|
|
2461
|
+
var PT = {"layout":{"contentTop":2.35,"contentBottom":6.9,"contentBottomWithNote":6.4,"pageNumY":7.0},"common":{"headEyebrowY":0.48,"headTitleY":0.82,"headRuleY":1.72,"leadY":1.88,"bodyY":2.35,"bodyYWithLead":2.55,"pagerY":7.0},"cover":{"metaY":0.7,"titleY":2.4,"titleH":2.0,"subtitleY":4.5,"subtitleH":0.8},"closing":{"eyebrowY":0.7,"titleY":1.2,"titleH":1.2,"pointsY":3.0,"pointTitleH":0.6,"pointBodyH":1.2},"points":{"listY":2.5,"rowH":0.72,"rowHMin":0.5,"markSize":0.14,"metricY":4.7,"metricW":2.6,"metricValH":0.9,"metricCapY":5.6},"metrics":{"bandY":3.1,"cardH":2.3,"valY":3.45,"valH":1.1,"capY":4.55,"capH":0.7,"gap":0.3,"maxW":2.9},"table":{"y":2.5,"rowH":0.55,"rowHMin":0.32,"headRowH":0.5},"bar":{"hbarY0":2.6,"hbarY1":6.25,"chartX":0.6,"chartY":2.95,"chartW":1.2,"chartH":3.35,"noteY":6.55},"note":{"y":6.55,"h":0.4},"exhibit":{"badgeY":2.35,"chartY":2.75,"chartH":3.25,"soWhatY":6.05,"footnoteY":6.72},"twocol":{"colGap":0.5,"bodyH":3.6,"rowHMin":0.5},"hbar":{"labelW":1.9,"valW":1.0,"rowH":0.55,"barRatio":0.5},"diagram":{"layerBarW":1.35,"layerGap":0.15,"nodeGap":0.15,"bodyStartY":2.9,"maxLayerH":1.15,"nodeMaxW":2.2},"split":{"leftW":0.55,"rightW":0.415,"rightX":0.585,"pointsY":2.7,"rowH":0.78,"capY":2.55,"chartY":3.0,"chartH":3.7,"tableY":2.7,"tableRowH":0.5},"cards":{"startY":3.0,"gap":0.25,"maxH":2.0,"titleH":0.4},"timeline":{"labelY":2.95,"axisY":3.58,"dotY":3.51,"dotR":0.18,"nameY":3.9,"descY":4.45,"descH":1.2},"research":{"col3Gap":0.38,"matrixLabelW":1.5,"matrixCellH":0.85,"matrixY":2.2,"denseTableY":2.2,"denseRowH":0.42,"halfTableW":0.52,"halfChartX":0.57,"halfChartW":0.43},"arch":{"fullStartY":2.1,"fullEndY":6.9,"laneH":0.72,"laneHMin":0.5,"laneGap":0.14,"laneHeadW":1.3,"stepGap":0.12,"stepMaxW":1.9},"kpi":{"heroY":2.9,"heroW":0.52,"heroH":1.6,"dividerX":0.56,"metricY0":2.95,"metricRowH":0.85},"comparison":{"panelGap":0.4,"panelY":2.55,"panelH":3.4,"titleH":0.45,"rowH":0.62},"quote":{"markY":1.75,"textY":2.7,"textH":2.3,"authorY":5.25,"contextY":5.8},"donut":{"centerX":3.05,"centerY":4.6,"r":1.6,"holeR":0.95,"legendX":5.6,"legendRowH":0.55,"legendLabelW":3.4,"legendValW":1.3,"legendPctX":10.8,"legendPctW":1.3},"steps":{"y":3.05,"barH":1.35,"gap":0.12,"arrowW":0.3,"numH":0.3,"titleH":0.34,"pad":0.08,"maxPerRow":6},"heatmap":{"y":2.6,"labelW":1.7,"headH":0.42,"cellH":0.6,"cellGap":0.06,"legendW":1.6},"pyramid":{"y":2.35,"rowH":0.72,"gap":0.08,"minW":0.34,"labelW":3.2},"bullet":{"y":2.6,"rowH":0.8,"labelW":2.4,"valW":1.7,"barH":0.26},"image":{"y":2.3,"h":4.2,"halfW":0.56,"halfGap":0.06,"capY":6.6,"capH":0.3,"radius":0.09,"noteRowH":0.62,"gridGap":0.16,"gridCols":{"2":2,"3":3,"4":4,"6":3},"gridCapH":0.28,"compareGap":0.3,"compareTagH":0.26,"wallCellH":0.92,"wallGap":0.18,"wallMaxRows":2},"flagbar":{"hdH":0.26,"rowH":0.24,"maxRows":3,"gap":0.12},"sankey":{"y":2.45,"h":4.1,"nodeW":0.32,"nodeGap":0.14,"labelW":1.55,"minBandH":0.22,"maxNodes":12,"maxFlows":24},"treemap":{"y":2.45,"h":4.1,"gap":0.05,"labelMinH":0.34,"maxLeaves":16,"maxDepth":3},"boxplot":{"y":2.7,"h":3.7,"labelW":1.5,"groupGap":0.3,"boxMaxW":0.9,"whiskerCapW":0.34,"maxGroups":8},"network":{"y":2.4,"h":4.2,"nodeR":0.28,"nodeRMin":0.18,"labelMaxW":1.4,"maxNodes":18,"maxEdges":30},"marimekko":{"y":2.6,"h":3.75,"labelW":1.55,"colGap":0.06,"legendH":0.42,"maxCols":6,"maxSegs":4},"streamgraph":{"y":2.6,"h":3.75,"labelW":1.4,"bandMinH":0.12,"maxSeries":6}};
|
|
2462
2462
|
var PRESETS = {
|
|
2463
2463
|
'business-blue': { accent:'1A73E8', ink:'202124', body:'5F6368', faint:'80868B', bg:'FFFFFF', surface:'F8F9FA', line:'DADCE0', soft:'E8F0FE', onAccent:'FFFFFF', font:'Microsoft YaHei', fontDisplay:'Microsoft YaHei' },
|
|
2464
2464
|
'apple-mono': { accent:'1D1D1F', ink:'1D1D1F', body:'6E6E73', faint:'86868B', bg:'FFFFFF', surface:'F5F5F7', line:'D2D2D7', soft:'F5F5F7', onAccent:'FFFFFF', font:'Microsoft YaHei', fontDisplay:'Microsoft YaHei' },
|
|
@@ -3399,7 +3399,9 @@ function infoTableRows(sec) {
|
|
|
3399
3399
|
if (t === 'marimekko') {
|
|
3400
3400
|
var head = ['列', '总量' + u].concat((sec.legend || []).map(String));
|
|
3401
3401
|
return [head].concat((sec.cols || []).map(function (c, i) {
|
|
3402
|
-
return [String(c[0]), String(c[1])].concat(((sec.cells || [])[i] || []).map(
|
|
3402
|
+
return [String(c[0]), String(c[1])].concat((((sec.cells || [])[i] || []).map(function (el) {
|
|
3403
|
+
return Array.isArray(el) ? String(el[0]) + ' ' + el[1] : String(el);
|
|
3404
|
+
})));
|
|
3403
3405
|
}));
|
|
3404
3406
|
}
|
|
3405
3407
|
if (t === 'streamgraph') {
|
|
@@ -3547,7 +3549,11 @@ function infoApprox(sh, sec, S, y0, y1) {
|
|
|
3547
3549
|
var cx1 = MX;
|
|
3548
3550
|
cols.forEach(function (c, i) {
|
|
3549
3551
|
var cw = Math.max(0.2, (Number(c[1]) || 0) / total * availW);
|
|
3550
|
-
|
|
3552
|
+
/* 单元格兼容 [标签,数值] 对(与 B 通道 marimekkoSegs 同规则);非数值 → 0 */
|
|
3553
|
+
var shares = ((sec.cells || [])[i] || []).map(function (el) {
|
|
3554
|
+
var v = Number(Array.isArray(el) ? el[1] : el);
|
|
3555
|
+
return isFinite(v) ? v : 0;
|
|
3556
|
+
});
|
|
3551
3557
|
var sum = shares.reduce(function (a, b) { return a + b; }, 0) || 1;
|
|
3552
3558
|
var cy = P.y0;
|
|
3553
3559
|
shares.forEach(function (v, k) {
|
|
@@ -3697,13 +3703,20 @@ function slidesOf(model, S) {
|
|
|
3697
3703
|
});
|
|
3698
3704
|
}
|
|
3699
3705
|
|
|
3700
|
-
/*
|
|
3706
|
+
/* Exhibit 徽标文本:纯编号补 "Exhibit " 前缀(HTML 为 `Exhibit {no}` + CSS uppercase);
|
|
3707
|
+
调用方已带前缀的不重复(与 B 通道 exhibitBadge 同规则) */
|
|
3708
|
+
function exhibitBadge(no) {
|
|
3709
|
+
var t = String(no == null ? '' : no).trim();
|
|
3710
|
+
if (!t) return t;
|
|
3711
|
+
return /^exhibit[\s\-:]*/i.test(t) ? t.toUpperCase() : ('EXHIBIT ' + t.toUpperCase());
|
|
3712
|
+
}
|
|
3713
|
+
/* 章节页 */
|
|
3701
3714
|
(model.sections || []).forEach(function (sec) {
|
|
3702
3715
|
var type = sec.type || 'points';
|
|
3703
3716
|
var sh = [];
|
|
3704
3717
|
if (type !== 'quote') head(sh, sec.eyebrow, sec.title, sec.lead);
|
|
3705
3718
|
/* 非 exhibit 页型也可带 Exhibit 编号(帧头徽标;正文区下移让位,与 B 通道同规则) */
|
|
3706
|
-
var exBadge = (type !== 'exhibit' && sec.exhibitNo) ?
|
|
3719
|
+
var exBadge = (type !== 'exhibit' && sec.exhibitNo) ? exhibitBadge(sec.exhibitNo) : null;
|
|
3707
3720
|
var bodyY0 = sec.lead ? PT.common.bodyYWithLead : CONTENT_TOP;
|
|
3708
3721
|
var bodyY = exBadge ? bodyY0 + 0.42 : bodyY0;
|
|
3709
3722
|
if (exBadge) {
|
|
@@ -3714,7 +3727,7 @@ function slidesOf(model, S) {
|
|
|
3714
3727
|
var _F = PT.flagbar || { hdH: 0.26, rowH: 0.24, maxRows: 3, gap: 0.12 };
|
|
3715
3728
|
var flagH = flagItems.length
|
|
3716
3729
|
? (_F.hdH + Math.min(_F.maxRows, flagItems.length) * _F.rowH + 0.06) : 0;
|
|
3717
|
-
var bodyBottom = chartBottom(!!sec.soWhat, !!sec.footnote);
|
|
3730
|
+
var bodyBottom = chartBottom(!!sec.soWhat, !!(sec.footnote || sec.note));
|
|
3718
3731
|
var flagY = 0;
|
|
3719
3732
|
if (flagH) {
|
|
3720
3733
|
flagY = CONTENT_BOTTOM - flagH;
|
|
@@ -3748,9 +3761,14 @@ function slidesOf(model, S) {
|
|
|
3748
3761
|
sh.push(shape('rect', kdivX, K.heroY + 0.15, 0.025, 3.1, S.line));
|
|
3749
3762
|
var mRegK = regOf('kpi', 'metrics') || { x: kdivX + 0.35, y: K.metricY0, w: CW * (1 - K.dividerX) - 0.5 };
|
|
3750
3763
|
var kmets = sec.metrics || [];
|
|
3751
|
-
|
|
3764
|
+
/* 容量按最小允许行高判断,行高按全部指标自适应压缩 —— 禁静默丢数据(与 B 通道同规则) */
|
|
3765
|
+
var kAvailA = CONTENT_BOTTOM - mRegK.y;
|
|
3766
|
+
var kCap = Math.max(1, Math.floor(kAvailA / 0.42));
|
|
3752
3767
|
var kRows = Math.min(kmets.length, kCap);
|
|
3753
|
-
|
|
3768
|
+
if (kRows < kmets.length && typeof console !== 'undefined')
|
|
3769
|
+
console.warn('[pptx-export] KPI 页「' + (sec.title || '') + '」支撑指标 ' + kmets.length +
|
|
3770
|
+
' 个超出容量,仅渲染前 ' + kRows + ' 个 —— 建议拆页');
|
|
3771
|
+
var kRowH = fitRowH(kAvailA, kRows, K.metricRowH, 0.42);
|
|
3754
3772
|
var kTopH = Math.min(0.55, kRowH * 0.62);
|
|
3755
3773
|
kmets.slice(0, kRows).forEach(function (m, i) {
|
|
3756
3774
|
var ky = mRegK.y + i * kRowH;
|
|
@@ -3901,9 +3919,20 @@ function slidesOf(model, S) {
|
|
|
3901
3919
|
var lt = isRec(l) ? (l.t || '') : String(l[0] || '');
|
|
3902
3920
|
var ld = isRec(l) ? (l.d || '') : String(l[1] || '');
|
|
3903
3921
|
sh.push(shape('roundRect', x2, y2, w2, rowHP, acc ? S.soft : S.surface, { adj: 5000, line: acc ? undefined : S.line }));
|
|
3904
|
-
var lwP = Math.min(P.labelW, w2 - 0.44);
|
|
3905
|
-
|
|
3906
|
-
|
|
3922
|
+
var lwP = Math.min(P.labelW, (w2 - 0.44) * (P.labelFrac == null ? 0.32 : P.labelFrac));
|
|
3923
|
+
var descW = w2 - 0.44 - lwP;
|
|
3924
|
+
/* 窄层判定:说明列 < 1.2in,或标题在标题列内放不下单行 → 单框混排(与 B 通道同规则) */
|
|
3925
|
+
var narrowP = descW < 1.2 || (ld && estLines(lt, lwP, 13.5) > 1) || (!ld && estLines(lt, w2 - 0.44, 13.5) > 1);
|
|
3926
|
+
if (narrowP) {
|
|
3927
|
+
/* 顶层窄 → 标题上、说明下单框混排(HTML 窄屏 .pyr__lvl 即单列,与 B 通道同规则) */
|
|
3928
|
+
sh.push(txSp(x2 + 0.22, y2 + 0.03, w2 - 0.44, 0.30,
|
|
3929
|
+
[[{ t: lt, sz: 12.5, b: 1, col: acc ? S.accent : S.ink, font: S.font }]]));
|
|
3930
|
+
sh.push(txSp(x2 + 0.22, y2 + 0.33, w2 - 0.44, Math.max(0.2, rowHP - 0.36),
|
|
3931
|
+
[[{ t: ld, sz: 10.5, col: S.faint, font: S.font }]]));
|
|
3932
|
+
} else {
|
|
3933
|
+
sh.push(txSp(x2 + 0.22, y2, lwP, rowHP, [[{ t: lt, sz: 13.5, b: 1, col: acc ? S.accent : S.ink, font: S.font }]], { anchor: 'ctr' }));
|
|
3934
|
+
if (ld) sh.push(txSp(x2 + 0.22 + lwP, y2, descW, rowHP, [[{ t: ld, sz: 11, col: S.faint, font: S.font }]], { anchor: 'ctr' }));
|
|
3935
|
+
}
|
|
3907
3936
|
});
|
|
3908
3937
|
} else if (type === 'steps') {
|
|
3909
3938
|
var S2 = PT.steps, st = sec.steps || [], maxPer = S2.maxPerRow || 6, groups = sec.groups || [];
|
|
@@ -4252,12 +4281,12 @@ function slidesOf(model, S) {
|
|
|
4252
4281
|
var eReg = regOf('exhibit', 'primary')
|
|
4253
4282
|
|| { x: MX, y: PT.exhibit.chartY, w: CW, badgeY: PT.exhibit.badgeY };
|
|
4254
4283
|
if (sec.exhibitNo) {
|
|
4255
|
-
sh.push(txSp(MX, eReg.badgeY != null ? eReg.badgeY : PT.exhibit.badgeY, CW, 0.35, [[{ t:
|
|
4284
|
+
sh.push(txSp(MX, eReg.badgeY != null ? eReg.badgeY : PT.exhibit.badgeY, CW, 0.35, [[{ t: exhibitBadge(sec.exhibitNo), sz: 11.5, b: 1, col: S.accent, font: S.font, spc: 200 }]]));
|
|
4256
4285
|
}
|
|
4257
4286
|
var ec2 = sec.chart || {};
|
|
4258
4287
|
if (ec2.labels && ec2.values) {
|
|
4259
4288
|
var edcols2 = (ec2.colors || dataColors(model.style, model.theme));
|
|
4260
|
-
var hh2 = Math.max(1.2, chartBottom(!!sec.soWhat, !!sec.footnote) - eReg.y - 0.05);
|
|
4289
|
+
var hh2 = Math.max(1.2, chartBottom(!!sec.soWhat, !!(sec.footnote || sec.note)) - eReg.y - 0.05);
|
|
4261
4290
|
if (ec2.type === 'hbar') {
|
|
4262
4291
|
chartBlockShapes(sh, ec2, S, eReg.x, eReg.y, eReg.w, hh2, edcols2);
|
|
4263
4292
|
} else {
|