universal-pptx-generator by ajaxhe/universal-pptx-generator-skill
npx skills add https://github.com/ajaxhe/universal-pptx-generator-skill --skill universal-pptx-generator此技能可以根据任意用户指定的 PPT 模板 ,结合提供的图文素材 (文档、图片等),自动生成一份风格统一的演示文稿。
⭐⭐⭐ 核心理念:每个模板都是独特的,必须针对性分析!
不同 PPT 模板使用的字体、对齐方式、字号、颜色、位置、背景样式 都完全不同。绝不能 将一个模板的配置直接应用到另一个模板!每次使用新模板时,都必须重新分析 XML 提取精确参数。
核心能力:
关键词 : PPT生成、模板分析、演示文稿、幻灯片、图文排版、自动化、pptxgenjs、图表、数据可视化
不同类型的页面可能使用不同的背景处理方式:
| 页面类型 | 典型特征 | 背景处理方式 |
|---|---|---|
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 主标题 + 副标题 + Logo |
| 背景图/渐变/斜切形状 |
| 目录页 (TOC) | 目录列表 + 装饰元素 | 纯色背景 + 装饰形状 |
| 章节页 (Chapter) | 大号章节编号 + 章节标题 | 纯色背景 + 装饰形状 |
| 内容页 (Content) | 标题 + 正文/图片/图表 | 纯色背景/背景图 |
| 结束页 (Thanks) | 感谢语 + 联系方式 | 纯色背景 + 装饰形状 |
PPT 背景有三种主要类型:
<!-- XML 特征 -->
<p:bg>
<p:bgPr>
<a:solidFill>
<a:schemeClr val="tx2"/> <!-- 使用主题色 -->
</a:solidFill>
</p:bgPr>
</p:bg>
<!-- 或直接指定颜色 -->
<a:solidFill>
<a:srgbClr val="0D1E43"/> <!-- 直接 RGB 值 -->
</a:solidFill>
pptxgenjs 对应代码:
slide.background = { color: '0D1E43' }; // 深蓝色
<!-- XML 特征 -->
<p:bg>
<p:bgPr>
<a:blipFill>
<a:blip r:embed="rId2"/> <!-- 引用图片资源 -->
</a:blipFill>
</p:bgPr>
</p:bg>
<!-- 或在形状中作为图片填充 -->
<p:pic>
<p:blipFill>
<a:blip r:embed="rId2"/>
</p:blipFill>
</p:pic>
pptxgenjs 对应代码:
slide.background = { path: 'workspace/backgrounds/cover-bg.png' };
<!-- XML 特征 -->
<a:gradFill>
<a:gsLst>
<a:gs pos="0">
<a:srgbClr val="0052D9"><a:alpha val="50000"/></a:srgbClr>
</a:gs>
<a:gs pos="100000">
<a:srgbClr val="0D1E43"/>
</a:gs>
</a:gsLst>
<a:lin ang="5400000"/> <!-- 角度:5400000/60000 = 90° -->
</a:gradFill>
pptxgenjs 对应代码:
slide.background = {
color: '0D1E43', // 基础色
// 注:pptxgenjs 对渐变背景支持有限,通常用形状模拟
};
// 用形状模拟渐变
slide.addShape('rect', {
x: 0, y: 0, w: '100%', h: '100%',
fill: {
type: 'gradient',
gradientType: 'linear',
degrees: 90,
stops: [
{ position: 0, color: '0052D9', alpha: 50 },
{ position: 100, color: '0D1E43' }
]
}
});
很多模板使用主题色(schemeClr)而非直接颜色值:
| schemeClr 值 | 含义 | 典型颜色 |
|---|---|---|
dk1 | 深色1 (主要文字) | 000000 |
lt1 / bg1 | 浅色1 (背景) | FFFFFF |
dk2 / tx2 | 深色2 (次要背景) | 0060FF / 0D1E43 |
lt2 | 浅色2 | E7E6E6 |
accent1 | 强调色1 | 0060F0 |
accent2 | 强调色2 | A736FF |
从 theme1.xml 提取主题色映射:
cat workspace/template-analysis/ppt/theme/theme1.xml | grep -E "dk1|lt1|dk2|lt2|accent" | head -20
# 完整的页面背景分析脚本
import re
import os
def analyze_slide_background(slide_path, rels_path):
"""分析单页幻灯片的背景类型"""
with open(slide_path, 'r', encoding='utf-8') as f:
content = f.read()
result = {
'background_type': None,
'background_color': None,
'background_image': None,
'decorative_shapes': [],
'scheme_color': None
}
# 1. 检查是否有 <p:bg> 背景定义
bg_match = re.search(r'<p:bg>(.*?)</p:bg>', content, re.DOTALL)
if bg_match:
bg_content = bg_match.group(1)
# 纯色背景
if '<a:solidFill>' in bg_content:
result['background_type'] = 'solid'
# 直接颜色
color = re.search(r'srgbClr val="([^"]+)"', bg_content)
if color:
result['background_color'] = color.group(1)
# 主题色
scheme = re.search(r'schemeClr val="([^"]+)"', bg_content)
if scheme:
result['scheme_color'] = scheme.group(1)
# 渐变背景
elif '<a:gradFill>' in bg_content:
result['background_type'] = 'gradient'
# 图片背景
elif '<a:blipFill>' in bg_content:
result['background_type'] = 'image'
embed = re.search(r'r:embed="([^"]+)"', bg_content)
if embed:
result['background_image'] = embed.group(1)
# 2. 检查是否有全屏图片作为背景(无 <p:bg> 时)
if not result['background_type']:
pics = re.findall(r'<p:pic>(.*?)</p:pic>', content, re.DOTALL)
for pic in pics:
# 检查是否是大尺寸图片(可能是背景图)
ext_match = re.search(r'<a:ext cx="(\d+)" cy="(\d+)"/>', pic)
if ext_match:
cx, cy = int(ext_match.group(1)), int(ext_match.group(2))
# 如果尺寸接近全屏(>80%),视为背景图
if cx > 10000000 and cy > 5000000: # EMU 单位
result['background_type'] = 'image_shape'
embed = re.search(r'r:embed="([^"]+)"', pic)
if embed:
result['background_image'] = embed.group(1)
break
# 3. 如果还是没有找到背景,检查是否使用装饰形状构成背景
if not result['background_type']:
result['background_type'] = 'shapes_composite'
# 4. 分析装饰性形状(半透明方块等)
shapes = re.findall(r'<p:sp>(.*?)</p:sp>', content, re.DOTALL)
for shape in shapes:
# 检查是否有透明度设置
alpha = re.search(r'<a:alpha val="(\d+)"', shape)
if alpha:
transparency = 100 - int(alpha.group(1)) / 1000
color = re.search(r'srgbClr val="([^"]+)"', shape)
if color and transparency > 0:
result['decorative_shapes'].append({
'color': color.group(1),
'transparency': transparency
})
# 5. 从 rels 文件获取实际图片路径
if result['background_image'] and os.path.exists(rels_path):
with open(rels_path, 'r', encoding='utf-8') as f:
rels_content = f.read()
img_id = result['background_image']
img_path = re.search(rf'{img_id}"[^>]*Target="([^"]+)"', rels_content)
if img_path:
result['background_image_path'] = img_path.group(1)
return result
# 分析所有关键页面
def analyze_all_pages(template_dir):
slides_dir = f'{template_dir}/ppt/slides'
rels_dir = f'{slides_dir}/_rels'
page_types = {
1: '封面页',
2: '目录页',
3: '章节页',
4: '内容页'
}
results = {}
for slide_num, page_type in page_types.items():
slide_path = f'{slides_dir}/slide{slide_num}.xml'
rels_path = f'{rels_dir}/slide{slide_num}.xml.rels'
if os.path.exists(slide_path):
result = analyze_slide_background(slide_path, rels_path)
result['page_type'] = page_type
results[f'slide{slide_num}'] = result
print(f"\n=== {page_type} (slide{slide_num}) ===")
print(f"背景类型: {result['background_type']}")
if result['background_color']:
print(f"背景颜色: #{result['background_color']}")
if result['scheme_color']:
print(f"主题色引用: {result['scheme_color']}")
if result['background_image_path']:
print(f"背景图片: {result['background_image_path']}")
if result['decorative_shapes']:
print(f"装饰形状: {len(result['decorative_shapes'])}个")
for s in result['decorative_shapes'][:3]:
print(f" - 颜色: #{s['color']}, 透明度: {s['transparency']}%")
return results
# 执行分析
# results = analyze_all_pages('workspace/template-analysis')
┌─────────────────────────────────────────────────────────────┐
│ 通用 PPT 生成流程 │
├─────────────────────────────────────────────────────────────┤
│ 1. 模板深度分析阶段 (关键!) │
│ └── 解压 PPTX → 精确分析每页 XML → 提取字号/颜色/位置 │
│ │
│ 2. 素材处理阶段 │
│ └── 解析 DOCX/PDF → 提取文本/图片 → 结构化内容 │
│ │
│ 3. 内容规划阶段 │
│ └── 分析内容 → 设计结构 → 分配页面 │
│ └── ⭐ 识别数据 → 选择图表类型 → 准备图表数据 │
│ │
│ 4. PPT 生成阶段 │
│ └── 应用精确的模板参数 → 填充内容 → 生成图表 → 输出 PPTX │
│ │
│ 5. 清理阶段 │
│ └── 删除临时文件 → 保留最终 PPTX │
└─────────────────────────────────────────────────────────────┘
必须精确提取模板中每一页的实际参数,而非使用推测值!
分析时需要从 slide XML 中提取:
sz="8000" 表示 80pt (sz ÷ 100)<a:off x="..." y="..."/> EMU单位,转换为英寸或百分比srgbClr val="FFFFFF" 直接使用b="1" 表示粗体algn="ctr" 居中, algn="r" 右对齐, algn="l" 或无属性表示左对齐PPTX 文件本质是 ZIP 压缩包,包含 XML 和媒体资源:
# 创建工作目录
mkdir -p workspace/template-analysis workspace/backgrounds workspace/images
# 解压模板 (使用 Python 处理特殊字符文件名)
python3 -c "
import zipfile
import glob
files = glob.glob('模板*.pptx')
if files:
with zipfile.ZipFile(files[0], 'r') as zip_ref:
zip_ref.extractall('workspace/template-analysis')
print('Done:', files[0])
"
template-analysis/
├── [Content_Types].xml # 内容类型定义
├── _rels/
├── docProps/
│ ├── app.xml # 应用属性
│ └── core.xml # 核心属性(作者、创建时间等)
└── ppt/
├── presentation.xml # 演示文稿主配置(尺寸、幻灯片列表)
├── presProps.xml # 演示属性
├── tableStyles.xml # 表格样式
├── viewProps.xml # 视图属性
├── _rels/
│ └── presentation.xml.rels # ⭐ 幻灯片关系映射
├── media/ # ⭐ 媒体资源(背景图、图片)
│ ├── image1.png
│ ├── image2.png
│ └── ...
├── slideLayouts/ # ⭐ 幻灯片布局定义
│ ├── slideLayout1.xml # 封面布局
│ ├── slideLayout2.xml # 内容布局
│ └── ...
├── slideMasters/ # ⭐ 母版定义(全局样式)
│ └── slideMaster1.xml
├── slides/ # ⭐⭐⭐ 幻灯片内容 (最重要!)
│ ├── slide1.xml
│ ├── slide2.xml
│ └── ...
└── theme/ # ⭐ 主题配色/字体
└── theme1.xml
⚠️ 关键:必须分析每一页的实际 XML,提取精确参数!
⚠️⚠️⚠️ 特别重要:必须提取每个元素的字体名称!
⚠️⚠️⚠️ 新增:必须分析形状边框和背景渐变!
使用 Python 脚本精确提取参数(包含字体、边框、渐变信息 ):
# 分析幻灯片的精确参数(含字体、边框、渐变)
import re
import sys
def analyze_slide(slide_path):
with open(slide_path, 'r', encoding='utf-8') as f:
content = f.read()
# 提取文本内容
texts = re.findall(r'<a:t>([^<]+)</a:t>', content)
print('=== 文本内容 ===')
for t in texts:
if t.strip():
print(repr(t))
# ⭐⭐⭐ 提取字体名称 - 极其重要!
latin_fonts = re.findall(r'latin typeface="([^"]+)"', content)
ea_fonts = re.findall(r'ea typeface="([^"]+)"', content)
print('\n=== 字体 (Latin/西文) ===')
for f in set(latin_fonts):
print(f' {f}')
print('\n=== 字体 (EA/东亚) ===')
for f in set(ea_fonts):
print(f' {f}')
# 提取字号 (sz 值 ÷ 100 = pt)
sizes = re.findall(r'sz="(\d+)"', content)
print('\n=== 字号 (百分之一点) ===')
for s in set(sizes):
print(f'{s} -> {int(s)/100}pt')
# 提取颜色
colors = re.findall(r'srgbClr val="([^"]+)"', content)
print('\n=== sRGB颜色 ===')
for c in set(colors):
print(f'#{c}')
# 提取位置 (EMU 单位,1英寸=914400 EMU)
positions = re.findall(r'<a:off x="(\d+)" y="(\d+)"/>', content)
print('\n=== 位置信息 (转换为20x11.25英寸画布的百分比) ===')
for i, (x, y) in enumerate(positions):
x_inch = int(x) / 914400
y_inch = int(y) / 914400
x_pct = x_inch / 20 * 100
y_pct = y_inch / 11.25 * 100
print(f'{i}: x={x_pct:.1f}%, y={y_pct:.1f}% (x={x_inch:.2f}in, y={y_inch:.2f}in)')
# 提取尺寸
extents = re.findall(r'<a:ext cx="(\d+)" cy="(\d+)"/>', content)
print('\n=== 尺寸信息 ===')
for i, (cx, cy) in enumerate(extents):
w_inch = int(cx) / 914400
h_inch = int(cy) / 914400
w_pct = w_inch / 20 * 100
h_pct = h_inch / 11.25 * 100
print(f'{i}: w={w_pct:.1f}%, h={h_pct:.1f}% (w={w_inch:.2f}in, h={h_inch:.2f}in)')
# ⭐⭐⭐ 新增:分析边框设置
print('\n=== 边框分析 ===')
lns = re.findall(r'<a:ln[^>]*>(.*?)</a:ln>', content, re.DOTALL)
for i, ln in enumerate(lns):
if '<a:noFill/>' in ln:
print(f'边框{i}: 无边框 (noFill)')
elif '<a:solidFill>' in ln:
color = re.search(r'val="([^"]+)"', ln)
print(f'边框{i}: 有边框,颜色={color.group(1) if color else "未知"}')
else:
print(f'边框{i}: ⚠️ 默认黑色边框!需要在生成时设置 line: "none"')
# ⭐⭐⭐ 新增:分析渐变填充
print('\n=== 渐变分析 ===')
gradFills = re.findall(r'<a:gradFill[^>]*>(.*?)</a:gradFill>', content, re.DOTALL)
for i, grad in enumerate(gradFills):
# 提取角度
lin = re.search(r'<a:lin ang="(\d+)"', grad)
if lin:
angle = int(lin.group(1)) / 60000
print(f'渐变{i}: 线性渐变,角度={angle}°')
# 提取颜色停止点
stops = re.findall(r'<a:gs pos="(\d+)">(.*?)</a:gs>', grad, re.DOTALL)
for pos, gs_content in stops:
position = int(pos) / 1000
color = re.search(r'srgbClr val="([^"]+)"', gs_content)
alpha = re.search(r'<a:alpha val="(\d+)"', gs_content)
transparency = 100 - int(alpha.group(1))/1000 if alpha else 0
print(f' 停止点 {position}%: 颜色={color.group(1) if color else "主题色"}, 透明度={transparency}%')
# ⭐⭐⭐ 新增:分析透明度
print('\n=== 透明度分析 ===')
alphas = re.findall(r'<a:alpha val="(\d+)"/>', content)
for a in set(alphas):
opacity = int(a) / 1000
transparency = 100 - opacity
print(f'alpha={a} -> 不透明度={opacity}% -> pptxgenjs transparency={transparency}')
# ⭐⭐⭐ 详细分析每个元素的字体+字号+对齐+文本
print('\n=== 详细元素分析 (字体+字号+对齐+文本) ===')
sps = re.findall(r'<p:sp>(.*?)</p:sp>', content, re.DOTALL)
for i, sp in enumerate(sps):
texts = re.findall(r'<a:t>([^<]+)</a:t>', sp)
sizes = re.findall(r'sz="(\d+)"', sp)
latin = re.findall(r'latin typeface="([^"]+)"', sp)
ea = re.findall(r'ea typeface="([^"]+)"', sp)
bold = 'b="1"' in sp
# ⭐ 提取对齐方式
algn = re.findall(r'algn="([^"]+)"', sp)
align_map = {'l': '左对齐', 'ctr': '居中', 'r': '右对齐', 'just': '两端对齐'}
align_str = align_map.get(algn[0], algn[0]) if algn else '左对齐(默认)'
# ⭐ 检查是否有边框
has_border = '<a:ln' in sp and '<a:noFill/>' not in sp
if texts:
print(f'元素{i}: 文本="{texts[0][:20]}" 字号={[int(s)/100 for s in sizes[:2]]}pt 字体={latin[:1] or ea[:1]} 粗体={bold} 对齐={align_str} 有边框={has_border}')
# 分析每一页
for i in range(1, 11):
print(f'\n{"="*60}')
print(f'SLIDE {i}')
print("="*60)
try:
analyze_slide(f'workspace/template-analysis/ppt/slides/slide{i}.xml')
except FileNotFoundError:
print(f'slide{i}.xml not found')
break
从 theme1.xml 提取配色方案:
cat workspace/template-analysis/ppt/theme/theme1.xml | python3 -c "
import sys
import re
content = sys.stdin.read()
# 提取所有颜色
colors = re.findall(r'srgbClr val=\"([^\"]+)\"', content)
print('主题颜色:')
for c in set(colors):
print(f' #{c}')
# 提取字体
fonts = re.findall(r'typeface=\"([^\"]+)\"', content)
print('\n主题字体:')
for f in set(fonts):
if f:
print(f' {f}')
"
关键 XML 结构 - 颜色方案:
<a:clrScheme name="主题名称">
<a:dk1><a:sysClr val="windowText"/></a:dk1> <!-- 深色1 - 主要文字 -->
<a:lt1><a:sysClr val="window"/></a:lt1> <!-- 浅色1 - 背景 -->
<a:dk2><a:srgbClr val="050E24"/></a:dk2> <!-- 深色2 -->
<a:lt2><a:srgbClr val="E7E6E6"/></a:lt2> <!-- 浅色2 -->
<a:accent1><a:srgbClr val="79E8F5"/></a:accent1> <!-- 强调色1 - 青色 -->
<!-- ... -->
</a:clrScheme>
查看布局关系:
for i in 1 2 3 4 5 6 7 8 9 10; do
echo "=== Slide $i ==="
cat workspace/template-analysis/ppt/slides/_rels/slide$i.xml.rels 2>/dev/null | grep -E "(slideLayout|image)"
done
查看布局对应的背景图:
for i in 1 2 3 5 6 12; do
echo "=== slideLayout$i ==="
cat workspace/template-analysis/ppt/slideLayouts/_rels/slideLayout$i.xml.rels 2>/dev/null | grep image
done
建立映射表 (示例):
| 页面类型 | slide | slideLayout | 背景图 |
|---|---|---|---|
| 封面页 | slide1 | slideLayout1 | image1.png |
| 目录页 | slide2 | slideLayout5 | image6.png |
| 章节页 | slide3 | slideLayout6 | image7.png |
| 内容页 | slide4 | slideLayout2 | image4.png |
| 感谢页 | slide10 | slideLayout12 | image13.jpeg |
# 根据分析结果复制背景图
cp workspace/template-analysis/ppt/media/image1.png workspace/backgrounds/cover-bg.png
cp workspace/template-analysis/ppt/media/image6.png workspace/backgrounds/toc-bg.png
cp workspace/template-analysis/ppt/media/image7.png workspace/backgrounds/chapter-bg.png
cp workspace/template-analysis/ppt/media/image4.png workspace/backgrounds/content-bg.png
cp workspace/template-analysis/ppt/media/image13.jpeg workspace/backgrounds/thanks-bg.jpeg
# 使用 Python 解压 (处理特殊字符文件名)
python3 -c "
import zipfile
import glob
files = glob.glob('*.docx')
if files:
with zipfile.ZipFile(files[0], 'r') as zip_ref:
zip_ref.extractall('workspace/docx-extract')
print('Done:', files[0])
"
# 提取图片
mkdir -p workspace/images
cp workspace/docx-extract/word/media/*.png workspace/images/ 2>/dev/null
cp workspace/docx-extract/word/media/*.jpeg workspace/images/ 2>/dev/null
import re
with open('workspace/docx-extract/word/document.xml', 'r', encoding='utf-8') as f:
content = f.read()
texts = re.findall(r'<w:t[^>]*>([^<]+)</w:t>', content)
for t in texts:
if t.strip():
print(t.strip())
const contentStructure = {
title: "主标题",
subtitle: "副标题",
author: "作者",
chapters: [
{
number: "01",
title: "章节标题",
subtitle: "章节副标题",
pages: [
{
type: "content", // content | textOnly | dataCards | chart
subtitle: "页面小标题",
title: "页面大标题",
sections: [
{ title: "要点小标题1", desc: ["描述行1", "描述行2"] },
{ title: "要点小标题2", desc: "单行描述" }
],
image: "images/image1.png"
},
// ⭐ 图表页示例
{
type: "chart",
title: "数据分析图表",
chartType: "bar", // bar | line | pie | doughnut | area | radar
chartData: {
labels: ["Q1", "Q2", "Q3", "Q4"],
datasets: [
{ name: "2024年", values: [100, 150, 200, 180] },
{ name: "2025年", values: [120, 180, 220, 250] }
]
},
chartOptions: {
showLegend: true,
showValue: true,
showTitle: true
}
}
]
}
]
};
⚠️⚠️⚠️ 关键原则:所有配置必须从当前模板动态提取,绝不能写死!
不同的 PPT 模板会使用不同的字体、对齐方式、字号、颜色等,必须针对每个模板单独分析!
const pptxgen = require('pptxgenjs');
const pptx = new pptxgen();
// ============================================================
// ⚠️⚠️⚠️ 重要:以下所有配置都是占位符/示例!
// 实际使用时必须通过分析当前模板的 slide XML 获得精确值!
// 不同模板的字体、对齐、字号都不同,绝不能直接复制使用!
// ============================================================
const TEMPLATE_CONFIG = {
// ⭐⭐⭐ 字体配置 - 必须从当前模板的 slide XML 精确提取!
// 每个模板使用的字体都不同!必须从 <a:ea typeface="..."/> 提取!
// 示例:腾讯模板用 "腾讯体 W7",微软模板可能用 "微软雅黑",其他模板可能用 "思源黑体" 等
fonts: {
// ⚠️ 以下是示例值,必须替换为当前模板实际使用的字体!
title: '从slide1.xml提取的标题字体', // 从 <a:ea typeface="..."/> 获取
titleLatin: '从slide1.xml提取的西文字体', // 从 <a:latin typeface="..."/> 获取
body: '从slide4.xml提取的正文字体', // 从内容页提取
bodyLatin: '从slide4.xml提取的西文字体',
fallback: 'Microsoft YaHei' // 备选字体
},
// 配色配置 (从 slide XML 和 theme1.xml 提取)
colors: {
primary: 'FFFFFF', // 主要文字色
secondary: 'E7E6E6', // 次要文字色
accent: '79E8F5', // 强调色 (章节编号等)
dark: '050E24', // 深色/背景色
// ⭐⭐⭐ 主题色映射 - 从 theme1.xml 的 <a:clrScheme> 提取
// 用于将 schemeClr 转换为实际颜色
schemeColors: {
dk1: '000000', // 深色1
lt1: 'FFFFFF', // 浅色1 (bg1)
dk2: '0060FF', // 深色2 (tx2) - 常用于背景
lt2: 'FFFFFF', // 浅色2
accent1: '0060F0', // 强调色1
accent2: 'A736FF', // 强调色2
tx2: '0060FF' // 文本2 - 注意这是常见的背景色引用!
}
},
// ⭐⭐⭐ 背景配置 - 分页面类型配置!
// 不同页面可能使用不同的背景类型(纯色/图片/渐变)
backgrounds: {
// 封面页背景 - 通常使用图片或复杂形状组合
cover: {
type: 'image', // 'solid' | 'image' | 'gradient' | 'shapes'
image: 'workspace/backgrounds/cover-bg.png', // 如果是图片背景
color: null, // 如果是纯色背景
// 装饰形状(如斜切遮罩)
overlayShapes: [
{
type: 'custom', // 自定义形状
color: '0052D9',
transparency: 50,
// 形状路径点(从 <a:path> 提取)
}
]
},
// 目录页背景 - 通常使用纯色 + 装饰形状
toc: {
type: 'solid',
color: '0060FF', // 从 schemeClr val="tx2" 映射得到
// 或从 <p:bg><a:solidFill><a:schemeClr val="tx2"/> 提取后映射
decorativeShapes: [
{ x: 1.22, y: 2.31, w: 1.31, h: 1.31, color: 'FFFFFF', transparency: 90 },
{ x: -0.01, y: 2.66, w: 2.17, h: 2.17, color: 'FFFFFF', transparency: 10 },
{ x: 1.95, y: 4.59, w: 0.58, h: 0.58, color: 'FFFFFF', transparency: 50 }
]
},
// 章节页背景 - 与目录页类似
chapter: {
type: 'solid',
color: '0060FF',
decorativeShapes: [
// 同目录页的装饰形状
]
},
// 内容页背景 - 可能是纯色或图片
content: {
type: 'solid',
color: '0060FF',
// 如果有背景图,设置 type: 'image' 并指定路径
image: null
},
// 结束页/感谢页背景
thanks: {
type: 'solid',
color: '0060FF',
decorativeShapes: [
// 与目录页类似的装饰形状
]
}
},
// ⚠️ 字号配置 - 必须从当前模板的 slide XML 精确提取!
// 不同模板字号差异很大!必须从 sz="..." 属性获取!
// sz="8000" -> 80pt, sz="4800" -> 48pt
fontSizes: {
// ⚠️ 以下是示例结构,必须替换为当前模板实际的字号!
// 封面页 (从 slide1.xml 的 sz 属性提取)
coverTitle: '从sz属性计算',
Skills CLI 使用指南:AI Agent 技能包管理器安装与管理教程
33,600 周安装