diff --git a/core/admin.py b/core/admin.py
index 6b615da..da9e09b 100644
--- a/core/admin.py
+++ b/core/admin.py
@@ -6,6 +6,8 @@ from .models import (
Status,
PlanType,
FamilyMember,
+ SummaryCategory,
+ Summary,
ReadingRecord,
InsightRecord,
FamilyTask,
@@ -14,6 +16,19 @@ from .models import (
)
+@admin.register(SummaryCategory)
+class SummaryCategoryAdmin(admin.ModelAdmin):
+ list_display = ('name', 'created_at', 'updated_at')
+ search_fields = ('name',)
+
+
+@admin.register(Summary)
+class SummaryAdmin(admin.ModelAdmin):
+ list_display = ('date', 'category', 'speaker', 'source', 'created_at')
+ list_filter = ('date', 'category', 'speaker')
+ search_fields = ('content', 'source')
+
+
@admin.register(FamilyMember)
class FamilyMemberAdmin(admin.ModelAdmin):
list_display = ('name', 'created_at', 'updated_at')
diff --git a/core/forms.py b/core/forms.py
index dae4164..66e9639 100644
--- a/core/forms.py
+++ b/core/forms.py
@@ -4,6 +4,7 @@ from django.utils import timezone
from .models import (
ReadingRecord,
InsightRecord,
+ Summary,
FamilyTask,
TodayPlan,
SystemConfig,
@@ -35,6 +36,20 @@ class InsightRecordForm(forms.ModelForm):
'file': forms.FileInput(attrs={'class': 'form-control'}),
}
+class SummaryForm(forms.ModelForm):
+ """汇总记录表单"""
+ class Meta:
+ model = Summary
+ fields = ['date', 'category', 'speaker', 'content', 'source', 'file']
+ widgets = {
+ 'date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
+ 'category': forms.Select(attrs={'class': 'form-select'}),
+ 'speaker': forms.Select(attrs={'class': 'form-select'}),
+ 'content': forms.Textarea(attrs={'class': 'form-control', 'rows': 5, 'placeholder': '请输入汇总内容'}),
+ 'source': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '请输入来源'}),
+ 'file': forms.FileInput(attrs={'class': 'form-control'}),
+ }
+
class FamilyTaskForm(forms.ModelForm):
"""家庭事项表单"""
class Meta:
diff --git a/core/migrations/0006_add_summary.py b/core/migrations/0006_add_summary.py
new file mode 100644
index 0000000..dc97c97
--- /dev/null
+++ b/core/migrations/0006_add_summary.py
@@ -0,0 +1,47 @@
+# Generated by Django 5.1.4 on 2026-01-23 15:06
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('core', '0005_add_speaker_fields'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='SummaryCategory',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=20, unique=True, verbose_name='名称')),
+ ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
+ ('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
+ ],
+ options={
+ 'verbose_name': '汇总分类',
+ 'verbose_name_plural': '汇总分类',
+ 'ordering': ['name'],
+ },
+ ),
+ migrations.CreateModel(
+ name='Summary',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('date', models.DateField(default=django.utils.timezone.now, verbose_name='日期')),
+ ('content', models.TextField(verbose_name='内容')),
+ ('source', models.CharField(max_length=200, blank=True, null=True, verbose_name='来源')),
+ ('file', models.FileField(blank=True, null=True, upload_to='summary_files/', verbose_name='上传文件')),
+ ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
+ ('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
+ ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.summarycategory', verbose_name='分类')),
+ ('speaker', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.familymember', verbose_name='发言人')),
+ ],
+ options={
+ 'verbose_name': '汇总记录',
+ 'verbose_name_plural': '汇总记录',
+ 'ordering': ['-date', '-created_at'],
+ },
+ ),
+ ]
diff --git a/core/models.py b/core/models.py
index f6577b5..914b283 100644
--- a/core/models.py
+++ b/core/models.py
@@ -159,6 +159,39 @@ class TodayPlan(models.Model):
def __str__(self):
return f"{self.date} - {self.content[:20]}..."
+class SummaryCategory(models.Model):
+ """汇总分类"""
+ name = models.CharField(max_length=20, unique=True, verbose_name="名称")
+ created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
+ updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
+
+ class Meta:
+ verbose_name = "汇总分类"
+ verbose_name_plural = "汇总分类"
+ ordering = ['name']
+
+ def __str__(self):
+ return self.name
+
+class Summary(models.Model):
+ """汇总记录表"""
+ date = models.DateField(default=timezone.now, verbose_name="日期")
+ category = models.ForeignKey(SummaryCategory, on_delete=models.CASCADE, verbose_name="分类")
+ speaker = models.ForeignKey(FamilyMember, on_delete=models.CASCADE, verbose_name="发言人")
+ content = models.TextField(verbose_name="内容")
+ source = models.CharField(max_length=200, blank=True, null=True, verbose_name="来源")
+ file = models.FileField(upload_to='summary_files/', blank=True, null=True, verbose_name="上传文件")
+ created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
+ updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
+
+ class Meta:
+ verbose_name = "汇总记录"
+ verbose_name_plural = "汇总记录"
+ ordering = ['-date', '-created_at']
+
+ def __str__(self):
+ return f"{self.category.name} - {self.date}"
+
class SystemConfig(models.Model):
"""系统配置表"""
smtp_server = models.CharField(max_length=100, blank=True, null=True, verbose_name="SMTP服务器")
diff --git a/core/templates/core/report.html b/core/templates/core/report.html
index 7e62d3d..84cbc06 100644
--- a/core/templates/core/report.html
+++ b/core/templates/core/report.html
@@ -201,4 +201,36 @@
+
+
+
+
+
+ {% if yesterday_summary %}
+
+ {% for summary in yesterday_summary %}
+
+
+
+
+
{{ summary.content }}
+ {% if summary.source %}
+
来源:{{ summary.source }}
+ {% endif %}
+
+
+
+ {% endfor %}
+
+ {% else %}
+
昨日没有汇总记录
+ {% endif %}
+
+
+
{% endblock %}
\ No newline at end of file
diff --git a/core/templates/core/report_pdf.html b/core/templates/core/report_pdf.html
index 85f9a08..f647486 100644
--- a/core/templates/core/report_pdf.html
+++ b/core/templates/core/report_pdf.html
@@ -141,6 +141,35 @@
{% endif %}
+
+
+
昨日汇总记录
+ {% if yesterday_summary %}
+
+
+
+ | 分类 |
+ 发言人 |
+ 内容 |
+ 来源 |
+
+
+
+ {% for summary in yesterday_summary %}
+
+ | {{ summary.category.name }} |
+ {{ summary.speaker.name }} |
+ {{ summary.content }} |
+ {{ summary.source|default:"-" }} |
+
+ {% endfor %}
+
+
+ {% else %}
+
昨日没有汇总记录
+ {% endif %}
+
+
今日计划
diff --git a/core/views.py b/core/views.py
index 148e1cb..2c9da08 100644
--- a/core/views.py
+++ b/core/views.py
@@ -37,14 +37,17 @@ def is_weasyprint_available():
from .models import (
ReadingRecord,
InsightRecord,
+ Summary,
FamilyTask,
TodayPlan,
SystemConfig,
- FamilyMember
+ FamilyMember,
+ SummaryCategory
)
from .forms import (
ReadingRecordForm,
InsightRecordForm,
+ SummaryForm,
FamilyTaskForm,
TodayPlanForm,
SystemConfigForm
@@ -304,6 +307,69 @@ def delete_today_insight(request, pk):
context = {'insight': insight}
return render(request, 'core/delete_insight.html', context)
+# 汇总记录视图
+def summaries(request):
+ """汇总记录"""
+ logger.info("用户访问汇总记录页面")
+ today = timezone.now().date()
+ yesterday = today - timedelta(days=1)
+
+ summary_records = Summary.objects.filter(date=yesterday)
+
+ context = {
+ 'yesterday': yesterday,
+ 'summary_records': summary_records,
+ }
+
+ return render(request, 'core/summaries.html', context)
+
+# 添加汇总记录
+def add_summary(request):
+ """添加汇总记录"""
+ family_members = FamilyMember.objects.all()
+ categories = SummaryCategory.objects.all()
+ if request.method == 'POST':
+ form = SummaryForm(request.POST, request.FILES)
+ if form.is_valid():
+ form.save()
+ logger.info(f"添加汇总记录: {form.cleaned_data['content'][:20]}...")
+ return redirect('summaries')
+ else:
+ form = SummaryForm()
+
+ context = {'form': form, 'family_members': family_members, 'categories': categories}
+ return render(request, 'core/add_summary.html', context)
+
+# 编辑汇总记录
+def edit_summary(request, pk):
+ """编辑汇总记录"""
+ summary = get_object_or_404(Summary, pk=pk)
+ family_members = FamilyMember.objects.all()
+ categories = SummaryCategory.objects.all()
+ if request.method == 'POST':
+ form = SummaryForm(request.POST, request.FILES, instance=summary)
+ if form.is_valid():
+ form.save()
+ logger.info(f"编辑汇总记录: {form.cleaned_data['content'][:20]}...")
+ return redirect('summaries')
+ else:
+ form = SummaryForm(instance=summary)
+
+ context = {'form': form, 'summary': summary, 'family_members': family_members, 'categories': categories}
+ return render(request, 'core/edit_summary.html', context)
+
+# 删除汇总记录
+def delete_summary(request, pk):
+ """删除汇总记录"""
+ summary = get_object_or_404(Summary, pk=pk)
+ if request.method == 'POST':
+ summary.delete()
+ logger.info(f"删除汇总记录: {summary.content[:20]}...")
+ return redirect('summaries')
+
+ context = {'summary': summary}
+ return render(request, 'core/delete_summary.html', context)
+
# 家庭事项视图
def family_tasks(request):
"""家庭事项"""
@@ -445,6 +511,7 @@ def generate_report(request):
# 获取昨日记录
yesterday_reading = ReadingRecord.objects.filter(date=yesterday)
yesterday_insight = InsightRecord.objects.filter(date=yesterday)
+ yesterday_summary = Summary.objects.filter(date=yesterday)
# 获取今日计划
today_plan = TodayPlan.objects.filter(date=today)
@@ -478,6 +545,7 @@ def generate_report(request):
'yesterday': yesterday,
'yesterday_reading': yesterday_reading,
'yesterday_insight': yesterday_insight,
+ 'yesterday_summary': yesterday_summary,
'today_plan': today_plan,
'family_task_stats': family_task_stats,
'historical_dates': historical_dates,
@@ -496,6 +564,7 @@ def view_report(request, date):
# 获取指定日期的记录
yesterday_reading = ReadingRecord.objects.filter(date=yesterday)
yesterday_insight = InsightRecord.objects.filter(date=yesterday)
+ yesterday_summary = Summary.objects.filter(date=yesterday)
today_plan = TodayPlan.objects.filter(date=report_date)
# 获取家庭事项统计
@@ -506,6 +575,7 @@ def view_report(request, date):
'yesterday': yesterday,
'yesterday_reading': yesterday_reading,
'yesterday_insight': yesterday_insight,
+ 'yesterday_summary': yesterday_summary,
'today_plan': today_plan,
'family_task_stats': family_task_stats,
}
@@ -528,6 +598,7 @@ def generate_pdf_report(request, date):
# 获取指定日期的记录
yesterday_reading = ReadingRecord.objects.filter(date=yesterday)
yesterday_insight = InsightRecord.objects.filter(date=yesterday)
+ yesterday_summary = Summary.objects.filter(date=yesterday)
today_plan = TodayPlan.objects.filter(date=report_date)
# 获取家庭事项统计
@@ -538,6 +609,7 @@ def generate_pdf_report(request, date):
'yesterday': yesterday,
'yesterday_reading': yesterday_reading,
'yesterday_insight': yesterday_insight,
+ 'yesterday_summary': yesterday_summary,
'today_plan': today_plan,
'family_task_stats': family_task_stats,
}
@@ -579,6 +651,7 @@ def preview_pdf_report(request, date):
# 获取指定日期的记录
yesterday_reading = ReadingRecord.objects.filter(date=yesterday)
yesterday_insight = InsightRecord.objects.filter(date=yesterday)
+ yesterday_summary = Summary.objects.filter(date=yesterday)
today_plan = TodayPlan.objects.filter(date=report_date)
# 获取家庭事项统计
@@ -589,6 +662,7 @@ def preview_pdf_report(request, date):
'yesterday': yesterday,
'yesterday_reading': yesterday_reading,
'yesterday_insight': yesterday_insight,
+ 'yesterday_summary': yesterday_summary,
'today_plan': today_plan,
'family_task_stats': family_task_stats,
}
@@ -641,6 +715,7 @@ def send_email_view(request):
yesterday_reading = ReadingRecord.objects.filter(date=yesterday)
yesterday_insight = InsightRecord.objects.filter(date=yesterday)
+ yesterday_summary = Summary.objects.filter(date=yesterday)
today_plan = TodayPlan.objects.filter(date=report_date)
family_task_stats = FamilyTask.objects.values('type').annotate(count=Count('id'))
@@ -649,6 +724,7 @@ def send_email_view(request):
'yesterday': yesterday,
'yesterday_reading': yesterday_reading,
'yesterday_insight': yesterday_insight,
+ 'yesterday_summary': yesterday_summary,
'today_plan': today_plan,
'family_task_stats': family_task_stats,
}