# Element Abstraction ## Purpose 定义元素抽象层的规格,使用 dataclass 实现类型安全的元素数据类,支持创建时验证和未来扩展。 ## Requirements ### Requirement: 元素必须使用 dataclass 定义 系统必须使用 Python dataclass 定义所有元素类型(TextElement, ImageElement, ShapeElement, TableElement),提供类型安全和自动生成的方法。 #### Scenario: 文本元素使用 dataclass 定义 - **WHEN** 开发者查看 core/elements.py 中的 TextElement 类 - **THEN** 应使用 `@dataclass` 装饰器定义,包含 type、content、box、font 字段 #### Scenario: 图片元素使用 dataclass 定义 - **WHEN** 开发者查看 core/elements.py 中的 ImageElement 类 - **THEN** 应使用 `@dataclass` 装饰器定义,包含 type、src、box 字段 #### Scenario: 形状元素使用 dataclass 定义 - **WHEN** 开发者查看 core/elements.py 中的 ShapeElement 类 - **THEN** 应使用 `@dataclass` 装饰器定义,包含 type、shape、box、fill、line 字段 #### Scenario: 表格元素使用 dataclass 定义 - **WHEN** 开发者查看 core/elements.py 中的 TableElement 类 - **THEN** 应使用 `@dataclass` 装饰器定义,包含 type、data、position、col_widths、style 字段 ### Requirement: 元素必须在创建时进行验证 系统必须在元素对象创建时(`__post_init__` 方法)进行数据验证,确保元素数据的有效性,尽早发现错误。 #### Scenario: 文本元素验证 box 字段 - **WHEN** 创建 TextElement 对象时 box 字段不是包含 4 个数字的列表 - **THEN** 系统应抛出 ValueError 异常,提示 "box 必须包含 4 个数字" #### Scenario: 图片元素验证 src 字段 - **WHEN** 创建 ImageElement 对象时 src 字段为空 - **THEN** 系统应抛出 ValueError 异常,提示 "图片元素必须指定 src" #### Scenario: 形状元素验证 box 字段 - **WHEN** 创建 ShapeElement 对象时 box 字段不是包含 4 个数字的列表 - **THEN** 系统应抛出 ValueError 异常,提示 "box 必须包含 4 个数字" #### Scenario: 表格元素验证 data 字段 - **WHEN** 创建 TableElement 对象时 data 字段为空列表 - **THEN** 系统应抛出 ValueError 异常,提示 "表格数据不能为空" ### Requirement: 必须提供元素工厂函数 系统必须提供 `create_element(elem_dict)` 工厂函数,从字典创建对应类型的元素对象,统一元素创建入口。 #### Scenario: 从字典创建文本元素 - **WHEN** 调用 `create_element({'type': 'text', 'content': 'Hello', 'box': [1, 1, 8, 1]})` - **THEN** 系统应返回 TextElement 对象,包含相应的字段值 #### Scenario: 从字典创建图片元素 - **WHEN** 调用 `create_element({'type': 'image', 'src': 'image.png', 'box': [1, 1, 4, 3]})` - **THEN** 系统应返回 ImageElement 对象,包含相应的字段值 #### Scenario: 从字典创建形状元素 - **WHEN** 调用 `create_element({'type': 'shape', 'shape': 'rectangle', 'box': [1, 1, 2, 1]})` - **THEN** 系统应返回 ShapeElement 对象,包含相应的字段值 #### Scenario: 从字典创建表格元素 - **WHEN** 调用 `create_element({'type': 'table', 'data': [['A', 'B'], ['1', '2']], 'position': [1, 1]})` - **THEN** 系统应返回 TableElement 对象,包含相应的字段值 #### Scenario: 不支持的元素类型 - **WHEN** 调用 `create_element({'type': 'unknown'})` - **THEN** 系统应抛出异常,提示不支持的元素类型 ### Requirement: 元素类型必须支持未来扩展 系统的元素抽象层设计必须支持未来添加新元素类型(如 VideoElement),只需定义新的 dataclass 和在工厂函数中添加分支。 #### Scenario: 添加新元素类型的步骤清晰 - **WHEN** 开发者需要添加新元素类型(如 Video) - **THEN** 应只需要: 1. 在 core/elements.py 中定义新的 dataclass(如 VideoElement) 2. 在 `create_element()` 工厂函数中添加对应的分支 3. 在各个渲染器中实现渲染方法 #### Scenario: 新元素类型不影响现有元素 - **WHEN** 添加新元素类型 - **THEN** 现有元素类型(Text, Image, Shape, Table)的行为不应受到影响 ### Requirement: 元素数据类必须提供默认值 系统必须为元素数据类的可选字段提供合理的默认值,简化元素创建。 #### Scenario: 文本元素的默认值 - **WHEN** 创建 TextElement 对象时不提供 box 和 font 字段 - **THEN** 系统应使用默认值:box=[1, 1, 8, 1],font={} #### Scenario: 图片元素的默认值 - **WHEN** 创建 ImageElement 对象时不提供 box 字段 - **THEN** 系统应使用默认值:box=[1, 1, 4, 3] #### Scenario: 形状元素的默认值 - **WHEN** 创建 ShapeElement 对象时不提供 fill 和 line 字段 - **THEN** 系统应使用默认值或 None