下载地址
https://www.zhengdianxue.com/wp-content/uploads/skills/user_87f9fd3d--zhiketong.zip将提示词发送给你的 AI 安装该 skills
请根据 https://skillhub.cn/install/skillhub.md,安装 @user_87f9fd3d/zhiketong。基于直客通品牌PPT模版样式对PPT进行美化,包含直客通LOGO、品牌色调、品牌文化等品牌特征元素
阅读全文 (展开查看完整说明)
概述
Data Report PPT Generator
Overview
Generate a complete, editable .pptx data report by combining source PPT data with a template's visual style. The output PPT contains native editable charts (bar, line, doughnut), styled data tables, KPI highlight cards, timeline visuals, and preserved source images — all following strict color, font, and layout specifications.
When to Use
- User provides a source data PPTX and a template PPT/Python script
- User asks to "generate a data report PPT", "create a styled presentation
from data", or "convert data to slides"
- User wants native editable charts in the output PPT (not images)
- User wants strict style consistency with a template (colors, fonts, layout)
- User wants content generated from scratch first (Mode 0): "帮我从0到1做一份…PPT"、"帮我写一份营销活动方案PPT"、无源文件的类型+主题请求 → 先创作内容,落素版草稿,再自动美化
Pre-Workflow: Employee Identity Check & Report Consent (MANDATORY)
⚠️ This check MUST be performed BEFORE starting any workflow step. It determines whether Step 6 (auxiliary report) will be executed, AND obtains the user's consent for anonymous reporting in a single question — Step 6 will NOT ask again.
Before starting the PPT generation workflow, you MUST ask the user whether they are a 直客通 (ZKT) employee using AskUserQuestion. The question must clearly state that if they answer "Yes", an anonymous usage report will be automatically sent after the PPT is generated:
- If the user answers "是直客通员工" (Yes): Proceed with the full workflow (Steps 1–6). The user's "Yes" answer serves as both identity confirmation and consent for the anonymous report. Step 6 will execute the auxiliary report script directly without asking again. Remember the user's choice for Step 6.
- If the user answers "非直客通员工" (No): Proceed with the PPT generation workflow (Steps 1–5), but SKIP Step 6 entirely. Do not run the report script, do not ask about it again.
The question presented to the user MUST include the following information:
- This is a one-time check — they will NOT be asked again about the report
- If they confirm they are a ZKT employee, an anonymous usage report will be automatically sent after PPT generation
- The report contains only: skill name, an anonymous random ID (ZKT + 6 digits, auto-generated), execution status, and timestamp
- The report does NOT contain any real user identity (name, email, employee ID, OS username) or any PPT content
- The report is sent to
https://pro-ai.zhiketong.net
This check only determines whether an anonymous usage report will be sent. It does NOT collect or store any real user identity information.
Pre-Workflow: Source Content Beautification Mode (MANDATORY)
⚠️ This question MUST be asked AFTER the employee identity check, BEFORE starting any workflow step. It determines whether to beautify based on the user's source file content, or use the skill's default generation logic.
After the employee identity check, you MUST ask the user whether to beautify based on their uploaded source content using AskUserQuestion:
- If the user answers "是,根据源文件美化" (Yes): Content MUST be 100% from the source file — do NOT add, remove, or modify any text content, tables, or data. However, the following template elements MUST still follow the skill's template specifications:
- Cover style and background image (use template
cover_bg.jpg/cover_logo.png) - Inner page header style (CN title + EN subtitle + inner logo position)
- Inner page logo position (exact template coordinates)
- Color palette / element tone specifications (brand red, dark, light pink, gray)
- Original images from the source PPT MUST be preserved — extract and embed them without compression or distortion. Use proportional scaling, NOT stretching/squashing.
- Cover style and background image (use template
- If the user answers "否,按默认逻辑生成" (No): Proceed with the skill's default generation logic (Steps 1-6 as defined below), including company intro pages, TOC, section dividers, data charts, etc.
- Auto-route to Mode 0: If the user request is itself "从 0 到 1 生成新内容"(无源文件、只给了 PPT 类型与主题),DO NOT ask this binary question — enter the Mode 0 (Content Creation) section directly and follow its flow. The identity check from the previous step still applies.
The question presented to the user MUST include the following information:
- If "Yes": Content will be 100% from the source file, but cover style, inner page header, logo position, and color tones will follow the template specification
- If "Yes": Original images in the source PPT will be preserved — no compression or distortion
- If "No": The skill's default generation logic will be used (including company intro, TOC, section dividers, charts, and data cards)
<!– ===================== MODE 0 ADDED (2026-09-03) START ===================== –>
Mode 0: Content Creation Mode(从 0 到 1 · 先创作内容再自动美化)
本模式是本 skill 的内容"供给侧"入口:当用户手上还没有任何源文件、想直接要一份"某类型"的酒店业务 PPT 时,先帮他把整份内容(结构/文案/数据位)从 0 写出来,落成一份"素版内容草稿 PPTX",再自动交给下方 Workflow 的「根据源文件美化」路径套标准模板,一次对话闭环。
Trigger(命中即自动路由,不再问"是否美化源文件")
- 用户请求"从 0 到 1 / 帮我写 / 帮我做一份…PPT",且给的是类型与主题而非上传文件,例如:
- "帮我做一份酒店国庆营销活动方案 PPT"
- "生成一份给总经理看的 Q3 经营数据总结 PPT(数字我后面自己填)"
- "做一份会员储值促销培训 PPT"
- 用户明说"先帮我写内容 / 先出大纲 / 内容你来起草,我先定稿"。
- 不适用:已有源文件要美化(走 Source Beautification);已有数据表要出报告(走 Default Generation)。
前置(MANDATORY)
- 员工身份确认(复用主流程 Pre-Workflow 提问)→ 决定是否执行 Step 6 上报。
- 命中本模式后,跳过"根据源文件美化 / 按默认逻辑生成"二选一提问(草稿必然走源文件美化路径)。
Step C1 类型与信息采集(AskUserQuestion,只问缺的信息)
用户一句话里已给的信息不要重复问;缺的关键信息必须问。每次先确认"PPT 类型"(用户明确要求:通过询问确定类型,勿默认只有三类)。
- Q1 类型(必问,除非已明说):营销活动方案 →
references/frameworks/marketing_activity.md;经营数据总结(总经理/管理班子)→gm_data_report.md;促销/产品培训 →promo_training.md;其他(用户自行描述,AI 现场拟结构,不套固定蓝图) - Q2 主题与周期:活动名/节日/统计周期(如"国庆黄金周""Q3 总结")
- Q3 受众与场合:总经理汇报 / 运营团队 / 一线销售 / 全员培训
- Q4 酒店与品牌:店名/品牌(用于封面副题与用语语境)
- Q5 素材:可提供的真实数据、海报/照片(可"暂无,后补")
- Q6 数据模式(必选其一;本次已答过则沿用):
- 占位符模式:数字一律写作〔待填:指标·口径·周期〕,如〔待填:9月入住率〕;绝不臆造数字。
- 假设值模式:按行业常识填假设值,数值文本用品牌红
#a8282f并加"(假设)"后缀,醒目提醒替换。
- Q7 篇幅与详略:如"12–15 页""高层只看结论""要可落地执行细节"
- Q8 是否先出大纲确认:默认先生成大纲→用户确认→再展开全文;可改"直接出完整草稿"。
Step C2 定结构(按框架或现场拟大纲)
- 命中
references/frameworks/蓝图 → 读取对应文件按其"逐页蓝图"规划(可增删页)。 - 自定义类型 → 用"结论先行 + 金字塔"现场拟大纲(封面 → 摘要/总述 → 分章[章节页+内容页] → 收尾页),先让用户确认目录再展开。
- 每页明确给出:CN 标题、EN 副题、版式标签、内容要点、数据占位或假设值、可视化建议。
- 大纲必须同时规划"章节分组"(成片含目录页与章节页,见下方《Mode 0 固定版式规则》):把内容页划分为 3–5 个章节,每章给出编号(01/02/…)、CN 章节名(≤6 字)、PART 名(PART ONE/TWO/…)与所含内容页序号。
Mode 0 固定版式规则(2026-09-03 修订 · 不可违反)
由用户实测反馈固化,适用
beautify_content_json.py生成的所有 Mode 0 品牌成片。
Rule M1 — 成片固定结构页(非可选):成片页面顺序固定为:封面 → 公司介绍 / 公司实力 / 技术资质 三页固定内容(Rule 1 样式,由 assets/PPT模版-简版.py 的 create_slide_02/03/04 复刻)→ 目录页(Rule 2 样式:红顶条 + CONTENTS 88pt 白字 + 章节横排,章节数 3–5 均匀分布)→ 每章节[章节页(Rule 3 样式) + 其内容页] → 封底(Rule 4 样式:THANKS 80pt + 居中 Logo)。
- 章节定义来自 content.json 的
structure.chapters(见 C3 契约);缺失时退回"纯内容页模式"并提示补结构。 - 未经用户明确要求,不得省略任何结构页。
Rule M2 — 文案溢出另起一页(禁止超出页面范围):
- 所有版式(
two_col/bullets/kpi_cards+bullets 等)渲染前必须逐条目精确估算占高(按字号×行距×栏宽折算行数,保守取值),单页容量不足时自动另起一页生成续页:续页标题加"(续)"、EN 副题加" – Cont.",页眉样式与母页一致。 - 双栏版式左右条目按行配对(第 i 左 ↔ 第 i 右),行高取两侧较高者,避免跨栏错位。
- 生成后强制执行边界自检:任何形状(背景图/装饰线除外)不得超出页面边界;自检不过不得交付。
Rule M3 — content.json 结构契约(V2):
"structure": {
"company_intro": true,
"back_cover": true,
"chapters": [
{"num": "01", "part": "PART ONE", "cn": "策略与目标", "pages": [1, 2, 3]}
]
}pages 为 slides[] 的 1 基序号;未分组的内容页会自动追加在所有章节之后(兜底防遗漏)。
Step C3 逐页创作 → 生成"素版内容草稿 PPTX"
- 按 C2 规划逐页写内容(遵循蓝图与
metrics_glossary.md的口径/占位规范)。 - 内容整理成与
scripts/build_content_draft.py一致的 JSON 契约:- 顶层
title/subtitle(封面文案);structure(章节结构,见 Rule M3,必填);slides[]每页一个对象:type:"content":title(CN)en(EN副题)summary(结论句,可空)bullets[]、cards[](数据卡 label/value)、table{headers[],rows[][]}、timeline[]{date,title,desc}、image_note(图片占位)、layout(版式标签)type:"section":章节页label(PART ONE)cnen(仅素版草稿使用;品牌成片的章节页由structure.chapters驱动)
- 版式标签 layout 与美化能力对应:
kpi_cards(≥3 数据卡)、table、timeline(多时间节点→美化自动触发 Rule 12)、two_col(双栏)、bullets、image
- 顶层
- 用户给了图片素材 → 存到
assets/images/source_images/,页内用image_note写 [图片占位:文件名],美化阶段替换为真实图片。 - 运行(若内容极简也可按同一契约手工写,仍建议走脚本保持一致):
/Users/zkt/.workbuddy/binaries/python/envs/default/bin/python3
scripts/build_content_draft.py <内容.json> <草稿输出.pptx>- 素版要求:白底、微软雅黑黑字、无阴影/描边/装饰、不放成图图表(美化阶段按数据重建原生图表);页数 = 最终页数(含封面文案页)。
Step C4 用户校对(软性必须,勿跳过)
- 用 present_files 打开草稿 PPTX,请用户:补真实数字 / 改文案 / 增删页 / 或回复"直接美化"。
- 用户确认后进 C5;若用户就此打住(只要内容草稿),流程在 C4 结束,草稿即交付物。
Step C5 自动美化(Mode 0 专用渲染器)
- 把 Mode 0 的 content.json(含
structure)交给scripts/beautify_content_json.py直接渲染为品牌成片:
/Users/zkt/.workbuddy/binaries/python/envs/default/bin/python3
scripts/beautify_content_json.py <content.json> <output.pptx>- 成片结构按 Rule M1 注入固定结构页:公司介绍×3 → 目录 → 章节页+内容页 → 封底;内容页正文不改一字。
- 溢出按 Rule M2 自动分页:条目精确估高 + 续页机制 + 生成后边界自检,任何形状不得超出页面范围。
- 封面/封底背景与 Logo、内页页眉 CN+EN、Logo 位置、配色、字体按模板替换;
- 草稿里的
layout/image_note只是给美化阶段的提示:数据卡→KPI 高亮卡;表格→居中样式表;多时间节点→时间轴(Rule 12);双栏→左右分区(左右条目按行配对渲染);图片占位→嵌assets/images/source_images/对应原图(按比例不拉伸,Rule 10)。渲染后删除这些提示标注本身。 - 模板图片(cover_bg/logo、inner_logo、公司页图标 icon_dev/icon_finance/icon_team/logo_bottom/circle_bg/bottom_bar、end_bg/logo)由
generate_ppt.py的ensure_images_downloaded()管理;如 CDN 因 403 需浏览器 UA,可手动用 curl-A下载到assets/images/。 - 脚本输出后执行重叠自检(忽略背景底/卡片容器与其内部文字、公司实力页文字压圆装饰等模板预期层叠)+ 边界自检,全部通过后再交付。
- Step 6 上报:按 Step C0 身份结果执行(ZKT 员工自动执行,其余跳过)。
- 交付:品牌化 PPTX;如需 PDF,向用户确认后转换交付(符合用户 PDF 交付偏好)。
内容红线(写内容时严禁)
- 不编造"看起来像真"的数字:占位符模式必须留〔待填〕;假设值模式必须标红 + (假设)。
- 金额/客单/价格敏感数字宁可占位也不猜。
- 结论句尽量"数据依据 + 业务原因 + 建议动作"三段式,便于总经理类受众直接决策。
<!– ===================== MODE 0 ADDED (2026-09-03) END ===================== –>
Workflow
⚠️ The workflow has 6 steps. For ZKT employees, all 6 steps MUST be completed. Step 6 uses an anonymous random ID — no real user identity is collected or transmitted.
Step 1: Analyze Source PPTX
Extract all content from the source PPTX file:
from pptx import Presentation
from pptx.enum.shapes import MSO_SHAPE_TYPE
prs = Presentation(source_pptx_path)
for i, slide in enumerate(prs.slides):
for shape in slide.shapes:
# Extract text, tables, images
if shape.has_text_frame: ...
if shape.has_table: ...
if shape.shape_type == MSO_SHAPE_TYPE.PICTURE: ...Key extraction targets:
- Page titles and body text
- Table data (headers, rows, totals)
- KPI numbers (PV, UV, GMV, sales, members)
- Trend data (time series for charts)
- Images (preserve non-data images; extract data from chart/table screenshots)
Step 2: Ensure Template Images (V2 Auto-Download)
IMPORTANT (V2 Fix): Template images (cover, back cover, logos) must come from the skill's IMAGE_URLS dictionary (public URL links), NOT from the source PPT. The source PPT may contain different images (e.g., hotel photos vs. template design backgrounds), which would produce incorrect cover/back cover visuals.
generate_ppt.py now includes a built-in ensure_images_downloaded() function that automatically checks assets/images/ and downloads missing images from IMAGE_URLS URLs. This runs before any PPT generation, so you should NOT manually extract images from the source PPT to fill assets/images/.
If you need to add source-specific images (e.g., marketing plan photos), extract them separately with names that don't collide with template image names:
# Only extract source-specific images (NOT cover_bg, cover_logo, etc.)
def extract_source_images(shapes, output_dir, slide_idx):
for shape in shapes:
if shape.shape_type == MSO_SHAPE_TYPE.PICTURE:
img = shape.image
# Use source-specific naming to avoid collision with template images
filename = f"source_{slide_idx}_{shape.name}.{img.ext}"
with open(f'{output_dir}/{filename}', 'wb') as f:
f.write(img.blob)Template images (managed by IMAGE_URLS, auto-downloaded):
cover_bg.png— cover background (red theme design)cover_logo.png— cover logoback_bg.jpg— back cover backgroundback_logo.png— back cover logoinner_logo.png— inner page logo (top-right)- Additional: icon_dev, icon_finance, icon_team, logo_bottom, circle_bg,
bottom_bar, icon_a, icon_b, icon_c
Step 3: Generate Template PPTX
If the template PPTX doesn't exist, generate it from the template Python script:
python3 assets/PPT模版-简版.pyThis produces PPT模版-简版.pptx with 25 pre-styled slides including cover, company intro pages (2-4), table of contents, section dividers, and content page layouts.
V2 Fix: The template script now uses cross-platform relative paths (assets/PPT模版-简版.pptx) instead of Windows-only absolute paths, and downloads images to assets/images/ (same directory as generate_ppt.py) instead of a temp directory.
Step 4: Run the Generation Script
Execute the bundled generation script with source, template, and output paths:
python3 scripts/generate_ppt.py
<source.pptx>
<template.pptx>
<output.pptx>
[--template-py assets/PPT模版-简版.py]The script:
- Auto-downloads missing template images from
IMAGE_URLS(V2 new —
prevents using source PPT images as substitutes)
- Loads the template PPTX (25 slides)
- Modifies cover, TOC, section dividers with source content
- Rebuilds content slides with styled tables, native charts, data highlights
- Preserves template images (cover bg, logos, back cover)
- Adds new slides as needed (e.g., incentive plan)
- Saves the output PPTX
Step 5: Verify Output (With Overlap Self-Check)
MANDATORY: After generating the PPTX, you MUST perform an overlap self-check on ALL slides. If any overlap is detected, fix the layout and regenerate.
Check the generated PPTX:
from pptx import Presentation
prs = Presentation(output_path)
for i, slide in enumerate(prs.slides):
charts = sum(1 for s in slide.shapes if s.has_chart)
tables = sum(1 for s in slide.shapes if s.has_table)
pics = sum(1 for s in slide.shapes if s.shape_type == 13)
print(f"Slide {i+1}: charts={charts} tables={tables} pics={pics}")Mandatory Overlap Self-Check (NON-NEGOTIABLE)
Every generated PPT MUST pass a bounding-box overlap check on all slides. Add the following check_no_overlap() function to your generation script and call it for every slide after generating:
def check_no_overlap(slide, slide_idx):
"""检测幻灯片中所有形状/文本框是否有重叠"""
shapes_info = []
for shape in slide.shapes:
try:
l, t, w, h = shape.left, shape.top, shape.width, shape.height
except Exception:
continue
if w <= 0 or h <= 0:
continue
shapes_info.append({
"name": shape.name,
"left": l, "top": t, "right": l + w, "bottom": t + h,
"shape": shape
})
overlaps = []
n = len(shapes_info)
for i in range(n):
for j in range(i + 1, n):
a = shapes_info[i]
b = shapes_info[j]
a_overlaps_b = (
a["left"] < b["right"] and a["right"] > b["left"] and
a["top"] < b["bottom"] and a["bottom"] > b["top"]
)
if a_overlaps_b:
overlap_w = min(a["right"], b["right"]) - max(a["left"], b["left"])
overlap_h = min(a["bottom"], b["bottom"]) - max(a["top"], b["top"])
# Ignore trivial overlaps (< 50000 EMU ≈ 0.05 inch)
if overlap_w < 50000 or overlap_h < 50000:
continue
has_text_a = a["shape"].has_text_frame
has_text_b = b["shape"].has_text_frame
if has_text_a and has_text_b:
overlaps.append({
"slide": slide_idx + 1,
"shape_a": a["name"], "shape_b": b["name"],
"text_a": a["shape"].text_frame.text.strip()[:30],
"text_b": b["shape"].text_frame.text.strip()[:30],
})
if overlaps:
print(f" ⚠️ Page {slide_idx + 1}: {len(overlaps)} overlap(s) detected!")
for o in overlaps:
print(f" - '{o['text_a']}' vs '{o['text_b']}'")
return False
else:
print(f" ✅ Page {slide_idx + 1} — no overlaps")
return True
def run_overlap_check(prs):
"""对所有页面执行重叠自检,返回是否全部通过"""
all_clean = True
for i, slide in enumerate(prs.slides):
if not check_no_overlap(slide, i):
all_clean = False
return all_cleanIf overlaps are detected:
- Identify the two overlapping elements and their y coordinates
- Adjust vertical spacing by increasing gaps between zones
- Re-run the generation script
- Re-run the overlap check
- Repeat until ALL pages pass — do NOT deliver a PPT with overlaps
Step 6: Run Auxiliary Report Script (Conditional — ZKT Employees Only, Auto-Execute)
⚠️ This step is ONLY executed if the user identified as a 直客通 (ZKT) employee in the Pre-Workflow check. The user's "Yes" answer in the Pre-Workflow already serves as consent — DO NOT ask for confirmation again. Execute the script directly.
If the user is NOT a ZKT employee, SKIP this step entirely — do not run the script, do not ask about it.
Privacy guarantee: The auxiliary script generates and uses a random anonymous ID (format: ZKT + 6 digits, e.g., ZKT483927). It does NOT collect, read, or transmit any real user identity information (name, email, employee ID, OS username, agent identifier, file contents, or PPT data). The anonymous ID is randomly generated on first run and persisted in a local
.invoker_idfile for reuse on subsequent calls.
After the PPT is generated successfully, execute the auxiliary script directly:
python3 scripts/report_invocation.pyExecution flow (NO user confirmation needed — consent was already obtained in Pre-Workflow):
- Read the script comments (top of
scripts/report_invocation.py) to understand its purpose - Inform the user (in your final reply, not as a blocking question) — briefly state that the anonymous usage report has been sent, including:
- The anonymous ID used (e.g., ZKT483927)
- What was sent: skill_name, anonymous ID, status, timestamp
- Where it was sent:
https://pro-ai.zhiketong.net
- Execute the script directly — do not pause or ask for confirmation
Do NOT ask the user "是否需要运行该脚本?" or use AskUserQuestion in this step. Consent was already obtained in the Pre-Workflow check.
Anonymous ID Mechanism
The script automatically manages the anonymous ID — you do NOT need to generate or pass it manually:
- First run: Script generates
ZKT+ 6 random digits (e.g.,ZKT483927), writes toscripts/.invoker_id - Subsequent runs: Script reads the existing
.invoker_idfile and reuses the same ID - The ID is: randomly generated, persistent per installation, not derived from any user or system information
Configuration is read from scripts/report_invocation.config.json. Resolution priority is environment variable > JSON config > built-in default.
Optional environment overrides (normally not needed — the script handles everything automatically):
export SKILL_NAME="data-report-ppt-generator"
export INVOKE_STATUS="completed"
export AI_TICKET_TOKEN="akt_xxxxxxxxxxxxxxxx" # only if token auth is requiredOverride map: AI_TICKET_BASE_URL→base_url, AI_TICKET_TOKEN→token, SKILL_NAME→skill_name, INVOKE_STATUS→status. Point REPORT_CONFIG_FILE to a different JSON path if needed.
The script uses only the Python standard library, so it runs anywhere Python 3 is available — no extra dependency needed.
- All platforms (recommended — Windows / macOS / Linux / Git Bash):
python3 scripts/report_invocation.py- macOS / Linux (lightweight alternative, no Python needed):
sh scripts/report_invocation.shThe .sh variant uses bare curl + sed and shares the same config file, anonymous ID mechanism, and env-var override map. Use it on Unix when you want to avoid spawning Python just for a single call.
Style Specifications
All details in references/style_guide.md. Key rules:
Colors (NO other colors allowed)
| Color | Hex | Usage |
|---|---|---|
| White | #ffffff | Page backgrounds, table alternating rows |
| Red | #a8282f | Key data text, section numbers, small accents |
| Black | #0d0d0d | Table headers, body text, chart bars |
| Gray | #f6f6f6 | Rounded rect backgrounds for data cards |
| Pink | #fceeeb | Table alternating rows, data card backgrounds |
| Text Gray | #7f7f7f | English subtitles, chart labels |
Fonts
- Chinese body: Microsoft YaHei (微软雅黑), sans-serif
- English (cover/back/section): Arial Black, ALL CAPS
- Inner page title: 27pt black (#0d0d0d) Microsoft YaHei
- Inner page English subtitle: 10pt gray (#7f7f7f) Microsoft YaHei
- Key data: Red (#a8282f) bold, auto-sized to fit card width
Shapes
- ALL shapes, textboxes, connectors, lines: NO shadow, NO stroke/border, NO reflection, NO glow — flat design only. This is GLOBAL — every single shape, connector, oval, rectangle, textbox and line must have zero shadow effects. Use
_strip_shadow(shape)immediately after creating any shape, connector, or textbox. For circles with visible borders, useshape.line.color.rgb+shape.line.widthexplicitly (do NOT rely on default line styling). - Rounded rectangles: 10% corner radius (small rounded)
- Table header: Black (#0d0d0d) fill, white text
- Table last row: White fill, red (#a8282f) bold text, 2.25pt black top border
- ALL table cells: MUST use
cell.vertical_anchor = MSO_ANCHOR.MIDDLEfor vertical centering andPP_ALIGN.CENTERfor horizontal centering
Charts (Native, Editable)
- Bar chart: Black/red/gray bars, gray axis, gray labels
- Line chart: Red/black/gray lines, circle markers, bottom legend
- Doughnut chart: MUST use specific palette: black (#0d0d0d), red (#a8282f), gray (#f6f6f6), pink (#fceeeb) in that order. White borders between segments. Right legend. Do NOT use
_style_chart()for doughnut charts — use a dedicated color palette - All chart fonts: Microsoft YaHei, 9pt, gray (#7f7f7f)
See references/chart_specs.md for detailed chart styling code.
Data Highlight Cards
- Background: Gray (#f6f6f6) or pink (#fceeeb) small rounded rectangle
- Label: 12pt gray Microsoft YaHei, centered
- Value: Red (#a8282f) bold, auto-sized (48pt max, shrinks to fit)
- Use
add_data_highlight()function for auto-sizing
Mandatory Template Requirements
IMPORTANT: These are NON-NEGOTIABLE rules. Every generated PPT MUST follow them regardless of the source data content. All specs below are extracted directly from the actual template PPTX PPT模版-简版.pptx and verified against it. Violating any of these rules will produce a PPT that does not match the template specification.
Rule 1: Must Include Company Intro Pages (Slides 2-4)
The template's slides 2-4 (公司介绍/公司实力/技术资质) are part of the standard deck structure and MUST be preserved in every output. They are NOT optional.
Slide 2 — 公司介绍 (Industry Unicorn):
- Three-column layout: 发展情况 / 融资情况 / 核心团队
- English title "Industry Unicorn" Arial Black 54pt at (1.01, 0.81)
- Chinese title "行业独角兽" 微软雅黑 24pt Bold at (1.03, 1.73)
- Icons: icon_dev / icon_finance / icon_team at their respective columns
- Bottom logo strip: logo_bottom.png at (1.11, 6.05) 11.14×0.86 in
Slide 3 — 公司实力 (Company Strength):
- English title "Company Strength " Arial Black 54pt at (1.01, 0.81), line_spacing=0.9
- Chinese title "公司实力" 微软雅黑 24pt Bold at (1.03, 1.73)
- Right-side circle_bg.png image at (7.22, 1.40) 5.73×5.85 in
- Three decorative ovals: light pink (5.17,2.85 3.41×3.41), red (8.44,4.25 2.20×2.20), dark (7.36,5.27 1.51×1.51)
- Red and dark ovals: MUST have solid white (#ffffff) border, 8pt width
- Red oval overlay text (centered on the red circle):
- "10,000" 微软雅黑 Bold 28pt white CENTERED
- "种+" 微软雅黑 14pt white CENTERED
- "系统功能" 微软雅黑 14pt white CENTERED
- "70亿+" — mixed font sizes crucial:
- Leading space: Arial Black 66pt red
- "7" and "0": Arial Black 70pt red
- "亿": Arial Black 40pt Bold red
- "+": Arial Black 40pt red
- Position: (8.79, 2.47) 3.39×1.16 in, line_spacing=0.9
- "2025年交易额" — split format:
- "2025" Arial Black 24pt red
- "年交易额" 微软雅黑 Bold 24pt red
- DISTRIBUTE alignment, line_spacing=0.9
- "9000" Arial 44pt Bold + "家+" 微软雅黑 Bold 22pt, CENTERED, at (5.69, 4.06)
- "合作伙伴" 微软雅黑 18pt CENTERED at (5.50, 4.76)
- "月订单量" 微软雅黑 12pt WHITE text at (7.51, 6.08) — shows on dark circle
- "1000万+" 微软雅黑 15pt Bold WHITE text at (7.44, 5.77) — shows on dark circle
- Left data text at (1.03, 4.04): 3 lines with mixed formatting — numbers (300, 1200, 60) MUST be bold, other text regular. line_spacing=2.0. Lines:
- "年 客房 销售量 " (regular) + "300" (bold) + "万间夜" (bold) — 微软雅黑 14pt
- "年 自助餐 销售量 " (regular) + "1200" (bold) + "万份" (bold)
- "年 储值卡 销售量 " (regular) + "60" (bold) + "万张" (bold)
Slide 4 — 技术资质 (Technical Certifications):
- English title "Technical" / "Certifications" Arial Black 54pt (two lines) at (1.01, 0.81)
- Chinese title "技术资质" 微软雅黑 24pt Bold at (1.03, 2.65)
- Bottom decoration bar: bottom_bar.png at (-0.31, 3.41) 14.07×4.13 in
Required images: icon_dev.png, icon_finance.png, icon_team.png, logo_bottom.png, circle_bg.png, bottom_bar.png (all in IMAGE_URLS).
Rule 2: TOC Must Match Template Slide 5 Style
The table of contents page MUST use the template's horizontal-row layout with a red top bar — NOT a vertical list, and NOT with background cards.
Precise specs extracted from the actual template PPTX:
- Top red bar: Rectangle at (0, 0) → 13.33×2.09 in, fill #A8282F (brand red) — NOT dark/black
- "CONTENTS" title: Arial Black 88pt WHITE (#ffffff) at (0.70, 0.82) 9.40×1.58 in — MUST be UPPERCASE
- Chapters arranged HORIZONTALLY (not vertically):
- Each chapter block is 1.52×1.81 in (number + separator + title stacked vertically)
- First chapter starts at L=0.83 in, spacing = 2.54 in between chapters
- Number: Arial Black 66pt, CENTERED, at T=3.48 in
- Separator: red (#A8282F) rectangle 0.40×0.04 in at T=4.76 in (offset +0.56 in from chapter left)
- Title: 微软雅黑 20pt Bold, DISTRIBUTE alignment, at T=4.90 in
- Background: White (#ffffff) — no rounded rect backgrounds on items
- Important: The number and title colors inherit from the theme; do NOT force red/black colors on them in the style (content customization may override)
Rule 3: Section Divider Must Match Template Slide 6 Style
Section divider pages MUST use the template's centered layout with a red vertical separator line — NOT left-aligned, and NOT with black background.
Precise specs extracted from the actual template PPTX:
- "PART ONE" (or TWO/THREE/FOUR):
- Font: Arial Black 66pt
- Position: (0.69, 3.09) 11.95×1.09 in
- Alignment: CENTER
- Vertical separator line: L=6.67 in, T=-0.03 in, H=1.84 in, color #A8282F (brand red)
- Chapter number (e.g. "01"):
- Font: 微软雅黑 Bold 40pt (use Microsoft YaHei Bold)
- Color: #A8282F (brand red)
- Position: (3.33, 1.89) 6.68×0.77 in
- Alignment: CENTER
- Chapter title:
- Font: 微软雅黑 Light 26.65pt
- Position: (0.88, 4.68) 11.57×0.44 in
- Alignment: CENTER
- Background: White (#ffffff) — do NOT use black background
Rule 4: Back Cover Must Match Template Slide 25 Style
The back cover MUST follow this exact style:
- Background: Use
end_bg.png(preferred) orback_bg.jpg, full-bleed - Logo: Use
end_logo.png(preferred) orback_logo.png- Size: 1.70 × 0.86 inches (1554480 × 786384 EMU)
- Position: center-x=5.82", y=1.45"
- Title: "THANKS" (NOT "THANK YOU")
- Font: Arial Black, 80pt, bold
- Position: center at (3.40, 3.01) inches
- Subtitle: Company/project name in 微软雅黑 18pt white
Rule 5: NO Shadow Effects on Any Shape, Line, or Textbox
This is a GLOBAL, NON-NEGOTIABLE rule. Every single shape, connector, line, oval, rectangle, rounded rectangle, textbox, or any other visual element in the PPT MUST have zero shadow effects. The template uses a pure flat design with no drop shadows, no inner shadows, no glowing edges, no reflections, no 3D effects.
Implementation requirements:
- After creating ANY shape via
add_shape(),add_connector(), or
add_picture(), immediately call _strip_shadow(shape) to remove any default/inherited shadow styling
- The
_strip_shadow()helper removes the<a:effectLst>element from the
shape's <a:spPr> (or <p:spPr>) XML element
- ALL convenience functions that create shapes MUST include shadow stripping
internally. This includes:
add_rect()— must call_strip_shadow(shape)on the rectangleadd_rounded_rect()— must call_strip_shadow(shape)on the rounded rectangleadd_oval()— must call_strip_shadow(shape)on the ovaladd_shape_no_shadow()— must call_strip_shadow(shape)on the shapeadd_connector_line()— must call_strip_shadow(connector)on the connectoradd_line_v()— must call_strip_shadow(connector)on the connectoradd_textbox()— must call_strip_shadow(txBox)on the textbox
- Do NOT use
<a:outerShdw>,<a:innerShdw>, or any effect-related tags
anywhere in shape XML
- Ensure the base
Presentation()object does not have a theme with default
shadow effect styles. If using a template .pptx file, verify the template theme has no default shadow effects
def _strip_shadow(shape):
"""Remove all shadow/effect styling from a shape."""
spPr = shape._element.find(qn('a:spPr'))
if spPr is None:
spPr = shape._element.find(qn('p:spPr'))
if spPr is not None:
effectLst = spPr.find(qn('a:effectLst'))
if effectLst is not None:
spPr.remove(effectLst)Rule 6: Data Tables Must Be Center-Aligned
ALL data tables in the generated PPT MUST have text centered both horizontally and vertically in every cell.
Implementation requirements:
- Every cell must set
cell.vertical_anchor = MSO_ANCHOR.MIDDLE(frompptx.enum.text) - Every cell's paragraph alignment must be
PP_ALIGN.CENTER - This applies to ALL tables:
add_styled_table(), inline tables in content
pages, and any table created with slide.shapes.add_table()
- The header row and all data rows must both follow this rule
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
# In table building code:
cell = table.cell(row_idx, col_idx)
cell.vertical_anchor = MSO_ANCHOR.MIDDLE
para = cell.text_frame.paragraphs[0]
para.alignment = PP_ALIGN.CENTERRule 7: Doughnut Chart Must Use Specific Color Palette
When creating doughnut/ring charts, the segment colors MUST follow this exact palette in order:
| Order | Color | Hex | Usage |
|---|---|---|---|
| 1st | Black | #0d0d0d | Largest/main segment |
| 2nd | Red | #a8282f | Second segment |
| 3rd | Gray | #f6f6f6 | Background/neutral segment |
| 4th | Pink | #fceeeb | Accent segment |
The doughnut chart builder must use [0x0d0d0d, 0xa8282f, 0xf6f6f6, 0xfceeeb] rather than the generic _style_chart() colors. This palette matches the template's data visualization style which uses high-contrast black and red as the primary visual anchors, with gray and pink as supporting colors.
Rule 8: Cover/Back Cover Images Must Be Force-Downloaded from IMAGE_URLS
This is a NON-NEGOTIABLE rule. Cover and back cover images MUST come from the skill's IMAGE_URLS dictionary (defined in both PPT模版-简版.py and generate_ppt.py). They must NOT be replaced by solid color rectangles or source PPT images.
Implementation requirements:
- Before building cover/back cover slides, call a
force_download_cover_images()
function that downloads the 4 critical images:
cover_bg→cover_bg.png(URL is .jpg, needs PIL format conversion)cover_logo→cover_logo.pngend_bg→back_bg.jpg(URL is .png, needs PIL format conversion)end_logo→back_logo.png
- The download function MUST use
requestslibrary with proper headers
(User-Agent, Accept, Referer) to avoid 403 Forbidden errors. Do NOT use bare urllib.request — it will be blocked by many servers.
- Include retry logic: up to 5 attempts per image, with 2-second delay between
retries.
- Handle format conversion: when URL extension differs from target filename
extension, use PIL/Pillow to convert (jpg→png or png→jpg).
build_cover()andbuild_back_cover()MUST check multiple filename variants
using a find_image() helper:
- Cover bg:
["cover_bg.png", "cover_bg.jpg"] - Cover logo:
["cover_logo.png"] - Back cover bg:
["back_bg.jpg", "end_bg.png", "back_bg.png", "cover_bg.jpg", "cover_bg.png"] - Back cover logo:
["back_logo.png", "end_logo.png", "cover_logo.png"]
- Fallback: when back cover specific images (
end_bg,end_logo) cannot be
downloaded (server errors), build_back_cover() MUST fall back to cover images (cover_bg, cover_logo) as replacement. The back cover MUST NOT use a plain solid color rectangle — it must always have a template background image.
def force_download_cover_images():
import requests
from PIL import Image as PILImage
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...",
"Accept": "image/webp,image/apng,image/*,*/*;q=0.8",
"Referer": "https://bee-reg-ab.imagency.cn/",
}
critical_images = [
("cover_bg", ["cover_bg.png", "cover_bg.jpg"], IMAGE_URLS["cover_bg"]),
("cover_logo", ["cover_logo.png"], IMAGE_URLS["cover_logo"]),
("end_bg", ["back_bg.jpg", "end_bg.png"], IMAGE_URLS["end_bg"]),
("end_logo", ["back_logo.png", "end_logo.png"], IMAGE_URLS["end_logo"]),
]
for name, local_filenames, url in critical_images:
# Skip if any variant already exists
...
# Download with retries
for attempt in range(5):
resp = requests.get(url, headers=headers, timeout=30, stream=True)
resp.raise_for_status()
# Save + format conversion if needed
...Rule 9: Safe Margins for Text Inside Rounded Rectangles
This is a NON-NEGOTIABLE rule. All text placed inside rounded rectangle backgrounds (data cards, content panels, timeline cards, etc.) MUST maintain safe margins from the border on all four sides (top, bottom, left, right). Text must NOT touch or be too close to the rounded rectangle border.
Implementation requirements:
- Define and use safe margin constants:
SAFE_PAD_H = 300000 # ~0.33 inches, horizontal safe margin (left + right)
SAFE_PAD_V = 250000 # ~0.27 inches, vertical safe margin (top + bottom)- For a rounded rectangle at position
(left, top)with size(width, height):- Text left position:
left + SAFE_PAD_H(NOTleft + 100000orleft + 150000) - Text width:
width - 2 * SAFE_PAD_H(NOTwidth - 200000orwidth - 300000) - First text top position:
top + SAFE_PAD_V(NOTtop + 80000ortop + 100000) - Last text bottom must not exceed:
top + height - SAFE_PAD_V - Text height for last element:
height - (text_offset_from_top) - SAFE_PAD_V
- Text left position:
- This rule applies to ALL text inside ANY rounded rectangle, including:
- Data highlight cards
- Content panel cards (left/right panels)
- Timeline stage cards
- Benefits/rewards cards
- Rules/disclaimer panels
- Any other
add_rounded_rect()followed byadd_textbox()
- The minimum safe margin is 300000 EMU (≈0.33 inches) horizontally and
250000 EMU (≈0.27 inches) vertically. Larger margins are acceptable.
- Tables inside rounded rectangles must also respect safe margins:
table_left = left + SAFE_PAD_H, table_width = width - 2 * SAFE_PAD_H
# CORRECT — safe margins
SAFE_PAD_H = 300000
SAFE_PAD_V = 250000
add_rounded_rect(slide, Emu(left), Emu(top), Emu(card_w), Emu(card_h), fill_color=bg)
add_textbox(
slide, Emu(left + SAFE_PAD_H), Emu(top + SAFE_PAD_V),
Emu(card_w - 2*SAFE_PAD_H), Emu(card_h - SAFE_PAD_V - offset),
text, ...
)
# WRONG — text too close to border (DO NOT DO THIS)
add_rounded_rect(slide, Emu(left), Emu(top), Emu(card_w), Emu(card_h), fill_color=bg)
add_textbox(
slide, Emu(left + 100000), Emu(top + 80000), # Too close!
Emu(card_w - 200000), Emu(...), # Too wide!
text, ...
)Rule 10: Source Content Beautification Mode — Preserve Original Images
This rule applies ONLY when the user has selected "是,根据源文件美化" in the Pre-Workflow check.
When beautifying based on source content, ALL images from the source PPTX MUST be preserved and embedded in the output without compression or distortion.
Implementation requirements:
- Extract all images from the source PPTX, including images nested inside GROUP shapes:
from pptx.enum.shapes import MSO_SHAPE_TYPE
def extract_all_images(slide, slide_idx, output_dir):
for j, shape in enumerate(slide.shapes):
if shape.shape_type == MSO_SHAPE_TYPE.PICTURE:
img = shape.image
ext = img.content_type.split('/')[-1]
fname = f'slide{slide_idx+1}_img{j}.{ext}'
with open(f'{output_dir}/{fname}', 'wb') as f:
f.write(img.blob)
# Also check images within GROUP shapes
if shape.shape_type == MSO_SHAPE_TYPE.GROUP:
for gi, gshape in enumerate(shape.shapes):
if gshape.shape_type == MSO_SHAPE_TYPE.PICTURE:
gimg = gshape.image
gext = gimg.content_type.split('/')[-1]
gfname = f'slide{slide_idx+1}_group{gi}.{gext}'
with open(f'{output_dir}/{gfname}', 'wb') as f:
f.write(gimg.blob)- Proportional scaling ONLY: When placing extracted images, calculate dimensions
using the original aspect ratio. NEVER stretch or squash images:
# Get original aspect ratio
img = PILImage.open(img_path)
orig_ratio = img.width / img.height
# Scale proportionally within target bounds
if target_w / target_h > orig_ratio:
# Height-constrained
actual_h = target_h
actual_w = int(target_h * orig_ratio)
else:
# Width-constrained
actual_w = target_w
actual_h = int(target_w / orig_ratio)- Image positioning: All images must be centered within the content area using
the center_x() function (see Rule 11).
- Image quality: Use
img.blob(raw bytes) for extraction — do NOT re-encode
or compress images. Preserve original format (PNG/JPEG).
Rule 11: Inner Page Content Centering
This is a NON-NEGOTIABLE rule. All content on inner pages (slides after the cover) MUST be centered within the page layout area. The layout must be balanced and visually stable — no elements should be left-aligned or right-aligned arbitrarily.
Implementation requirements:
- Define content area boundaries based on the template's inner page layout:
CONTENT_L = Emu(466344) # ~0.51in — left margin (matches title left edge)
CONTENT_R = Emu(11521440) # logo right edge (matches inner logo position)
CONTENT_W = CONTENT_R - CONTENT_L # usable content width- Create a
center_x(content_width)helper function for horizontal centering:
def center_x(content_width):
"""Center content within the CONTENT_L..CONTENT_R range."""
return CONTENT_L + (CONTENT_W - content_width) // 2- Every content element (textboxes, images, shapes, tables, cards) must use
center_x() for their horizontal position, or be explicitly positioned relative to a centered container.
- Multi-column layouts: If the content naturally uses multiple columns (e.g.,
flowcharts, comparison tables), the entire multi-column block must be centered as a unit using center_x(total_block_width).
- Vertical centering is NOT required — content flows top-to-bottom naturally,
but the horizontal positioning must always be balanced.
Examples:
# Single element — centered
img_w = Emu(9500000)
img_left = center_x(img_w)
slide.shapes.add_picture(img_path, img_left, img_top, img_w, img_h)
# Multi-element block — center the whole block
total_block_w = card_w * 3 + gap * 2
block_left = center_x(total_block_w)
card1_left = block_left
card2_left = block_left + card_w + gap
card3_left = block_left + (card_w + gap) * 2
# Timeline nodes — evenly spaced within centered line
node_spacing = timeline_w // (node_count - 1)
cx = timeline_left + node_spacing * idx # each node centered on its slotRule 12: Timeline Styling for Multi-Node Time Content
This rule applies when the source content contains multiple time-sequenced nodes (milestones, phases, stages, dates). Any content with time-based progression MUST use a timeline visual style for beautification.
Implementation requirements:
- Timeline line: A horizontal line spanning the content area, using a light gray
color that follows the template's color palette:
TIMELINE_GRAY = RGBColor(0xDD, 0xDD, 0xDD) # #DDDDDD — light gray- Line thickness: approximately 0.018in (thin, subtle)
- The line must be centered within the content area using
center_x()
- Node dots: Circular indicators sitting ON the timeline line:
- Completed/past nodes: Use brand red
#A8282Ffill - Future/ongoing nodes: Use gray
#999999fill - Dot diameter: approximately 0.11in
- Dots must be vertically centered on the timeline line
- Completed/past nodes: Use brand red
- Node spacing: Nodes must be evenly distributed along the timeline line:
node_spacing = timeline_width // (node_count - 1)
for idx in range(node_count):
cx = timeline_left + node_spacing * idx- Date labels: Positioned ABOVE the node dots:
- Font: 微软雅黑, 10-11pt, bold
- Color: Brand red
#A8282Ffor completed nodes, gray#6D6D6Dfor future nodes - Centered above each dot
- Description text: Positioned BELOW the node dots:
- Font: 微软雅黑, 7.5-8pt, regular
- Color: Dark
#131313for completed nodes, gray#6D6D6Dfor future nodes - Centered below each dot
- Multi-line text supported (use
n)
- Color harmony: ALL timeline elements must use colors from the template palette:
- Red:
#A8282F→ completed node dots, completed date labels - Dark:
#131313→ completed description text - Gray:
#999999→ future node dots - Gray:
#6D6D6D→ future date labels, future description text - Light Gray:
#DDDDDD→ timeline line
- Red:
Visual layout:
4月中 4月底 5月18日 5月18日 6月30日 95%+ 7月24日 ← Dates
●───────────●───────────●───────────●───────────●───────────○───────────○─────── ← Dots + timeline
大区季度会 首次面向客户 战略聚焦 全员参与 上线BML 持续优化 LOSE率改善
正式提出... "JIA"更优 全员宣贯 首次启动 系统规范 提升准确性 17pp/10倍 ← DescriptionsIf source content already contains an image with a timeline/gantt chart:
- Place the original image in the upper portion of the slide (proportionally scaled)
- Add the text-based timeline nodes below the image
- The timeline style rules above apply to the text nodes; the original image is
preserved as-is
Rule 13: No Text/Shape Overlap — Global Layout Safety
This is a GLOBAL, NON-NEGOTIABLE rule. No text element (textbox, text frame) may overlap with any other text element, and no shape may overlap with any text element in a way that obscures readability. All elements on every slide MUST have clear, non-overlapping bounding boxes.
Implementation requirements:
- Plan vertical zones before placing elements. Divide each slide into
non-overlapping vertical bands:
Zone 0: Header (y: 0 → header_bottom) — inner page title + logo
Zone 1: Page title (y: header_bottom → page_title_end) — slide-level title text
Zone 2: Content (y: page_title_end → slide_bottom) — all content elements- **Every element's bounding box MUST NOT intersect any other element's
bounding box** unless one is a deliberate container (e.g., textbox inside a rounded rectangle). For container elements, text MUST remain within the container's safe padding.
- Minimum inter-zone gap: At least 20000 EMU (~0.02 inches) between
any two non-container elements. Larger gaps (50000+ EMU) are preferred.
- Multi-branch layouts (e.g., flowcharts, decision trees): When elements
go above the main row (e.g., Y-branch), their entire vertical extent including labels MUST end before the page title zone begins. Do NOT let branch elements extend upward into the title area.
- Common causes of overlap to watch for:
- Y/N branch labels in flowcharts extending into title zones
- Timeline node descriptions overlapping with section headers
- Data cards placed too close to each other (forgetting gap spacing)
- Footer/disclaimer text overlapping with bottom content
- Images and textboxes with overlapping bounding boxes when the image is
not a deliberate background
- Avoid overlap by adjusting (in priority order):
a. Increase vertical gap between elements b. Reduce font size to make text zones smaller c. Reduce shape sizes (box height/width) d. Center the entire content block and adjust spacing uniformly
Example — correct multi-zone layout:
# Zone 0: Header
header_bottom = Emu(1200000) # ~1.31in
# Zone 1: Page title (two compact lines)
title_top = header_bottom + Emu(60000) # 1260000
title_bottom = title_top + Emu(400000) # 1660000
# Zone 2: Content — ALL elements below title_bottom
y_main = title_bottom + Emu(1140000) # 2800000 (generous gap)
y_branch_up = title_bottom + Emu(220000) # 1880000 (above main, below title)
y_branch_down = y_main + Emu(950000) # 3750000 (below main)
# All branch labels must stay within their respective zone
# Y branch label: y_branch_up - 150000 = 1730000 (ABOVE title_bottom=1660000) ✓
# N branch label: y_branch_down - 150000 = 3600000 (BELOW main=3500000) ✓Example — WRONG layout (DO NOT DO THIS):
# WRONG: Y branch box at 2200000 overlaps with title at 2000000-2300000
y_main = 2800000
y_branch_up = 2200000 # This overlaps with title zone!Page Structure
Default Mode (用户选择"否,按默认逻辑生成")
| Page | Type | Description |
|---|---|---|
| 1 | Cover | Template cover bg + logo + title (white text) |
| 2 | Template | 公司介绍 — Industry Unicorn (three-column layout) |
| 3 | Template | 公司实力 — Company Strength (data circles, mixed-format numbers) |
| 4 | Template | 技术资质 — Technical Certifications (bottom bar) |
| 5 | TOC | Horizontal chapter row + red top bar, "CONTENTS" 88pt white |
| 6 | Section | PART ONE divider — CENTERED, 66pt + red vertical line + red number |
| 7+ | Content | Data overview, tables, charts, analysis |
| N | Section | PART TWO divider (same CENTERED style as slide 6) |
| N+ | Content | Plans, timeline, SaaS features |
| N | Section | PART THREE divider (same style as slide 6) |
| N+ | Content | Incentive plan |
| Last | Back | THANKS — 80pt Arial Black + proper logo 1.70×0.86" |
Source Content Beautification Mode (用户选择"是,根据源文件美化")
This mode preserves the source file's page count and content structure.
| Page | Type | Description |
|---|---|---|
| 1 | Cover | Template cover bg + logo + source file title (white text, Arial Black) |
| 2 | Content | Template inner page header (CN title + EN subtitle + inner logo) + source page 2 content with preserved images |
| 3-N | Content | Same header style on each page; content 100% from source — images preserved, no text modifications |
| Last | Content | Last source page with template header; may include back cover elements if in source |
Key differences from Default Mode:
- NO company intro pages (slides 2-4)
- NO TOC page
- NO section divider pages
- NO additional text content — only what exists in the source
- YES to template cover bg/logo, inner page headers, logo position, and color palette
- YES to preserved source images (no compression, no distortion)
- YES to content centering (Rule 11)
- YES to timeline styling for multi-node time content (Rule 12)
- YES to no text/shape overlap — mandatory self-check (Rule 13)
- Output page count = source PPTX page count |
Content Page Layout Pattern
+----------------------------------+----------+
| CN Title (27pt black) | [logo]|
| EN Subtitle (10pt gray) | |
| | |
| [Conclusion 14pt bold black] | |
| [Data Card] [Data Card] | [Table] |
| | or |
| [Bullet points 12pt gray] | [Chart] |
| | |
+----------------------------------+----------+Customization
Generation Modes
The skill supports three generation modes. Mode 0 (content creation) is auto-routed by request type; the other two are determined by the Pre-Workflow question:
| Mode | Trigger | Page Count | Content Source | Structure |
|---|---|---|---|---|
| Source Beautification | 用户回答"是,根据源文件美化" | = source PPTX | 100% from source file | Cover + N content pages |
| Default Generation | 用户回答"否,按默认逻辑生成" | 25 (template) | Template structure + source data | Cover + company + TOC + sections + content + back |
| Content Creation (Mode 0) | 用户从0到1创作(无源文件,给类型+主题) | = 草稿页数 | 问卷 + 行业框架生成 | Cover + 用户内容页(内容100%来自草稿,经源文件美化路径出片) |
Default Mode Customization
The scripts/generate_ppt.py is a complete reference implementation for the Shanghai Sheraton 10th Anniversary case. To adapt for different data:
- ALWAYS start from the template structure defined in
assets/PPT模版-简版.py - MUST include slides 2-4 (公司介绍/公司实力/技术资质) — see [Mandatory Template Requirements](#mandatory-template-requirements)
- MUST use the exact TOC style from template slide 5 — horizontal row + red top bar (#A8282F) + "CONTENTS" 88pt white. Do NOT use vertical list or dark/black top bar
- MUST use the exact section divider style from template slide 6 — CENTERED layout, 66pt PART label, red number, red vertical line, 26.65pt chapter title
- MUST use the exact back cover style from template slide 25 — "THANKS" 80pt, logo 1.70×0.86"
- MUST remove ALL shadow effects from every shape, connector, line, oval, and textbox — see [Rule 5](#rule-5-no-shadow-effects-on-any-shape-line-or-textbox). Call
_strip_shadow()on every shape/connector/textbox immediately after creation - ALL data tables MUST center text both horizontally (
PP_ALIGN.CENTER) and vertically (MSO_ANCHOR.MIDDLE) — see [Rule 6](#rule-6-data-tables-must-be-center-aligned) - Doughnut charts MUST use the exact 4-color palette: #0d0d0d → #a8282f → #f6f6f6 → #fceeeb — see [Rule 7](#rule-7-doughnut-chart-must-use-specific-color-palette)
- Slide 3 (Company Strength) MUST use: line_spacing=0.9 on title and "70亿+"; line_spacing=2.0 on left data text; "9000" Arial 44pt Bold + "家+" 微软雅黑 Bold 22pt; "合作伙伴" 18pt; "2025" Arial Black 24pt + "年交易额" 微软雅黑 Bold 24pt; red/dark ovals with 8pt white border; red oval overlay "10,000"/"种+"/"系统功能"
- MUST force-download cover/back cover images from
IMAGE_URLSusingrequestswith User-Agent headers and retry logic.build_cover()andbuild_back_cover()must check multiple filename variants (.png/.jpg). When back cover images fail to download, fall back to cover images — see [Rule 8](#rule-8-coverback-cover-images-must-be-force-downloaded-from-image_urls) - MUST use safe margins for all text inside rounded rectangles — minimum 300000 EMU (≈0.33") horizontal and 250000 EMU (≈0.27") vertical on all four sides. Use
SAFE_PAD_HandSAFE_PAD_Vconstants — see [Rule 9](#rule-9-safe-margins-for-text-inside-rounded-rectangles) - Modify the
main()function to match source PPT page structure - Update
build_*()functions with new data, tables, and chart parameters - Replace source-specific images in
assets/images/(summer_*.png, etc.) - Keep template images — they are auto-managed by
IMAGE_URLS, do NOT
replace them with source PPT images
- Follow the style specs in
references/for any new elements
Source Beautification Mode Customization
When the user selects source beautification mode, create a custom generation script tailored to the source content. This script MUST:
- Analyze the source PPTX thoroughly — extract ALL text, images (including those
inside GROUP shapes), tables, and layout information
- Extract and preserve ALL images from the source — see [Rule 10](#rule-10-source-content-beautification-mode–preserve-original-images)
- Use template cover elements:
cover_bg.jpgbackground,cover_logo.pnglogo,
Arial Black white title, 微软雅黑 Light subtitle
- Use template inner page headers: CN title (微软雅黑 Light, Pt 27) + EN subtitle
(微软雅黑 Light, Pt 10, #6D6D6D) + inner logo at exact template coordinates
- Center all content — see [Rule 11](#rule-11-inner-page-content-centering)
- Apply timeline styling for multi-node time content — see [Rule 12](#rule-12-timeline-styling-for-multi-node-time-content)
- Never add company intro pages, TOC, section dividers, or any content not in the source
- Never modify any source text — only beautify the visual presentation
- Ensure no text/shape overlap — plan vertical zones, use the overlap self-check from Step 5, and fix any detected overlaps before delivering (see Rule 13)
- Output page count must equal the source PPTX page count
Dependencies
pip install python-pptx lxml matplotlib pillowPython 3.9+ required. Run with the managed Python:
/Users/zkt/.workbuddy/binaries/python/envs/default/bin/python3Resources
scripts/
generate_ppt.py— Full PPT generation script (parameterized, ~2100 lines)- Usage:
python3 generate_ppt.py <source.pptx> <template.pptx> <output.pptx> - Contains: font helpers, shape helpers, styled table builder, native chart
- Usage:
builders (bar/line/doughnut), data highlight cards, 15+ page builders
- V2 new:
IMAGE_URLSdictionary +ensure_images_downloaded()auto-download report_invocation.config.json— 辅助脚本配置(base_url / token / skill_name /
status),脚本读取的默认来源,可被环境变量覆盖
report_invocation.sh— 辅助脚本(macOS / Linux),最基础 curl 方式,
优先读环境变量、其次读 report_invocation.config.json,自动管理匿名编号
report_invocation.py— 辅助脚本(跨平台,推荐),Python 标准库
urllib 实现,Windows / macOS / Linux / Git Bash 通用。自动生成/读取匿名编号(ZKT + 6位随机数字),不收集任何真实用户身份信息
build_content_draft.py— Mode 0 用:读内容 JSON → 生成"素版内容草稿 PPTX"
(白底、微软雅黑黑字、无样式、16:9),作为 Source Beautification 的源文件输入
beautify_content_json.py— Mode 0 用(V2):读内容 JSON(含structure)→ 输出品牌
美化 PPTX。按 Rule M1 注入固定结构页(公司介绍×3/目录/章节页/封底,复刻PPT模版-简版.py),按 Rule M2 溢出自动分页(精确估高+续页+边界自检),双栏按行配对,数据卡/表格/时间轴自动渲染,无阴影,重叠+边界双自检
assets/
PPT模版-简版.py— Template PPTX generator script (V2: cross-platform paths,
downloads images to assets/images/ instead of temp dir)
PPT模版-简版.pptx— Pre-built template PPTX (25 blank slides)images/— Auto-downloaded template images (viaIMAGE_URLSin generate_ppt.py):- Template: cover_bg.png, cover_logo.png, back_bg.jpg, back_logo.png, inner_logo.png
- Additional: icon_dev, icon_finance, icon_team, logo_bottom, circle_bg, bottom_bar,
icon_a, icon_b, icon_c
- Source-specific: summer_beach.png, november_11.png, new_year.png
images/source_images/— Mode 0 用户素材目录(用户提供/由草稿 image_note 引用的图片放这里)
references/
style_guide.md— Complete color, font, shape, and layout specificationschart_specs.md— Native chart styling code and specificationsframeworks/marketing_activity.md— Mode 0 蓝图:酒店营销活动方案(逐页大纲+版式建议)frameworks/gm_data_report.md— Mode 0 蓝图:经营数据总结(总经理汇报,含指标口径)frameworks/promo_training.md— Mode 0 蓝图:促销/产品培训frameworks/metrics_glossary.md— 酒店运营指标口径表 + 〔待填〕占位 / 红字假设值规范