File size: 7,013 Bytes
b4f2238 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | """
替换词 Admin 配置
Requirements: 6.1, 3.6
"""
from typing import Any, ClassVar
from django.contrib import admin
from django.db.models import QuerySet
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _
from apps.documents.models import Placeholder
def _get_placeholder_usage_service() -> Any:
from apps.documents.services.placeholders.placeholder_usage_service import PlaceholderUsageService
return PlaceholderUsageService()
def _get_code_placeholder_catalog_service() -> Any:
from apps.documents.services.code_placeholders.catalog_service import CodePlaceholderCatalogService
return CodePlaceholderCatalogService()
def _get_placeholder_admin_service() -> Any:
from ..services import PlaceholderAdminService
return PlaceholderAdminService()
class PlaceholderUsageFilter(admin.SimpleListFilter):
title = _("用途")
parameter_name: str = "usage"
def lookups(self, request: Any, model_admin: Any) -> Any:
return (
("contract", _("合同文件")),
("case", _("案件文件")),
("both", _("合同+案件")),
("unused", _("未使用")),
)
def queryset(self, request: Any, queryset: Any) -> Any:
value = self.value()
if not value:
return queryset
usage_map = getattr(self, "_usage_map_cache", None)
if usage_map is None:
usage_map = _get_placeholder_usage_service().get_usage_map()
self._usage_map_cache = usage_map
return _get_placeholder_admin_service().filter_by_usage(queryset, value, usage_map)
class PlaceholderAdmin(admin.ModelAdmin):
"""
替换词管理
提供替换词的 CRUD 操作,支持搜索和过滤.
"""
list_display: tuple[Any, ...] = (
"key",
"usage_display",
"example_value_display",
"is_active",
)
list_filter: tuple[Any, ...] = (
"is_active",
PlaceholderUsageFilter,
)
search_fields: tuple[Any, ...] = (
"key",
"display_name",
"description",
)
ordering: tuple[Any, ...] = ("key",)
fieldsets: tuple[Any, ...] = (
(None, {"fields": ("key", "display_name")}),
(_("示例和说明"), {"fields": ("example_value", "description")}),
(_("状态"), {"fields": ("is_active",)}),
)
actions: ClassVar = ["activate_placeholders", "deactivate_placeholders"]
def has_add_permission(self, request: Any) -> Any:
return False
def _catalog_cache(self) -> Any:
if not hasattr(self, "_cached_code_placeholder_catalog"):
catalog = _get_code_placeholder_catalog_service()
definitions = {d.key: d for d in catalog.list_definitions()}
self._cached_code_placeholder_catalog = definitions
return self._cached_code_placeholder_catalog
def _usage_map_cache(self, request: Any) -> Any:
if request is not None and getattr(request, "_placeholder_usage_map_cached", None) is not None:
return request._placeholder_usage_map_cached
usage_map = _get_placeholder_usage_service().get_usage_map()
if request is not None:
request._placeholder_usage_map_cached = usage_map
self._usage_map_for_changelist = usage_map
return usage_map
def _ensure_code_placeholders(self, request: Any) -> None:
if getattr(request, "_code_placeholders_synced", False):
return
definitions = self._catalog_cache()
service = _get_placeholder_admin_service()
service.ensure_code_placeholders(definitions)
request._code_placeholders_synced = True
def get_queryset(self, request: Any) -> QuerySet[Any]:
self._ensure_code_placeholders(request)
self._usage_map_cache(request)
qs = super().get_queryset(request)
code_keys = list(self._catalog_cache().keys())
service = _get_placeholder_admin_service()
return service.get_filtered_queryset(qs, code_keys)
@admin.display(description=_("用途"))
def usage_display(self, obj: Any) -> Any:
usage_map = getattr(self, "_usage_map_for_changelist", None)
if usage_map is None:
usage_map = _get_placeholder_usage_service().get_usage_map()
types = usage_map.get(obj.key, set()) or set()
parts: list[Any] = []
if "contract" in types:
parts.append(str(_("合同文件")))
if "case" in types:
parts.append(str(_("案件文件")))
if not parts:
return format_html('<span style="color: #999;">{}</span>', "-")
return " / ".join(parts)
@admin.display(description=_("来源服务"))
def code_service_display(self, obj: Any) -> Any:
definition = self._catalog_cache().get(obj.key)
return definition.source if definition else ""
@admin.display(description=_("分类"))
def code_category_display(self, obj: Any) -> Any:
definition = self._catalog_cache().get(obj.key)
return definition.category if definition else ""
@admin.display(description=_("示例值"))
def example_value_display(self, obj: Any) -> Any:
"""显示示例值"""
if obj.example_value:
# 截断过长的示例值
value = obj.example_value
if len(value) > 50:
value = value[:50] + "..."
return format_html(
'<span title="{}" style="color: #666; font-style: italic;">{}</span>', obj.example_value, value
)
return format_html('<span style="color: #999;">{}</span>', "-")
@admin.action(description=_("启用选中的替换词"))
def activate_placeholders(self, request: Any, queryset: Any) -> None:
"""批量启用替换词"""
updated = queryset.filter(is_active=False).update(is_active=True)
self.message_user(request, _("已启用 %(count)d 个替换词") % {"count": updated})
@admin.action(description=_("禁用选中的替换词"))
def deactivate_placeholders(self, request: Any, queryset: Any) -> None:
"""批量禁用替换词"""
updated = queryset.filter(is_active=True).update(is_active=False)
self.message_user(request, _("已禁用 %(count)d 个替换词") % {"count": updated})
@admin.action(description=_("复制选中的替换词"))
def duplicate_placeholders(self, request: Any, queryset: QuerySet[Any]) -> None:
"""复制替换词"""
service = _get_placeholder_admin_service()
count: int = 0
for placeholder in queryset:
service.duplicate_placeholder(placeholder)
count += 1
self.message_user(request, _("已复制 %(count)d 个替换词") % {"count": count})
def get_readonly_fields(self, request: Any, obj: Any = None) -> Any:
"""编辑时 key 字段只读"""
if obj: # 编辑现有对象
return ("key",)
return ()
|