马一丁

Add README of "Export as PDF"

  1 +# PDF导出优化系统使用指南
  2 +
  3 +## 概述
  4 +
  5 +全新的PDF导出系统现已集成到ReportEngine中,提供了智能布局优化功能,确保PDF文档美观且无溢出问题。
  6 +
  7 +## 核心特性
  8 +
  9 +### 1. 智能布局优化
  10 +
  11 +系统会自动分析文档内容并优化布局参数:
  12 +
  13 +- **KPI卡片优化**
  14 + - 自动调整每行列数(1-3列)
  15 + - 根据数值长度动态调整字号
  16 + - 防止数值溢出
  17 +
  18 +- **表格优化**
  19 + - 根据列数自动缩小字号
  20 + - 智能调整单元格内边距
  21 + - 支持长内容自动换行
  22 +
  23 +- **文本优化**
  24 + - 检测长文本自动增加行高
  25 + - 防止标题孤行
  26 + - 优化段落间距
  27 +
  28 +### 2. 配置持久化
  29 +
  30 +所有优化决策都会保存到日志文件中:
  31 +- 位置:`logs/pdf_layouts/layout_YYYYMMDD_HHMMSS.json`
  32 +- 内容:文档统计信息、优化策略、最终配置
  33 +
  34 +### 3. 前端集成
  35 +
  36 +用户只需点击"下载PDF"按钮,系统将:
  37 +1. 自动分析报告内容
  38 +2. 应用最佳布局优化
  39 +3. 生成高质量PDF
  40 +4. 自动下载到本地
  41 +
  42 +## 使用方法
  43 +
  44 +### 方式一:通过Web界面(推荐)
  45 +
  46 +1. 启动系统:`python app.py`
  47 +2. 生成报告:在Report Engine中生成最终报告
  48 +3. 点击"下载PDF"按钮
  49 +4. 系统自动优化并下载PDF
  50 +
  51 +### 方式二:通过API
  52 +
  53 +#### 根据任务ID导出
  54 +
  55 +```bash
  56 +curl -X GET \
  57 + "http://localhost:5000/api/report/export/pdf/YOUR_TASK_ID?optimize=true" \
  58 + -o report.pdf
  59 +```
  60 +
  61 +#### 从IR JSON直接导出
  62 +
  63 +```bash
  64 +curl -X POST \
  65 + "http://localhost:5000/api/report/export/pdf-from-ir" \
  66 + -H "Content-Type: application/json" \
  67 + -d '{
  68 + "document_ir": {...},
  69 + "optimize": true
  70 + }' \
  71 + -o report.pdf
  72 +```
  73 +
  74 +### 方式三:通过Python脚本
  75 +
  76 +```python
  77 +from pathlib import Path
  78 +import json
  79 +from ReportEngine.renderers import PDFRenderer
  80 +
  81 +# 读取IR数据
  82 +with open('report_ir.json', 'r', encoding='utf-8') as f:
  83 + document_ir = json.load(f)
  84 +
  85 +# 创建渲染器并导出PDF
  86 +renderer = PDFRenderer()
  87 +renderer.render_to_pdf(
  88 + document_ir,
  89 + 'output.pdf',
  90 + optimize_layout=True # 启用布局优化
  91 +)
  92 +```
  93 +
  94 +## 配置选项
  95 +
  96 +### 全局配置
  97 +
  98 +```python
  99 +from ReportEngine.renderers import PDFLayoutOptimizer, PDFLayoutConfig
  100 +
  101 +# 自定义配置
  102 +config = PDFLayoutConfig(
  103 + page=PageLayout(
  104 + font_size_base=14,
  105 + line_height=1.6
  106 + ),
  107 + kpi_card=KPICardLayout(
  108 + font_size_value=32,
  109 + min_height=120
  110 + ),
  111 + # ... 更多配置
  112 +)
  113 +
  114 +# 使用自定义配置
  115 +optimizer = PDFLayoutOptimizer(config)
  116 +renderer = PDFRenderer(layout_optimizer=optimizer)
  117 +```
  118 +
  119 +### 优化策略
  120 +
  121 +| 场景 | 触发条件 | 优化措施 |
  122 +|------|---------|---------|
  123 +| KPI数量多 | > 6个 | 调整为3列布局 |
  124 +| KPI数量少 | ≤ 2个 | 调整为1列布局 |
  125 +| KPI数值长 | > 10字符 | 字号从32px调整为28px |
  126 +| KPI数值很长 | > 15字符 | 字号从32px调整为24px |
  127 +| 表格列多 | > 6列 | 字号从13/12px调整为11/10px |
  128 +| 文本很长 | > 200字符 | 行高从1.6增加到1.8 |
  129 +
  130 +## 测试
  131 +
  132 +运行测试脚本验证所有功能:
  133 +
  134 +```bash
  135 +# 设置环境变量
  136 +export DYLD_LIBRARY_PATH=/opt/homebrew/lib:$DYLD_LIBRARY_PATH
  137 +
  138 +# 运行测试
  139 +python test_pdf_optimized.py
  140 +```
  141 +
  142 +测试将生成:
  143 +- `test_pdf_optimized.pdf` - 启用优化的PDF
  144 +- `test_pdf_default.pdf` - 默认设置的PDF(对比)
  145 +- `test_layout_config.json` - 布局配置
  146 +- `logs/pdf_layouts/` - 优化日志
  147 +
  148 +## 优化日志格式
  149 +
  150 +```json
  151 +{
  152 + "timestamp": "2024-11-18T19:41:10.983000",
  153 + "document_stats": {
  154 + "kpi_count": 10,
  155 + "table_count": 2,
  156 + "chart_count": 2,
  157 + "max_kpi_value_length": 14,
  158 + "max_table_columns": 8
  159 + },
  160 + "optimizations": [
  161 + "KPI数值过长(14字符),字号从32调整为28",
  162 + "KPI卡片较多(10个),每行列数从2调整为3",
  163 + "表格列数较多(8列),缩小字号和内边距"
  164 + ],
  165 + "final_config": {
  166 + "page": {...},
  167 + "kpi_card": {...},
  168 + "table": {...}
  169 + }
  170 +}
  171 +```
  172 +
  173 +## 故障排除
  174 +
  175 +### 问题1:WeasyPrint库加载失败
  176 +
  177 +**症状**
  178 +```
  179 +OSError: cannot load library 'libpango-1.0-0'
  180 +```
  181 +
  182 +**解决方案**
  183 +```bash
  184 +# macOS
  185 +export DYLD_LIBRARY_PATH=/opt/homebrew/lib:$DYLD_LIBRARY_PATH
  186 +
  187 +# 或在脚本中设置
  188 +import os
  189 +os.environ['DYLD_LIBRARY_PATH'] = '/opt/homebrew/lib'
  190 +```
  191 +
  192 +### 问题2:字体文件缺失
  193 +
  194 +**症状**
  195 +```
  196 +FileNotFoundError: 未找到字体文件
  197 +```
  198 +
  199 +**解决方案**
  200 +确保以下字体文件存在:
  201 +- `ReportEngine/renderers/assets/fonts/SourceHanSerifSC-Medium.otf`
  202 +
  203 +### 问题3:PDF布局仍有问题
  204 +
  205 +**解决方案**
  206 +1. 检查优化日志:`logs/pdf_layouts/`
  207 +2. 查看应用了哪些优化策略
  208 +3. 如需自定义,修改配置参数
  209 +4. 禁用优化对比:`optimize_layout=False`
  210 +
  211 +## 性能优化建议
  212 +
  213 +1. **首次导出**:需要加载字体文件,可能需要几秒钟
  214 +2. **字体子集化**:对于大型报告,考虑使用字体子集以减小文件大小
  215 +3. **图表处理**:图表会自动转换为表格,提高PDF渲染速度
  216 +4. **批量导出**:复用同一个PDFRenderer实例可以提高效率
  217 +
  218 +## 架构说明
  219 +
  220 +```
  221 +┌─────────────────────────────────────────┐
  222 +│ Web UI / API │
  223 +│ (用户点击"下载PDF"按钮) │
  224 +└──────────────┬──────────────────────────┘
  225 +
  226 +
  227 +┌─────────────────────────────────────────┐
  228 +│ Flask API Endpoint │
  229 +│ /api/report/export/pdf/:task_id │
  230 +└──────────────┬──────────────────────────┘
  231 +
  232 +
  233 +┌─────────────────────────────────────────┐
  234 +│ PDFLayoutOptimizer │
  235 +│ • 分析文档结构 │
  236 +│ • 智能调整布局参数 │
  237 +│ • 保存优化日志 │
  238 +└──────────────┬──────────────────────────┘
  239 +
  240 +
  241 +┌─────────────────────────────────────────┐
  242 +│ HTMLRenderer │
  243 +│ • 将IR转换为HTML │
  244 +└──────────────┬──────────────────────────┘
  245 +
  246 +
  247 +┌─────────────────────────────────────────┐
  248 +│ PDFRenderer │
  249 +│ • 注入优化的CSS │
  250 +│ • 嵌入字体 │
  251 +│ • 使用WeasyPrint生成PDF │
  252 +└──────────────┬──────────────────────────┘
  253 +
  254 +
  255 +┌─────────────────────────────────────────┐
  256 +│ 优化的PDF文件 │
  257 +│ • 无溢出 │
  258 +│ • 布局美观 │
  259 +│ • 自动分页 │
  260 +└─────────────────────────────────────────┘
  261 +```
  262 +
  263 +## 更新日志
  264 +
  265 +### v1.0.0 (2024-11-18)
  266 +
  267 +**新增功能**
  268 +- ✅ PDF布局智能优化器
  269 +- ✅ 自动调整字号、行间距、网格列数
  270 +- ✅ 配置持久化系统
  271 +- ✅ Flask API集成
  272 +- ✅ 前端一键导出
  273 +
  274 +**优化措施**
  275 +- ✅ KPI卡片防溢出
  276 +- ✅ 表格自适应布局
  277 +- ✅ 长文本行高优化
  278 +- ✅ 标题防孤行
  279 +- ✅ 图表转表格渲染
  280 +
  281 +**测试覆盖**
  282 +- ✅ 多种KPI场景测试
  283 +- ✅ 复杂表格测试
  284 +- ✅ 图表渲染测试
  285 +- ✅ 长文本测试
  286 +
  287 +## 未来计划
  288 +
  289 +- [ ] 支持更多纸张尺寸(A3、Letter等)
  290 +- [ ] 添加PDF水印功能
  291 +- [ ] 支持页眉页脚自定义
  292 +- [ ] 提供更多布局模板
  293 +- [ ] 优化大型文档渲染性能
  294 +
  295 +## 技术栈
  296 +
  297 +- **PDF生成**:WeasyPrint
  298 +- **布局优化**:自研PDFLayoutOptimizer
  299 +- **字体**:思源宋体(SourceHanSerifSC)
  300 +- **后端框架**:Flask
  301 +- **前端**:原生JavaScript
  302 +
  303 +## 贡献者
  304 +
  305 +欢迎提交Issue和PR来改进PDF导出系统!
  306 +
  307 +## 许可证
  308 +
  309 +本项目遵循项目主仓库的许可证。
  1 +# PDF导出功能快速启动
  2 +
  3 +## 立即开始
  4 +
  5 +### 1. 启动系统
  6 +
  7 +```bash
  8 +# 设置环境变量(macOS必需)
  9 +export DYLD_LIBRARY_PATH=/opt/homebrew/lib:$DYLD_LIBRARY_PATH
  10 +
  11 +# 启动Flask应用
  12 +python app.py
  13 +```
  14 +
  15 +### 2. 生成报告
  16 +
  17 +1. 在浏览器中打开 `http://localhost:5000`
  18 +2. 启动 Insight、Media、Query Engine
  19 +3. 输入搜索主题,点击搜索
  20 +4. 切换到 Report Engine 标签
  21 +5. 点击"生成最终报告"
  22 +
  23 +### 3. 导出PDF
  24 +
  25 +报告生成完成后:
  26 +1. 点击"**下载PDF**"按钮
  27 +2. 系统自动:
  28 + - 分析报告内容
  29 + - 优化布局参数
  30 + - 生成高质量PDF
  31 + - 自动下载文件
  32 +
  33 +## 快速测试
  34 +
  35 +想立即看到效果?运行测试脚本:
  36 +
  37 +```bash
  38 +# 设置环境变量
  39 +export DYLD_LIBRARY_PATH=/opt/homebrew/lib:$DYLD_LIBRARY_PATH
  40 +
  41 +# 运行测试(生成示例PDF)
  42 +python test_pdf_optimized.py
  43 +
  44 +# 查看结果
  45 +open test_pdf_optimized.pdf
  46 +```
  47 +
  48 +测试会生成:
  49 +- ✅ 包含10个KPI卡片的报告
  50 +- ✅ 复杂的8列表格
  51 +- ✅ 多个图表和色块
  52 +- ✅ 自动优化的布局
  53 +
  54 +## 优化效果对比
  55 +
  56 +系统会自动:
  57 +
  58 +| 问题 | 优化前 | 优化后 |
  59 +|------|--------|--------|
  60 +| KPI数值溢出 | ⚠️ 字号固定32px,长数值溢出 | ✅ 自动缩小到28px或24px |
  61 +| KPI布局拥挤 | ⚠️ 固定2列,10个卡片显得拥挤 | ✅ 自动调整为3列 |
  62 +| 表格字体过大 | ⚠️ 8列表格字体过大 | ✅ 字号从13/12px缩小到11/10px |
  63 +| 长文本难读 | ⚠️ 行高固定1.6 | ✅ 自动增加到1.8 |
  64 +
  65 +## 查看优化日志
  66 +
  67 +想了解系统做了哪些优化?
  68 +
  69 +```bash
  70 +# 查看最新的优化日志
  71 +cat logs/pdf_layouts/layout_*.json
  72 +
  73 +# 或打开保存的配置文件
  74 +cat test_layout_config.json
  75 +```
  76 +
  77 +日志示例:
  78 +```json
  79 +{
  80 + "optimizations": [
  81 + "KPI数值过长(14字符),字号从32调整为28",
  82 + "KPI卡片较多(10个),每行列数从2调整为3",
  83 + "表格列数较多(8列),缩小字号和内边距"
  84 + ]
  85 +}
  86 +```
  87 +
  88 +## 常见问题
  89 +
  90 +### Q: 为什么PDF生成需要几秒钟?
  91 +A: 首次生成需要加载字体文件和分析文档,后续会更快。
  92 +
  93 +### Q: 可以禁用自动优化吗?
  94 +A: 可以,在API中设置 `optimize=false`
  95 +```bash
  96 +curl "http://localhost:5000/api/report/export/pdf/TASK_ID?optimize=false"
  97 +```
  98 +
  99 +### Q: 如何自定义布局参数?
  100 +A: 参考 [PDF_EXPORT_GUIDE.md](PDF_EXPORT_GUIDE.md) 中的"配置选项"章节。
  101 +
  102 +## 技术亮点
  103 +
  104 +**智能布局分析**
  105 +- 自动检测KPI数量、表格复杂度、文本长度
  106 +- 根据内容特征动态调整参数
  107 +
  108 +**无损质量**
  109 +- 使用WeasyPrint专业PDF引擎
  110 +- 完整保留CSS样式
  111 +- 完美支持中文字体
  112 +
  113 +**开箱即用**
  114 +- 前端一键导出
  115 +- 无需额外配置
  116 +- 自动应用最佳实践
  117 +
  118 +## 下一步
  119 +
  120 +- 📖 阅读完整文档:[PDF_EXPORT_GUIDE.md](PDF_EXPORT_GUIDE.md)
  121 +- 🧪 运行测试:`python test_pdf_optimized.py`
  122 +- 🎨 自定义布局:修改配置参数
  123 +- 🚀 集成到生产:通过API批量导出
  124 +
  125 +## 问题反馈
  126 +
  127 +遇到问题?
  128 +1. 查看 [PDF_EXPORT_GUIDE.md](PDF_EXPORT_GUIDE.md) 的"故障排除"章节
  129 +2. 检查 `logs/pdf_layouts/` 目录的优化日志
  130 +3. 提交Issue到项目仓库
  131 +
  132 +---
  133 +
  134 +享受全新的PDF导出体验! 🎉
  1 +# Python PDF 导出 - 使用指南
  2 +
  3 +## ✅ 解决方案说明
  4 +
  5 +已将PDF导出从浏览器端(jsPDF)改为**Python直接生成**,使用WeasyPrint库,完美解决中文乱码问题。
  6 +
  7 +### 优势
  8 +-**无乱码**:使用思源宋体(SourceHanSerifSC),完美显示所有中文字符
  9 +-**样式保留**:100%保留HTML的所有CSS样式
  10 +-**自动优化**:自动处理分页、布局、图表转表格
  11 +-**高质量**:生成的PDF可直接用于打印和分发
  12 +
  13 +## 📦 依赖安装
  14 +
  15 +### 1. 安装系统依赖(已完成)
  16 +```bash
  17 +brew install pango cairo gdk-pixbuf
  18 +```
  19 +
  20 +### 2. 安装Python库(已完成)
  21 +```bash
  22 +pip3 install weasyprint
  23 +```
  24 +
  25 +## 🚀 使用方法
  26 +
  27 +### 方法一:直接使用Python(推荐)
  28 +
  29 +```bash
  30 +# 设置环境变量
  31 +export DYLD_LIBRARY_PATH=/opt/homebrew/lib:$DYLD_LIBRARY_PATH
  32 +
  33 +# 运行导出
  34 +python3 ReportEngine/scripts/export_to_pdf.py final_reports/ir/report_ir_xxx.json
  35 +
  36 +# 或从项目根目录运行
  37 +python3 -m ReportEngine.scripts.export_to_pdf final_reports/ir/report_ir_xxx.json
  38 +```
  39 +
  40 +### 方法二:使用便捷脚本(如果有的话)
  41 +
  42 +```bash
  43 +# 基本用法(自动生成同名PDF)
  44 +./pdf_export.sh final_reports/ir/report_ir_xxx.json
  45 +
  46 +# 指定输出路径
  47 +./pdf_export.sh final_reports/ir/report_ir_xxx.json my_report.pdf
  48 +```
  49 +
  50 +### 方法三:在代码中使用
  51 +
  52 +```python
  53 +from ReportEngine.renderers import PDFRenderer
  54 +import json
  55 +
  56 +# 读取报告数据
  57 +with open("report_ir.json", "r") as f:
  58 + document_ir = json.load(f)
  59 +
  60 +# 生成PDF
  61 +renderer = PDFRenderer()
  62 +renderer.render_to_pdf(document_ir, "output.pdf")
  63 +```
  64 +
  65 +## 📊 测试样例
  66 +
  67 +已生成两个测试PDF:
  68 +
  69 +1. **综合样式测试** ([test_comprehensive.pdf](test_comprehensive.pdf))
  70 + - 包含所有样式元素
  71 + - 字体、标点、列表、表格、KPI卡片等
  72 +
  73 +2. **真实报告** ([report_土木工程_python.pdf](report_土木工程_python.pdf))
  74 + - 使用真实的土木工程报告数据
  75 + - 完整展示实际使用效果
  76 +
  77 +## ✨ 特性说明
  78 +
  79 +### 1. 字体支持
  80 +- 优先使用:`SourceHanSerifSC-Medium.otf`(24MB完整版)
  81 +- 备选方案:`SourceHanSerifSC-Medium-Subset.ttf`(3.7MB子集版)
  82 +- 覆盖:所有常用汉字、标点符号、数字、英文
  83 +
  84 +### 2. 样式保留
  85 +- 响应式布局 → PDF优化布局
  86 +- 交互按钮 → 自动隐藏
  87 +- Chart.js图表 → 自动显示fallback表格
  88 +- 所有CSS样式完整保留
  89 +
  90 +### 3. 分页优化
  91 +- 标题不孤立(避免标题单独在页末)
  92 +- 表格和卡片避免跨页断裂
  93 +- 引用块和callout保持完整
  94 +
  95 +## 🔧 故障排除
  96 +
  97 +### 问题1:找不到libpango库
  98 +
  99 +**症状**
  100 +```
  101 +OSError: cannot load library 'libpango-1.0-0'
  102 +```
  103 +
  104 +**解决**
  105 +```bash
  106 +# 使用提供的pdf_export.sh脚本(已自动设置环境变量)
  107 +./pdf_export.sh <your_file.json>
  108 +
  109 +# 或手动设置环境变量
  110 +export DYLD_LIBRARY_PATH=/opt/homebrew/lib:$DYLD_LIBRARY_PATH
  111 +```
  112 +
  113 +### 问题2:字体文件缺失
  114 +
  115 +**症状**
  116 +```
  117 +FileNotFoundError: 未找到字体文件
  118 +```
  119 +
  120 +**解决**
  121 +确保以下任一字体文件存在:
  122 +- `ReportEngine/renderers/assets/fonts/SourceHanSerifSC-Medium.otf`
  123 +- `ReportEngine/renderers/assets/fonts/SourceHanSerifSC-Medium-Subset.ttf`
  124 +
  125 +### 问题3:PDF仍然有乱码
  126 +
  127 +**解决**
  128 +1. 检查字体文件是否完整(应该是24MB或3.7MB)
  129 +2. 使用pdftotext验证:`pdftotext output.pdf - | head`
  130 +3. 如有问题,重新生成字体子集或使用完整版
  131 +
  132 +## 📝 开发说明
  133 +
  134 +### 核心文件
  135 +
  136 +- [PDFRenderer](../renderers/pdf_renderer.py) - PDF渲染器主类
  137 +- [HTMLRenderer](../renderers/html_renderer.py) - HTML渲染器(被PDF渲染器使用)
  138 +- [export_to_pdf.py](../scripts/export_to_pdf.py) - 命令行工具
  139 +- [pdf_export.sh](../../pdf_export.sh) - 便捷启动脚本(如果有的话)
  140 +
  141 +### 工作流程
  142 +
  143 +```
  144 +Document IR (JSON)
  145 +
  146 +HTMLRenderer.render()
  147 +
  148 +HTML with embedded font (base64)
  149 +
  150 +WeasyPrint
  151 +
  152 +PDF (with SourceHanSerif font)
  153 +```
  154 +
  155 +## 🎯 下一步
  156 +
  157 +如需集成到Web应用:
  158 +
  159 +1. **Flask/FastAPI后端**
  160 + ```python
  161 + from flask import send_file
  162 + from ReportEngine.renderers import PDFRenderer
  163 +
  164 + @app.route('/export_pdf')
  165 + def export_pdf():
  166 + renderer = PDFRenderer()
  167 + pdf_bytes = renderer.render_to_bytes(document_ir)
  168 + return send_file(io.BytesIO(pdf_bytes), mimetype='application/pdf')
  169 + ```
  170 +
  171 +2. **前端按钮**
  172 + ```javascript
  173 + document.getElementById('export-btn').addEventListener('click', () => {
  174 + window.open('/export_pdf', '_blank');
  175 + });
  176 + ```
  177 +
  178 +---
  179 +
  180 +**生成时间**: 2025-11-18
  181 +**版本**: 1.0
  182 +**状态**: ✅ 已测试,无乱码