feat(家庭事项): 按到期时间分类显示,一个月内显示详情,超过一个月显示数量

- 修改视图逻辑,将未完成事项分为即将到期(一个月内)和远期事项
- 即将到期的事项显示完整详情表格
- 超过一个月的远期事项只显示数量,不显示详情
- 支持显示已过期的事项(红色标记)
- 合并远程更新
This commit is contained in:
2026-03-16 18:27:52 +08:00
11 changed files with 466 additions and 15 deletions

View File

@@ -2,7 +2,7 @@ from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse, JsonResponse
from django.utils import timezone
from django.db import models
from django.db.models import Count
from django.db.models import Count, Q
from django.core.mail import send_mail, EmailMessage
from django.conf import settings
from django.views.decorators.csrf import csrf_exempt
@@ -48,7 +48,9 @@ from .models import (
TodayPlan,
SystemConfig,
FamilyMember,
SummaryCategory
SummaryCategory,
PublicContentType,
PublicContent
)
from .forms import (
ReadingRecordForm,
@@ -56,7 +58,8 @@ from .forms import (
SummaryForm,
FamilyTaskForm,
TodayPlanForm,
SystemConfigForm
SystemConfigForm,
PublicContentForm
)
# 首页视图
@@ -75,8 +78,10 @@ def index(request):
today_plan = TodayPlan.objects.filter(date=today)
# 获取未完成的家庭事项(排除已完成状态)
# 获取未完成的家庭事项(排除已完成状态和已截止的事项
pending_family_tasks = FamilyTask.objects.exclude(status__name='completed')
# 过滤掉截止日期早于今天的事项(如果设置了截止日期)
pending_family_tasks = pending_family_tasks.filter(Q(deadline__gte=today) | Q(deadline__isnull=True))
context = {
'yesterday': yesterday,
@@ -400,30 +405,30 @@ def delete_summary(request, pk):
def family_tasks(request):
"""家庭事项 - 显示未完成的事项,一个月内显示详情,超过一个月显示数量"""
logger.info("用户访问家庭事项页面")
today = timezone.now().date()
one_month_later = today + timedelta(days=30)
# 获取所有未完成的事项
# 获取所有未完成的事项(排除已完成状态)
all_pending_tasks = FamilyTask.objects.exclude(status__name='completed')
# 一个月内到期的事项(显示详情)
# 包括:有截止日期且在一个月内,或者没有截止日期的事项
upcoming_tasks = all_pending_tasks.filter(
models.Q(deadline__isnull=True) | models.Q(deadline__lte=one_month_later)
Q(deadline__isnull=True) | Q(deadline__lte=one_month_later)
)
# 超过一个月到期的事项(只显示数量)
future_tasks = all_pending_tasks.filter(deadline__gt=one_month_later)
future_tasks_count = future_tasks.count()
context = {
'upcoming_tasks': upcoming_tasks,
'future_tasks_count': future_tasks_count,
'total_pending_count': all_pending_tasks.count(),
'today': today,
}
return render(request, 'core/family_tasks.html', context)
# 添加家庭事项
@@ -969,3 +974,70 @@ def user_logout(request):
messages.success(request, '已成功注销!')
return redirect('login')
# 公开内容视图
def public_content(request):
"""公开内容页面 - 无需登录"""
logger.info("用户访问公开内容页面")
# 获取所有已发布的公开内容
public_contents = PublicContent.objects.filter(is_published=True)
# 按类型分组
content_by_type = {}
for content in public_contents:
type_name = content.type.name
if type_name not in content_by_type:
content_by_type[type_name] = []
content_by_type[type_name].append(content)
context = {
'content_by_type': content_by_type,
}
return render(request, 'core/public_content.html', context)
# 添加公开内容
@login_required
def add_public_content(request):
"""添加公开内容"""
if request.method == 'POST':
form = PublicContentForm(request.POST, request.FILES)
if form.is_valid():
form.save()
logger.info(f"添加公开内容: {form.cleaned_data['title']}")
return redirect('public_content')
else:
form = PublicContentForm()
context = {'form': form}
return render(request, 'core/add_public_content.html', context)
# 编辑公开内容
@login_required
def edit_public_content(request, pk):
"""编辑公开内容"""
content = get_object_or_404(PublicContent, pk=pk)
if request.method == 'POST':
form = PublicContentForm(request.POST, request.FILES, instance=content)
if form.is_valid():
form.save()
logger.info(f"编辑公开内容: {form.cleaned_data['title']}")
return redirect('public_content')
else:
form = PublicContentForm(instance=content)
context = {'form': form, 'content': content}
return render(request, 'core/edit_public_content.html', context)
# 删除公开内容
@login_required
def delete_public_content(request, pk):
"""删除公开内容"""
content = get_object_or_404(PublicContent, pk=pk)
if request.method == 'POST':
content.delete()
logger.info(f"删除公开内容: {content.title}")
return redirect('public_content')
context = {'content': content}
return render(request, 'core/delete_public_content.html', context)