1
0
Files
PPTX/core/presentation.py
lanyuanxiaoyao f34405be36 feat: 移除图片适配模式功能
移除图片 fit 和 background 参数支持,简化图片渲染逻辑。系统恢复到直接使用 python-pptx 原生图片添加功能,图片将被拉伸到指定尺寸。

变更内容:
- 移除 ImageElement 的 fit 和 background 字段
- 移除 metadata.dpi 配置
- 删除 utils/image_utils.py 图片处理工具模块
- 删除 validators/image_config.py 验证器
- 简化 PPTX 和 HTML 渲染器的图片处理逻辑
- HTML 渲染器使用硬编码 DPI=96(Web 标准)
- 删除相关测试文件(单元测试、集成测试、e2e 测试)
- 更新规格文档和用户文档
- 保留 Pillow 依赖用于未来可能的图片处理需求

影响:
- 删除 11 个文件
- 修改 10 个文件
- 净减少 1558 行代码
- 所有 402 个测试通过

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-04 14:23:12 +08:00

139 lines
4.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
演示文稿模块
管理整个演示文稿的生成流程。
"""
from pathlib import Path
from loaders.yaml_loader import load_yaml_file, validate_presentation_yaml, YAMLError
from core.template import Template
from core.elements import create_element
class Presentation:
"""演示文稿类,管理整个演示文稿的生成流程"""
def __init__(self, pres_file, templates_dir=None):
"""
初始化演示文稿
Args:
pres_file: 演示文稿 YAML 文件路径
templates_dir: 模板目录
"""
self.pres_file = Path(pres_file)
self.templates_dir = templates_dir
# 加载演示文稿文件
self.data = load_yaml_file(pres_file)
validate_presentation_yaml(self.data, str(pres_file))
# 获取演示文稿尺寸
metadata = self.data.get("metadata", {})
self.size = metadata.get("size", "16:9")
self.description = metadata.get("description") # 可选的描述字段
# 验证尺寸值
if not isinstance(self.size, str):
raise ValueError(
f"无效的尺寸值: {self.size},尺寸必须是字符串(如 '16:9''4:3'"
)
# 模板缓存
self.template_cache = {}
# 解析并保存内联模板
self.inline_templates = self.data.get('templates', {})
def get_template(self, template_name):
"""
获取模板(优先检查内联模板,检测同名冲突)
Args:
template_name: 模板名称
Returns:
Template 对象
Raises:
YAMLError: 内联和外部模板同名
"""
# 1. 先检查内联模板
if template_name in self.inline_templates:
# 2. 检查外部模板是否也存在同名
if self._external_template_exists(template_name):
raise YAMLError(
f"模板名称冲突: '{template_name}' 同时存在于内联模板和外部模板目录\n"
f"请使用不同的模板名称以避免冲突"
)
inline_data = self.inline_templates[template_name]
return Template.from_data(inline_data, template_name)
# 3. 回退到外部模板
if template_name not in self.template_cache:
self.template_cache[template_name] = Template(
template_name, self.templates_dir
)
return self.template_cache[template_name]
def _external_template_exists(self, template_name):
"""检查外部模板文件是否存在"""
if not self.templates_dir:
return False
template_path = Path(self.templates_dir) / f"{template_name}.yaml"
return template_path.exists()
def render_slide(self, slide_data):
"""
渲染单个幻灯片(支持混合模式)
Args:
slide_data: 幻灯片数据字典
Returns:
dict: 包含 background 和 elements 的字典
支持三种模式:
1. 纯模板模式:只有 template 字段
2. 纯自定义模式:只有 elements 字段
3. 混合模式:同时有 template 和 elements 字段
"""
has_template = "template" in slide_data
has_custom_elements = slide_data.get("elements")
elements_from_template = []
vars_values = {}
# 步骤1渲染模板如果有
if has_template:
template_name = slide_data["template"]
template = self.get_template(template_name)
vars_values = slide_data.get("vars", {})
elements_from_template = template.render(vars_values)
# 步骤2处理自定义元素如果有
elements_from_custom = []
if has_custom_elements:
custom_elements = slide_data["elements"]
if has_template:
# 混合模式:使用模板变量解析自定义元素
template = self.get_template(slide_data["template"])
elements_from_custom = [
template.resolve_element(elem, vars_values)
for elem in custom_elements
]
else:
# 纯自定义模式(原有行为)
elements_from_custom = custom_elements
# 步骤3合并元素模板元素在前自定义元素在后
final_elements = elements_from_template + elements_from_custom
# 步骤4转换为元素对象
element_objects = [create_element(elem) for elem in final_elements]
return {
"background": slide_data.get("background"),
"elements": element_objects,
"description": slide_data.get("description"), # 保留幻灯片描述
}