File size: 4,254 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 | """
替换词 API
提供替换词的 CRUD 接口.
"""
from __future__ import annotations
import logging
from datetime import date, datetime
from typing import Any
from django.utils.translation import gettext_lazy as _
from ninja import Router
from apps.core.security.auth import JWTOrSessionAuth
from apps.documents.schemas import PlaceholderIn, PlaceholderOut, PlaceholderPreviewOut, PlaceholderUpdate
from apps.documents.services.placeholders import EnhancedContextBuilder
from apps.documents.services.placeholders.placeholder_service import PlaceholderService
logger = logging.getLogger("apps.documents.api")
router = Router(auth=JWTOrSessionAuth())
def _get_placeholder_service() -> PlaceholderService:
"""工厂函数:创建 PlaceholderService 实例"""
return PlaceholderService()
def _safe_value(value: Any) -> Any:
if value is None:
return None
if isinstance(value, (str, int, float, bool)):
return value
if isinstance(value, (datetime, date)):
return value.isoformat()
if isinstance(value, dict):
return {str(k): _safe_value(v) for k, v in value.items()}
if isinstance(value, (list, tuple, set)):
return [_safe_value(v) for v in value]
return str(value)
@router.get("/placeholders", response=list[PlaceholderOut])
def list_placeholders(request: Any, is_active: bool | None = None) -> Any:
"""
获取替换词列表
Args:
is_active: 启用状态过滤
"""
service = _get_placeholder_service()
return service.list_placeholders(is_active=is_active) # type: ignore[return-value]
@router.get("/placeholders/{placeholder_id}", response=PlaceholderOut)
def get_placeholder(request: Any, placeholder_id: int) -> Any:
"""获取替换词详情"""
service = _get_placeholder_service()
return service.get_placeholder_by_id(placeholder_id)
@router.get("/placeholders/by-key/{key}", response=PlaceholderOut)
def get_placeholder_by_key(request: Any, key: str) -> Any:
"""根据键获取替换词"""
service = _get_placeholder_service()
return service.get_placeholder_by_key(key)
@router.post("/placeholders", response=PlaceholderOut)
def create_placeholder(request: Any, payload: PlaceholderIn) -> Any:
"""创建替换词"""
service = _get_placeholder_service()
return service.create_placeholder(
key=payload.key,
display_name=payload.display_name,
example_value=payload.example_value,
description=payload.description,
is_active=payload.is_active,
)
@router.put("/placeholders/{placeholder_id}", response=PlaceholderOut)
def update_placeholder(request: Any, placeholder_id: int, payload: PlaceholderUpdate) -> Any:
"""更新替换词"""
service = _get_placeholder_service()
return service.update_placeholder(
placeholder_id=placeholder_id,
key=payload.key,
display_name=payload.display_name,
example_value=payload.example_value,
description=payload.description,
is_active=payload.is_active,
)
@router.delete("/placeholders/{placeholder_id}", response=dict[str, Any])
def delete_placeholder(request: Any, placeholder_id: int) -> Any:
"""删除替换词(软删除)"""
service = _get_placeholder_service()
service.delete_placeholder(placeholder_id)
return {"success": True, "message": _("替换词已删除")}
@router.get("/placeholders/preview/{contract_id}", response=PlaceholderPreviewOut)
def preview_placeholders(request: Any, contract_id: int) -> Any:
builder = EnhancedContextBuilder()
context = builder.build_contract_context(contract_id)
keys = request.GET.get("keys")
required_keys: list[str] | None = None
if keys:
required_keys = [k.strip() for k in keys.split(",") if k.strip()]
if required_keys is None:
values = {k: _safe_value(v) for k, v in context.items()}
missing_keys: list[str] = []
else:
values = {k: _safe_value(context.get(k)) for k in required_keys if k in context}
missing_keys = [k for k in required_keys if k not in context]
return { # type: ignore[return-value]
"contract_id": contract_id,
"values": values,
"missing_keys": missing_keys,
}
|