diff --git a/core/admin.py b/core/admin.py
index da9e09b..fbd798c 100644
--- a/core/admin.py
+++ b/core/admin.py
@@ -13,6 +13,8 @@ from .models import (
FamilyTask,
TodayPlan,
SystemConfig,
+ PublicContentType,
+ PublicContent,
)
@@ -96,3 +98,17 @@ class TodayPlanAdmin(admin.ModelAdmin):
@admin.register(SystemConfig)
class SystemConfigAdmin(admin.ModelAdmin):
list_display = ('smtp_server', 'smtp_port', 'smtp_username', 'recipient_email', 'send_time', 'created_at')
+
+
+@admin.register(PublicContentType)
+class PublicContentTypeAdmin(admin.ModelAdmin):
+ list_display = ('name', 'created_at', 'updated_at')
+ search_fields = ('name',)
+
+
+@admin.register(PublicContent)
+class PublicContentAdmin(admin.ModelAdmin):
+ list_display = ('title', 'type', 'is_published', 'sort_order', 'created_at')
+ list_filter = ('type', 'is_published')
+ search_fields = ('title', 'content')
+ ordering = ('sort_order', '-created_at')
diff --git a/core/forms.py b/core/forms.py
index 66e9639..66f0914 100644
--- a/core/forms.py
+++ b/core/forms.py
@@ -8,7 +8,8 @@ from .models import (
FamilyTask,
TodayPlan,
SystemConfig,
- FamilyMember
+ FamilyMember,
+ PublicContent
)
class ReadingRecordForm(forms.ModelForm):
@@ -109,4 +110,19 @@ class SystemConfigForm(forms.ModelForm):
if not re.match(email_pattern, recipient_email):
logger.warning(f"收件人邮箱格式不正确: {recipient_email}")
raise forms.ValidationError("请输入有效的邮箱地址,格式如:example@domain.com")
- return recipient_email
\ No newline at end of file
+ return recipient_email
+
+
+class PublicContentForm(forms.ModelForm):
+ """公开内容表单"""
+ class Meta:
+ model = PublicContent
+ fields = ['type', 'title', 'content', 'file', 'url', 'sort_order', 'is_published']
+ widgets = {
+ 'type': forms.Select(attrs={'class': 'form-select'}),
+ 'title': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '请输入标题'}),
+ 'content': forms.Textarea(attrs={'class': 'form-control', 'rows': 5, 'placeholder': '请输入内容'}),
+ 'file': forms.FileInput(attrs={'class': 'form-control'}),
+ 'url': forms.URLInput(attrs={'class': 'form-control', 'placeholder': '请输入链接地址'}),
+ 'sort_order': forms.NumberInput(attrs={'class': 'form-control', 'placeholder': '请输入排序值'}),
+ }
\ No newline at end of file
diff --git a/core/models.py b/core/models.py
index 914b283..3c8d24d 100644
--- a/core/models.py
+++ b/core/models.py
@@ -216,3 +216,37 @@ class SystemConfig(models.Model):
"""获取系统配置,单例模式"""
config, created = cls.objects.get_or_create(pk=1)
return config
+
+class PublicContentType(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 PublicContent(models.Model):
+ """公开内容表"""
+ type = models.ForeignKey(PublicContentType, on_delete=models.CASCADE, verbose_name="类型")
+ title = models.CharField(max_length=200, verbose_name="标题")
+ content = models.TextField(blank=True, null=True, verbose_name="内容")
+ file = models.FileField(upload_to='public_files/', blank=True, null=True, verbose_name="上传文件")
+ url = models.URLField(blank=True, null=True, verbose_name="链接地址")
+ sort_order = models.IntegerField(default=0, verbose_name="排序")
+ is_published = models.BooleanField(default=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 = ['sort_order', '-created_at']
+
+ def __str__(self):
+ return f"{self.type.name} - {self.title}"
diff --git a/core/templates/core/add_public_content.html b/core/templates/core/add_public_content.html
new file mode 100644
index 0000000..88729d2
--- /dev/null
+++ b/core/templates/core/add_public_content.html
@@ -0,0 +1,76 @@
+{% extends 'core/base.html' %}
+
+{% block content %}
+
+
+
+
+{% endblock %}
diff --git a/core/templates/core/base.html b/core/templates/core/base.html
index a5679d7..5a156ba 100644
--- a/core/templates/core/base.html
+++ b/core/templates/core/base.html
@@ -449,6 +449,11 @@
首页
+
+
+ 公开内容
+
+
{% if user.is_authenticated %}
diff --git a/core/templates/core/delete_public_content.html b/core/templates/core/delete_public_content.html
new file mode 100644
index 0000000..9c9337c
--- /dev/null
+++ b/core/templates/core/delete_public_content.html
@@ -0,0 +1,48 @@
+{% extends 'core/base.html' %}
+
+{% block content %}
+
+
+
+ 删除公开内容
+
+
+
+
+
+
+
+
+
您确定要删除以下公开内容吗?
+
+
+ {{ content.get_type_display }}
+
+
{{ content.title }}
+ {% if content.content %}
+
{{ content.content|truncatechars:100 }}
+ {% endif %}
+
+
+
+ 此操作不可撤销!
+
+
+
+
+
+
+{% endblock %}
diff --git a/core/templates/core/edit_public_content.html b/core/templates/core/edit_public_content.html
new file mode 100644
index 0000000..ec53e89
--- /dev/null
+++ b/core/templates/core/edit_public_content.html
@@ -0,0 +1,76 @@
+{% extends 'core/base.html' %}
+
+{% block content %}
+
+
+
+
+{% endblock %}
diff --git a/core/templates/core/public_content.html b/core/templates/core/public_content.html
new file mode 100644
index 0000000..a974d36
--- /dev/null
+++ b/core/templates/core/public_content.html
@@ -0,0 +1,80 @@
+{% extends 'core/base.html' %}
+
+{% block content %}
+
+
+
+ 公开内容
+
+ {% if user.is_authenticated %}
+
+ {% endif %}
+
+
+{% if content_by_type %}
+ {% for type_name, contents in content_by_type.items %}
+
+
+
+
+ {% for content in contents %}
+
+
+
+
+ {% if content.url %}
+
+ {{ content.title }}
+
+ {% else %}
+ {{ content.title }}
+ {% endif %}
+
+ {% if content.content %}
+
{{ content.content|truncatechars:200 }}
+ {% endif %}
+ {% if content.file %}
+
+ 下载文件
+
+ {% endif %}
+
+ {% if user.is_authenticated %}
+
+ {% endif %}
+
+
+ {% endfor %}
+
+
+
+ {% endfor %}
+{% else %}
+
+
+
暂无公开内容
+
请稍后再来查看
+ {% if user.is_authenticated %}
+
+ 添加内容
+
+ {% endif %}
+
+{% endif %}
+{% endblock %}
diff --git a/core/urls.py b/core/urls.py
index a7e193c..4eb95bf 100644
--- a/core/urls.py
+++ b/core/urls.py
@@ -68,4 +68,10 @@ urlpatterns = [
# 历史记录查询
path('history/', history_views.history_records, name='history_records'),
path('history/pdf/', history_views.history_pdf, name='history_pdf'),
+
+ # 公开内容
+ path('public/', views.public_content, name='public_content'),
+ path('public/add/', views.add_public_content, name='add_public_content'),
+ path('public//edit/', views.edit_public_content, name='edit_public_content'),
+ path('public//delete/', views.delete_public_content, name='delete_public_content'),
]
\ No newline at end of file
diff --git a/core/views.py b/core/views.py
index 37b5368..69122bb 100644
--- a/core/views.py
+++ b/core/views.py
@@ -47,7 +47,9 @@ from .models import (
TodayPlan,
SystemConfig,
FamilyMember,
- SummaryCategory
+ SummaryCategory,
+ PublicContentType,
+ PublicContent
)
from .forms import (
ReadingRecordForm,
@@ -55,7 +57,8 @@ from .forms import (
SummaryForm,
FamilyTaskForm,
TodayPlanForm,
- SystemConfigForm
+ SystemConfigForm,
+ PublicContentForm
)
# 首页视图
@@ -955,3 +958,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)