from django.contrib import admin from django.contrib.admin import action from django.utils.safestring import mark_safe from . import models class StateParameterInline(admin.StackedInline): model = models.StateParameter extra = 1 class ProcessNodeInline(admin.StackedInline): model = models.ProcessNode extra = 1 autocomplete_fields = ('state',) ordering = ('order',) @admin.register(models.State) class StateAdmin(admin.ModelAdmin): list_display = ( 'id', 'name', 'description', 'created_at', 'updated_at', 'parameter_overview', ) search_fields = ('name', 'description') list_filter = ('created_at', 'updated_at', 'processes__name') inlines = [StateParameterInline] @admin.display(description='参数概览') def parameter_overview(self, obj: models.State): params = obj.parameters.all() if params: result = "
".join([f"{param.key}={param.value}" for param in params]) else: result = "-" return mark_safe(result) @admin.register(models.Process) class ProcessAdmin(admin.ModelAdmin): list_display = ( 'id', 'name', 'node_count', 'description', 'updated_at', ) search_fields = ('name', 'description') list_filter = ('created_at', 'updated_at') inlines = [ProcessNodeInline] @admin.display(description='节点数量') def node_count(self, obj: models.Process): return obj.process_nodes.count() class StateFlowRecordInline(admin.StackedInline): model = models.StateFlowRecord extra = 0 fields = ('state', 'completed_at', 'completed_by', 'is_cancelled', 'cancelled_at') readonly_fields = ('completed_at', 'completed_by', 'cancelled_at') can_delete = False ordering = ('completed_at',) @admin.register(models.BusinessObject) class BusinessObjectAdmin(admin.ModelAdmin): list_display = ( 'id', 'name', 'process', 'content_object_display', 'current_state_display', 'progress', 'params', 'updated_at', ) search_fields = ('name', 'description') list_filter = ('process', 'created_at', 'updated_at') actions = ['advance_to_next_state_action', 'reset_progress_action'] autocomplete_fields = ('process',) inlines = [StateFlowRecordInline] fieldsets = [ ('基本信息', { 'fields': ['name', 'process', 'description'] }), ('关联对象(可选)', { 'fields': ['content_type', 'object_id'], 'description': '可选择关联到实际的业务对象,如订单、工单等' }), ] @admin.display(description='关联对象') def content_object_display(self, obj: models.BusinessObject): """显示关联对象""" if obj.content_object: return f"{obj.content_type} #{obj.object_id}" return "-" @action(description='前进到下一个状态') def advance_to_next_state_action(self, request, queryset): from . import services success_count = 0 messages = [] for obj in queryset: success, message = services.advance_to_next_state(obj, request.user) if success: success_count += 1 messages.append(f"{obj.name}: {message}") self.message_user(request, f'成功推进 {success_count}/{queryset.count()} 个业务对象。详情: {"; ".join(messages[:5])}') @action(description='重置进度') def reset_progress_action(self, request, queryset): from . import services for obj in queryset: services.reset_business_object_progress(obj) self.message_user(request, f'已重置 {queryset.count()} 个业务对象的进度。') @admin.display(description='当前状态', ordering='process') def current_state_display(self, obj: models.BusinessObject): from . import services current_state = obj.get_current_state() overall_status = services.get_overall_status(obj) if overall_status == 'not_started': return '未开始' elif overall_status == 'completed': return '已完成' elif current_state: return current_state.name return '-' @admin.display(description='进度') def progress(self, obj: models.BusinessObject): return f"{obj.get_progress_percentage():.1f}%" @admin.display(description='本步骤参数') def params(self, obj: models.BusinessObject): current_state = obj.get_current_state() if current_state: params = current_state.parameters.all() if params: return ", ".join([f"{param.key}={param.value}" for param in params]) return "-" @admin.register(models.StateFlowRecord) class StateFlowRecordAdmin(admin.ModelAdmin): list_display = ('id', 'business_object', 'state', 'completed_at', 'completed_by', 'is_cancelled', 'cancelled_at') search_fields = ('business_object__name', 'state__name') list_filter = ('state', 'is_cancelled', 'completed_at', 'completed_by') readonly_fields = ('business_object', 'state', 'completed_at', 'completed_by', 'cancelled_at') fields = ('business_object', 'state', 'completed_at', 'completed_by', 'is_cancelled', 'cancelled_at') autocomplete_fields = ('business_object', 'state', 'completed_by')