feat(历史记录): 添加历史记录查询功能及PDF导出
新增历史记录查询页面,支持按时间范围筛选阅读记录、感悟记录、汇总记录、家庭事项和今日计划 添加历史记录PDF导出功能,生成包含所有记录的格式化PDF报告
This commit is contained in:
150
core/history_views.py
Normal file
150
core/history_views.py
Normal file
@@ -0,0 +1,150 @@
|
||||
from django.shortcuts import render
|
||||
from django.http import HttpResponse
|
||||
from django.utils import timezone
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.conf import settings
|
||||
from datetime import datetime, timedelta
|
||||
from loguru import logger
|
||||
import os
|
||||
|
||||
from .models import (
|
||||
ReadingRecord,
|
||||
InsightRecord,
|
||||
Summary,
|
||||
FamilyTask,
|
||||
TodayPlan,
|
||||
)
|
||||
from .views import is_weasyprint_available
|
||||
|
||||
|
||||
@login_required
|
||||
def history_records(request):
|
||||
"""历史记录查询页面"""
|
||||
logger.info("用户访问历史记录查询页面")
|
||||
|
||||
start_date_str = request.GET.get('start_date')
|
||||
end_date_str = request.GET.get('end_date')
|
||||
|
||||
if not start_date_str or not end_date_str:
|
||||
today = timezone.now().date()
|
||||
start_date = datetime(today.year, 1, 1).date()
|
||||
end_date = today
|
||||
else:
|
||||
start_date = datetime.strptime(start_date_str, '%Y-%m-%d').date()
|
||||
end_date = datetime.strptime(end_date_str, '%Y-%m-%d').date()
|
||||
|
||||
# 查询各个类型的记录
|
||||
reading_records = ReadingRecord.objects.filter(
|
||||
date__range=[start_date, end_date]
|
||||
).order_by('-date')
|
||||
|
||||
insight_records = InsightRecord.objects.filter(
|
||||
date__range=[start_date, end_date]
|
||||
).order_by('-date')
|
||||
|
||||
summary_records = Summary.objects.filter(
|
||||
date__range=[start_date, end_date]
|
||||
).order_by('-date')
|
||||
|
||||
family_tasks = FamilyTask.objects.filter(
|
||||
created_at__date__range=[start_date, end_date]
|
||||
).order_by('-created_at')
|
||||
|
||||
today_plans = TodayPlan.objects.filter(
|
||||
date__range=[start_date, end_date]
|
||||
).order_by('-date')
|
||||
|
||||
context = {
|
||||
'start_date': start_date,
|
||||
'end_date': end_date,
|
||||
'reading_records': reading_records,
|
||||
'insight_records': insight_records,
|
||||
'summary_records': summary_records,
|
||||
'family_tasks': family_tasks,
|
||||
'today_plans': today_plans,
|
||||
}
|
||||
|
||||
return render(request, 'core/history_records.html', context)
|
||||
|
||||
|
||||
@login_required
|
||||
def history_pdf(request):
|
||||
"""导出历史记录PDF"""
|
||||
if not is_weasyprint_available():
|
||||
logger.error("WeasyPrint库不可用,无法生成PDF报告")
|
||||
return HttpResponse("PDF功能不可用,请检查WeasyPrint库是否正确安装", status=500)
|
||||
|
||||
start_date_str = request.GET.get('start_date')
|
||||
end_date_str = request.GET.get('end_date')
|
||||
|
||||
if not start_date_str or not end_date_str:
|
||||
return HttpResponse("请提供开始时间和结束时间", status=400)
|
||||
|
||||
try:
|
||||
start_date = datetime.strptime(start_date_str, '%Y-%m-%d').date()
|
||||
end_date = datetime.strptime(end_date_str, '%Y-%m-%d').date()
|
||||
except ValueError:
|
||||
return HttpResponse("日期格式错误", status=400)
|
||||
|
||||
if start_date > end_date:
|
||||
return HttpResponse("开始时间不能晚于结束时间", status=400)
|
||||
|
||||
logger.info(f"用户导出历史记录PDF: {start_date} 至 {end_date}")
|
||||
|
||||
try:
|
||||
# 查询各个类型的记录
|
||||
reading_records = ReadingRecord.objects.filter(
|
||||
date__range=[start_date, end_date]
|
||||
).order_by('-date')
|
||||
|
||||
insight_records = InsightRecord.objects.filter(
|
||||
date__range=[start_date, end_date]
|
||||
).order_by('-date')
|
||||
|
||||
summary_records = Summary.objects.filter(
|
||||
date__range=[start_date, end_date]
|
||||
).order_by('-date')
|
||||
|
||||
family_tasks = FamilyTask.objects.filter(
|
||||
created_at__date__range=[start_date, end_date]
|
||||
).order_by('-created_at')
|
||||
|
||||
today_plans = TodayPlan.objects.filter(
|
||||
date__range=[start_date, end_date]
|
||||
).order_by('-date')
|
||||
|
||||
context = {
|
||||
'start_date': start_date,
|
||||
'end_date': end_date,
|
||||
'reading_records': reading_records,
|
||||
'insight_records': insight_records,
|
||||
'summary_records': summary_records,
|
||||
'family_tasks': family_tasks,
|
||||
'today_plans': today_plans,
|
||||
}
|
||||
|
||||
# 渲染HTML模板
|
||||
html_string = render(request, 'core/history_pdf.html', context).content.decode('utf-8')
|
||||
|
||||
# 生成PDF
|
||||
pdf_file = f"history_{start_date_str}_to_{end_date_str}.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)
|
||||
Reference in New Issue
Block a user