Files
trade-assistant/backend/app/api/v1/translate.py
T
TradeMate Dev 7b62c2f8b4 feat: 修复 H5 底部导航覆盖 + 更新项目进度文档
## H5 底部导航修复 (Bug #10)
- 精简 App.vue,移除重复 tabbar,仅保留全局样式
- uni-page 设置 height: calc(100% - 50px) + overflow-y: auto
- 内容区域精确停在底部导航上方,独立滚动不再叠加
- 恢复 custom-tab-bar 组件

## 项目进度文档
- PROGRESS.md 更新至 10 个 Bug 修复
- 新增 H5 底部导航修复记录
- 新增历史变更条目
2026-05-12 20:24:42 +08:00

156 lines
4.2 KiB
Python

from fastapi import APIRouter, HTTPException, Response, Depends
from typing import Optional, Dict, Any, Annotated
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession
from app.database import get_db
from app.services.translation import TranslationService
from app.services.tts import tts_service
from app.services.preference import UserPreferenceService
from app.core.security import decode_token
from app.api.v1.deps import get_current_user_id
router = APIRouter()
class TranslateRequest(BaseModel):
text: str
target_lang: str
source_lang: Optional[str] = "auto"
context: Optional[str] = None
class ReplyRequest(BaseModel):
inquiry: str
tone: str = "professional"
count: int = 3
context: Optional[Dict[str, Any]] = None
class ExtractRequest(BaseModel):
text: str
extract_type: str = "auto"
@router.post("")
async def translate_text(
data: TranslateRequest,
user_id: str = Depends(get_current_user_id),
):
service = TranslationService()
result = await service.translate(
text=data.text,
target_lang=data.target_lang,
source_lang=data.source_lang,
context=data.context,
user_id=user_id,
)
return result
@router.post("/reply")
async def generate_reply(
data: ReplyRequest,
user_id: str = Depends(get_current_user_id),
db: Annotated[AsyncSession, Depends(get_db)] = None,
):
pref_service = UserPreferenceService(db)
pref_context = await pref_service.get_preference_context(user_id, "reply")
service = TranslationService()
results = await service.generate_reply(
inquiry=data.inquiry,
context=data.context,
tone=data.tone,
count=data.count,
preference_context=pref_context,
)
return {"suggestions": results, "inquiry": data.inquiry, "count": len(results)}
@router.post("/extract")
async def extract_info(
data: ExtractRequest,
user_id: str = Depends(get_current_user_id),
):
service = TranslationService()
result = await service.extract_info(data.text, data.extract_type)
return {"extracted": result, "type": data.extract_type}
class TTSRequest(BaseModel):
text: str
lang: str = "en"
rate: str = "0%"
pitch: str = "0Hz"
@router.post("/tts")
async def text_to_speech(
data: TTSRequest,
user_id: str = Depends(get_current_user_id),
):
audio = await tts_service.synthesize(data.text, data.lang, data.rate, data.pitch)
if not audio:
raise HTTPException(status_code=501, detail="TTS not available (edge-tts not installed or synthesis failed)")
return Response(content=audio, media_type="audio/mpeg", headers={
"Content-Disposition": f'attachment; filename="tts-{data.lang}.mp3"',
})
@router.get("/tts")
async def text_to_speech_get(
text: str = "",
lang: str = "en",
user_id: str = Depends(get_current_user_id),
):
if not text.strip():
raise HTTPException(status_code=400, detail="Text is required")
audio = await tts_service.synthesize(text, lang)
if not audio:
raise HTTPException(status_code=501, detail="TTS not available")
return Response(content=audio, media_type="audio/mpeg", headers={
"Content-Disposition": f'attachment; filename="tts-{lang}.mp3"',
})
@router.post("/feedback")
async def feedback(
data: dict,
user_id: str = Depends(get_current_user_id),
):
from app.ai.trade_corpus import TradeCorpus
corpus = TradeCorpus()
entry_id = data.get("entry_id")
rating = data.get("rating")
if entry_id and rating:
await corpus.rate_entry(entry_id, rating)
return {"status": "ok"}
public_router = APIRouter(tags=["translate-public"])
@public_router.post("/translate")
async def public_translate(data: TranslateRequest):
service = TranslationService()
result = await service.translate(
text=data.text,
target_lang=data.target_lang,
source_lang=data.source_lang,
context=data.context,
user_id=None,
)
return result
@public_router.post("/extract")
async def public_extract(data: ExtractRequest):
service = TranslationService()
result = await service.extract_info(data.text, data.extract_type)
return {"extracted": result, "type": data.extract_type}