@topmindspace/tms-skills 0.1.3 → 0.1.5

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.
Files changed (32) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +6 -6
  3. package/package.json +2 -2
  4. package/top-ppt-html/README.md +5 -5
  5. package/top-ppt-html/SKILL.md +15 -12
  6. package/top-ppt-html/agents/openai.yaml +2 -2
  7. package/top-ppt-html/assets/examples/2026-09-09-architecture-graphite-dark.html +72 -27
  8. package/top-ppt-html/assets/examples/2026-09-09-presentation-business-blue.html +72 -27
  9. package/top-ppt-html/assets/examples/2026-09-09-research-mckinsey.html +72 -27
  10. package/top-ppt-html/assets/pptx-export.js +69 -25
  11. package/top-ppt-html/assets/style-gallery.html +1 -1
  12. package/top-ppt-html/assets/templates/architecture.html +70 -25
  13. package/top-ppt-html/assets/templates/presentation.html +70 -25
  14. package/top-ppt-html/assets/templates/research.html +70 -25
  15. package/top-ppt-html/package-lock.json +2 -2
  16. package/top-ppt-html/package.json +2 -2
  17. package/top-ppt-html/references/default-surface.md +1 -1
  18. package/top-ppt-html/references/modes.md +1 -1
  19. package/top-ppt-html/references/playbook.md +9 -8
  20. package/top-ppt-html/references/pptx-export.md +1 -1
  21. package/top-ppt-html/references/presentation-craft.md +4 -3
  22. package/top-ppt-html/references/tech-design.md +1 -1
  23. package/top-ppt-html/scripts/audit_skill.py +11 -0
  24. package/top-ppt-html/scripts/build_pptx.js +24 -10
  25. package/top-ppt-html/scripts/cross_verify.py +1 -1
  26. package/top-ppt-html/scripts/negative_tests.py +65 -9
  27. package/top-ppt-html/scripts/quality_gate.py +30 -19
  28. package/top-ppt-html/scripts/render_from_model.py +1 -1
  29. package/top-ppt-html/scripts/sync_runtime.py +10 -4
  30. package/top-ppt-html/scripts/test_feedback_gates.py +180 -0
  31. package/top-ppt-html/scripts/validate_pptx.py +157 -0
  32. package/top-ppt-html/scripts/validate_report.py +31 -1
@@ -207,7 +207,7 @@ var STYLE_DATA_COLORS = {"business-blue":["1a73e8","3526bb","21a199","b77148","9
207
207
  var STYLE_DATA_COLORS_DARK = {"business-blue":["8ab4f8","7966e0","88e7e5","d4ad91","cbce83"],"apple-mono":["f5f5f7","2997ff","2dd4bf","ff9f0a","bf5af2"],"mckinsey":["7fb2e5","6f6bdb","8ce3d8","d1a694","cbc586"],"brand-red":["ff5a66","e09e66","e788cb","91d4c2","83b4ce"],"warm-sand":["d9b36a","c2d571","df9391","97b5ce","8e89c7"],"deep-teal":["4fc3b0","7aaecd","97d8a4","c99cac","c29c8f"],"graphite-dark":["4da3ff","6c66e0","88e7dc","d4a691","cec983"],"indigo-violet":["a5a4f0","a967e0","89c3e7","d3c792","aece83"],"spectrum":["8ba0f8","9066e0","88d6e7","d4ba91","bdce83"]};
208
208
  var GRID = {"columns":12,"gutter":0.16,"colW":0.8644,"x":[0.6,1.6244,2.6488,3.6732,4.6976,5.722,6.7464,7.7708,8.7952,9.8196,10.844,11.8684,12.733],"y":[2.35,3.27,4.19,5.11,6.03,6.9],"safe":{"top":0.4,"bottom":0.4,"left":0.6,"right":0.6}};
209
209
  var TYPO = {"levels":[{"id":"C0","name":"封面/章节幕标题","role":"coverTitle","usage":"封面主标题、章节幕标题"},{"id":"T1","name":"页码/章节徽章","role":"caption","usage":"页码徽章、章节编号"},{"id":"T2","name":"页面主标题/结论标题","role":"h1","usage":"每页顶部结论句(research 行动标题)"},{"id":"T3","name":"副标题/语境说明","role":"lead","usage":"主标题下方导语"},{"id":"T4","name":"模块标题/图表标题","role":"h2","usage":"卡片标题、图表标题、面板标题"},{"id":"T5","name":"证据编号/轻量标签","role":"micro","usage":"Exhibit 编号、状态标签"},{"id":"T6","name":"证据块标题/小节标题","role":"h2","usage":"分栏小标题、证据块标题"},{"id":"T7","name":"正文解释段落","role":"body","usage":"证据解释、管理解读正文、表格正文"},{"id":"T8","name":"结论条文字","role":"body","usage":"so-what 结论条、核心结论框"},{"id":"T9","name":"SO WHAT 标签","role":"caption","usage":"so-what 标签行"},{"id":"T10","name":"SO WHAT 正文/业务含义","role":"body","usage":"so-what 正文、行动含义、表格行动项"},{"id":"T11","name":"图表轴/图例/刻度/微标签","role":"micro","usage":"坐标轴、图例、刻度、单位(禁用于表格正文与完整短句)"},{"id":"T12","name":"图表数据标签","role":"caption","usage":"折线点值、柱形标签、百分比标注"},{"id":"T13","name":"关键 KPI 大数字","role":"h1","usage":"KPI 大数字、hero 数值"},{"id":"T14","name":"注释/口径/来源/页脚","role":"micro","usage":"footnote、来源行、页脚、小页码"}],"tableSemanticRule":{"body":["T7","T10"],"microAllowed":["T11"],"microForbiddenFor":["表格正文","行动项","风险项","解释句","建议句","长项目符号","完整短句"]}};
210
- var CONT = {"pad":{"card":0.18,"panel":0.2,"cell":0.08,"band":0.16,"soWhat":0.16,"kpi":0.18,"chart":0.1,"head":0.05,"footer":0.05,"node":0.06},"minPad":0.06,"textMetrics":{"lineFactor":1.45,"emAsciiRatio":0.52},"overflowRule":"溢出处置优先级:① 优化内容(列表化/精炼/合并/拆页/换组合版式)→ ② 调整容器尺寸与行宽 → ③ 有限度缩小字号(见 fontShrink)→ ④ 仍装不下则拆页。禁止无限缩字号硬塞,也禁止把「精简」当第一手段砍掉决策必需信息。","fontShrink":{"ladder":[15,14,13.5,13,12.5,12,11.5,11,10.5,10,9.5,9,8.5],"maxShrinkSteps":4,"floorPt":{"presentation":10,"research":9,"architecture":10},"preferContentFirst":true,"warnBelow":9.5},"continuousTextRule":"语义连续的一句话 / so-what 主句 / 结论句 / 表格单元格正文不得拆成多个独立文本框(避免异常空格、断句、基线漂移);局部加粗高亮必须用同一文本框内富文本。"};
210
+ var CONT = {"pad":{"card":0.18,"panel":0.2,"cell":0.08,"band":0.16,"soWhat":0.16,"kpi":0.18,"chart":0.1,"head":0.05,"footer":0.05,"node":0.06},"minPad":0.06,"textMetrics":{"lineFactor":1.45,"emAsciiRatio":0.52},"overflowRule":"溢出处置优先级(禁静默截断):① 重构承载(列表/卡片/表/图/组合版式)→ ② 拆页/分章(议程→主张→证据卡→明细;01a/01b;信息须完整)→ ③ 换布局形态(V1–V4/多列/卡栅格)→ ④ 有限 fontShrink(阶梯内、模式 floor 以上、最多 4 档)→ ⑤ 禁止:静默截断、砍 so-what/证据/口径、为审美稀疏删决策必需信息。单页字数预算是预警不是删字许可证。","fontShrink":{"ladder":[15,14,13.5,13,12.5,12,11.5,11,10.5,10,9.5,9,8.5],"maxShrinkSteps":4,"floorPt":{"presentation":10,"research":9,"architecture":10},"preferContentFirst":true,"warnBelow":9.5},"continuousTextRule":"语义连续的一句话 / so-what 主句 / 结论句 / 表格单元格正文不得拆成多个独立文本框(避免异常空格、断句、基线漂移);局部加粗高亮必须用同一文本框内富文本。"};
211
211
  var REG = {"bar":{"html":"svg-bars","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":160}},"hbar":{"html":"svg-hbars","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":100}},"stack":{"html":"svg-stack","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":160},"nativeOpt":{"barGrouping":"stacked"}},"stackline":{"html":"svg-stackline","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":40},"nativeOpt":{"barGrouping":"percentStacked"}},"line":{"html":"svg-line","pptx":"native","nativeType":"line","dataTable":"notes","min":{"vbHeightMin":160}},"dualline":{"html":"svg-dualline","pptx":"native","nativeType":"line","dataTable":"notes","min":{"vbHeightMin":160}},"area":{"html":"svg-area","pptx":"native","nativeType":"area","dataTable":"notes","min":{"vbHeightMin":160}},"donut":{"html":"svg-donut","pptx":"native","nativeType":"doughnut","dataTable":"notes","min":{"pxWidthMin":140}},"multidonut":{"html":"svg-mdonut","pptx":"native","nativeType":"doughnut","dataTable":"notes","min":{"pxWidthMin":140}},"pie":{"html":"svg-pie","pptx":"native","nativeType":"pie","dataTable":"notes","min":{"pxWidthMin":140}},"radar":{"html":"svg-radar","pptx":"native","nativeType":"radar","dataTable":"notes","min":{"pxWidthMin":220}},"scatter":{"html":"svg-scatter","pptx":"native","nativeType":"scatter","dataTable":"notes","min":{"vbHeightMin":180}},"bubble":{"html":"svg-bubble","pptx":"native","nativeType":"bubble","dataTable":"notes","min":{"vbHeightMin":180}},"waterfall":{"html":"svg-wf","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":170},"nativeTrick":"stacked+hiddenBase+connector"},"gauge":{"html":"svg-gauge","pptx":"native","nativeType":"doughnut","dataTable":"notes","min":{"pxWidthMin":180},"nativeTrick":"doughnut+firstSliceAng+hiddenRemainder"},"pareto":{"html":"svg-pareto","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":180},"nativeTrick":"multiType+bar+line"},"gantt":{"html":"svg-gantt","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":130},"path":{"forbidPresetShapes":true}},"vsbar":{"html":"svg-vsbar","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":100},"path":{"forbidPresetShapes":true}},"progress":{"html":"svg-progress","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":100},"path":{"forbidPresetShapes":true}},"sparkline":{"html":"svg-spark","pptx":"shape","dataTable":"off","min":{"vbHeightMin":20},"path":{"forbidPresetShapes":true}},"funnel":{"html":"svg-funnel","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":160},"path":{"minSamplePoints":8,"forbidPresetShapes":true}},"treemap":{"html":"svg-treemap","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":170},"path":{"forbidPresetShapes":true}},"marimekko":{"html":"svg-marimekko","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":160},"path":{"forbidPresetShapes":true}},"boxplot":{"html":"svg-boxplot","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":180},"path":{"forbidPresetShapes":true}},"network":{"html":"svg-network","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":200},"path":{"forbidPresetShapes":true}},"sankey":{"html":"svg-sankey","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":200},"path":{"minSamplePoints":16,"trackBothEdges":true,"forbidPresetShapes":true}},"streamgraph":{"html":"svg-stream","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":160},"path":{"minSamplePoints":24,"trackBothEdges":true,"forbidPresetShapes":true}},"slope":{"html":"svg-slope","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":180},"path":{"forbidPresetShapes":true}},"dumbbell":{"html":"svg-dumbbell","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":160},"path":{"forbidPresetShapes":true}},"lollipop":{"html":"svg-lollipop","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":140},"path":{"forbidPresetShapes":true}},"dotplot":{"html":"svg-dotplot","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":120},"path":{"forbidPresetShapes":true}},"bulletchart":{"html":"svg-bullet","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":140},"path":{"forbidPresetShapes":true}},"waffle":{"html":"svg-waffle","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":160},"path":{"forbidPresetShapes":true}},"radialbar":{"html":"svg-radialbar","pptx":"shape","dataTable":"notes","min":{"pxWidthMin":200},"path":{"minSamplePoints":16,"forbidPresetShapes":true}},"rose":{"html":"svg-rose","pptx":"shape","dataTable":"notes","min":{"pxWidthMin":180},"path":{"minSamplePoints":16,"forbidPresetShapes":true}},"candlestick":{"html":"svg-candle","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":180},"path":{"forbidPresetShapes":true}}};
212
212
  var DEEP = {"triggers":["高保真","1:1","一比一","精确还原","按图还原","正式交付","不能偏移","像素级","严格对照","逐页验收"],"complexCharts":["sankey","streamgraph","treemap","marimekko","boxplot","network","rose","radialbar","candlestick","funnel"],"checks":{"anchors":true,"containerOverflow":true,"renderCompare":true,"manifest":true},"renderCompare":{"engine":"soffice","fallback":"powerpoint-com","skipIfMissing":true,"dpi":96}};
213
213
  var IMG = {"layouts":["full","half","bleed","grid","compare","wall"],"multiLayouts":["grid","compare","wall"],"fitEnum":["cover","contain"],"fitDefault":"cover","formats":["png","jpeg","jpg","webp","svg"],"ratioDefault":{"full":"3:1","half":"4:3","bleed":"21:9","grid":"4:3","compare":"4:3","wall":"1:1"},"ratioCssClass":{"full":"media--r3-1","half":"media--r4-3","bleed":"media--r21-9","grid":"media--r4-3","compare":"media--r4-3","wall":"media--r1-1"},"recommendedSizePx":{"full":"2400×800","half":"1400×1050","bleed":"2560×1100","grid":"900×675","compare":"1400×1050","wall":"480×480"},"maxInlineBytes":1572864,"maxTotalInlineBytes":8388608,"maxPerPage":6,"placeholderLabel":"配图占位","placeholderHintPrefix":"建议 ","placeholderHintSuffix":"px","zeroExternal":true,"qualityRule":"位图优先提供 ≥2× 显示尺寸;截图用 16:9 或 4:3 锁定比例;数据图不要用截图(应用内联 SVG 图表,可随主题变色)。"};
@@ -1778,6 +1778,7 @@ window.REPORT_MODEL = {
1778
1778
 
1779
1779
  /* __TOPPPT_RUNTIME_START__ */
1780
1780
  /* ══ PPTX 导出运行时(assets/pptx-export.js 的内联副本 · 由 scripts/sync_runtime.py 注入,禁止手改) ══ */
1781
+ /* __TOPPPT_RUNTIME_SHA__:68c55206c33160af */
1781
1782
  /* ═══════════════════════════════════════════════════════════════════════════
1782
1783
  * TopPPT HTML· 浏览器端 PPTX 预览运行时
1783
1784
  * 零依赖、随报告单文件分发;OOXML 序列化器(仅供预览,页面不导出文件)。
@@ -1859,7 +1860,7 @@ var STYLE_DATA_COLORS = {"business-blue":["1a73e8","3526bb","21a199","b77148","9
1859
1860
  var STYLE_DATA_COLORS_DARK = {"business-blue":["8ab4f8","7966e0","88e7e5","d4ad91","cbce83"],"apple-mono":["f5f5f7","2997ff","2dd4bf","ff9f0a","bf5af2"],"mckinsey":["7fb2e5","6f6bdb","8ce3d8","d1a694","cbc586"],"brand-red":["ff5a66","e09e66","e788cb","91d4c2","83b4ce"],"warm-sand":["d9b36a","c2d571","df9391","97b5ce","8e89c7"],"deep-teal":["4fc3b0","7aaecd","97d8a4","c99cac","c29c8f"],"graphite-dark":["4da3ff","6c66e0","88e7dc","d4a691","cec983"],"indigo-violet":["a5a4f0","a967e0","89c3e7","d3c792","aece83"],"spectrum":["8ba0f8","9066e0","88d6e7","d4ba91","bdce83"]};
1860
1861
  var GRID = {"columns":12,"gutter":0.16,"colW":0.8644,"x":[0.6,1.6244,2.6488,3.6732,4.6976,5.722,6.7464,7.7708,8.7952,9.8196,10.844,11.8684,12.733],"y":[2.35,3.27,4.19,5.11,6.03,6.9],"safe":{"top":0.4,"bottom":0.4,"left":0.6,"right":0.6}};
1861
1862
  var TYPO = {"levels":[{"id":"C0","name":"封面/章节幕标题","role":"coverTitle","usage":"封面主标题、章节幕标题"},{"id":"T1","name":"页码/章节徽章","role":"caption","usage":"页码徽章、章节编号"},{"id":"T2","name":"页面主标题/结论标题","role":"h1","usage":"每页顶部结论句(research 行动标题)"},{"id":"T3","name":"副标题/语境说明","role":"lead","usage":"主标题下方导语"},{"id":"T4","name":"模块标题/图表标题","role":"h2","usage":"卡片标题、图表标题、面板标题"},{"id":"T5","name":"证据编号/轻量标签","role":"micro","usage":"Exhibit 编号、状态标签"},{"id":"T6","name":"证据块标题/小节标题","role":"h2","usage":"分栏小标题、证据块标题"},{"id":"T7","name":"正文解释段落","role":"body","usage":"证据解释、管理解读正文、表格正文"},{"id":"T8","name":"结论条文字","role":"body","usage":"so-what 结论条、核心结论框"},{"id":"T9","name":"SO WHAT 标签","role":"caption","usage":"so-what 标签行"},{"id":"T10","name":"SO WHAT 正文/业务含义","role":"body","usage":"so-what 正文、行动含义、表格行动项"},{"id":"T11","name":"图表轴/图例/刻度/微标签","role":"micro","usage":"坐标轴、图例、刻度、单位(禁用于表格正文与完整短句)"},{"id":"T12","name":"图表数据标签","role":"caption","usage":"折线点值、柱形标签、百分比标注"},{"id":"T13","name":"关键 KPI 大数字","role":"h1","usage":"KPI 大数字、hero 数值"},{"id":"T14","name":"注释/口径/来源/页脚","role":"micro","usage":"footnote、来源行、页脚、小页码"}],"tableSemanticRule":{"body":["T7","T10"],"microAllowed":["T11"],"microForbiddenFor":["表格正文","行动项","风险项","解释句","建议句","长项目符号","完整短句"]}};
1862
- var CONT = {"pad":{"card":0.18,"panel":0.2,"cell":0.08,"band":0.16,"soWhat":0.16,"kpi":0.18,"chart":0.1,"head":0.05,"footer":0.05,"node":0.06},"minPad":0.06,"textMetrics":{"lineFactor":1.45,"emAsciiRatio":0.52},"overflowRule":"溢出处置优先级:① 优化内容(列表化/精炼/合并/拆页/换组合版式)→ ② 调整容器尺寸与行宽 → ③ 有限度缩小字号(见 fontShrink)→ ④ 仍装不下则拆页。禁止无限缩字号硬塞,也禁止把「精简」当第一手段砍掉决策必需信息。","fontShrink":{"ladder":[15,14,13.5,13,12.5,12,11.5,11,10.5,10,9.5,9,8.5],"maxShrinkSteps":4,"floorPt":{"presentation":10,"research":9,"architecture":10},"preferContentFirst":true,"warnBelow":9.5},"continuousTextRule":"语义连续的一句话 / so-what 主句 / 结论句 / 表格单元格正文不得拆成多个独立文本框(避免异常空格、断句、基线漂移);局部加粗高亮必须用同一文本框内富文本。"};
1863
+ var CONT = {"pad":{"card":0.18,"panel":0.2,"cell":0.08,"band":0.16,"soWhat":0.16,"kpi":0.18,"chart":0.1,"head":0.05,"footer":0.05,"node":0.06},"minPad":0.06,"textMetrics":{"lineFactor":1.45,"emAsciiRatio":0.52},"overflowRule":"溢出处置优先级(禁静默截断):① 重构承载(列表/卡片/表/图/组合版式)→ ② 拆页/分章(议程→主张→证据卡→明细;01a/01b;信息须完整)→ ③ 换布局形态(V1–V4/多列/卡栅格)→ ④ 有限 fontShrink(阶梯内、模式 floor 以上、最多 4 档)→ ⑤ 禁止:静默截断、砍 so-what/证据/口径、为审美稀疏删决策必需信息。单页字数预算是预警不是删字许可证。","fontShrink":{"ladder":[15,14,13.5,13,12.5,12,11.5,11,10.5,10,9.5,9,8.5],"maxShrinkSteps":4,"floorPt":{"presentation":10,"research":9,"architecture":10},"preferContentFirst":true,"warnBelow":9.5},"continuousTextRule":"语义连续的一句话 / so-what 主句 / 结论句 / 表格单元格正文不得拆成多个独立文本框(避免异常空格、断句、基线漂移);局部加粗高亮必须用同一文本框内富文本。"};
1863
1864
  var REG = {"bar":{"html":"svg-bars","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":160}},"hbar":{"html":"svg-hbars","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":100}},"stack":{"html":"svg-stack","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":160},"nativeOpt":{"barGrouping":"stacked"}},"stackline":{"html":"svg-stackline","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":40},"nativeOpt":{"barGrouping":"percentStacked"}},"line":{"html":"svg-line","pptx":"native","nativeType":"line","dataTable":"notes","min":{"vbHeightMin":160}},"dualline":{"html":"svg-dualline","pptx":"native","nativeType":"line","dataTable":"notes","min":{"vbHeightMin":160}},"area":{"html":"svg-area","pptx":"native","nativeType":"area","dataTable":"notes","min":{"vbHeightMin":160}},"donut":{"html":"svg-donut","pptx":"native","nativeType":"doughnut","dataTable":"notes","min":{"pxWidthMin":140}},"multidonut":{"html":"svg-mdonut","pptx":"native","nativeType":"doughnut","dataTable":"notes","min":{"pxWidthMin":140}},"pie":{"html":"svg-pie","pptx":"native","nativeType":"pie","dataTable":"notes","min":{"pxWidthMin":140}},"radar":{"html":"svg-radar","pptx":"native","nativeType":"radar","dataTable":"notes","min":{"pxWidthMin":220}},"scatter":{"html":"svg-scatter","pptx":"native","nativeType":"scatter","dataTable":"notes","min":{"vbHeightMin":180}},"bubble":{"html":"svg-bubble","pptx":"native","nativeType":"bubble","dataTable":"notes","min":{"vbHeightMin":180}},"waterfall":{"html":"svg-wf","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":170},"nativeTrick":"stacked+hiddenBase+connector"},"gauge":{"html":"svg-gauge","pptx":"native","nativeType":"doughnut","dataTable":"notes","min":{"pxWidthMin":180},"nativeTrick":"doughnut+firstSliceAng+hiddenRemainder"},"pareto":{"html":"svg-pareto","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":180},"nativeTrick":"multiType+bar+line"},"gantt":{"html":"svg-gantt","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":130},"path":{"forbidPresetShapes":true}},"vsbar":{"html":"svg-vsbar","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":100},"path":{"forbidPresetShapes":true}},"progress":{"html":"svg-progress","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":100},"path":{"forbidPresetShapes":true}},"sparkline":{"html":"svg-spark","pptx":"shape","dataTable":"off","min":{"vbHeightMin":20},"path":{"forbidPresetShapes":true}},"funnel":{"html":"svg-funnel","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":160},"path":{"minSamplePoints":8,"forbidPresetShapes":true}},"treemap":{"html":"svg-treemap","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":170},"path":{"forbidPresetShapes":true}},"marimekko":{"html":"svg-marimekko","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":160},"path":{"forbidPresetShapes":true}},"boxplot":{"html":"svg-boxplot","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":180},"path":{"forbidPresetShapes":true}},"network":{"html":"svg-network","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":200},"path":{"forbidPresetShapes":true}},"sankey":{"html":"svg-sankey","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":200},"path":{"minSamplePoints":16,"trackBothEdges":true,"forbidPresetShapes":true}},"streamgraph":{"html":"svg-stream","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":160},"path":{"minSamplePoints":24,"trackBothEdges":true,"forbidPresetShapes":true}},"slope":{"html":"svg-slope","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":180},"path":{"forbidPresetShapes":true}},"dumbbell":{"html":"svg-dumbbell","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":160},"path":{"forbidPresetShapes":true}},"lollipop":{"html":"svg-lollipop","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":140},"path":{"forbidPresetShapes":true}},"dotplot":{"html":"svg-dotplot","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":120},"path":{"forbidPresetShapes":true}},"bulletchart":{"html":"svg-bullet","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":140},"path":{"forbidPresetShapes":true}},"waffle":{"html":"svg-waffle","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":160},"path":{"forbidPresetShapes":true}},"radialbar":{"html":"svg-radialbar","pptx":"shape","dataTable":"notes","min":{"pxWidthMin":200},"path":{"minSamplePoints":16,"forbidPresetShapes":true}},"rose":{"html":"svg-rose","pptx":"shape","dataTable":"notes","min":{"pxWidthMin":180},"path":{"minSamplePoints":16,"forbidPresetShapes":true}},"candlestick":{"html":"svg-candle","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":180},"path":{"forbidPresetShapes":true}}};
1864
1865
  var DEEP = {"triggers":["高保真","1:1","一比一","精确还原","按图还原","正式交付","不能偏移","像素级","严格对照","逐页验收"],"complexCharts":["sankey","streamgraph","treemap","marimekko","boxplot","network","rose","radialbar","candlestick","funnel"],"checks":{"anchors":true,"containerOverflow":true,"renderCompare":true,"manifest":true},"renderCompare":{"engine":"soffice","fallback":"powerpoint-com","skipIfMissing":true,"dpi":96}};
1865
1866
  var IMG = {"layouts":["full","half","bleed","grid","compare","wall"],"multiLayouts":["grid","compare","wall"],"fitEnum":["cover","contain"],"fitDefault":"cover","formats":["png","jpeg","jpg","webp","svg"],"ratioDefault":{"full":"3:1","half":"4:3","bleed":"21:9","grid":"4:3","compare":"4:3","wall":"1:1"},"ratioCssClass":{"full":"media--r3-1","half":"media--r4-3","bleed":"media--r21-9","grid":"media--r4-3","compare":"media--r4-3","wall":"media--r1-1"},"recommendedSizePx":{"full":"2400×800","half":"1400×1050","bleed":"2560×1100","grid":"900×675","compare":"1400×1050","wall":"480×480"},"maxInlineBytes":1572864,"maxTotalInlineBytes":8388608,"maxPerPage":6,"placeholderLabel":"配图占位","placeholderHintPrefix":"建议 ","placeholderHintSuffix":"px","zeroExternal":true,"qualityRule":"位图优先提供 ≥2× 显示尺寸;截图用 16:9 或 4:3 锁定比例;数据图不要用截图(应用内联 SVG 图表,可随主题变色)。"};
@@ -2056,6 +2057,16 @@ function modeFloorPtA(mode) {
2056
2057
  var m = String(mode || 'presentation');
2057
2058
  return (floors[m] != null) ? floors[m] : 10;
2058
2059
  }
2060
+ function snapFont(pt, ladder, floor) {
2061
+ var lad = (ladder || FONT_LADDER).filter(function (v) { return v >= (floor == null ? 0 : floor); });
2062
+ if (!lad.length) return floor == null ? pt : Math.max(floor, pt);
2063
+ var best = lad[0], bd = Math.abs(lad[0] - pt);
2064
+ for (var i = 1; i < lad.length; i++) {
2065
+ var d = Math.abs(lad[i] - pt);
2066
+ if (d < bd) { bd = d; best = lad[i]; }
2067
+ }
2068
+ return best;
2069
+ }
2059
2070
  function fitFont(items, widthIn, availIn, opts) {
2060
2071
  opts = opts || {};
2061
2072
  var max = (opts.max == null) ? 99 : opts.max, lf = opts.lineFactor || 1.45;
@@ -2400,7 +2411,7 @@ function imageLayoutShapes(sh, S, layout, img, items, points, isPh, fit, y0, y1)
2400
2411
  sh.push(shape('rect', rxI, lyI + rowHI / 2 - 0.06, 0.12, 0.12, S.accent));
2401
2412
  sh.push(txSp(rxI + 0.26, lyI, rwI - 0.3, rowHI - 0.04,
2402
2413
  [[{ t: (pt[0] || '') + ' ', sz: fzI, b: 1, col: S.ink, font: S.font },
2403
- { t: pt[1] || '', sz: fzI - 1, col: S.body, font: S.font }]], { anchor: 't' }));
2414
+ { t: pt[1] || '', sz: snapFont(fzI - 1), col: S.body, font: S.font }]], { anchor: 't' }));
2404
2415
  });
2405
2416
  capY = iy + Math.max(ihh, ih * 0.5);
2406
2417
  } else if (layout === 'bleed') {
@@ -2449,24 +2460,55 @@ function hbarRows(sh, ec, S, y0, y1, dcols, x0, w) {
2449
2460
  }
2450
2461
  /* 竖柱 / 堆叠柱 */
2451
2462
  function vbarShapes(sh, ec, S, x, y, w, h, dcols) {
2452
- var labels = ec.labels || [], values = ec.values || [];
2463
+ /* Multi-series aware (mirrors lineShapes): ec.series[{name,values}] or single ec.values. */
2464
+ var labels = ec.labels || [];
2465
+ var series = (ec.series && ec.series.length)
2466
+ ? ec.series
2467
+ : [{ name: '数值', values: ec.values || [] }];
2453
2468
  var nb = Math.max(1, labels.length);
2469
+ var ns = Math.max(1, series.length);
2454
2470
  var baseY = y + h, plotW = w, step = plotW / nb;
2455
- var bw = Math.min(1.1, step * 0.55);
2456
- var vmax = ec.max || Math.max.apply(null, values.concat([1]));
2457
- var top = values.length ? Math.max.apply(null, values) : 0;
2471
+ var cluster = Math.min(1.1, step * (ns > 1 ? 0.78 : 0.55));
2472
+ var bw = cluster / ns;
2473
+ var all = [];
2474
+ series.forEach(function (se) {
2475
+ (se.values || []).forEach(function (v) { all.push(Number(v) || 0); });
2476
+ });
2477
+ var vmax = ec.max || Math.max.apply(null, all.concat([1]));
2478
+ var top = all.length ? Math.max.apply(null, all) : 0;
2458
2479
  sh.push(shape('rect', x, baseY, plotW, 0.02, S.line));
2459
- values.forEach(function (v, i) {
2460
- var hh = Math.max(0.05, v / vmax * (h - 0.5));
2461
- var bx = x + i * step + (step - bw) / 2;
2462
- var hot = v === top;
2463
- var dc = dcols ? dcols[i % 5] : null;
2464
- sh.push(shape('roundRect', bx, baseY - hh, bw, hh, dc || (hot ? S.accent : S.faint), { adj: 6000 }));
2465
- sh.push(txSp(bx - 0.3, baseY - hh - 0.4, bw + 0.6, 0.32,
2466
- [[{ t: valText(v, ec.unit), sz: 12.5, b: 1, col: hot ? S.accent : S.body, font: S.font }]], { align: 'ctr' }));
2467
- sh.push(txSp(bx - 0.3, baseY + 0.08, bw + 0.6, 0.32,
2468
- [[{ t: labels[i], sz: 10.5, col: S.faint, font: S.font }]], { align: 'ctr' }));
2480
+ series.forEach(function (se, si) {
2481
+ var vals = se.values || [];
2482
+ var col = dcols ? dcols[si % 5] : (si === 0 ? S.accent : S.faint);
2483
+ vals.forEach(function (v, i) {
2484
+ var num = Number(v) || 0;
2485
+ var hh = Math.max(0.05, num / vmax * (h - 0.5));
2486
+ var bx = x + i * step + (step - cluster) / 2 + si * bw;
2487
+ var hot = ns === 1 && num === top;
2488
+ sh.push(shape('roundRect', bx, baseY - hh, Math.max(0.04, bw * 0.92), hh,
2489
+ hot ? (dcols ? dcols[i % 5] : S.accent) : col, { adj: 6000 }));
2490
+ if (ns === 1) {
2491
+ sh.push(txSp(bx - 0.3, baseY - hh - 0.4, bw + 0.6, 0.32,
2492
+ [[{ t: valText(num, ec.unit), sz: 12.5, b: 1, col: hot ? S.accent : S.body, font: S.font }]], { align: 'ctr' }));
2493
+ }
2494
+ });
2469
2495
  });
2496
+ labels.forEach(function (lb, i) {
2497
+ var lx = x + i * step;
2498
+ sh.push(txSp(lx, baseY + 0.08, step, 0.32,
2499
+ [[{ t: lb, sz: 10.5, col: S.faint, font: S.font }]], { align: 'ctr' }));
2500
+ });
2501
+ /* Multi-series legend along top of plot (keeps category labels; avoids blank chart). */
2502
+ if (ns > 1) {
2503
+ var lx2 = x;
2504
+ series.forEach(function (se, si) {
2505
+ var col2 = dcols ? dcols[si % 5] : (si === 0 ? S.accent : S.faint);
2506
+ sh.push(shape('rect', lx2, y, 0.12, 0.12, col2));
2507
+ sh.push(txSp(lx2 + 0.16, y - 0.02, 1.4, 0.24,
2508
+ [[{ t: String(se.name || ('系列' + (si + 1))), sz: 10, col: S.body, font: S.font }]]));
2509
+ lx2 += 1.6;
2510
+ });
2511
+ }
2470
2512
  }
2471
2513
  /* 折线 / 双折线 / 面积 */
2472
2514
  function lineShapes(sh, ec, S, x, y, w, h, dcols) {
@@ -2873,8 +2915,11 @@ function infoApprox(sh, sec, S, y0, y1) {
2873
2915
  totals.push(tt);
2874
2916
  }
2875
2917
  var maxTot = Math.max.apply(null, totals.concat([1]));
2876
- var plotH3 = P.y1 - P.y0;
2877
- var cyMid = (P.y0 + P.y1) / 2;
2918
+ /* Reserve legend INSIDE the plot box so 6-series pages do not crush the annotation band. */
2919
+ var legH = Math.min(1.2, Math.max(0.28, series.length * 0.22 + 0.08));
2920
+ var plotBottom = P.y1 - legH;
2921
+ var plotH3 = Math.max(0.6, plotBottom - P.y0);
2922
+ var cyMid = P.y0 + plotH3 / 2;
2878
2923
  var base = totals.map(function (tv) { return cyMid - tv / maxTot * plotH3 / 2; });
2879
2924
  series.forEach(function (se, si) {
2880
2925
  var upper = base.map(function (bv, i3) { return bv + (values[si][i3] || 0) / maxTot * plotH3 / 2; });
@@ -2884,12 +2929,12 @@ function infoApprox(sh, sec, S, y0, y1) {
2884
2929
  sh.push(shape('rect', MX + i4 * stepX, (base[i4] + base[i4 + 1]) / 2, stepX, hgt, palette[si % palette.length]));
2885
2930
  }
2886
2931
  base = upper;
2887
- sh.push(shape('rect', MX, P.y1 + 0.06 + si * 0.26, 0.12, 0.12, palette[si % palette.length]));
2888
- sh.push(txSp(MX + 0.16, P.y1 + si * 0.26, 1.5, 0.26,
2932
+ sh.push(shape('rect', MX, plotBottom + 0.04 + si * 0.2, 0.12, 0.12, palette[si % palette.length]));
2933
+ sh.push(txSp(MX + 0.16, plotBottom + 0.02 + si * 0.2, 1.5, 0.2,
2889
2934
  [[{ t: String(se.name || ('系列' + (si + 1))), sz: 10, col: S.body, font: S.font }]], { anchor: 'ctr' }));
2890
2935
  });
2891
2936
  labels.forEach(function (lb, i5) {
2892
- sh.push(txSp(MX + (nPts > 1 ? i5 / (nPts - 1) : 0.5) * CW - 0.4, P.y1 - 0.02, 0.8, 0.24,
2937
+ sh.push(txSp(MX + (nPts > 1 ? i5 / (nPts - 1) : 0.5) * CW - 0.4, plotBottom - 0.22, 0.8, 0.2,
2893
2938
  [[{ t: String(lb), sz: 9.5, col: S.faint, font: S.font }]], { align: 'ctr' }));
2894
2939
  });
2895
2940
  }
@@ -3081,8 +3126,8 @@ function slidesOf(model, S) {
3081
3126
  var iy = iR.y;
3082
3127
  var capH2 = img.caption ? 0.32 : 0;
3083
3128
  var ih = Math.max(1.2, iR.h);
3084
- imageLayoutShapes(sh, S, layout, img, items, sec.points || [], isPh, fit, iy, iy + ih);
3085
- if (img.caption) sh.push(txSp(MX, iy + ih + 0.04, CW, capH2, [[{ t: img.caption, sz: 10.5, col: S.faint, font: S.font }]]));
3129
+ var capYImg = imageLayoutShapes(sh, S, layout, img, items, sec.points || [], isPh, fit, iy, iy + ih);
3130
+ if (img.caption) sh.push(txSp(MX, capYImg + 0.04, CW, capH2, [[{ t: img.caption, sz: 10.5, col: S.faint, font: S.font }]]));
3086
3131
  } else if (type === 'donut') {
3087
3132
  var dcn = sec.chart || {};
3088
3133
  if (dcn.labels && dcn.values) donutChart(sh, dcn, S, dcn.colors || donutColors(model.style, S, model.theme));
@@ -3399,7 +3444,7 @@ function slidesOf(model, S) {
3399
3444
  sh.push(shape('rect', x, ly2 + rowHP / 2 - 0.06, 0.12, 0.12, S.accent));
3400
3445
  sh.push(txSp(x + 0.28, ly2, w - 0.4, rowHP - 0.04,
3401
3446
  [[{ t: pt[0] + ' ', sz: fzP, b: 1, col: S.ink, font: S.font },
3402
- { t: pt[1], sz: fzP - 1, col: S.body, font: S.font }]]));
3447
+ { t: pt[1], sz: snapFont(fzP - 1), col: S.body, font: S.font }]]));
3403
3448
  });
3404
3449
  };
3405
3450
  if (lt2 === 'table') {
@@ -3520,7 +3565,7 @@ function slidesOf(model, S) {
3520
3565
  sh.push(shape('rect', ptsR.x, y11 + rowHPt / 2 - P2.markSize / 2, P2.markSize, P2.markSize, S.accent));
3521
3566
  sh.push(txSp(ptsR.x + 0.32, y11, textW, rowHPt - 0.04,
3522
3567
  [[{ t: p[0] + ' ', sz: fzP, b: 1, col: S.ink, font: S.font },
3523
- { t: p[1], sz: fzP - 1, col: S.body, font: S.font }]]));
3568
+ { t: p[1], sz: snapFont(fzP - 1), col: S.body, font: S.font }]]));
3524
3569
  });
3525
3570
  if (hasM) {
3526
3571
  var gx2 = PW - MX - nm2 * mw2;
@@ -1788,6 +1788,7 @@ window.REPORT_MODEL = {
1788
1788
 
1789
1789
  /* __TOPPPT_RUNTIME_START__ */
1790
1790
  /* ══ PPTX 导出运行时(assets/pptx-export.js 的内联副本 · 由 scripts/sync_runtime.py 注入,禁止手改) ══ */
1791
+ /* __TOPPPT_RUNTIME_SHA__:68c55206c33160af */
1791
1792
  /* ═══════════════════════════════════════════════════════════════════════════
1792
1793
  * TopPPT HTML· 浏览器端 PPTX 预览运行时
1793
1794
  * 零依赖、随报告单文件分发;OOXML 序列化器(仅供预览,页面不导出文件)。
@@ -1869,7 +1870,7 @@ var STYLE_DATA_COLORS = {"business-blue":["1a73e8","3526bb","21a199","b77148","9
1869
1870
  var STYLE_DATA_COLORS_DARK = {"business-blue":["8ab4f8","7966e0","88e7e5","d4ad91","cbce83"],"apple-mono":["f5f5f7","2997ff","2dd4bf","ff9f0a","bf5af2"],"mckinsey":["7fb2e5","6f6bdb","8ce3d8","d1a694","cbc586"],"brand-red":["ff5a66","e09e66","e788cb","91d4c2","83b4ce"],"warm-sand":["d9b36a","c2d571","df9391","97b5ce","8e89c7"],"deep-teal":["4fc3b0","7aaecd","97d8a4","c99cac","c29c8f"],"graphite-dark":["4da3ff","6c66e0","88e7dc","d4a691","cec983"],"indigo-violet":["a5a4f0","a967e0","89c3e7","d3c792","aece83"],"spectrum":["8ba0f8","9066e0","88d6e7","d4ba91","bdce83"]};
1870
1871
  var GRID = {"columns":12,"gutter":0.16,"colW":0.8644,"x":[0.6,1.6244,2.6488,3.6732,4.6976,5.722,6.7464,7.7708,8.7952,9.8196,10.844,11.8684,12.733],"y":[2.35,3.27,4.19,5.11,6.03,6.9],"safe":{"top":0.4,"bottom":0.4,"left":0.6,"right":0.6}};
1871
1872
  var TYPO = {"levels":[{"id":"C0","name":"封面/章节幕标题","role":"coverTitle","usage":"封面主标题、章节幕标题"},{"id":"T1","name":"页码/章节徽章","role":"caption","usage":"页码徽章、章节编号"},{"id":"T2","name":"页面主标题/结论标题","role":"h1","usage":"每页顶部结论句(research 行动标题)"},{"id":"T3","name":"副标题/语境说明","role":"lead","usage":"主标题下方导语"},{"id":"T4","name":"模块标题/图表标题","role":"h2","usage":"卡片标题、图表标题、面板标题"},{"id":"T5","name":"证据编号/轻量标签","role":"micro","usage":"Exhibit 编号、状态标签"},{"id":"T6","name":"证据块标题/小节标题","role":"h2","usage":"分栏小标题、证据块标题"},{"id":"T7","name":"正文解释段落","role":"body","usage":"证据解释、管理解读正文、表格正文"},{"id":"T8","name":"结论条文字","role":"body","usage":"so-what 结论条、核心结论框"},{"id":"T9","name":"SO WHAT 标签","role":"caption","usage":"so-what 标签行"},{"id":"T10","name":"SO WHAT 正文/业务含义","role":"body","usage":"so-what 正文、行动含义、表格行动项"},{"id":"T11","name":"图表轴/图例/刻度/微标签","role":"micro","usage":"坐标轴、图例、刻度、单位(禁用于表格正文与完整短句)"},{"id":"T12","name":"图表数据标签","role":"caption","usage":"折线点值、柱形标签、百分比标注"},{"id":"T13","name":"关键 KPI 大数字","role":"h1","usage":"KPI 大数字、hero 数值"},{"id":"T14","name":"注释/口径/来源/页脚","role":"micro","usage":"footnote、来源行、页脚、小页码"}],"tableSemanticRule":{"body":["T7","T10"],"microAllowed":["T11"],"microForbiddenFor":["表格正文","行动项","风险项","解释句","建议句","长项目符号","完整短句"]}};
1872
- var CONT = {"pad":{"card":0.18,"panel":0.2,"cell":0.08,"band":0.16,"soWhat":0.16,"kpi":0.18,"chart":0.1,"head":0.05,"footer":0.05,"node":0.06},"minPad":0.06,"textMetrics":{"lineFactor":1.45,"emAsciiRatio":0.52},"overflowRule":"溢出处置优先级:① 优化内容(列表化/精炼/合并/拆页/换组合版式)→ ② 调整容器尺寸与行宽 → ③ 有限度缩小字号(见 fontShrink)→ ④ 仍装不下则拆页。禁止无限缩字号硬塞,也禁止把「精简」当第一手段砍掉决策必需信息。","fontShrink":{"ladder":[15,14,13.5,13,12.5,12,11.5,11,10.5,10,9.5,9,8.5],"maxShrinkSteps":4,"floorPt":{"presentation":10,"research":9,"architecture":10},"preferContentFirst":true,"warnBelow":9.5},"continuousTextRule":"语义连续的一句话 / so-what 主句 / 结论句 / 表格单元格正文不得拆成多个独立文本框(避免异常空格、断句、基线漂移);局部加粗高亮必须用同一文本框内富文本。"};
1873
+ var CONT = {"pad":{"card":0.18,"panel":0.2,"cell":0.08,"band":0.16,"soWhat":0.16,"kpi":0.18,"chart":0.1,"head":0.05,"footer":0.05,"node":0.06},"minPad":0.06,"textMetrics":{"lineFactor":1.45,"emAsciiRatio":0.52},"overflowRule":"溢出处置优先级(禁静默截断):① 重构承载(列表/卡片/表/图/组合版式)→ ② 拆页/分章(议程→主张→证据卡→明细;01a/01b;信息须完整)→ ③ 换布局形态(V1–V4/多列/卡栅格)→ ④ 有限 fontShrink(阶梯内、模式 floor 以上、最多 4 档)→ ⑤ 禁止:静默截断、砍 so-what/证据/口径、为审美稀疏删决策必需信息。单页字数预算是预警不是删字许可证。","fontShrink":{"ladder":[15,14,13.5,13,12.5,12,11.5,11,10.5,10,9.5,9,8.5],"maxShrinkSteps":4,"floorPt":{"presentation":10,"research":9,"architecture":10},"preferContentFirst":true,"warnBelow":9.5},"continuousTextRule":"语义连续的一句话 / so-what 主句 / 结论句 / 表格单元格正文不得拆成多个独立文本框(避免异常空格、断句、基线漂移);局部加粗高亮必须用同一文本框内富文本。"};
1873
1874
  var REG = {"bar":{"html":"svg-bars","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":160}},"hbar":{"html":"svg-hbars","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":100}},"stack":{"html":"svg-stack","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":160},"nativeOpt":{"barGrouping":"stacked"}},"stackline":{"html":"svg-stackline","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":40},"nativeOpt":{"barGrouping":"percentStacked"}},"line":{"html":"svg-line","pptx":"native","nativeType":"line","dataTable":"notes","min":{"vbHeightMin":160}},"dualline":{"html":"svg-dualline","pptx":"native","nativeType":"line","dataTable":"notes","min":{"vbHeightMin":160}},"area":{"html":"svg-area","pptx":"native","nativeType":"area","dataTable":"notes","min":{"vbHeightMin":160}},"donut":{"html":"svg-donut","pptx":"native","nativeType":"doughnut","dataTable":"notes","min":{"pxWidthMin":140}},"multidonut":{"html":"svg-mdonut","pptx":"native","nativeType":"doughnut","dataTable":"notes","min":{"pxWidthMin":140}},"pie":{"html":"svg-pie","pptx":"native","nativeType":"pie","dataTable":"notes","min":{"pxWidthMin":140}},"radar":{"html":"svg-radar","pptx":"native","nativeType":"radar","dataTable":"notes","min":{"pxWidthMin":220}},"scatter":{"html":"svg-scatter","pptx":"native","nativeType":"scatter","dataTable":"notes","min":{"vbHeightMin":180}},"bubble":{"html":"svg-bubble","pptx":"native","nativeType":"bubble","dataTable":"notes","min":{"vbHeightMin":180}},"waterfall":{"html":"svg-wf","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":170},"nativeTrick":"stacked+hiddenBase+connector"},"gauge":{"html":"svg-gauge","pptx":"native","nativeType":"doughnut","dataTable":"notes","min":{"pxWidthMin":180},"nativeTrick":"doughnut+firstSliceAng+hiddenRemainder"},"pareto":{"html":"svg-pareto","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":180},"nativeTrick":"multiType+bar+line"},"gantt":{"html":"svg-gantt","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":130},"path":{"forbidPresetShapes":true}},"vsbar":{"html":"svg-vsbar","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":100},"path":{"forbidPresetShapes":true}},"progress":{"html":"svg-progress","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":100},"path":{"forbidPresetShapes":true}},"sparkline":{"html":"svg-spark","pptx":"shape","dataTable":"off","min":{"vbHeightMin":20},"path":{"forbidPresetShapes":true}},"funnel":{"html":"svg-funnel","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":160},"path":{"minSamplePoints":8,"forbidPresetShapes":true}},"treemap":{"html":"svg-treemap","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":170},"path":{"forbidPresetShapes":true}},"marimekko":{"html":"svg-marimekko","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":160},"path":{"forbidPresetShapes":true}},"boxplot":{"html":"svg-boxplot","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":180},"path":{"forbidPresetShapes":true}},"network":{"html":"svg-network","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":200},"path":{"forbidPresetShapes":true}},"sankey":{"html":"svg-sankey","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":200},"path":{"minSamplePoints":16,"trackBothEdges":true,"forbidPresetShapes":true}},"streamgraph":{"html":"svg-stream","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":160},"path":{"minSamplePoints":24,"trackBothEdges":true,"forbidPresetShapes":true}},"slope":{"html":"svg-slope","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":180},"path":{"forbidPresetShapes":true}},"dumbbell":{"html":"svg-dumbbell","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":160},"path":{"forbidPresetShapes":true}},"lollipop":{"html":"svg-lollipop","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":140},"path":{"forbidPresetShapes":true}},"dotplot":{"html":"svg-dotplot","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":120},"path":{"forbidPresetShapes":true}},"bulletchart":{"html":"svg-bullet","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":140},"path":{"forbidPresetShapes":true}},"waffle":{"html":"svg-waffle","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":160},"path":{"forbidPresetShapes":true}},"radialbar":{"html":"svg-radialbar","pptx":"shape","dataTable":"notes","min":{"pxWidthMin":200},"path":{"minSamplePoints":16,"forbidPresetShapes":true}},"rose":{"html":"svg-rose","pptx":"shape","dataTable":"notes","min":{"pxWidthMin":180},"path":{"minSamplePoints":16,"forbidPresetShapes":true}},"candlestick":{"html":"svg-candle","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":180},"path":{"forbidPresetShapes":true}}};
1874
1875
  var DEEP = {"triggers":["高保真","1:1","一比一","精确还原","按图还原","正式交付","不能偏移","像素级","严格对照","逐页验收"],"complexCharts":["sankey","streamgraph","treemap","marimekko","boxplot","network","rose","radialbar","candlestick","funnel"],"checks":{"anchors":true,"containerOverflow":true,"renderCompare":true,"manifest":true},"renderCompare":{"engine":"soffice","fallback":"powerpoint-com","skipIfMissing":true,"dpi":96}};
1875
1876
  var IMG = {"layouts":["full","half","bleed","grid","compare","wall"],"multiLayouts":["grid","compare","wall"],"fitEnum":["cover","contain"],"fitDefault":"cover","formats":["png","jpeg","jpg","webp","svg"],"ratioDefault":{"full":"3:1","half":"4:3","bleed":"21:9","grid":"4:3","compare":"4:3","wall":"1:1"},"ratioCssClass":{"full":"media--r3-1","half":"media--r4-3","bleed":"media--r21-9","grid":"media--r4-3","compare":"media--r4-3","wall":"media--r1-1"},"recommendedSizePx":{"full":"2400×800","half":"1400×1050","bleed":"2560×1100","grid":"900×675","compare":"1400×1050","wall":"480×480"},"maxInlineBytes":1572864,"maxTotalInlineBytes":8388608,"maxPerPage":6,"placeholderLabel":"配图占位","placeholderHintPrefix":"建议 ","placeholderHintSuffix":"px","zeroExternal":true,"qualityRule":"位图优先提供 ≥2× 显示尺寸;截图用 16:9 或 4:3 锁定比例;数据图不要用截图(应用内联 SVG 图表,可随主题变色)。"};
@@ -2066,6 +2067,16 @@ function modeFloorPtA(mode) {
2066
2067
  var m = String(mode || 'presentation');
2067
2068
  return (floors[m] != null) ? floors[m] : 10;
2068
2069
  }
2070
+ function snapFont(pt, ladder, floor) {
2071
+ var lad = (ladder || FONT_LADDER).filter(function (v) { return v >= (floor == null ? 0 : floor); });
2072
+ if (!lad.length) return floor == null ? pt : Math.max(floor, pt);
2073
+ var best = lad[0], bd = Math.abs(lad[0] - pt);
2074
+ for (var i = 1; i < lad.length; i++) {
2075
+ var d = Math.abs(lad[i] - pt);
2076
+ if (d < bd) { bd = d; best = lad[i]; }
2077
+ }
2078
+ return best;
2079
+ }
2069
2080
  function fitFont(items, widthIn, availIn, opts) {
2070
2081
  opts = opts || {};
2071
2082
  var max = (opts.max == null) ? 99 : opts.max, lf = opts.lineFactor || 1.45;
@@ -2410,7 +2421,7 @@ function imageLayoutShapes(sh, S, layout, img, items, points, isPh, fit, y0, y1)
2410
2421
  sh.push(shape('rect', rxI, lyI + rowHI / 2 - 0.06, 0.12, 0.12, S.accent));
2411
2422
  sh.push(txSp(rxI + 0.26, lyI, rwI - 0.3, rowHI - 0.04,
2412
2423
  [[{ t: (pt[0] || '') + ' ', sz: fzI, b: 1, col: S.ink, font: S.font },
2413
- { t: pt[1] || '', sz: fzI - 1, col: S.body, font: S.font }]], { anchor: 't' }));
2424
+ { t: pt[1] || '', sz: snapFont(fzI - 1), col: S.body, font: S.font }]], { anchor: 't' }));
2414
2425
  });
2415
2426
  capY = iy + Math.max(ihh, ih * 0.5);
2416
2427
  } else if (layout === 'bleed') {
@@ -2459,24 +2470,55 @@ function hbarRows(sh, ec, S, y0, y1, dcols, x0, w) {
2459
2470
  }
2460
2471
  /* 竖柱 / 堆叠柱 */
2461
2472
  function vbarShapes(sh, ec, S, x, y, w, h, dcols) {
2462
- var labels = ec.labels || [], values = ec.values || [];
2473
+ /* Multi-series aware (mirrors lineShapes): ec.series[{name,values}] or single ec.values. */
2474
+ var labels = ec.labels || [];
2475
+ var series = (ec.series && ec.series.length)
2476
+ ? ec.series
2477
+ : [{ name: '数值', values: ec.values || [] }];
2463
2478
  var nb = Math.max(1, labels.length);
2479
+ var ns = Math.max(1, series.length);
2464
2480
  var baseY = y + h, plotW = w, step = plotW / nb;
2465
- var bw = Math.min(1.1, step * 0.55);
2466
- var vmax = ec.max || Math.max.apply(null, values.concat([1]));
2467
- var top = values.length ? Math.max.apply(null, values) : 0;
2481
+ var cluster = Math.min(1.1, step * (ns > 1 ? 0.78 : 0.55));
2482
+ var bw = cluster / ns;
2483
+ var all = [];
2484
+ series.forEach(function (se) {
2485
+ (se.values || []).forEach(function (v) { all.push(Number(v) || 0); });
2486
+ });
2487
+ var vmax = ec.max || Math.max.apply(null, all.concat([1]));
2488
+ var top = all.length ? Math.max.apply(null, all) : 0;
2468
2489
  sh.push(shape('rect', x, baseY, plotW, 0.02, S.line));
2469
- values.forEach(function (v, i) {
2470
- var hh = Math.max(0.05, v / vmax * (h - 0.5));
2471
- var bx = x + i * step + (step - bw) / 2;
2472
- var hot = v === top;
2473
- var dc = dcols ? dcols[i % 5] : null;
2474
- sh.push(shape('roundRect', bx, baseY - hh, bw, hh, dc || (hot ? S.accent : S.faint), { adj: 6000 }));
2475
- sh.push(txSp(bx - 0.3, baseY - hh - 0.4, bw + 0.6, 0.32,
2476
- [[{ t: valText(v, ec.unit), sz: 12.5, b: 1, col: hot ? S.accent : S.body, font: S.font }]], { align: 'ctr' }));
2477
- sh.push(txSp(bx - 0.3, baseY + 0.08, bw + 0.6, 0.32,
2478
- [[{ t: labels[i], sz: 10.5, col: S.faint, font: S.font }]], { align: 'ctr' }));
2490
+ series.forEach(function (se, si) {
2491
+ var vals = se.values || [];
2492
+ var col = dcols ? dcols[si % 5] : (si === 0 ? S.accent : S.faint);
2493
+ vals.forEach(function (v, i) {
2494
+ var num = Number(v) || 0;
2495
+ var hh = Math.max(0.05, num / vmax * (h - 0.5));
2496
+ var bx = x + i * step + (step - cluster) / 2 + si * bw;
2497
+ var hot = ns === 1 && num === top;
2498
+ sh.push(shape('roundRect', bx, baseY - hh, Math.max(0.04, bw * 0.92), hh,
2499
+ hot ? (dcols ? dcols[i % 5] : S.accent) : col, { adj: 6000 }));
2500
+ if (ns === 1) {
2501
+ sh.push(txSp(bx - 0.3, baseY - hh - 0.4, bw + 0.6, 0.32,
2502
+ [[{ t: valText(num, ec.unit), sz: 12.5, b: 1, col: hot ? S.accent : S.body, font: S.font }]], { align: 'ctr' }));
2503
+ }
2504
+ });
2479
2505
  });
2506
+ labels.forEach(function (lb, i) {
2507
+ var lx = x + i * step;
2508
+ sh.push(txSp(lx, baseY + 0.08, step, 0.32,
2509
+ [[{ t: lb, sz: 10.5, col: S.faint, font: S.font }]], { align: 'ctr' }));
2510
+ });
2511
+ /* Multi-series legend along top of plot (keeps category labels; avoids blank chart). */
2512
+ if (ns > 1) {
2513
+ var lx2 = x;
2514
+ series.forEach(function (se, si) {
2515
+ var col2 = dcols ? dcols[si % 5] : (si === 0 ? S.accent : S.faint);
2516
+ sh.push(shape('rect', lx2, y, 0.12, 0.12, col2));
2517
+ sh.push(txSp(lx2 + 0.16, y - 0.02, 1.4, 0.24,
2518
+ [[{ t: String(se.name || ('系列' + (si + 1))), sz: 10, col: S.body, font: S.font }]]));
2519
+ lx2 += 1.6;
2520
+ });
2521
+ }
2480
2522
  }
2481
2523
  /* 折线 / 双折线 / 面积 */
2482
2524
  function lineShapes(sh, ec, S, x, y, w, h, dcols) {
@@ -2883,8 +2925,11 @@ function infoApprox(sh, sec, S, y0, y1) {
2883
2925
  totals.push(tt);
2884
2926
  }
2885
2927
  var maxTot = Math.max.apply(null, totals.concat([1]));
2886
- var plotH3 = P.y1 - P.y0;
2887
- var cyMid = (P.y0 + P.y1) / 2;
2928
+ /* Reserve legend INSIDE the plot box so 6-series pages do not crush the annotation band. */
2929
+ var legH = Math.min(1.2, Math.max(0.28, series.length * 0.22 + 0.08));
2930
+ var plotBottom = P.y1 - legH;
2931
+ var plotH3 = Math.max(0.6, plotBottom - P.y0);
2932
+ var cyMid = P.y0 + plotH3 / 2;
2888
2933
  var base = totals.map(function (tv) { return cyMid - tv / maxTot * plotH3 / 2; });
2889
2934
  series.forEach(function (se, si) {
2890
2935
  var upper = base.map(function (bv, i3) { return bv + (values[si][i3] || 0) / maxTot * plotH3 / 2; });
@@ -2894,12 +2939,12 @@ function infoApprox(sh, sec, S, y0, y1) {
2894
2939
  sh.push(shape('rect', MX + i4 * stepX, (base[i4] + base[i4 + 1]) / 2, stepX, hgt, palette[si % palette.length]));
2895
2940
  }
2896
2941
  base = upper;
2897
- sh.push(shape('rect', MX, P.y1 + 0.06 + si * 0.26, 0.12, 0.12, palette[si % palette.length]));
2898
- sh.push(txSp(MX + 0.16, P.y1 + si * 0.26, 1.5, 0.26,
2942
+ sh.push(shape('rect', MX, plotBottom + 0.04 + si * 0.2, 0.12, 0.12, palette[si % palette.length]));
2943
+ sh.push(txSp(MX + 0.16, plotBottom + 0.02 + si * 0.2, 1.5, 0.2,
2899
2944
  [[{ t: String(se.name || ('系列' + (si + 1))), sz: 10, col: S.body, font: S.font }]], { anchor: 'ctr' }));
2900
2945
  });
2901
2946
  labels.forEach(function (lb, i5) {
2902
- sh.push(txSp(MX + (nPts > 1 ? i5 / (nPts - 1) : 0.5) * CW - 0.4, P.y1 - 0.02, 0.8, 0.24,
2947
+ sh.push(txSp(MX + (nPts > 1 ? i5 / (nPts - 1) : 0.5) * CW - 0.4, plotBottom - 0.22, 0.8, 0.2,
2903
2948
  [[{ t: String(lb), sz: 9.5, col: S.faint, font: S.font }]], { align: 'ctr' }));
2904
2949
  });
2905
2950
  }
@@ -3091,8 +3136,8 @@ function slidesOf(model, S) {
3091
3136
  var iy = iR.y;
3092
3137
  var capH2 = img.caption ? 0.32 : 0;
3093
3138
  var ih = Math.max(1.2, iR.h);
3094
- imageLayoutShapes(sh, S, layout, img, items, sec.points || [], isPh, fit, iy, iy + ih);
3095
- if (img.caption) sh.push(txSp(MX, iy + ih + 0.04, CW, capH2, [[{ t: img.caption, sz: 10.5, col: S.faint, font: S.font }]]));
3139
+ var capYImg = imageLayoutShapes(sh, S, layout, img, items, sec.points || [], isPh, fit, iy, iy + ih);
3140
+ if (img.caption) sh.push(txSp(MX, capYImg + 0.04, CW, capH2, [[{ t: img.caption, sz: 10.5, col: S.faint, font: S.font }]]));
3096
3141
  } else if (type === 'donut') {
3097
3142
  var dcn = sec.chart || {};
3098
3143
  if (dcn.labels && dcn.values) donutChart(sh, dcn, S, dcn.colors || donutColors(model.style, S, model.theme));
@@ -3409,7 +3454,7 @@ function slidesOf(model, S) {
3409
3454
  sh.push(shape('rect', x, ly2 + rowHP / 2 - 0.06, 0.12, 0.12, S.accent));
3410
3455
  sh.push(txSp(x + 0.28, ly2, w - 0.4, rowHP - 0.04,
3411
3456
  [[{ t: pt[0] + ' ', sz: fzP, b: 1, col: S.ink, font: S.font },
3412
- { t: pt[1], sz: fzP - 1, col: S.body, font: S.font }]]));
3457
+ { t: pt[1], sz: snapFont(fzP - 1), col: S.body, font: S.font }]]));
3413
3458
  });
3414
3459
  };
3415
3460
  if (lt2 === 'table') {
@@ -3530,7 +3575,7 @@ function slidesOf(model, S) {
3530
3575
  sh.push(shape('rect', ptsR.x, y11 + rowHPt / 2 - P2.markSize / 2, P2.markSize, P2.markSize, S.accent));
3531
3576
  sh.push(txSp(ptsR.x + 0.32, y11, textW, rowHPt - 0.04,
3532
3577
  [[{ t: p[0] + ' ', sz: fzP, b: 1, col: S.ink, font: S.font },
3533
- { t: p[1], sz: fzP - 1, col: S.body, font: S.font }]]));
3578
+ { t: p[1], sz: snapFont(fzP - 1), col: S.body, font: S.font }]]));
3534
3579
  });
3535
3580
  if (hasM) {
3536
3581
  var gx2 = PW - MX - nm2 * mw2;