288 lines
11 KiB
Python
288 lines
11 KiB
Python
from django.contrib import admin
|
||
from django.contrib.admin.actions import delete_selected
|
||
from django.urls import reverse
|
||
from django.utils.html import format_html
|
||
from .models import Branch, EquipmentImage, Drawing, PublicScreen
|
||
from .models import Activity, Branch, Event, Contact, VideoTerminal, Budget, EquipmentBudget, InfrastructureBudget, BudgetTemplate, TemplateEquipmentItem, TemplateInfrastructureItem
|
||
from django_select2.forms import Select2Widget
|
||
from unfold.admin import ModelAdmin
|
||
from django.contrib.admin import AdminSite
|
||
from django.contrib.auth.models import User, Group
|
||
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
|
||
from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin
|
||
from django.db.models import Count, Q
|
||
|
||
from django.utils.html import format_html
|
||
from django.urls import reverse
|
||
from django import forms
|
||
|
||
|
||
# 定义Activity的内联admin类
|
||
class ActivityInline(admin.TabularInline): # 改为更紧凑的表格形式内联(原StackedInline为堆叠形式)
|
||
model = Activity
|
||
extra = 1 # 在Branch表单中默认显示1个额外的Activity表单(可根据需求调整数值)
|
||
fields = ('name', 'scope', 'start_time', 'end_time') # 限制内联表单显示的字段
|
||
readonly_fields = ('start_time',) # 可选:将开始时间设为只读字段(避免误修改)
|
||
# 可选:添加帮助文本提示
|
||
help_texts = {
|
||
'name': '请输入活动名称(必填)',
|
||
'scope': '选择活动范围(内部/外部)'
|
||
}
|
||
|
||
|
||
admin.site.unregister(User)
|
||
admin.site.unregister(Group)
|
||
|
||
|
||
@admin.register(User)
|
||
class UserAdmin(BaseUserAdmin, ModelAdmin):
|
||
pass
|
||
|
||
|
||
@admin.register(Group)
|
||
class GroupAdmin(BaseGroupAdmin, ModelAdmin):
|
||
pass
|
||
|
||
|
||
@admin.register(Branch)
|
||
class BranchAdmin(ModelAdmin):
|
||
inlines = [ActivityInline]
|
||
list_display = ('name', 'location', 'category', 'display_mature_status', 'background_color')
|
||
search_fields = ['name', 'location']
|
||
fieldsets = (
|
||
(None, {
|
||
'fields': ('name', 'location', 'contact_info', 'description', 'category', 'is_mature', 'background_color')
|
||
}),
|
||
)
|
||
|
||
def display_mature_status(self, obj):
|
||
return '💼' if obj.is_mature else '📒'
|
||
display_mature_status.short_description = '是否成熟'
|
||
|
||
def activity_count(self, obj):
|
||
return obj.activity_set.count()
|
||
|
||
activity_count.short_description = '活动数量'
|
||
|
||
def get_queryset(self, request):
|
||
queryset = super().get_queryset(request)
|
||
queryset = queryset.annotate(
|
||
inspection_person_count=Count('contact', filter=Q(contact__category='机房/设备间巡检人')))
|
||
return queryset
|
||
|
||
actions = ['set_branches_to_type_b']
|
||
|
||
def set_branches_to_type_b(self, request, queryset):
|
||
queryset.update(category='B型')
|
||
|
||
set_branches_to_type_b.short_description = '将选中的分支机构统一改为B型'
|
||
|
||
|
||
# 注册Activity模型(如果需要的话,虽然在这个示例中我们主要关注Branch)
|
||
@admin.register(Activity)
|
||
class ActivityAdmin(ModelAdmin):
|
||
list_display = ('branch', 'scope', 'name', 'start_time', 'end_time')
|
||
search_fields = ["branch__name"] # 改为关联Branch模型的name字段
|
||
add_form_template = 'admin/huodong/add_form.html'
|
||
|
||
autocomplete_fields = ['branch']
|
||
|
||
|
||
@admin.register(Event)
|
||
class EventAdmin(ModelAdmin):
|
||
list_display = ('name', 'start_time', 'end_time', 'description')
|
||
filter_horizontal = ('branches',)
|
||
|
||
|
||
class ContactAdminForm(forms.ModelForm):
|
||
class Meta:
|
||
model = Contact
|
||
fields = '__all__'
|
||
widgets = {
|
||
# 使用复选框实现多选
|
||
'category': forms.CheckboxSelectMultiple(choices=Contact.CATEGORY_CHOICES)
|
||
}
|
||
|
||
|
||
class EquipmentImageAdmin(admin.ModelAdmin):
|
||
def bulk_delete_selected(self, request, queryset):
|
||
count = queryset.count()
|
||
queryset.delete()
|
||
self.message_user(request, f'已成功删除{count}条设备图片记录')
|
||
bulk_delete_selected.short_description = '批量删除选中的设备图片'
|
||
actions = ['bulk_delete_selected']
|
||
list_display = ['id', 'branch', 'uploaded_at', 'delete_link']
|
||
|
||
def delete_link(self, obj):
|
||
url = reverse('admin:huodong_equipmentimage_delete', args=[obj.id])
|
||
return format_html('<a class="deletelink" href="{}">删除</a>', url)
|
||
delete_link.short_description = '操作'
|
||
list_filter = ['branch']
|
||
search_fields = ['branch__name']
|
||
|
||
autocomplete_fields = ['branch']
|
||
|
||
def get_form(self, request, obj=None, **kwargs):
|
||
form = super().get_form(request, obj, **kwargs)
|
||
# 设置默认分支机构为最后一个设备间图片的分支机构
|
||
try:
|
||
latest_image = EquipmentImage.objects.latest('uploaded_at')
|
||
form.base_fields['branch'].initial = latest_image.branch_id
|
||
except EquipmentImage.DoesNotExist:
|
||
pass
|
||
return form
|
||
|
||
def save_model(self, request, obj, form, change):
|
||
super().save_model(request, obj, form, change)
|
||
# Count images for the current branch
|
||
count = EquipmentImage.objects.filter(branch=obj.branch).count()
|
||
self.message_user(request, f"【{obj.branch.name}】已经有{count}张设备间图片。")
|
||
|
||
admin.site.register(EquipmentImage, EquipmentImageAdmin)
|
||
|
||
class DrawingAdmin(admin.ModelAdmin):
|
||
def bulk_delete_selected(self, request, queryset):
|
||
count = queryset.count()
|
||
queryset.delete()
|
||
self.message_user(request, f'已成功删除{count}条图纸记录')
|
||
bulk_delete_selected.short_description = '批量删除选中的图纸'
|
||
actions = ['bulk_delete_selected']
|
||
list_display = ('id', 'branch', 'uploaded_at', 'delete_link')
|
||
|
||
def delete_link(self, obj):
|
||
url = reverse('admin:huodong_drawing_delete', args=[obj.id])
|
||
return format_html('<a class="deletelink" href="{}">删除</a>', url)
|
||
delete_link.short_description = '操作'
|
||
list_filter = ('branch', 'uploaded_at')
|
||
search_fields = ('branch__name',)
|
||
autocomplete_fields = ['branch']
|
||
|
||
admin.site.register(Drawing, DrawingAdmin)
|
||
|
||
class PublicScreenAdmin(ModelAdmin):
|
||
def delete_link(self, obj):
|
||
if obj.id:
|
||
delete_url = reverse('admin:huodong_publicscreen_delete', args=[obj.id])
|
||
return format_html('<a href="{}" class="text-red-600 hover:text-red-900">删除</a>', delete_url)
|
||
return '-'
|
||
delete_link.short_description = '操作'
|
||
|
||
def bulk_delete_selected(self, request, queryset):
|
||
count = queryset.count()
|
||
queryset.delete()
|
||
self.message_user(request, f'已成功删除{count}条公共电子屏记录')
|
||
bulk_delete_selected.short_description = '批量删除选中的公共电子屏'
|
||
|
||
list_display = ('id', 'branch', 'screen_type', 'last_drill', 'delete_link')
|
||
list_filter = ['branch', 'screen_type']
|
||
autocomplete_fields = ['branch']
|
||
actions = ['bulk_delete_selected']
|
||
|
||
admin.site.register(PublicScreen, PublicScreenAdmin)
|
||
@admin.register(Contact)
|
||
class ContactAdmin(ModelAdmin):
|
||
form = ContactAdminForm # 指定自定义表单
|
||
list_display = ('branch', 'category', 'name', 'phone', 'email') # 可选:显示分类字段
|
||
|
||
autocomplete_fields = ['branch']
|
||
|
||
@admin.register(VideoTerminal)
|
||
class VideoTerminalAdmin(ModelAdmin):
|
||
list_display = ('branch', 'terminal_type', 'description', 'created_at')
|
||
list_filter = ('terminal_type', 'branch')
|
||
search_fields = ('branch__name', 'description')
|
||
autocomplete_fields = ['branch']
|
||
|
||
|
||
# 预算相关Admin配置
|
||
|
||
# 设备预算内联
|
||
class EquipmentBudgetInline(admin.TabularInline):
|
||
model = EquipmentBudget
|
||
extra = 1
|
||
fields = ('project', 'model', 'unit_price', 'procurement_method', 'quantity', 'subtotal')
|
||
readonly_fields = ('subtotal',) # 小计自动计算,设为只读
|
||
|
||
# 基础设施预算内联
|
||
class InfrastructureBudgetInline(admin.TabularInline):
|
||
model = InfrastructureBudget
|
||
extra = 1
|
||
fields = ('name', 'remarks', 'unit_price', 'unit', 'quantity', 'subtotal', 'description')
|
||
readonly_fields = ('subtotal',) # 小计自动计算,设为只读
|
||
|
||
# 预算Admin
|
||
@admin.register(Budget)
|
||
class BudgetAdmin(ModelAdmin):
|
||
list_display = ('branch', 'name', 'total_budget', 'created_at')
|
||
list_filter = ('branch',)
|
||
search_fields = ('branch__name', 'name')
|
||
autocomplete_fields = ['branch']
|
||
readonly_fields = ('total_budget',) # 总预算自动计算,设为只读
|
||
inlines = [EquipmentBudgetInline, InfrastructureBudgetInline]
|
||
|
||
def save_model(self, request, obj, form, change):
|
||
super().save_model(request, obj, form, change)
|
||
# 保存后重新计算总预算
|
||
obj.update_total_budget()
|
||
|
||
# 设备预算Admin(如果需要单独管理)
|
||
@admin.register(EquipmentBudget)
|
||
class EquipmentBudgetAdmin(ModelAdmin):
|
||
list_display = ('budget', 'project', 'model', 'unit_price', 'procurement_method', 'quantity', 'subtotal')
|
||
list_filter = ('budget__branch', 'project', 'procurement_method')
|
||
search_fields = ('budget__branch__name', 'project', 'model')
|
||
autocomplete_fields = ['budget']
|
||
readonly_fields = ('subtotal',)
|
||
|
||
# 基础设施预算Admin(如果需要单独管理)
|
||
@admin.register(InfrastructureBudget)
|
||
class InfrastructureBudgetAdmin(ModelAdmin):
|
||
list_display = ('budget', 'name', 'unit_price', 'unit', 'quantity', 'subtotal')
|
||
list_filter = ('budget__branch', 'name')
|
||
search_fields = ('budget__branch__name', 'name', 'description')
|
||
autocomplete_fields = ['budget']
|
||
readonly_fields = ('subtotal',)
|
||
|
||
|
||
# 预算模板相关Admin配置
|
||
|
||
# 模板设备项内联
|
||
class TemplateEquipmentItemInline(admin.TabularInline):
|
||
model = TemplateEquipmentItem
|
||
extra = 1
|
||
|
||
# 模板基础设施项内联
|
||
class TemplateInfrastructureItemInline(admin.TabularInline):
|
||
model = TemplateInfrastructureItem
|
||
extra = 1
|
||
|
||
# 模板设备项Admin(如果需要单独管理)
|
||
@admin.register(TemplateEquipmentItem)
|
||
class TemplateEquipmentItemAdmin(ModelAdmin):
|
||
list_display = ('template', 'project', 'model', 'unit_price', 'procurement_method')
|
||
list_filter = ('template', 'project', 'procurement_method')
|
||
search_fields = ('template__name', 'project', 'model')
|
||
autocomplete_fields = ['template']
|
||
|
||
# 模板基础设施项Admin(如果需要单独管理)
|
||
@admin.register(TemplateInfrastructureItem)
|
||
class TemplateInfrastructureItemAdmin(ModelAdmin):
|
||
list_display = ('template', 'name', 'unit_price', 'unit')
|
||
list_filter = ('template', 'unit')
|
||
search_fields = ('template__name', 'name', 'description')
|
||
autocomplete_fields = ['template']
|
||
|
||
# 预算模板Admin
|
||
@admin.register(BudgetTemplate)
|
||
class BudgetTemplateAdmin(ModelAdmin):
|
||
list_display = ('name', 'description', 'is_default', 'created_at')
|
||
list_filter = ('is_default',)
|
||
search_fields = ('name', 'description')
|
||
inlines = [TemplateEquipmentItemInline, TemplateInfrastructureItemInline]
|
||
|
||
def save_model(self, request, obj, form, change):
|
||
# 如果设置为默认模板,将其他模板的默认状态取消
|
||
if obj.is_default:
|
||
BudgetTemplate.objects.exclude(id=obj.id).update(is_default=False)
|
||
super().save_model(request, obj, form, change)
|