competition-ppt
中国国际大学生创新大赛(国赛)路演PPT制作。当用户提到"竞赛PPT"、"国赛"、"路演PPT"、"创新创业大赛"、"比赛幻灯片"时触发。基于两份国赛金奖级模板的设计方法论,使用python-pptx + PIL生成原创高质量PPT。
Source facts
- Repository
- 2750527986liu-maker/competition-ppt-skill
- Last source activity
- May 26, 2026 at 14:46
- Detected SKILL.md language
- Chinese
- Stars
- 14
- Forks
- 1
Install options
The review-first prompt is selected by default. You can switch to a direct command or download a local copy.
Review the source files
Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.
Showing SKILL.md
SKILL.md
Source instructions · Read-only preview- name
- competition-ppt
- description
- 中国国际大学生创新大赛(国赛)路演PPT制作。当用户提到"竞赛PPT"、"国赛"、"路演PPT"、"创新创业大赛"、"比赛幻灯片"时触发。基于两份国赛金奖级模板的设计方法论,使用python-pptx + PIL生成原创高质量PPT。
# 竞赛PPT制作 Skill
## 触发条件
用户需要制作参加中国国际大学生创新大赛(或类似创新创业比赛)的路演PPT。
## 第一步:需求收集(必须先做)
在开始制作前,用 AskUserQuestion 工具收集以下信息:
1. **项目文件**:用户是否有策划书、路演稿、流程大纲等文件?如果有,先全部读取理解内容。
2. **参考模板**:用户是否提供了参考PPT模板?如果有,必须用python-pptx分析其结构(见"模板分析"章节),**不要直接复制模板素材**,而是学习其设计思路。
3. **页数要求**:一般20-43页,根据内容量决定。
4. **配色偏好**:默认深蓝+金色,用户可指定。
## 第二步:模板分析(如有参考模板)
如果用户提供了参考PPT,**必须**执行以下分析流程:
### 2.1 用python-pptx提取结构信息
```python
from pptx import Presentation
prs = Presentation("模板路径.pptx")
slides_list = list(prs.slides)
print(f"尺寸: {prs.slide_width/914400:.1f} x {prs.slide_height/914400:.1f} 英寸")
print(f"总页数: {len(slides_list)}")
for i, slide in enumerate(slides_list):
pics = sum(1 for s in slide.shapes if s.shape_type == 13)
groups = sum(1 for s in slide.shapes if s.shape_type == 6)
# 提取文本和图片位置
for shape in slide.shapes:
if shape.has_text_frame:
print(f" 文本: {shape.text[:100]} @({shape.left/914400:.1f},{shape.top/914400:.1f})")
if shape.shape_type == 13:
print(f" 图片: @({shape.left/914400:.1f},{shape.top/914400:.1f}) {shape.width/914400:.1f}x{shape.height/914400:.1f}")
```
### 2.2 提取背景图片(理解配色和视觉风格)
```python
from pptx.oxml.ns import qn
import os
os.makedirs("template-bg", exist_ok=True)
for i, slide in enumerate(slides_list):
bg_elem = slide.background._element
nsmap = {'a': 'http://schemas.openxmlformats.org/drawingml/2006/main',
'r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'}
blip = bg_elem.find('.//a:blipFill/a:blip', nsmap)
if blip is not None:
embed = blip.get(qn('r:embed'))
if embed:
rel = slide.part.rels[embed]
img_part = rel.target_part
ext = img_part.content_type.split('/')[-1].replace('jpeg','jpg')
with open(f"template-bg/slide{i+1:02d}.{ext}", 'wb') as f:
f.write(img_part.blob)
```
### 2.3 用Read工具查看背景图片
将提取的背景图片复制到用户可见的工作文件夹,用Read工具查看,理解:
- 封面的配色方案(渐变色、主色调)
- 内容页的背景风格(浅色/深色、有无纹理)
- 特殊页面(时间线、致谢页)的设计
### 2.4 总结设计语言(不复制素材)
从模板中学习以下设计原则,然后**自己制作**设计素材:
- 配色方案(主色、辅色、强调色)
- 排版节奏(标题位置、内容区域划分)
- 元素密度(每页多少图片、多少文字块)
- 装饰手法(边框、分割线、图标风格)
## 第三步:内容大纲
### 3.1 国赛标准结构(参考两份模板的共同模式)
根据对两份国赛级PPT(41页冰雪经济 + 43页低空经济)的分析,标准结构如下:
| 编号 | 页面类型 | 内容 | 建议页数 |
|------|---------|------|---------|
| 1 | 封面 | 项目名称+副标题+团队+赛道+负责人 | 1页 |
| 2 | 政策背景 | 国家/行业政策支撑 | 1-2页 |
| 3 | 行业现状 | 市场数据、图表 | 1-2页 |
| 4 | 痛点分析 | 行业核心痛点(通常3个) | 1-2页 |
| 5 | 项目概述 | 技术原理+核心突破+产品展示 | 1-2页 |
| 6 | 研发历程 | 时间线展示 | 1页 |
| 7-N | 核心技术 | 每个核心技术独立1-2页 | 3-6页 |
| N+1 | 核心子系统 | 系统架构展示 | 1-2页 |
| N+2 | 核心母系统 | 整体系统集成 | 1页 |
| N+3 | 衍生技术 | 技术延伸应用 | 1-2页 |
| N+4 | 衍生场景 | 应用场景拓展 | 1页 |
| N+5 | 技术参数 | 关键指标对比表 | 1页 |
| N+6 | 技术壁垒/专利 | 知识产权保护 | 1页 |
| N+7 | 项目荣誉 | 获奖/认证 | 1页 |
| N+8 | 应用案例 | 实际落地案例(每个1页) | 2-4页 |
| N+9 | 应用场景 | 典型使用场景 | 1-2页 |
| N+10 | 竞品分析 | 对比表格/雷达图 | 1页 |
| N+11 | 服务客群/商业模式 | 用户画像+盈利模式 | 2-4页 |
| N+12 | 行业/技术认可 | 合作方背书 | 1-2页 |
| N+13 | 媒体报道 | 权威媒体引用 | 1页 |
| N+14 | 领导关怀 | 领导视察/指导 | 1页(可选) |
| N+15 | 个人成长 | 负责人成长历程 | 1-2页 |
| N+16 | 团队介绍 | 负责人+成员+顾问 | 2-3页 |
| N+17 | 学科引领/带动教育 | 产教融合成果 | 1-2页 |
| N+18 | 社会价值 | 产业+人才+行业价值 | 1页 |
| N+19 | 财务分析 | 收入预测+盈利模型 | 1页 |
| N+20 | 未来规划 | 发展路线图 | 1页 |
| N+21 | 致谢 | 感谢聆听 | 1页 |
**关键原则**:
- 竞赛PPT要**信息密度高、论证充分**,不要怕页数多
- 每个核心技术点**独立成页**
- 团队/教育/社会价值需要**多页展开**
- 案例、荣誉、媒体报道都是**加分页**
### 3.2 页面标题体系(必须遵守)
每页内容页必须包含:
1. **Section标签**:左上角深色圆角矩形,显示页面类别(如"核心技术"、"痛点分析")
2. **副标题**:以"——"开头,描述本页核心论点
3. **页码**:右下角 "X/总数"
```
[Section标签] ——副标题描述本页核心论点
─────────────────────────────────────────
正文内容区域
```
## 第四步:设计素材制作
### 4.1 用PIL生成原创背景(不要复制模板素材)
```python
from PIL import Image, ImageDraw, ImageFilter
import math, random
W, H = 2000, 1125 # 13.33x7.5英寸 @ 150DPI
def gradient(draw, w, h, c1, c2, direction='vertical'):
for i in range(h if direction == 'vertical' else w):
ratio = i / (h if direction == 'vertical' else w)
r = int(c1[0] + (c2[0] - c1[0]) * ratio)
g = int(c1[1] + (c2[1] - c1[1]) * ratio)
b = int(c1[2] + (c2[2] - c1[2]) * ratio)
if direction == 'vertical':
draw.line([(0, i), (w, i)], fill=(r, g, b))
else:
draw.line([(i, 0), (i, h)], fill=(r, g, b))
```
**必须生成的素材**(每种都需要):
1. **cover-bg.png** (2000x1125):封面背景。深色渐变+抽象几何/光线/网络线条
2. **content-bg.png** (2000x1125):内容页背景。浅色+微妙网格/纹理+角落点缀
3. **timeline-bg.png** (2000x1125):时间线/研发历程背景。彩墨飞溅/渐变色块
4. **dark-section-bg.png** (2000x1125):深色强调页背景。深蓝+对角线纹理
5. **thankyou-bg.png** (2000x1125):致谢页背景。深色+中央金色光晕
6. **gold-line.png** (900x6):金色渐变分割线
7. **section-badge.png** (400x80):深色section标签底图(可选,也可以用代码画)
8. **moon-icon.png** 或其他项目相关图标 (200x200)
**封面背景制作要点**:
- 深色渐变(如深蓝→更深蓝)
- 添加径向光晕(金色/蓝色)
- 抽象几何线条(网络节点、数据流、网格线)
- 不能太花哨,要保持专业感
**内容页背景制作要点**:
- 浅色为主(白/浅灰/浅蓝)
- 极其微妙的网格纹理
- 角落淡淡的蓝色水彩点缀
- 保持文字可读性
### 4.2 配色方案
默认配色(可按项目主题调整):
```python
NAVY = RGBColor(0x0A, 0x16, 0x28) # 深海军蓝,用于标题和section标签
DARK_BLUE = RGBColor(0x0F, 0x1D, 0x35) # 深蓝
GOLD = RGBColor(0xC9, 0xA8, 0x4C) # 金色,用于强调和装饰
LIGHT_GOLD = RGBColor(0xE8, 0xD5, 0x8C) # 浅金色
WHITE = RGBColor(0xFF, 0xFF, 0xFF) # 白色
DARK_TEXT = RGBColor(0x1E, 0x29, 0x3B) # 深色正文
SUB_TEXT = RGBColor(0x64, 0x74, 0x8B) # 灰色副文本
ACCENT_BLUE = RGBColor(0x38, 0x6F, 0xC4) # 蓝色强调
```
### 4.3 字体
- **标题**:等线(DengXian),Windows自带,现代清秀
- **正文**:等线(DengXian)或微软雅黑
- **数据/数字**:等线 Bold,突出显示
- **英文**:等线自动适配
## 第五步:PPT生成代码模板
### 5.1 基础框架
```python
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
import os
W = Inches(13.33)
H = Inches(7.5)
IMG = "项目图片目录"
BG = "设计素材目录"
OUT = "输出路径.pptx"
prs = Presentation()
prs.slide_width = W
prs.slide_height = H
BLANK = prs.slide_layouts[6] # blank layout
# 颜色定义(根据项目主题调整)
NAVY = RGBColor(0x0A, 0x16, 0x28)
GOLD = RGBColor(0xC9, 0xA8, 0x4C)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
DARK_TEXT = RGBColor(0x1E, 0x29, 0x3B)
SUB_TEXT = RGBColor(0x64, 0x74, 0x8B)
ACCENT = RGBColor(0x38, 0x6F, 0xC4)
```
### 5.2 核心Helper函数
```python
def add_bg(slide, bg_path):
"""添加全出血背景图"""
if os.path.exists(bg_path):
slide.background.fill.background()
pic = slide.shapes.add_picture(bg_path, Emu(0), Emu(0), W, H)
sp = pic._element
sp.getparent().remove(sp)
slide.shapes._spTree.insert(2, sp)
def text_box(slide, left, top, width, height, text, font_size=18,
color=DARK_TEXT, bold=False, align=PP_ALIGN.LEFT,
font_name="等线", line_spacing=1.5):
"""添加文本框"""
txBox = slide.shapes.add_textbox(Inches(left), Inches(top), Inches(width), Inches(height))
tf = txBox.text_frame
tf.word_wrap = True
p = tf.paragraphs[0]
p.alignment = align
run = p.add_run()
run.text = text
run.font.size = Pt(font_size)
run.font.color.rgb = color
run.font.bold = bold
run.font.name = font_name
if line_spacing:
p.line_spacing = Pt(font_size * line_spacing)
return txBox
def multi_text(slide, left, top, width, height, lines, font_size=16,
color=DARK_TEXT, bold=False, align=PP_ALIGN.LEFT,
font_name="等线", line_spacing=1.5):
"""添加多段文本"""
txBox = slide.shapes.add_textbox(Inches(left), Inches(top), Inches(width), Inches(height))
tf = txBox.text_frame
tf.word_wrap = True
for i, line_text in enumerate(lines):
p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
p.alignment = align
p.space_after = Pt(6)
run = p.add_run()
run.text = line_text
run.font.size = Pt(font_size)
run.font.color.rgb = color
run.font.bold = bold
run.font.name = font_name
p.line_spacing = Pt(font_size * line_spacing)
return txBox
def gold_line(slide, left, top, width):
"""金色分割线"""
shape = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE,
Inches(left), Inches(top), Inches(width), Pt(3))
shape.fill.solid()
shape.fill.fore_color.rgb = GOLD
shape.line.fill.background()
def section_badge(slide, text, left=0.3, top=0.2):
"""左上角Section标签"""
shape = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE,
Inches(left), Inches(top), Inches(2.6), Inches(0.6))
shape.fill.solid()
shape.fill.fore_color.rgb = NAVY
shape.line.fill.background()
tf = shape.text_frame
p = tf.paragraphs[0]
p.alignment = PP_ALIGN.CENTER
run = p.add_run()
run.text = text
run.font.size = Pt(22)
run.font.color.rgb = WHITE
run.font.bold = True
run.font.name = "等线"
def sub_header(slide, text, left=3.2, top=0.2):
"""副标题(——前缀)"""
text_box(slide, left, top, 9.5, 0.6, f"——{text}", font_size=16, color=SUB_TEXT)
def card_shape(slide, left, top, width, height, fill=WHITE):
"""白色卡片"""
shape = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE,
Inches(left), Inches(top), Inches(width), Inches(height))
shape.fill.solid()
shape.fill.fore_color.rgb = fill
shape.line.color.rgb = RGBColor(0xE2, 0xE8, 0xF0)
shape.line.width = Pt(1)
return shape
def add_img(slide, path, left, top, width=None, height=None):
"""安全添加图片"""
if not os.path.exists(path):
return None
if width and height:
return slide.shapes.add_picture(path, Inches(left), Inches(top),
Inches(width), Inches(height))
elif width:
return slide.shapes.add_picture(path, Inches(left), Inches(top), width=Inches(width))
else:
return slide.shapes.add_picture(path, Inches(left), Inches(top))
def page_num(slide, num, total):
"""页码"""
text_box(slide, 12.0, 6.9, 1.0, 0.4, f"{num}/{total}",
View on GitHubThis SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub