feat(pdf): 添加PDF文件列表功能并优化报告页面

- 新增PDF文件列表页面,显示服务器上所有历史PDF报告
- 在报告页面添加"更早的"按钮链接到PDF列表
- 将历史PDF链接显示从30天改为7天
- 优化PDF生成错误处理和日志记录
- 更新按钮文字描述为"预览PDF模板"
This commit is contained in:
2026-01-20 21:07:13 +08:00
parent c22c001ee0
commit eee44ad342
5 changed files with 157 additions and 50 deletions

View File

@@ -435,12 +435,27 @@ def generate_report(request):
# 获取家庭事项统计
family_task_stats = FamilyTask.objects.values('type').annotate(count=Count('id'))
# 获取过去30天的日期列表用于生成历史PDF链接
# 获取最近7天的日期列表用于生成历史PDF链接
historical_dates = []
for i in range(1, 31):
for i in range(1, 8):
historical_date = today - timedelta(days=i)
historical_dates.append(historical_date)
# 检查是否有更早的PDF文件
has_earlier_pdfs = False
seven_days_ago = today - timedelta(days=7)
pdf_files = [f for f in os.listdir(settings.REPORTS_ROOT) if f.endswith('.pdf')]
for pdf_file in pdf_files:
try:
# 从文件名中提取日期
date_str = pdf_file.replace('report_', '').replace('.pdf', '')
file_date = datetime.strptime(date_str, '%Y-%m-%d').date()
if file_date < seven_days_ago:
has_earlier_pdfs = True
break
except Exception:
continue
context = {
'today': today,
'yesterday': yesterday,
@@ -449,6 +464,7 @@ def generate_report(request):
'today_plan': today_plan,
'family_task_stats': family_task_stats,
'historical_dates': historical_dates,
'has_earlier_pdfs': has_earlier_pdfs,
}
return render(request, 'core/report.html', context)
@@ -487,47 +503,52 @@ def generate_pdf_report(request, date):
return HttpResponse("PDF功能不可用请检查WeasyPrint库是否正确安装", status=500)
logger.info(f"用户生成PDF报告: {date}")
report_date = datetime.strptime(date, '%Y-%m-%d').date()
yesterday = report_date - timedelta(days=1)
# 获取指定日期的记录
yesterday_reading = ReadingRecord.objects.filter(date=yesterday)
yesterday_insight = InsightRecord.objects.filter(date=yesterday)
today_plan = TodayPlan.objects.filter(date=report_date)
# 获取家庭事项统计
family_task_stats = FamilyTask.objects.values('type').annotate(count=Count('id'))
context = {
'today': report_date,
'yesterday': yesterday,
'yesterday_reading': yesterday_reading,
'yesterday_insight': yesterday_insight,
'today_plan': today_plan,
'family_task_stats': family_task_stats,
}
# 渲染HTML模板
html_string = render(request, 'core/report_pdf.html', context).content.decode('utf-8')
# 生成PDF
pdf_file = f"report_{date}.pdf"
pdf_path = os.path.join(settings.REPORTS_ROOT, pdf_file)
# 确保报告目录存在
os.makedirs(settings.REPORTS_ROOT, exist_ok=True)
# 动态导入WeasyPrint
from weasyprint import HTML
HTML(string=html_string).write_pdf(pdf_path)
logger.info(f"PDF报告生成成功: {pdf_path}")
# 返回PDF文件
with open(pdf_path, 'rb') as f:
response = HttpResponse(f.read(), content_type='application/pdf')
response['Content-Disposition'] = f'attachment; filename="{pdf_file}"'
return response
try:
report_date = datetime.strptime(date, '%Y-%m-%d').date()
yesterday = report_date - timedelta(days=1)
# 获取指定日期的记录
yesterday_reading = ReadingRecord.objects.filter(date=yesterday)
yesterday_insight = InsightRecord.objects.filter(date=yesterday)
today_plan = TodayPlan.objects.filter(date=report_date)
# 获取家庭事项统计
family_task_stats = FamilyTask.objects.values('type').annotate(count=Count('id'))
context = {
'today': report_date,
'yesterday': yesterday,
'yesterday_reading': yesterday_reading,
'yesterday_insight': yesterday_insight,
'today_plan': today_plan,
'family_task_stats': family_task_stats,
}
# 渲染HTML模板
html_string = render(request, 'core/report_pdf.html', context).content.decode('utf-8')
# 生成PDF
pdf_file = f"report_{date}.pdf"
pdf_path = os.path.join(settings.REPORTS_ROOT, pdf_file)
# 确保报告目录存在
os.makedirs(settings.REPORTS_ROOT, exist_ok=True)
# 动态导入WeasyPrint
from weasyprint import HTML
HTML(string=html_string).write_pdf(pdf_path)
logger.info(f"PDF报告生成成功: {pdf_path}")
# 返回PDF文件
with open(pdf_path, 'rb') as f:
response = HttpResponse(f.read(), content_type='application/pdf')
response['Content-Disposition'] = f'attachment; filename="{pdf_file}"'
return response
except Exception as e:
logger.error(f"生成PDF报告失败: {str(e)}")
return HttpResponse(f"生成PDF报告失败: {str(e)}", status=500)
# 系统配置
def system_settings(request):
@@ -625,3 +646,36 @@ def send_email_view(request):
def send_email(request):
"""发送邮件别名"""
return send_email_view(request)
# PDF文件列表
def pdf_list(request):
"""显示服务器上已有的PDF文件列表"""
logger.info("用户访问PDF文件列表页面")
# 获取所有PDF文件
pdf_files = [f for f in os.listdir(settings.REPORTS_ROOT) if f.endswith('.pdf')]
# 解析文件名,提取日期,并按日期降序排序
pdf_info = []
for pdf_file in pdf_files:
try:
# 从文件名中提取日期
date_str = pdf_file.replace('report_', '').replace('.pdf', '')
file_date = datetime.strptime(date_str, '%Y-%m-%d').date()
pdf_info.append({
'filename': pdf_file,
'date': file_date,
'date_str': date_str
})
except Exception as e:
logger.error(f"解析PDF文件名失败: {pdf_file}, 错误: {str(e)}")
continue
# 按日期降序排序
pdf_info.sort(key=lambda x: x['date'], reverse=True)
context = {
'pdf_files': pdf_info
}
return render(request, 'core/pdf_list.html', context)