feat: add translation billing stats and remove Export/Settings pages

- Add TranslationLog model to track translation API usage per task
- Integrate Dify API actual price (total_price) into translation stats
- Display translation statistics in admin dashboard with per-task costs
- Remove unused Export and Settings pages to simplify frontend
- Add GET /api/v2/admin/translation-stats endpoint

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
egg
2025-12-12 17:38:12 +08:00
parent d20751d56b
commit 65abd51d60
21 changed files with 682 additions and 662 deletions

View File

@@ -40,6 +40,8 @@ class TranslationResponse:
total_tokens: int
latency: float
conversation_id: str
total_price: float = 0.0
currency: str = "USD"
@dataclass
@@ -50,6 +52,8 @@ class BatchTranslationResponse:
latency: float
conversation_id: str
missing_markers: List[int] = field(default_factory=list)
total_price: float = 0.0
currency: str = "USD"
class DifyTranslationError(Exception):
@@ -252,6 +256,11 @@ class DifyClient:
translated_text = data.get("answer", "")
usage = data.get("metadata", {}).get("usage", {})
# Extract price info from usage or metadata (may be string or number)
raw_price = usage.get("total_price", 0.0)
total_price = float(raw_price) if raw_price else 0.0
currency = usage.get("currency", "USD") or "USD"
self._total_tokens += usage.get("total_tokens", 0)
self._total_requests += 1
@@ -259,7 +268,9 @@ class DifyClient:
translated_text=translated_text,
total_tokens=usage.get("total_tokens", 0),
latency=usage.get("latency", 0.0),
conversation_id=data.get("conversation_id", "")
conversation_id=data.get("conversation_id", ""),
total_price=total_price,
currency=currency
)
def translate_batch(
@@ -297,6 +308,11 @@ class DifyClient:
answer = data.get("answer", "")
usage = data.get("metadata", {}).get("usage", {})
# Extract price info from usage or metadata (may be string or number)
raw_price = usage.get("total_price", 0.0)
total_price = float(raw_price) if raw_price else 0.0
currency = usage.get("currency", "USD") or "USD"
translations = self._parse_batch_response(answer, len(texts))
# Check for missing markers
@@ -314,7 +330,9 @@ class DifyClient:
total_tokens=usage.get("total_tokens", 0),
latency=usage.get("latency", 0.0),
conversation_id=data.get("conversation_id", ""),
missing_markers=missing_markers
missing_markers=missing_markers,
total_price=total_price,
currency=currency
)
def get_stats(self) -> dict: