260 lines
6.2 KiB
Markdown
260 lines
6.2 KiB
Markdown
# 海报系统重构方案 (方案 C)
|
||
|
||
> 完整重构计划,将海报系统改造为 YAML 配置化、模块化的架构
|
||
|
||
## 一、当前状态 (方案 B 完成后)
|
||
|
||
### 已完成
|
||
- ✅ `domain/poster/poster_service.py` - 轻量服务 (无数据库依赖)
|
||
- ✅ `domain/aigc/engines/poster_generate_v2.py` - V2 引擎
|
||
- ✅ API 可用: `POST /api/v2/aigc/execute` (engine=poster_generate)
|
||
|
||
### 遗留问题
|
||
| 问题 | 文件 | 说明 |
|
||
|-----|------|------|
|
||
| 巨型模板文件 | `vibrant_template.py` (78KB) | 难以维护 |
|
||
| 模板 bug | `_generate_legacy` | images 参数处理不一致 |
|
||
| 配置硬编码 | 模板内部 | 颜色、字体、布局都写死 |
|
||
| 旧服务残留 | `api/services/poster.py` | 3000+ 行,依赖已删除模块 |
|
||
|
||
---
|
||
|
||
## 二、目标架构
|
||
|
||
```
|
||
domain/poster/ # 海报核心模块
|
||
├── __init__.py
|
||
├── poster_service.py # 主服务 (已有)
|
||
├── poster_renderer.py # 渲染器 (已有)
|
||
├── template_manager.py # 模板管理器 (新增)
|
||
└── templates/ # 模板目录 (新增)
|
||
├── base.py # 基类
|
||
├── vibrant/
|
||
│ ├── config.yaml # 模板配置
|
||
│ ├── handler.py # 渲染逻辑
|
||
│ └── preview.png # 预览图
|
||
├── business/
|
||
│ ├── config.yaml
|
||
│ └── handler.py
|
||
└── collage/
|
||
├── config.yaml
|
||
└── handler.py
|
||
|
||
prompts/poster/ # 海报 Prompt
|
||
├── v1.0.0.yaml # 文案生成 Prompt
|
||
└── templates.yaml # 模板元数据索引
|
||
```
|
||
|
||
---
|
||
|
||
## 三、模板配置 YAML 化
|
||
|
||
### 示例: `templates/vibrant/config.yaml`
|
||
|
||
```yaml
|
||
meta:
|
||
id: vibrant
|
||
name: 活力风格
|
||
description: 适合景点、活动等充满活力的场景
|
||
version: "1.0.0"
|
||
preview: preview.png
|
||
|
||
# 画布配置
|
||
canvas:
|
||
width: 1350
|
||
height: 1800
|
||
background: transparent
|
||
|
||
# 颜色主题
|
||
colors:
|
||
presets:
|
||
ocean_deep:
|
||
gradient: [[0, 30, 80], [20, 120, 220]]
|
||
sunset_warm:
|
||
gradient: [[255, 94, 77], [255, 154, 0]]
|
||
cool_mint:
|
||
gradient: [[64, 224, 208], [127, 255, 212]]
|
||
default: ocean_deep
|
||
|
||
# 毛玻璃效果
|
||
glass_effect:
|
||
max_opacity: 240
|
||
blur_radius: 22
|
||
transition_height: 120
|
||
intensity_multiplier: 1.5
|
||
|
||
# 字体配置
|
||
fonts:
|
||
title:
|
||
path: assets/font/兰亭粗黑简.TTF
|
||
size: 72
|
||
color: [255, 255, 255]
|
||
content:
|
||
path: assets/font/兰亭粗黑简.TTF
|
||
size: 36
|
||
color: [255, 255, 255, 200]
|
||
tag:
|
||
path: assets/font/兰亭粗黑简.TTF
|
||
size: 28
|
||
color: [255, 255, 255, 180]
|
||
|
||
# 布局配置
|
||
layout:
|
||
title:
|
||
position: [50, 1200]
|
||
max_width: 1250
|
||
content:
|
||
position: [50, 1350]
|
||
max_width: 1250
|
||
line_height: 1.5
|
||
tag:
|
||
position: [50, 1700]
|
||
```
|
||
|
||
---
|
||
|
||
## 四、重构步骤
|
||
|
||
### Phase 1: 模板管理器 (1天)
|
||
|
||
```python
|
||
# domain/poster/template_manager.py
|
||
|
||
class TemplateManager:
|
||
"""
|
||
模板管理器
|
||
- 从 YAML 加载模板配置
|
||
- 动态实例化模板处理器
|
||
- 支持热重载
|
||
"""
|
||
|
||
def __init__(self, templates_dir: str):
|
||
self.templates_dir = Path(templates_dir)
|
||
self._configs = {}
|
||
self._handlers = {}
|
||
|
||
def load_template(self, template_id: str) -> TemplateConfig:
|
||
"""加载模板配置"""
|
||
config_path = self.templates_dir / template_id / 'config.yaml'
|
||
...
|
||
|
||
def get_handler(self, template_id: str) -> BaseTemplateHandler:
|
||
"""获取模板处理器"""
|
||
...
|
||
```
|
||
|
||
### Phase 2: 拆分巨型模板 (2天)
|
||
|
||
将 `vibrant_template.py` (78KB) 拆分为:
|
||
|
||
```
|
||
templates/vibrant/
|
||
├── config.yaml # 配置 (从代码中提取)
|
||
├── handler.py # 核心渲染逻辑 (~500行)
|
||
├── effects.py # 特效函数 (毛玻璃等)
|
||
├── text_layout.py # 文字排版
|
||
└── color_utils.py # 颜色处理
|
||
```
|
||
|
||
### Phase 3: 统一模板接口 (1天)
|
||
|
||
```python
|
||
# domain/poster/templates/base.py
|
||
|
||
class BaseTemplateHandler(ABC):
|
||
"""模板处理器基类"""
|
||
|
||
def __init__(self, config: TemplateConfig):
|
||
self.config = config
|
||
|
||
@abstractmethod
|
||
def render(
|
||
self,
|
||
image: Image.Image,
|
||
content: Dict[str, Any],
|
||
**options
|
||
) -> RenderResult:
|
||
"""渲染海报"""
|
||
pass
|
||
|
||
def render_to_base64(self, ...) -> str:
|
||
"""渲染并返回 Base64"""
|
||
...
|
||
|
||
def render_to_fabric_json(self, ...) -> dict:
|
||
"""渲染并返回 Fabric.js JSON"""
|
||
...
|
||
```
|
||
|
||
### Phase 4: 清理旧代码 (0.5天)
|
||
|
||
- 删除 `api/services/poster.py` (3000+ 行)
|
||
- 删除 `poster/poster_generator.py` (旧入口)
|
||
- 更新 `utils/__init__.py` 移除无效导入
|
||
|
||
### Phase 5: 海报 Prompt 管理 (0.5天)
|
||
|
||
```yaml
|
||
# prompts/poster/v1.0.0.yaml
|
||
|
||
meta:
|
||
name: poster_content
|
||
version: "1.0.0"
|
||
description: "海报文案生成"
|
||
|
||
system: |
|
||
你是一个专业的营销文案策划,擅长创作吸引眼球的海报文案。
|
||
|
||
user: |
|
||
请为以下景区/产品创作海报文案:
|
||
|
||
## 产品信息
|
||
{{ product_info }}
|
||
|
||
## 要求
|
||
- 标题: 10字以内,吸引眼球
|
||
- 副标题: 20字以内,突出卖点
|
||
- 标签: 3-5个热门标签
|
||
```
|
||
|
||
---
|
||
|
||
## 五、预期收益
|
||
|
||
| 指标 | 当前 | 重构后 |
|
||
|-----|------|--------|
|
||
| 模板文件大小 | 78KB (单文件) | ~5KB (配置) + ~500行 (代码) |
|
||
| 新增模板难度 | 需要写 Python | 只需写 YAML 配置 |
|
||
| 配置修改 | 改代码重启 | 改 YAML 热重载 |
|
||
| 代码可维护性 | 低 | 高 |
|
||
|
||
---
|
||
|
||
## 六、时间估算
|
||
|
||
| 阶段 | 工作量 | 优先级 |
|
||
|-----|--------|--------|
|
||
| Phase 1: 模板管理器 | 1天 | P1 |
|
||
| Phase 2: 拆分模板 | 2天 | P1 |
|
||
| Phase 3: 统一接口 | 1天 | P1 |
|
||
| Phase 4: 清理旧代码 | 0.5天 | P2 |
|
||
| Phase 5: Prompt 管理 | 0.5天 | P2 |
|
||
| **总计** | **5天** | |
|
||
|
||
---
|
||
|
||
## 七、风险与注意事项
|
||
|
||
1. **向后兼容**: Java 端调用接口不变
|
||
2. **模板效果**: 重构后视觉效果需与原版一致
|
||
3. **性能**: 配置加载需要缓存,避免每次渲染都读文件
|
||
4. **测试**: 需要对比测试,确保输出一致
|
||
|
||
---
|
||
|
||
## 八、下一步行动
|
||
|
||
1. [ ] 确认是否立即开始方案 C
|
||
2. [ ] 或先处理热点爬虫需求
|
||
3. [ ] 或先完善其他功能
|