@topmindspace/tms-skills 0.1.17 → 0.1.19
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 +84 -0
- package/README.en.md +3 -3
- package/README.md +3 -3
- 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/SKILL.md +4 -4
- package/top-ppt-html/assets/examples/2026-09-09-architecture-graphite-dark.html +144 -58
- package/top-ppt-html/assets/examples/2026-09-09-presentation-business-blue.html +144 -58
- package/top-ppt-html/assets/examples/2026-09-09-research-mckinsey.html +144 -58
- package/top-ppt-html/assets/examples/2026-09-26-topmind-tms-skills-showcase.html +214 -211
- package/top-ppt-html/assets/examples/2026-09-26-topmind-tms-skills-showcase.model.json +33 -39
- package/top-ppt-html/assets/pptx-export.js +120 -46
- package/top-ppt-html/assets/style-gallery.html +21 -4
- package/top-ppt-html/assets/templates/architecture.html +158 -61
- package/top-ppt-html/assets/templates/engine.css +23 -11
- package/top-ppt-html/assets/templates/presentation.html +158 -63
- package/top-ppt-html/assets/templates/research.html +164 -69
- package/top-ppt-html/package-lock.json +2 -2
- package/top-ppt-html/package.json +1 -1
- package/top-ppt-html/references/chart-decision-tree.md +26 -25
- package/top-ppt-html/references/components-atoms.md +5 -4
- package/top-ppt-html/references/content-rules.md +17 -9
- package/top-ppt-html/references/failure-modes.md +31 -3
- package/top-ppt-html/references/high-fidelity.md +14 -1
- package/top-ppt-html/references/icons.md +2 -2
- package/top-ppt-html/references/layout-grammar.md +3 -1
- package/top-ppt-html/references/layouts-combo.md +1 -1
- package/top-ppt-html/references/layouts-research.md +1 -1
- package/top-ppt-html/references/modes.md +1 -1
- package/top-ppt-html/references/page-type-matrix.md +10 -6
- package/top-ppt-html/references/pptx-export.md +5 -5
- package/top-ppt-html/references/tech-design.md +2 -0
- package/top-ppt-html/scripts/build_icon_assets.js +92 -0
- package/top-ppt-html/scripts/build_pptx.js +226 -71
- package/top-ppt-html/scripts/cross_verify.py +84 -1
- package/top-ppt-html/scripts/extract_model.py +26 -1
- package/top-ppt-html/scripts/icon_lib.js +53 -0
- package/top-ppt-html/scripts/icon_raster.js +86 -0
- package/top-ppt-html/scripts/layout-constants.json +45 -2
- package/top-ppt-html/scripts/lib_layout_regions.js +9 -4
- package/top-ppt-html/scripts/model-schema.json +8 -3
- package/top-ppt-html/scripts/package_skill.py +1 -0
- package/top-ppt-html/scripts/render_from_model.py +254 -37
- package/top-ppt-html/scripts/scaffold_report.py +47 -24
- package/top-ppt-html/scripts/sync_runtime.py +21 -4
- package/top-ppt-html/scripts/test_feedback_gates.py +73 -0
- package/top-ppt-html/scripts/validate_pptx.py +162 -3
- package/top-ppt-html/scripts/validate_report.py +24 -0
|
@@ -330,7 +330,13 @@ border-color:color-mix(in srgb,var(--accent-on) 20%,transparent);color:var(--acc
|
|
|
330
330
|
rows-2 / rows-3:等高行分区(纵向节奏,替代等高卡片堆叠) */
|
|
331
331
|
.g-211{grid-template-columns:minmax(0,2fr) minmax(0,1fr) minmax(0,1fr)}
|
|
332
332
|
.g-121{grid-template-columns:minmax(0,1fr) minmax(0,2fr) minmax(0,1fr)}
|
|
333
|
-
.g-quad{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:minmax(
|
|
333
|
+
.g-quad{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:minmax(min-content,1fr);align-items:stretch}
|
|
334
|
+
.g-half{grid-template-columns:minmax(0,1.05fr) minmax(0,1fr);align-items:stretch}
|
|
335
|
+
@media (max-width:1180px){.g-half{grid-template-columns:1fr}}
|
|
336
|
+
.g-2--equal,.g-3--equal,.g-4--equal{grid-auto-rows:minmax(min-content,1fr);align-items:stretch}
|
|
337
|
+
.grid.g-2>.card,.grid.g-3>.card,.grid.g-4>.card,
|
|
338
|
+
.grid.g-quad>.card,.grid.g-half>.card,.grid.g-2--equal>.card,
|
|
339
|
+
.grid.g-3--equal>.card,.grid.g-4--equal>.card{align-self:stretch}
|
|
334
340
|
.g-aside{grid-template-columns:minmax(0,1fr) minmax(200px,.36fr);align-items:start}
|
|
335
341
|
.g-aside__side{position:sticky;top:calc(var(--bar-h) + 16px)}
|
|
336
342
|
.g-mosaic{grid-template-columns:repeat(3,minmax(0,1fr));
|
|
@@ -346,7 +352,7 @@ grid-template-areas:"main main main" "s1 s2 s3"}
|
|
|
346
352
|
.kv--2col{grid-template-columns:auto minmax(0,1fr) auto minmax(0,1fr)}
|
|
347
353
|
/* ── 拼贴栅格 g-bento(Bento / 马赛克):4 列基准 + 跨列/跨行工具类 ──
|
|
348
354
|
.sp-2/.sp-3/.sp-4 跨列(span),.rw-2 跨行;窄屏自动降列并收敛 span。 */
|
|
349
|
-
.g-bento{grid-template-columns:repeat(4,minmax(0,1fr));grid-auto-rows:minmax(
|
|
355
|
+
.g-bento{grid-template-columns:repeat(4,minmax(0,1fr));grid-auto-rows:minmax(min-content,1fr)}
|
|
350
356
|
.sp-2{grid-column:span 2}.sp-3{grid-column:span 3}.sp-4{grid-column:span 4}
|
|
351
357
|
.rw-2{grid-row:span 2}
|
|
352
358
|
@media (max-width:1180px){.g-bento{grid-template-columns:repeat(2,minmax(0,1fr))}
|
|
@@ -381,19 +387,21 @@ background:color-mix(in srgb,var(--bg) 86%,transparent);
|
|
|
381
387
|
backdrop-filter:saturate(160%) blur(14px);-webkit-backdrop-filter:saturate(160%) blur(14px);
|
|
382
388
|
border-bottom:1px solid var(--border-soft);
|
|
383
389
|
transition:height var(--dur-medium) var(--ease-standard)}
|
|
384
|
-
.bar__in{height:100%;display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4)}
|
|
385
|
-
.brand{display:flex;align-items:center;gap:var(--sp-3);min-width:0}
|
|
390
|
+
.bar__in{height:100%;display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);overflow:hidden}
|
|
391
|
+
.brand{display:flex;align-items:center;gap:var(--sp-3);min-width:0;flex:1 1 auto;overflow:hidden}
|
|
386
392
|
.brand__mark{width:34px;height:34px;flex:none;border-radius:10px;background:var(--accent);
|
|
387
393
|
color:var(--accent-on);display:grid;place-items:center;font-size:13px;font-weight:700}
|
|
394
|
+
.brand__txt{min-width:0;overflow:hidden;flex:1 1 auto}
|
|
388
395
|
.brand__title{font-size:var(--fs-sm);font-weight:600;color:var(--text);white-space:nowrap;
|
|
389
|
-
overflow:hidden;text-overflow:ellipsis}
|
|
396
|
+
overflow:hidden;text-overflow:ellipsis;max-width:100%}
|
|
390
397
|
.brand__sub{font-size:var(--fs-xs);color:var(--text-3);white-space:nowrap;overflow:hidden;
|
|
391
|
-
text-overflow:ellipsis}
|
|
392
|
-
.nav{display:flex;align-items:center;gap:var(--sp-1)}
|
|
398
|
+
text-overflow:ellipsis;max-width:100%}
|
|
399
|
+
.nav{display:flex;align-items:center;gap:var(--sp-1);flex:0 1 auto;min-width:0;overflow:hidden}
|
|
393
400
|
.nav a{padding:8px 14px;border-radius:var(--r-full);color:var(--text-2);text-decoration:none;
|
|
394
401
|
font-size:var(--fs-sm);font-weight:500;white-space:nowrap;transition:background-color var(--dur-short),color var(--dur-short)}
|
|
395
402
|
.nav a:hover{background:var(--surface-2);color:var(--text)}
|
|
396
403
|
@media (max-width:1180px){.nav{display:none}}
|
|
404
|
+
@media (max-width:1360px){.brand__sub{display:none}}
|
|
397
405
|
.iconbtn{width:40px;height:40px;flex:none;display:grid;place-items:center;
|
|
398
406
|
border:1px solid var(--border);border-radius:var(--r-full);background:transparent;
|
|
399
407
|
color:var(--text-2);cursor:pointer;transition:background-color var(--dur-short),color var(--dur-short)}
|
|
@@ -448,12 +456,15 @@ transition:background-color var(--dur-short),box-shadow var(--dur-short),transfo
|
|
|
448
456
|
.btn--ghost{background:transparent;color:var(--text);border-color:var(--border)}
|
|
449
457
|
.btn--onDark{background:var(--surface);color:var(--text)}
|
|
450
458
|
.card{background:var(--surface);border:1px solid var(--border-soft);border-radius:var(--r-lg);
|
|
451
|
-
padding:clamp(20px,2vw,30px);transition:border-color var(--dur-short),box-shadow var(--dur-short),background-color var(--dur-medium)
|
|
459
|
+
padding:clamp(20px,2vw,30px);transition:border-color var(--dur-short),box-shadow var(--dur-short),background-color var(--dur-medium);
|
|
460
|
+
display:flex;flex-direction:column;min-width:0}
|
|
452
461
|
.card:hover{border-color:var(--border);box-shadow:var(--shadow-1)}
|
|
453
462
|
.card--flat{background:var(--surface-1);border-color:transparent}
|
|
454
463
|
.card--flat:hover{background:var(--surface-2)}
|
|
455
464
|
.card--accent{background:var(--accent-soft);border-color:transparent}
|
|
456
|
-
.card__hd{display:flex;align-items:center;gap:var(--sp-3);margin-bottom:var(--sp-3)}
|
|
465
|
+
.card__hd{display:flex;align-items:center;gap:var(--sp-3);margin-bottom:var(--sp-3);flex:none}
|
|
466
|
+
.card>.ul,.card>.t-body,.card>.t-sm{flex:1 1 auto}
|
|
467
|
+
.card>.so-what,.card>.tbd-legend,.card>.flagbar{flex:none;margin-top:auto}
|
|
457
468
|
.card__ico{width:34px;height:34px;flex:none;border-radius:10px;background:var(--accent-soft);
|
|
458
469
|
color:var(--accent-text);display:grid;place-items:center;font-size:15px;font-weight:600}
|
|
459
470
|
.card__ico svg{width:18px;height:18px}
|
|
@@ -815,8 +826,9 @@ color:var(--accent);font-variant-numeric:tabular-nums;line-height:1;min-width:2.
|
|
|
815
826
|
.agenda__a:hover .agenda__go{color:var(--accent);transform:translateX(4px)}
|
|
816
827
|
.agenda__go svg{width:20px;height:20px;display:block}
|
|
817
828
|
@media (min-width:900px){
|
|
818
|
-
|
|
819
|
-
.agenda--2col
|
|
829
|
+
/* R4:列优先(先左列后右列),与 PPTX Agenda 列填充一致——grid 行优先会打乱阅读顺序 */
|
|
830
|
+
.agenda--2col{display:block;column-count:2;column-gap:clamp(20px,3vw,48px)}
|
|
831
|
+
.agenda--2col .agenda__i{break-inside:avoid;border-top:1px solid var(--border-soft)}}
|
|
820
832
|
/* ── 页码指示(翻页导航) ── */
|
|
821
833
|
.pager{position:fixed;right:clamp(10px,1.6vw,26px);top:50%;transform:translateY(-50%);
|
|
822
834
|
z-index:60;display:flex;flex-direction:column;align-items:center;gap:10px}
|
|
@@ -2391,7 +2403,7 @@ window.REPORT_MODEL = {
|
|
|
2391
2403
|
|
|
2392
2404
|
/* __TOPPPT_RUNTIME_START__ */
|
|
2393
2405
|
/* ══ PPTX 导出运行时(assets/pptx-export.js 的内联副本 · 由 scripts/sync_runtime.py 注入,禁止手改) ══ */
|
|
2394
|
-
/* __TOPPPT_RUNTIME_SHA__:
|
|
2406
|
+
/* __TOPPPT_RUNTIME_SHA__:af6e25f25fd2e116 */
|
|
2395
2407
|
/* ═══════════════════════════════════════════════════════════════════════════
|
|
2396
2408
|
* TopPPT HTML· 浏览器端 PPTX 预览运行时
|
|
2397
2409
|
* 零依赖、随报告单文件分发;OOXML 序列化器(仅供预览,页面不导出文件)。
|
|
@@ -2515,7 +2527,8 @@ function regionOf(pageType, slotId, opts) {
|
|
|
2515
2527
|
if (type === 'bar' && slot === 'primary') {
|
|
2516
2528
|
var by = P.chartY || 2.95;
|
|
2517
2529
|
var bb = opts.bottom != null ? opts.bottom : bottomDefault;
|
|
2518
|
-
|
|
2530
|
+
/* chartX/chartW 历史误用已纠正:与 donut/table/hbar/exhibit 同口径,图表盒对齐版心 (MX, CW) */
|
|
2531
|
+
return { x: MX, y: by, w: CW, h: Math.max(1.2, bb - by) };
|
|
2519
2532
|
}
|
|
2520
2533
|
if (type === 'bar' && slot === 'hbar') {
|
|
2521
2534
|
var y0 = P.hbarY0 || 2.6;
|
|
@@ -2550,6 +2563,15 @@ function regionOf(pageType, slotId, opts) {
|
|
|
2550
2563
|
return { x: MX, y: P.heroY || 2.9, w: CW * (P.heroW || 0.52), h: P.heroH || 1.6,
|
|
2551
2564
|
dividerX: P.dividerX, metricY0: P.metricY0, metricRowH: P.metricRowH };
|
|
2552
2565
|
}
|
|
2566
|
+
/* R3:kpi 支撑指标列——落在 dividerX 右侧(默认全宽返回会压住 hero) */
|
|
2567
|
+
if (type === 'kpi' && slot === 'metrics') {
|
|
2568
|
+
var dxK = P.dividerX != null ? P.dividerX : 0.56;
|
|
2569
|
+
return {
|
|
2570
|
+
x: MX + CW * dxK + 0.35, y: P.metricY0 || 2.95,
|
|
2571
|
+
w: CW * (1 - dxK) - 0.5,
|
|
2572
|
+
h: Math.max(0.6, bottomDefault - (P.metricY0 || 2.95)),
|
|
2573
|
+
};
|
|
2574
|
+
}
|
|
2553
2575
|
if (type === 'comparison' && (slot === 'left' || slot === 'primary' || slot === 'right')) {
|
|
2554
2576
|
var cg = P.panelGap || 0.4, pw = (CW - cg) / 2;
|
|
2555
2577
|
if (slot === 'right') return { x: MX + pw + cg, y: P.panelY || 2.55, w: pw, h: P.panelH || 3.4 };
|
|
@@ -2582,15 +2604,22 @@ function regionOf(pageType, slotId, opts) {
|
|
|
2582
2604
|
}
|
|
2583
2605
|
if (type === 'image' && slot === 'primary') {
|
|
2584
2606
|
var iy2 = Math.max(P.y || 2.3, opts.top || 0);
|
|
2585
|
-
|
|
2607
|
+
/* R2:有图注时图片不得越过 contentBottomWithNote(图注落注释带,属 annotation self) */
|
|
2608
|
+
var iBottom = (opts.bottom != null) ? opts.bottom
|
|
2609
|
+
: (opts.caption ? (L.contentBottomWithNote || 6.4) : bottomDefault);
|
|
2610
|
+
return { x: MX, y: iy2, w: CW, h: Math.max(1.2, Math.min(P.h || 4.2, iBottom - iy2)) };
|
|
2586
2611
|
}
|
|
2587
2612
|
if ((type === 'halftable') && (slot === 'left' || slot === 'primary')) {
|
|
2588
2613
|
var rs = PT.research || {};
|
|
2589
|
-
|
|
2614
|
+
var ht = opts.top != null ? opts.top : topDefault;
|
|
2615
|
+
var hb = opts.bottom != null ? opts.bottom : bottomDefault;
|
|
2616
|
+
return { x: MX, y: ht, w: CW * (rs.halfTableW || 0.52), h: Math.max(1, hb - ht) };
|
|
2590
2617
|
}
|
|
2591
2618
|
if ((type === 'halftable') && (slot === 'right' || slot === 'secondary')) {
|
|
2592
2619
|
var rs2 = PT.research || {};
|
|
2593
|
-
|
|
2620
|
+
var ht2 = opts.top != null ? opts.top : topDefault;
|
|
2621
|
+
var hb2 = opts.bottom != null ? opts.bottom : bottomDefault;
|
|
2622
|
+
return { x: MX + CW * (rs2.halfChartX || 0.57), y: ht2, w: CW * (rs2.halfChartW || 0.43), h: Math.max(1, hb2 - ht2) };
|
|
2594
2623
|
}
|
|
2595
2624
|
if (type === 'matrix' && slot === 'primary') {
|
|
2596
2625
|
var rm = PT.research || {};
|
|
@@ -2611,7 +2640,7 @@ function regionOf(pageType, slotId, opts) {
|
|
|
2611
2640
|
/* __TOPPPT_SCHEMA_START__ */
|
|
2612
2641
|
/* ── 由 scripts/sync_runtime.py 从 scripts/model-schema.json 注入 · 禁止手改 ── */
|
|
2613
2642
|
/* DSL schema 单源:浏览器端 validateModel 与 scripts/extract_model.py 消费同一份定义 */
|
|
2614
|
-
var MODEL_SCHEMA = {"version":"0.1","modes":["presentation","research","architecture"],"model":{"required":["title","sections:array","closing.title","closing.points:array"],"optional":["mode","style","theme","subtitle","meta","agenda:array"],"agendaMin":{"presentation":3,"research":3,"architecture":0},"sectionsMin":1,"sectionsRecommended":3,"agendaComfortMax":
|
|
2643
|
+
var MODEL_SCHEMA = {"version":"0.1","modes":["presentation","research","architecture"],"model":{"required":["title","sections:array","closing.title","closing.points:array"],"optional":["mode","style","theme","subtitle","meta","agenda:array"],"agendaMin":{"presentation":3,"research":3,"architecture":0},"agendaMax":7,"agendaMaxWithRefs":8,"agendaHint":"agenda 条目 = 章(篇/section),3–7 条;每章可含多页(sections[] 按页建模)。禁止把逐页标题当大纲。sections[].eyebrow 的 `NN ·` 前缀 = 章键,须与某条 agenda 对应;跳转锚点 = 该章第一页。含「参考资料」条目时 +1 仍 ≤8。","sectionsMin":1,"sectionsRecommended":3,"agendaComfortMax":8},"commonSectionFields":["eyebrow","title","lead","soWhat","footnote","flags","image","exhibitNo","layoutPreset"],"mutualExclusionHint":"verdict 与 soWhat 互斥:二者共用 annotation 结论条槽位,同页双填必叠印。comparison 页填 verdict 时不要再填 soWhat(渲染器已自动二选一,但模型侧应只给一个)。","flagsHint":"flags = 待核实/待二次修改条目字符串数组(如 '2027 增速 xx%(口径未定)');渲染为 accent 强调色标注行,提示用户核对。","imageHint":"image = 素材图片/配图占位对象。三选一必填:src(用户图,data: 内联或相对路径,零外链铁律禁 http(s))|items(多图版式:grid/compare/wall,元素 {src?, alt?, caption?, placeholder?})|placeholder:true(无图时出配图占位,原生形状渲染、pictures 不增)。其余可选:layout(full/half/bleed/grid/compare/wall,见 layout-constants.json imageSpec.layouts)、fit(cover 默认 / contain)、caption、alt、hint、ratio。","imageLayoutHint":"layout 与 HTML 版式对应:full=版心全宽图|half=左图右注(points 为右栏注解)|bleed=通栏出血|grid=多图网格(items 2/3/4/6 张)|compare=双图 A/B 对比(items 2 张)|wall=Logo 墙(items 3–12 张小图)。占位符标签文本由双引擎按 imageSpec 拼同一串,保证 A/B 通道逐页文本一致。","chartTypes":["bar","hbar","stack","stackline","line","dualline","area","donut","multidonut","pie","radar","scatter","bubble","waterfall","gauge","pareto","funnel","gantt","vsbar","progress","sparkline","slope","dumbbell","lollipop","dotplot","bulletchart","waffle","radialbar","rose","candlestick"],"chartTypesHint":"chart.type 可取值 = 本表(30 类:16 原生 + 14 形状还原)。其余 6 类复杂信息图(sankey/treemap/boxplot/network/marimekko/streamgraph)是**专属页型**而非 chart.type——它们要按列/段/节点等结构化载荷表达,故走 sections[].type。不变量:charts.registry.types == chartTypes ∪ 上述 6 类页型(sync_runtime.py 校验)。","chartDataTable":{"enum":["notes","inline","appendix","off"],"default":"notes","rule":"非原生图表(registry.pptx=shape)的 dataTable 不得为 off;缺失时按 registry 默认值补齐。"},"pageTypes":{"points":{"label":"要点列表页","modes":["presentation","research","architecture"],"required":["points:array"],"optional":["metrics:array"]},"metrics":{"label":"指标带页(4–6 个核心数字)","modes":["presentation","research"],"required":["metrics:array"]},"kpi":{"label":"大数指标页(hero 大数字 + 支撑指标行)","modes":["presentation","research"],"required":["hero:array"],"optional":["metrics:array"]},"table":{"label":"对比表页","modes":["presentation","research","architecture"],"required":["table.head:array","table.rows:array"],"optional":["table.colW:array"]},"timeline":{"label":"时间线 / 路线页","modes":["presentation","research"],"required":["phases:array"]},"steps":{"label":"步骤条页(N 步横排 + 箭头,可分组)","modes":["presentation","research","architecture"],"required":["steps:array"],"optional":["groups:array","note"]},"bar":{"label":"图表页(chart.type 见 chartTypes;native 通道走原生数据图表,shape 通道走高保真形状还原 + 数据表)","modes":["presentation","research"],"required":["chart.labels:array","chart.values:array"],"optional":["chart.type","chart.series:array","chart.points:array","chart.max","chart.unit","chart.colors:array","chart.start:array","chart.target:array","chart.dataTable","note"]},"donut":{"label":"环形图页(原生 pie 楔形 + 图例)","modes":["presentation","research"],"required":["chart.labels:array","chart.values:array"],"optional":["chart.unit","chart.centerLabel","chart.colors:array","chart.dataTable","note"]},"heatmap":{"label":"热力矩阵页(行 × 列 + 强度色阶)","modes":["presentation","research"],"required":["rowHeads:array","colHeads:array","cells:array"],"optional":["unit","scaleLabel:array","note"]},"bullet":{"label":"达成对比页(实际 vs 目标条)","modes":["presentation","research"],"required":["items:array"],"optional":["unit","max","note"]},"pyramid":{"label":"金字塔页(层级递进,顶层最窄)","modes":["presentation","research","architecture"],"required":["levels:array"],"optional":["note"]},"image":{"label":"素材图片页(full/half/bleed/grid/compare/wall,效果与位置锁定;支持配图占位)","modes":["presentation","research","architecture"],"required":["anyof:image.src:str|image.items:array|image.placeholder"],"optional":["image.caption","image.alt","image.layout","image.fit","image.ratio","image.hint","points:array","note"]},"cards":{"label":"卡片网格页(cards 元素须为 {title, points:[[k,v]…], icon?},不接受元组)","modes":["presentation","research"],"required":["cards:array"],"optional":["columns"],"cardItemHint":"cards[] 元素:{title:str, points:[[k,v]…]|[{t,d}…]|[str…], icon?:str}。icon = 语义图标名(icon_lib.js 键:增长/下降/数据/图表/趋势/占比/表格/效率/成果/安全/权限/检查/风险/团队/流程/计划/智能/洞察/工具/清单),HTML 与 PPTX 同名真导出;缺省按标题语义自动挑选。"},"split":{"label":"双区组合页(left / right 各可为 要点|图表|表格|图片:type = points(默认)| table | image | 图表类型名;图表/表格字段直接挂在对应侧)","modes":["presentation","research"],"required":["anyof:left.points:array|left.type:str"],"optional":["left.cap","left.image","left.labels:array","left.values:array","left.series:array","left.points:array","left.max","left.unit","left.colors:array","left.dataTable","left.head:array","left.rows:array","left.colW:array","right.type","right.cap","right.image","right.labels:array","right.values:array","right.series:array","right.points:array","right.max","right.unit","right.colors:array","right.dataTable","right.head:array","right.rows:array","right.colW:array"]},"comparison":{"label":"对比页(左右双栏 + 可选结论条)","modes":["presentation","research"],"required":["left.title","left.points:array","right.title","right.points:array"],"optional":["verdict"]},"quote":{"label":"引用 / 金句页(深色全幅)","modes":["presentation","research"],"required":["quote","author"],"optional":["context"]},"diagram":{"label":"分层架构页(architecture 模式走全幅几何)","modes":["presentation","research","architecture"],"required":["layers:array"],"optional":["legend:array"]},"exhibit":{"label":"Exhibit 编号图表页(research R2)","modes":["research"],"required":["chart.labels:array","chart.values:array"],"optional":["exhibitNo","chart.type","chart.series:array","chart.points:array","chart.max","chart.unit","chart.colors:array","chart.dataTable","note"]},"twocol":{"label":"双栏论证页(research R1)","modes":["research"],"required":["paragraphs:array"]},"threecol":{"label":"三栏证据页(research R6)","modes":["research"],"required":["paragraphs:array"]},"halftable":{"label":"半表半图页(research R7)","modes":["research"],"required":["table.head:array","table.rows:array","chart.labels:array","chart.values:array"],"optional":["table.colW:array","chart.type","chart.series:array","chart.points:array","chart.max","chart.unit","chart.colors:array","chart.dataTable","note"]},"matrix":{"label":"矩阵图页(research R8)","modes":["research"],"required":["rowHeads:array","colHeads:array","cells:array"]},"lane":{"label":"泳道页(architecture A2)","modes":["architecture"],"required":["lanes:array"]},"sankey":{"label":"桑基图页(节点-流带,流向与流量)","modes":["research","architecture"],"required":["flows:array"],"optional":["unit","chart.dataTable","note"]},"treemap":{"label":"树图页(面积编码的层级构成)","modes":["research","architecture"],"required":["items:array"],"optional":["unit","chart.dataTable","note"]},"boxplot":{"label":"箱线图页(分布对比:min/q1/median/q3/max)","modes":["research","architecture"],"required":["groups:array"],"optional":["unit","chart.dataTable","note"]},"network":{"label":"关系网络页(节点-边拓扑)","modes":["research","architecture"],"required":["nodes:array","edges:array"],"optional":["chart.dataTable","note"]},"marimekko":{"label":"马赛克图页(列宽 × 列高双重编码)","modes":["research","architecture"],"required":["cols:array","cells:array"],"optional":["unit","chart.dataTable","note"]},"streamgraph":{"label":"流带图页(时间上的构成演变)","modes":["research","architecture"],"required":["series:array"],"optional":["labels:array","chart.dataTable","note"]}}};
|
|
2615
2644
|
/* __TOPPPT_SCHEMA_END__ */
|
|
2616
2645
|
|
|
2617
2646
|
var _mode = 'presentation'; /* 当前模式(slidesOf 里按 model.mode 设置) */
|
|
@@ -2902,6 +2931,15 @@ function footnoteLine(sh, text, S) {
|
|
|
2902
2931
|
sh.push(txSp(R.x, R.y, R.w, R.h,
|
|
2903
2932
|
[[{ t: text, sz: 9.5, col: S.faint, font: S.font }]]));
|
|
2904
2933
|
}
|
|
2934
|
+
/* R2:sec.note 与 sec.footnote 共用注释带末行(footnoteY=6.72)。
|
|
2935
|
+
note.y=6.55 会压进 so-what 带(6.05–6.67)——同页二者必须合并为一行。 */
|
|
2936
|
+
function noteOrFootnote(sh, sec, S) {
|
|
2937
|
+
var parts = [];
|
|
2938
|
+
if (sec && sec.note) parts.push(String(sec.note));
|
|
2939
|
+
if (sec && sec.footnote) parts.push(String(sec.footnote));
|
|
2940
|
+
if (!parts.length) return;
|
|
2941
|
+
footnoteLine(sh, parts.join(' · '), S);
|
|
2942
|
+
}
|
|
2905
2943
|
/* 待核实清单条(accent 强调色标注 · 与 build_pptx.js / HTML .flagbar 同源) */
|
|
2906
2944
|
function flagBar(sh, items, S, yTop) {
|
|
2907
2945
|
var F = PT.flagbar || { hdH: 0.26, rowH: 0.24, maxRows: 3, gap: 0.12 };
|
|
@@ -3090,7 +3128,9 @@ function vbarShapes(sh, ec, S, x, y, w, h, dcols) {
|
|
|
3090
3128
|
: [{ name: '数值', values: ec.values || [] }];
|
|
3091
3129
|
var nb = Math.max(1, labels.length);
|
|
3092
3130
|
var ns = Math.max(1, series.length);
|
|
3093
|
-
|
|
3131
|
+
/* R2:类目标签带必须含在 h 内(原 baseY+0.08 画在图区外,会压进 so-what/来源行) */
|
|
3132
|
+
var labelH = 0.36;
|
|
3133
|
+
var baseY = y + Math.max(0.6, h - labelH), plotW = w, step = plotW / nb;
|
|
3094
3134
|
var cluster = Math.min(1.1, step * (ns > 1 ? 0.78 : 0.55));
|
|
3095
3135
|
var bw = cluster / ns;
|
|
3096
3136
|
var all = [];
|
|
@@ -3099,26 +3139,27 @@ function vbarShapes(sh, ec, S, x, y, w, h, dcols) {
|
|
|
3099
3139
|
});
|
|
3100
3140
|
var vmax = ec.max || Math.max.apply(null, all.concat([1]));
|
|
3101
3141
|
var top = all.length ? Math.max.apply(null, all) : 0;
|
|
3142
|
+
var plotH = Math.max(0.35, baseY - y);
|
|
3102
3143
|
sh.push(shape('rect', x, baseY, plotW, 0.02, S.line));
|
|
3103
3144
|
series.forEach(function (se, si) {
|
|
3104
3145
|
var vals = se.values || [];
|
|
3105
3146
|
var col = dcols ? dcols[si % 5] : (si === 0 ? S.accent : S.faint);
|
|
3106
3147
|
vals.forEach(function (v, i) {
|
|
3107
3148
|
var num = Number(v) || 0;
|
|
3108
|
-
var hh = Math.max(0.05, num / vmax * (
|
|
3149
|
+
var hh = Math.max(0.05, num / vmax * (plotH - 0.35));
|
|
3109
3150
|
var bx = x + i * step + (step - cluster) / 2 + si * bw;
|
|
3110
3151
|
var hot = ns === 1 && num === top;
|
|
3111
3152
|
sh.push(shape('roundRect', bx, baseY - hh, Math.max(0.04, bw * 0.92), hh,
|
|
3112
3153
|
hot ? (dcols ? dcols[i % 5] : S.accent) : col, { adj: 6000 }));
|
|
3113
3154
|
if (ns === 1) {
|
|
3114
|
-
sh.push(txSp(bx - 0.3, baseY - hh - 0.
|
|
3155
|
+
sh.push(txSp(bx - 0.3, baseY - hh - 0.36, bw + 0.6, 0.30,
|
|
3115
3156
|
[[{ t: valText(num, ec.unit), sz: 12.5, b: 1, col: hot ? S.accent : S.body, font: S.font }]], { align: 'ctr' }));
|
|
3116
3157
|
}
|
|
3117
3158
|
});
|
|
3118
3159
|
});
|
|
3119
3160
|
labels.forEach(function (lb, i) {
|
|
3120
3161
|
var lx = x + i * step;
|
|
3121
|
-
sh.push(txSp(lx, baseY + 0.
|
|
3162
|
+
sh.push(txSp(lx, baseY + 0.06, step, labelH - 0.08,
|
|
3122
3163
|
[[{ t: lb, sz: 10.5, col: S.faint, font: S.font }]], { align: 'ctr' }));
|
|
3123
3164
|
});
|
|
3124
3165
|
/* Multi-series legend along top of plot (keeps category labels; avoids blank chart). */
|
|
@@ -3141,7 +3182,10 @@ function lineShapes(sh, ec, S, x, y, w, h, dcols) {
|
|
|
3141
3182
|
var all = [];
|
|
3142
3183
|
series.forEach(function (se) { (se.values || []).forEach(function (v) { all.push(Number(v) || 0); }); });
|
|
3143
3184
|
var vmax = ec.max || Math.max.apply(null, all.concat([1]));
|
|
3144
|
-
|
|
3185
|
+
/* R2:类目标签带含在 h 内,禁画到图区外压 so-what */
|
|
3186
|
+
var labelH = 0.36;
|
|
3187
|
+
var baseY = y + Math.max(0.6, h - labelH);
|
|
3188
|
+
var plotH = Math.max(0.35, baseY - y - 0.2);
|
|
3145
3189
|
sh.push(shape('rect', x, baseY, w, 0.02, S.line));
|
|
3146
3190
|
var stepX = n > 1 ? w / (n - 1) : 0;
|
|
3147
3191
|
series.forEach(function (se, si) {
|
|
@@ -3161,7 +3205,7 @@ function lineShapes(sh, ec, S, x, y, w, h, dcols) {
|
|
|
3161
3205
|
});
|
|
3162
3206
|
labels.forEach(function (lb, i) {
|
|
3163
3207
|
var px = x + (n > 1 ? i * stepX : w / 2);
|
|
3164
|
-
sh.push(txSp(px - 0.5, baseY + 0.
|
|
3208
|
+
sh.push(txSp(px - 0.5, baseY + 0.06, 1.0, labelH - 0.08,
|
|
3165
3209
|
[[{ t: lb, sz: 10.5, col: S.faint, font: S.font }]], { align: 'ctr' }));
|
|
3166
3210
|
});
|
|
3167
3211
|
}
|
|
@@ -3613,25 +3657,44 @@ function slidesOf(model, S) {
|
|
|
3613
3657
|
c.push(txSp(MX, CV.subtitleY, CW - 1, CV.subtitleH, [[{ t: model.subtitle || '', sz: 18, col: S.soft, font: S.font }]]));
|
|
3614
3658
|
slides.push(c);
|
|
3615
3659
|
|
|
3616
|
-
/* Agenda(>8
|
|
3660
|
+
/* Agenda(>8 条自动双列;>12 条自动分页;长标题截断+全称入 notes;列优先与 HTML 一致) */
|
|
3617
3661
|
var items = model.agenda || [];
|
|
3618
3662
|
if (items.length) {
|
|
3619
|
-
var
|
|
3620
|
-
|
|
3621
|
-
var
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
var
|
|
3628
|
-
var
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3663
|
+
var ROWS_PER_PAGE = 12;
|
|
3664
|
+
var agPages = [];
|
|
3665
|
+
for (var ai = 0; ai < items.length; ai += ROWS_PER_PAGE) agPages.push(items.slice(ai, ai + ROWS_PER_PAGE));
|
|
3666
|
+
agPages.forEach(function (pageItems, pi) {
|
|
3667
|
+
var ag = [];
|
|
3668
|
+
var sub = agPages.length > 1 ? '(' + (pi + 1) + '/' + agPages.length + ')' : '';
|
|
3669
|
+
head(ag, 'AGENDA', '报告大纲' + sub);
|
|
3670
|
+
var colN = pageItems.length > 8 ? 2 : 1;
|
|
3671
|
+
var perCol = Math.ceil(pageItems.length / colN) || 1;
|
|
3672
|
+
var rowH = Math.min(1.05, (CONTENT_BOTTOM - CONTENT_TOP - 0.25) / Math.max(1, perCol));
|
|
3673
|
+
var numSz = rowH >= 0.85 ? 30 : (rowH >= 0.65 ? 22 : 18);
|
|
3674
|
+
var tSz = rowH >= 0.85 ? 16 : 14, dSz = rowH >= 0.85 ? 12 : 11;
|
|
3675
|
+
var agNotes = [];
|
|
3676
|
+
pageItems.forEach(function (it, i) {
|
|
3677
|
+
var col = Math.floor(i / perCol), row = i % perCol;
|
|
3678
|
+
var x = MX + col * (CW / colN), y = CONTENT_TOP + row * rowH;
|
|
3679
|
+
var titleBoxW = CW / colN - 1.15;
|
|
3680
|
+
var rawTitle = String(it[1] || '');
|
|
3681
|
+
var titleEstW = estTextH(rawTitle, titleBoxW, tSz, 1.2);
|
|
3682
|
+
var maxTitleH = rowH * 0.55;
|
|
3683
|
+
var title = rawTitle;
|
|
3684
|
+
if (titleEstW > maxTitleH) {
|
|
3685
|
+
var maxChars = Math.max(10, Math.floor(rawTitle.length * (maxTitleH / titleEstW)));
|
|
3686
|
+
if (rawTitle.length > maxChars) {
|
|
3687
|
+
title = rawTitle.slice(0, maxChars - 1) + '…';
|
|
3688
|
+
agNotes.push('条目 ' + it[0] + ' 全称:' + rawTitle);
|
|
3689
|
+
}
|
|
3690
|
+
}
|
|
3691
|
+
ag.push(txSp(x, y, 0.9, Math.min(0.9, rowH), [[{ t: it[0], sz: numSz, b: 1, col: S.accent, font: S.font }]]));
|
|
3692
|
+
ag.push(txSp(x + 1.0, y + 0.03, titleBoxW, Math.min(0.95, rowH),
|
|
3693
|
+
[[{ t: title, sz: tSz, b: 1, col: S.ink, font: S.font }],
|
|
3694
|
+
[{ t: it[2] || '', sz: dSz, col: S.body, font: S.font }]], { lineSpacing: tSz + 5 }));
|
|
3695
|
+
});
|
|
3696
|
+
slides.push(ag);
|
|
3633
3697
|
});
|
|
3634
|
-
slides.push(ag);
|
|
3635
3698
|
}
|
|
3636
3699
|
|
|
3637
3700
|
/* 章节页 */
|
|
@@ -3717,12 +3780,13 @@ function slidesOf(model, S) {
|
|
|
3717
3780
|
{ t: p[1], sz: fz - 1, col: S.body, font: S.font }]]));
|
|
3718
3781
|
});
|
|
3719
3782
|
});
|
|
3783
|
+
/* R2:verdict 与 soWhat 共用 annotation 槽位——只画一个(verdict 优先) */
|
|
3720
3784
|
if (sec.verdict) {
|
|
3721
3785
|
var vR = regOf('exhibit', 'annotation') || { x: MX, y: PT.exhibit.soWhatY, w: CW, h: 0.62 };
|
|
3722
|
-
sh.push(shape('rect', vR.x, vR.y, vR.w, vR.h, S.accent));
|
|
3786
|
+
sh.push(shape('rect', vR.x, vR.y, vR.w, vR.h, S.accent, { name: 'tr:soWhat' }));
|
|
3723
3787
|
sh.push(txSp(vR.x + 0.22, vR.y + 0.06, vR.w - 0.44, vR.h - 0.12,
|
|
3724
3788
|
[[{ t: '结论 ', sz: 11, b: 1, col: S.onAccent, font: S.font, spc: 150 },
|
|
3725
|
-
{ t: sec.verdict, sz: 12.5, b: 1, col: S.onAccent, font: S.font }]], { anchor: 'ctr' }));
|
|
3789
|
+
{ t: sec.verdict, sz: 12.5, b: 1, col: S.onAccent, font: S.font }]], { anchor: 'ctr', name: 'tr:soWhat' }));
|
|
3726
3790
|
}
|
|
3727
3791
|
} else if (type === 'quote') {
|
|
3728
3792
|
var Q = PT.quote;
|
|
@@ -3755,7 +3819,6 @@ function slidesOf(model, S) {
|
|
|
3755
3819
|
} else if (type === 'donut') {
|
|
3756
3820
|
var dcn = sec.chart || {};
|
|
3757
3821
|
if (dcn.labels && dcn.values) donutChart(sh, dcn, S, dcn.colors || donutColors(model.style, S, model.theme), bodyBottom);
|
|
3758
|
-
if (sec.note) sh.push(txSp(MX, PT.note.y, CW, PT.note.h, [[{ t: sec.note, sz: 11, col: S.faint, font: S.font }]]));
|
|
3759
3822
|
} else if (type === 'heatmap') {
|
|
3760
3823
|
var H = PT.heatmap;
|
|
3761
3824
|
var hR = regOf('heatmap', 'primary', { bottom: bodyBottom }) || { x: MX, y: H.y, w: CW, h: bodyBottom - H.y };
|
|
@@ -3902,7 +3965,7 @@ function slidesOf(model, S) {
|
|
|
3902
3965
|
} else if (type === 'bar') {
|
|
3903
3966
|
var ch = sec.chart || {};
|
|
3904
3967
|
var dcols2 = (ch.colors || dataColors(model.style, model.theme));
|
|
3905
|
-
var botY = chartBottom(!!sec.soWhat, !!sec.footnote
|
|
3968
|
+
var botY = chartBottom(!!sec.soWhat, !!(sec.footnote || sec.note)) - 0.05;
|
|
3906
3969
|
var isHBar = ch.type === 'hbar';
|
|
3907
3970
|
var bRR = regOf('bar', isHBar ? 'hbar' : 'primary', { bottom: botY }) ||
|
|
3908
3971
|
{ x: isHBar ? MX : MX + PT.bar.chartX, y: isHBar ? PT.bar.hbarY0 : PT.bar.chartY,
|
|
@@ -3929,13 +3992,12 @@ function slidesOf(model, S) {
|
|
|
3929
3992
|
} else {
|
|
3930
3993
|
chartBlockShapes(sh, ch, S, bx, bRR.y, bw, Math.max(1.5, bRR.h), dcols2);
|
|
3931
3994
|
}
|
|
3932
|
-
if (sec.note) sh.push(txSp(MX, PT.note.y, CW, PT.note.h, [[{ t: sec.note, sz: 11, col: S.faint, font: S.font }]]));
|
|
3933
3995
|
} else if (type === 'twocol' || type === 'threecol') {
|
|
3934
3996
|
var ps2 = sec.paragraphs || [];
|
|
3935
3997
|
var nCol = (type === 'threecol') ? 3 : 2;
|
|
3936
3998
|
var gapC = (type === 'threecol') ? PT.research.col3Gap : PT.twocol.colGap;
|
|
3937
|
-
|
|
3938
|
-
|
|
3999
|
+
/* R3:多栏均分用版心全宽(regOf('twocol') 返回单栏宽,当总宽会压扁三栏) */
|
|
4000
|
+
var tcR = { x: MX, y: bodyY, w: CW, h: bodyBottom - bodyY };
|
|
3939
4001
|
var gC = cols(tcR.w, nCol, gapC);
|
|
3940
4002
|
var perC = Math.ceil(ps2.length / nCol);
|
|
3941
4003
|
var availC = tcR.h;
|
|
@@ -4131,7 +4193,7 @@ function slidesOf(model, S) {
|
|
|
4131
4193
|
var dStart = dgR.y;
|
|
4132
4194
|
var dEnd = dgR.y + dgR.h;
|
|
4133
4195
|
var nLay = Math.max(1, lys.length);
|
|
4134
|
-
var lh2 = Math.max(0.
|
|
4196
|
+
var lh2 = Math.max(0.5, Math.min(D.maxLayerH, (dEnd - dStart) / nLay - D.layerGap));
|
|
4135
4197
|
lys.forEach(function (lay, li) {
|
|
4136
4198
|
var y9 = dStart + li * (lh2 + D.layerGap);
|
|
4137
4199
|
var focus = lay[2] === 'focus';
|
|
@@ -4147,9 +4209,26 @@ function slidesOf(model, S) {
|
|
|
4147
4209
|
var ntt = isRec(nd) ? nd.t : nd;
|
|
4148
4210
|
var nds = isRec(nd) ? (nd.d || '') : '';
|
|
4149
4211
|
sh.push(shape('roundRect', x10, y9, nw2, lh2, ndacc ? S.soft : S.surface, { adj: 4000, line: S.line }));
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4212
|
+
/* R1: 注解不得「浮回」标题上。标题顶对齐,注解钳在标题下边;空间不足降级单框混排。 */
|
|
4213
|
+
var padXn = 0.12, padYn = 0.10;
|
|
4214
|
+
var innerWn = nw2 - padXn * 2;
|
|
4215
|
+
var titleHn = 0.32, noteHn = 0.34, gapTNn = 0.04;
|
|
4216
|
+
var needHn = titleHn + gapTNn + (nds ? noteHn : 0) + padYn * 2;
|
|
4217
|
+
if (!nds || lh2 >= needHn) {
|
|
4218
|
+
var tYn = y9 + padYn;
|
|
4219
|
+
sh.push(txSp(x10 + padXn, nds ? tYn : y9 + lh2 / 2 - 0.18, innerWn, titleHn,
|
|
4220
|
+
[[{ t: ntt, sz: nds ? 11 : 12.5, b: 1, col: ndacc ? S.accent : S.ink, font: S.font }]],
|
|
4221
|
+
{ anchor: 'ctr' }));
|
|
4222
|
+
if (nds) {
|
|
4223
|
+
var nYn = Math.max(tYn + titleHn + gapTNn, y9 + lh2 - padYn - noteHn);
|
|
4224
|
+
sh.push(txSp(x10 + padXn, nYn, innerWn, Math.min(noteHn, y9 + lh2 - padYn - nYn),
|
|
4225
|
+
[[{ t: nds, sz: 10, col: S.faint, font: S.font }]], { anchor: 't' }));
|
|
4226
|
+
}
|
|
4227
|
+
} else {
|
|
4228
|
+
sh.push(txSp(x10 + padXn, y9 + padYn * 0.5, innerWn, lh2 - padYn,
|
|
4229
|
+
[[{ t: ntt, sz: 11, b: 1, col: ndacc ? S.accent : S.ink, font: S.font }],
|
|
4230
|
+
[{ t: nds, sz: 9, col: S.faint, font: S.font }]], { anchor: 't', lineSpacing: 12 }));
|
|
4231
|
+
}
|
|
4153
4232
|
});
|
|
4154
4233
|
if (li < lys.length - 1) {
|
|
4155
4234
|
var cy2 = y9 + lh2 + D.layerGap / 2;
|
|
@@ -4159,10 +4238,14 @@ function slidesOf(model, S) {
|
|
|
4159
4238
|
}
|
|
4160
4239
|
});
|
|
4161
4240
|
if (sec.legend) {
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4241
|
+
/* R2:图例进图区底部(与 HTML .arch__legend 同源),禁用 PH-0.62 固定偏移 */
|
|
4242
|
+
var lgH2 = 0.28;
|
|
4243
|
+
var lgY2 = Math.max(dStart, bodyBottom - lgH2 - 0.02);
|
|
4244
|
+
var nLg2 = Math.max(1, sec.legend.length);
|
|
4245
|
+
var step2 = Math.min(2.4, CW / nLg2);
|
|
4246
|
+
sec.legend.forEach(function (lg2, li2) {
|
|
4247
|
+
sh.push(txSp(MX + CW - nLg2 * step2 + li2 * step2, lgY2, step2 - 0.05, lgH2,
|
|
4248
|
+
[[{ t: '● ' + lg2, sz: 10, col: S.faint, font: S.font }]]));
|
|
4166
4249
|
});
|
|
4167
4250
|
}
|
|
4168
4251
|
} else if (type === 'exhibit') {
|
|
@@ -4219,8 +4302,10 @@ function slidesOf(model, S) {
|
|
|
4219
4302
|
}
|
|
4220
4303
|
}
|
|
4221
4304
|
/* research 通用可选件:so-what 结论条 + 页脚来源行 + 待核实条(共用同一槽位) */
|
|
4222
|
-
|
|
4223
|
-
if (sec.
|
|
4305
|
+
/* R2:verdict 已占 annotation 槽位时跳过 soWhat,禁止同槽双条叠印 */
|
|
4306
|
+
if (sec.soWhat && !sec.verdict) soWhatBar(sh, sec.soWhat, S);
|
|
4307
|
+
/* R2:note 与 footnote 共用注释带末行(禁 note.y=6.55 压 so-what) */
|
|
4308
|
+
noteOrFootnote(sh, sec, S);
|
|
4224
4309
|
if (flagH) flagBar(sh, flagItems, S, flagY);
|
|
4225
4310
|
slides.push(sh);
|
|
4226
4311
|
});
|
|
@@ -4390,9 +4475,10 @@ function validateModel(model) {
|
|
|
4390
4475
|
}
|
|
4391
4476
|
var agMax = (M.model && M.model.agendaComfortMax) || 16;
|
|
4392
4477
|
if ((model.agenda || []).length > agMax) {
|
|
4393
|
-
warnings.push('agenda ' + model.agenda.length + ' 条超出单页舒适上限 ' + agMax + '
|
|
4478
|
+
warnings.push('agenda ' + model.agenda.length + ' 条超出单页舒适上限 ' + agMax + ',将自动分页');
|
|
4394
4479
|
}
|
|
4395
|
-
var
|
|
4480
|
+
var agPageCount = hasAgenda ? Math.ceil(model.agenda.length / 12) : 0;
|
|
4481
|
+
var pages = 1 + agPageCount + secs.length + 1; /* 封面+大纲(可多页)+章节+收尾 */
|
|
4396
4482
|
return { ok: missing.length === 0, missing: missing, warnings: warnings, pages: pages };
|
|
4397
4483
|
}
|
|
4398
4484
|
|