Job JSON 完整 Schema
Job JSON 是 PptEngine 的声明式配置格式,支持两种模式:
- template 模式(默认):基于 PPT 模板 + slides 配置进行占位符替换
- composer 模式(推荐):基于 PageComposer + pages 配置从零构建 PPT
顶层字段
| 字段 |
必填 |
说明 |
mode |
否 |
"template" (默认) 或 "composer" |
template |
条件 |
template 模式必填 |
slides |
条件 |
template 模式必填 |
theme |
条件 |
composer 模式用,默认 "jp_finance" |
pages |
条件 |
composer 模式必填 |
datasources |
否 |
数据源配置(两种模式共用) |
transforms |
否 |
数据转换配置(两种模式共用) |
params |
否 |
自定义参数 |
output |
是 |
输出配置 |
Composer 模式 annotated skeleton
{
"mode": "composer",
"theme": "jp_finance", // THEMES 中的名称
"datasources": {
"数据源名称": {
"type": "csv", // "csv" | "xlsx" | "tushare"
// ... 类型相关字段见下方
}
},
"transforms": { // 可选
"转换后名称": {
"from": "数据源名称",
"ops": [{"type": "sort", "sort_by": ["trade_date"]}]
}
},
"pages": [ // 页面列表(按顺序生成)
{
"layout": "title_dark", // LAYOUT_REGISTRY 中的布局名称
"data": { // 传给布局函数的 data dict
"title": "报告标题",
"date": "2026-02"
}
},
{
"layout": "chart_full",
"data": {
"title": "营收与利润",
"source": "revenue_df", // ← 引用 datasources/transforms 中的名称
"categories_col": "年度",
"series_config": [
{"key": "营收", "name": "营收(亿元)", "type": "bar", "axis": "primary"},
{"key": "利润", "name": "利润(亿元)", "type": "line", "axis": "secondary"}
],
"style_config": {"color_scheme": "jp_finance"},
"layout_config": {
"legend_config": {"font_size_pt": 9},
"value_axis_config": {"number_format": "#,##0"}
}
}
}
],
"output": {
"path": "output/report.pptx",
"overwrite": true,
"add_metadata": true
}
}
source 引用解析规则
引擎在渲染时自动将 source 引用解析为实际 DataFrame:
- 顶层 source:
data.source → data.df(替换为 DataFrame)
- 嵌套 source(
two_charts):data.left.source / data.right.source → 各自的 df
- 引用范围:可引用
datasources 或 transforms 中的任意 key
style_config / layout_config 的 JSON 表达
style_config:直接传 StyleConfig 构造参数的 dict,如 {"color_scheme": "jp_finance", "line_width_pt": 2.0}
layout_config:支持嵌套子对象:
legend_config → LegendConfig 参数
value_axis_config / secondary_value_axis_config → ValueAxisConfig 参数
category_axis_config → CategoryAxisConfig 参数
date_axis_config → 预设名字符串:"daily", "weekly", "biweekly", "monthly", "quarterly", "yearly"
Template 模式 annotated skeleton
{
"template": {
"path": "aim/aim03.pptx", // 模板路径(相对于 ppt-st 项目根,或绝对路径)
"master": null, // 母版名称(可选)
"notes": null // 备注(可选)
},
"datasources": {
"数据源名称": { // 自定义名称,后续 source 字段引用
"type": "csv", // "csv" | "xlsx" | "tushare"
// ... 类型相关字段见下方
}
},
"transforms": { // 可选:数据转换
"转换后名称": {
"from": "数据源名称", // 字符串或数组(多源 concat)
"ops": [ // 有序操作列表
{"type": "sort", "sort_by": ["trade_date"]}
]
}
},
"slides": [ // 幻灯片列表(按顺序对应模板页)
{
"id": "slide_1", // 唯一标识
"layout": null, // 版式名(null 使用模板现有页)
"texts": [ // 文本替换
{"target": "文本框名", "value": "替换值(支持 Jinja2)"}
],
"tables": [ // 表格渲染
{"target": "表格名", "source": "数据源名", "columns": ["col1"], "header": ["列1"]}
],
"charts": [ // 图表渲染
{
"mode": "update", // "create" | "update" | "excel_embedded"
"target": "图表名", // update 模式下模板中的图表名称
"source": "数据源名",
"categories": "日期列名",
"series": [
{"key": "列名", "name": "显示名", "axis": "primary"}
]
}
]
}
],
"params": {}, // 自定义参数(传入渲染上下文)
"output": {
"path": "output/report.pptx", // 输出路径
"overwrite": true,
"add_metadata": true // 是否添加生成信息到 PPT 元数据
}
}
DataSource 字段表
type: "csv"
| 字段 |
必填 |
说明 |
path |
是 |
CSV 文件路径(相对于 data_dir 或绝对路径) |
encoding |
否 |
编码,默认 utf-8 |
type: "xlsx"
| 字段 |
必填 |
说明 |
path |
是 |
Excel 文件路径 |
sheet_name |
否 |
工作表名,默认第一个 |
encoding |
否 |
编码,默认 utf-8 |
type: "tushare"
| 字段 |
必填 |
说明 |
api_name |
否 |
API 接口名,默认 index_daily。支持 index_daily, pro_bar |
ts_code |
是 |
股票/指数代码,如 600519.SH, 000300.SH |
start_date |
否 |
起始日期 YYYYMMDD,默认一年前 |
end_date |
否 |
结束日期 YYYYMMDD,默认今天 |
fields |
否 |
返回字段列表 |
前置条件: 环境变量 TUSHARE_TOKEN 或 .env 文件中配置。
TransformOp 字段表
每个 op 是 transforms[name].ops[] 数组中的一项。
type: "groupby"
| 字段 |
必填 |
说明 |
by |
是 |
分组列名列表 |
agg |
是 |
聚合方式 {"列名": "sum/mean/count/..."} |
type: "pivot"
| 字段 |
必填 |
说明 |
index |
是 |
行索引列名 |
columns |
是 |
列索引列名 |
values |
是 |
值列名 |
type: "merge"
未实现 — 会抛 NotImplementedError。用 from: [src1, src2] 做 concat 替代。
type: "compute"
| 字段 |
必填 |
说明 |
expr |
是 |
pandas eval 表达式,如 "close / close.iloc[0] - 1" |
output_col |
是 |
输出列名 |
type: "filter"
| 字段 |
必填 |
说明 |
condition |
是 |
pandas query 表达式,如 "close > 100" |
type: "sort"
| 字段 |
必填 |
说明 |
sort_by |
是 |
排序列名列表 |
ascending |
否 |
是否升序,默认 true |
type: "rename"
| 字段 |
必填 |
说明 |
map |
是 |
列名映射 {"旧名": "新名"} |
SlideSpec
| 字段 |
必填 |
说明 |
id |
是 |
唯一标识 |
layout |
否 |
版式名称(null 使用模板现有页面) |
texts |
否 |
文本替换列表 [{target, value}] |
tables |
否 |
表格渲染列表 [{target, source, columns, header?, number_format?}] |
charts |
否 |
图表渲染列表(见 ChartSpec) |
ChartSpec
| 字段 |
必填 |
说明 |
mode |
否 |
"create" / "update" / "excel_embedded",默认 "update" |
target |
条件 |
update 模式下的模板图表名称 |
target_placeholder |
条件 |
create/excel_embedded 模式下的占位符名 |
source |
是 |
数据源名称(引用 datasources 或 transforms 的键) |
categories |
是 |
分类列名 |
series |
是 |
系列配置 [{key, name, axis?}] |
ComposerPageSpec(composer 模式)
| 字段 |
必填 |
说明 |
layout |
是 |
LAYOUT_REGISTRY 中的布局名称 |
data |
是 |
传给布局函数的 data dict(各布局字段见下表) |
各布局的 data 字段
| 布局 |
必填字段 |
可选字段 |
title_dark |
title |
subtitle, date |
title_light |
title |
subtitle, date |
kpi_cards |
title, cards: [{label, value}] |
cards[].change, cards[].color |
chart_full |
title, source, categories_col, series_config |
subtitle, style_config, layout_config |
chart_text |
title, source, categories_col, series_config, text_body |
text_title, text_bullets, style_config, layout_config |
two_charts |
title, left: {source, categories_col, series_config}, right: {...} |
left_title, right_title |
comparison_table |
title, headers, rows |
|
bullet_points |
title, items: [{icon, label, desc}] |
|
section_divider |
title, number |
|
conclusion_dark |
verdict |
items |
series_config 字段(composer 模式)
| 字段 |
必填 |
说明 |
key |
是 |
DataFrame 列名 |
name |
是 |
图表中显示的系列名称 |
type |
否 |
"bar", "line", "area"(默认按引擎决定) |
axis |
否 |
"primary" (左轴) 或 "secondary" (右轴) |
示例: Composer 模式完整版
{
"mode": "composer",
"theme": "jp_finance",
"datasources": {
"revenue": {"type": "csv", "path": "data/revenue.csv"},
"stock": {
"type": "tushare",
"api_name": "pro_bar",
"ts_code": "600519.SH",
"start_date": "20240101",
"end_date": "20241231"
}
},
"transforms": {
"stock_sorted": {
"from": "stock",
"ops": [{"type": "sort", "sort_by": ["trade_date"]}]
}
},
"pages": [
{
"layout": "title_dark",
"data": {"title": "贵州茅台2024年度分析", "date": "2024-12"}
},
{
"layout": "kpi_cards",
"data": {
"title": "核心指标",
"cards": [
{"label": "营收", "value": "1,505亿", "change": "+17.2%"},
{"label": "净利润", "value": "747亿", "change": "+19.1%"},
{"label": "毛利率", "value": "91.5%", "change": "+0.3pp"}
]
}
},
{
"layout": "chart_full",
"data": {
"title": "营收与利润趋势",
"source": "revenue",
"categories_col": "年度",
"series_config": [
{"key": "营收", "name": "营收(亿元)", "type": "bar", "axis": "primary"},
{"key": "净利润", "name": "净利润(亿元)", "type": "line", "axis": "secondary"}
],
"style_config": {"color_scheme": "jp_finance"},
"layout_config": {
"legend_config": {"font_size_pt": 9, "font_name": "黑体"},
"value_axis_config": {"number_format": "#,##0"},
"secondary_value_axis_config": {"number_format": "#,##0"}
}
}
},
{
"layout": "two_charts",
"data": {
"title": "股价与成交量",
"left_title": "日收盘价",
"right_title": "日成交量",
"left": {
"source": "stock_sorted",
"categories_col": "trade_date",
"series_config": [{"key": "close", "name": "收盘价", "type": "line", "axis": "primary"}],
"layout_config": {"date_axis_config": "monthly"}
},
"right": {
"source": "stock_sorted",
"categories_col": "trade_date",
"series_config": [{"key": "vol", "name": "成交量(手)", "type": "bar", "axis": "primary"}],
"layout_config": {"date_axis_config": "monthly"}
}
}
},
{
"layout": "conclusion_dark",
"data": {"verdict": "茅台护城河坚固,品牌溢价持续"}
}
],
"output": {"path": "output/moutai_2024.pptx"}
}
示例: Template 模式最小版
{
"template": {"path": "aim/aim03.pptx"},
"datasources": {},
"slides": [
{
"id": "cover",
"texts": [
{"target": "标题", "value": "2024年度报告"}
]
}
],
"output": {"path": "/tmp/minimal.pptx"}
}
示例: Template 模式完整版(含 Tushare + 变换 + 图表)
{
"template": {"path": "aim/aim03.pptx"},
"datasources": {
"stock": {
"type": "tushare",
"api_name": "pro_bar",
"ts_code": "600519.SH",
"start_date": "20240101",
"end_date": "20241231"
},
"index": {
"type": "tushare",
"api_name": "pro_bar",
"ts_code": "000300.SH",
"start_date": "20240101",
"end_date": "20241231"
}
},
"transforms": {
"merged": {
"from": ["stock", "index"],
"ops": [
{"type": "sort", "sort_by": ["trade_date"]},
{"type": "rename", "map": {"close": "收盘价"}}
]
}
},
"slides": [
{
"id": "cover",
"texts": [
{"target": "标题", "value": "贵州茅台2024年度分析"},
{"target": "日期", "value": "2024-12-31"}
]
},
{
"id": "chart_page",
"charts": [
{
"mode": "update",
"target": "当年收益率走势图",
"source": "merged",
"categories": "trade_date",
"series": [
{"key": "收盘价", "name": "茅台收盘价", "axis": "primary"}
]
}
]
}
],
"params": {"year": 2024},
"output": {
"path": "output/moutai_2024.pptx",
"overwrite": true,
"add_metadata": true
}
}