from django.contrib import admin from django.utils.html import format_html from article.models import NoticeReceipt, Notice, Article, Carousel, Section from users.models import User # —————— 板块 —————— @admin.register(Section) class SectionAdmin(admin.ModelAdmin): list_display = ('display_name', 'code', 'parent', 'is_enabled', 'order') list_filter = ('parent', 'enabled') search_fields = ('name', 'code') ordering = ('order', 'name') list_editable = ('order',) fieldsets = ( ('基本信息', { 'fields': ('name', 'code', 'parent', 'enabled', 'order') }), ) def display_name(self, obj): """在列表中显示层级缩进""" if obj.is_sub: return f"  └─ {obj.name}" # 使用全角空格+符号模拟缩进 return obj.name display_name.short_description = '板块名称' display_name.admin_order_field = 'name' def is_enabled(self, obj): return obj.enabled is_enabled.boolean = True is_enabled.short_description = '启用' def formfield_for_foreignkey(self, db_field, request, **kwargs): """限制 parent 只能选择主板块(无父级的板块)""" if db_field.name == "parent": kwargs["queryset"] = Section.objects.filter(parent__isnull=True) return super().formfield_for_foreignkey(db_field, request, **kwargs) def get_queryset(self, request): """优化查询,避免 N+1""" return super().get_queryset(request).select_related('parent') # —————— 轮播图 —————— @admin.register(Carousel) class CarouselAdmin(admin.ModelAdmin): list_display = ('title', 'image_thumb', 'link_url', 'order', 'active') list_editable = ('order', 'active') ordering = ('order',) def image_thumb(self, obj): if obj.image: return format_html('', obj.image.url) return "无图" image_thumb.short_description = "预览" # —————— 文章 —————— @admin.register(Article) class ArticleAdmin(admin.ModelAdmin): list_display = ('title', 'section', 'author', 'is_published', 'created_at') list_filter = ('section', 'is_published', 'created_at') search_fields = ('title', 'content') date_hierarchy = 'created_at' autocomplete_fields = ('author',) # 需要 UserAdmin 支持搜索 fieldsets = ( ('基本信息', {'fields': ('title', 'section', 'cover')}), ('内容', {'fields': ('content',)}), ('发布设置', {'fields': ('is_published',)}), ) # —————— 通知(带签收) —————— @admin.register(Notice) class NoticeAdmin(admin.ModelAdmin): list_display = ( 'title', 'publisher', 'require_sign', 'is_published', 'signed_count', 'total_target_users', 'created_at' ) list_filter = ('require_sign', 'is_published', 'created_at', 'target_departments') search_fields = ('title', 'content') filter_horizontal = ('target_departments',) readonly_fields = ('created_at', 'updated_at', 'publisher') date_hierarchy = 'created_at' fieldsets = ( ('基本信息', { 'fields': ('title', 'content', 'is_published') }), ('签收设置', { 'fields': ('require_sign', 'target_departments'), 'description': '勾选“是否需要签收”后,可指定接收部门。未指定则默认全员可见但不可签收。' }), ('时间信息', { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) def save_model(self, request, obj, form, change): if not change: obj.publisher = request.user super().save_model(request, obj, form, change) def signed_count(self, obj): return obj.receipts.count() signed_count.short_description = "已签收人数" def total_target_users(self, obj): if obj.target_departments.exists(): count = User.objects.filter( dept__in=obj.target_departments.all(), is_active=True ).count() else: count = User.objects.filter(is_active=True).count() return count total_target_users.short_description = "应签收人数" # —————— 签收记录 —————— @admin.register(NoticeReceipt) class NoticeReceiptAdmin(admin.ModelAdmin): list_display = ('notice', 'user', 'signed_at') list_filter = ('signed_at', 'notice__title') search_fields = ('user__cname', 'user__username', 'notice__title') readonly_fields = ('notice', 'user', 'signed_at') def has_add_permission(self, request): return False # 禁止手动添加