feat(pdf): 添加PDF文件列表功能并优化报告页面
- 新增PDF文件列表页面,显示服务器上所有历史PDF报告 - 在报告页面添加"更早的"按钮链接到PDF列表 - 将历史PDF链接显示从30天改为7天 - 优化PDF生成错误处理和日志记录 - 更新按钮文字描述为"预览PDF模板"
This commit is contained in:
@@ -70,7 +70,7 @@
|
||||
<a href="{% url 'today_records' %}" class="btn btn-outline-primary mb-2">添加今日信息</a>
|
||||
<a href="{% url 'yesterday_records' %}" class="btn btn-outline-primary mb-2">追加昨日信息</a>
|
||||
<a href="{% url 'today_plan' %}" class="btn btn-outline-primary mb-2">管理今日计划</a>
|
||||
<a href="{% url 'generate_report' %}" class="btn btn-outline-primary mb-2">查看今日报告</a>
|
||||
<a href="{% url 'generate_report' %}" class="btn btn-outline-primary mb-2">预览家庭日报PDF模板</a>
|
||||
<a href="{% url 'send_email' %}" class="btn btn-outline-success">发送今日邮件</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
43
core/templates/core/pdf_list.html
Normal file
43
core/templates/core/pdf_list.html
Normal file
@@ -0,0 +1,43 @@
|
||||
{% extends 'core/base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<h2>PDF文件列表</h2>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h5 class="card-title mb-0">服务器上的PDF文件</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if pdf_files %}
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>日期</th>
|
||||
<th>文件名</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for pdf in pdf_files %}
|
||||
<tr>
|
||||
<td>{{ pdf.date }}</td>
|
||||
<td>{{ pdf.filename }}</td>
|
||||
<td>
|
||||
<a href="{% url 'generate_pdf_report' pdf.date_str %}" class="btn btn-primary btn-sm" target="_blank">
|
||||
<i class="bi bi-file-pdf"></i> 查看
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p class="text-muted">服务器上没有PDF文件</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="{% url 'generate_report' %}" class="btn btn-secondary mt-3">
|
||||
<i class="bi bi-arrow-left"></i> 返回报告页面
|
||||
</a>
|
||||
{% endblock %}
|
||||
@@ -4,13 +4,13 @@
|
||||
<h2>家庭日报报告</h2>
|
||||
|
||||
<div class="mb-4">
|
||||
<a href="{% url 'generate_pdf_report' today|date:'Y-m-d' %}" class="btn btn-primary">
|
||||
<i class="bi bi-file-pdf"></i> 生成PDF报告
|
||||
</a>
|
||||
<a href="{% url 'send_email' %}" class="btn btn-success">
|
||||
<i class="bi bi-envelope"></i> 发送邮件
|
||||
</a>
|
||||
</div>
|
||||
<a href="{% url 'generate_pdf_report' today|date:'Y-m-d' %}" class="btn btn-primary" target="_blank">
|
||||
<i class="bi bi-file-pdf"></i> 预览PDF模板
|
||||
</a>
|
||||
<a href="{% url 'send_email' %}" class="btn btn-success">
|
||||
<i class="bi bi-envelope"></i> 发送邮件
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header bg-primary text-white">
|
||||
@@ -182,6 +182,13 @@
|
||||
</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% if has_earlier_pdfs %}
|
||||
<div class="col-md-3 mb-2">
|
||||
<a href="{% url 'pdf_list' %}" class="btn btn-outline-secondary btn-sm btn-block">
|
||||
更早的
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -46,4 +46,7 @@ urlpatterns = [
|
||||
|
||||
# 手动发送邮件
|
||||
path('send-email/', views.send_email, name='send_email'),
|
||||
|
||||
# PDF文件列表
|
||||
path('pdf-list/', views.pdf_list, name='pdf_list'),
|
||||
]
|
||||
138
core/views.py
138
core/views.py
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user