regenerate_latest_pdf.py
4.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
"""
使用新的SVG矢量图表功能重新生成最新报告的PDF
"""
import json
import sys
from pathlib import Path
from datetime import datetime
from loguru import logger
# 添加项目路径
sys.path.insert(0, str(Path(__file__).parent))
from ReportEngine.renderers import PDFRenderer
def find_latest_report():
"""找到最新的报告IR文件"""
ir_dir = Path("final_reports/ir")
if not ir_dir.exists():
logger.error(f"报告目录不存在: {ir_dir}")
return None
# 获取所有JSON文件并按修改时间排序
json_files = sorted(ir_dir.glob("*.json"), key=lambda x: x.stat().st_mtime, reverse=True)
if not json_files:
logger.error("未找到报告文件")
return None
latest_file = json_files[0]
logger.info(f"找到最新报告: {latest_file.name}")
return latest_file
def load_document_ir(file_path):
"""加载Document IR"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
document_ir = json.load(f)
logger.info(f"成功加载报告: {file_path.name}")
# 统计图表数量
chart_count = 0
chapters = document_ir.get('chapters', [])
def count_charts(blocks):
count = 0
for block in blocks:
if isinstance(block, dict):
if block.get('type') == 'widget' and block.get('widgetType', '').startswith('chart.js'):
count += 1
# 递归处理嵌套blocks
nested = block.get('blocks')
if isinstance(nested, list):
count += count_charts(nested)
return count
for chapter in chapters:
blocks = chapter.get('blocks', [])
chart_count += count_charts(blocks)
logger.info(f"报告包含 {len(chapters)} 个章节,{chart_count} 个图表")
return document_ir
except Exception as e:
logger.error(f"加载报告失败: {e}")
return None
def generate_pdf_with_vector_charts(document_ir, output_path):
"""使用SVG矢量图表生成PDF"""
try:
logger.info("=" * 60)
logger.info("开始生成PDF(带矢量图表)")
logger.info("=" * 60)
# 创建PDF渲染器
renderer = PDFRenderer()
# 渲染PDF
result_path = renderer.render_to_pdf(
document_ir,
output_path,
optimize_layout=True
)
logger.info("=" * 60)
logger.info(f"✓ PDF生成成功: {result_path}")
logger.info("=" * 60)
# 显示文件大小
file_size = result_path.stat().st_size
size_mb = file_size / (1024 * 1024)
logger.info(f"文件大小: {size_mb:.2f} MB")
return result_path
except Exception as e:
logger.error(f"生成PDF失败: {e}", exc_info=True)
return None
def main():
"""主函数"""
logger.info("🚀 使用SVG矢量图表重新生成最新报告的PDF")
logger.info("")
# 1. 找到最新报告
latest_report = find_latest_report()
if not latest_report:
logger.error("未找到报告文件")
return 1
# 2. 加载报告数据
document_ir = load_document_ir(latest_report)
if not document_ir:
logger.error("加载报告失败")
return 1
# 3. 生成输出文件名
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
report_name = latest_report.stem.replace("report_ir_", "")
output_filename = f"report_vector_{report_name}_{timestamp}.pdf"
output_path = Path("final_reports/pdf") / output_filename
# 确保输出目录存在
output_path.parent.mkdir(parents=True, exist_ok=True)
logger.info(f"输出路径: {output_path}")
logger.info("")
# 4. 生成PDF
result = generate_pdf_with_vector_charts(document_ir, output_path)
if result:
logger.info("")
logger.info("🎉 PDF生成完成!")
logger.info("")
logger.info("特性说明:")
logger.info(" ✓ 图表以SVG矢量格式渲染")
logger.info(" ✓ 支持无限缩放不失真")
logger.info(" ✓ 保留完整的图表视觉效果")
logger.info(" ✓ 折线图、柱状图、饼图等均为矢量曲线")
logger.info("")
logger.info(f"PDF文件位置: {result.absolute()}")
return 0
else:
logger.error("❌ PDF生成失败")
return 1
if __name__ == "__main__":
sys.exit(main())