diff --git a/backend/app/core/config.py b/backend/app/core/config.py index 87a2964..34844b5 100755 --- a/backend/app/core/config.py +++ b/backend/app/core/config.py @@ -28,6 +28,9 @@ class Settings(BaseSettings): # 数字分身 SQLite 数据库路径(直连数字分身应用的 SQLite) AVATAR_DB_PATH: str = os.getenv("AVATAR_DB_PATH", "") + # 数字分身后端服务地址(用于拼接头像等文件 URL) + AVATAR_BACKEND_URL: str = os.getenv("AVATAR_BACKEND_URL", "") + # 日志目录 LOG_DIR: str = "/app/logs" diff --git a/backend/app/services/avatar_service.py b/backend/app/services/avatar_service.py index 4faec7f..d20bca8 100644 --- a/backend/app/services/avatar_service.py +++ b/backend/app/services/avatar_service.py @@ -44,6 +44,28 @@ def is_available() -> bool: return engine is not None +def _resolve_photo_url(photo_url: str) -> str: + """将相对路径的头像 URL 补全为绝对路径""" + if not photo_url: + return "" + if photo_url.startswith(("http://", "https://")): + return photo_url + base = settings.AVATAR_BACKEND_URL + if base: + base = base.rstrip("/") + return f"{base}{photo_url}" + return photo_url + + +def _get_global_token_balance(db: Session) -> int: + """获取全局 token_account 余额(单行表)""" + try: + result = db.execute(text("SELECT balance FROM token_account LIMIT 1")).fetchone() + return result.balance if result and result.balance else 0 + except Exception: + return 0 + + class AvatarService: @staticmethod @@ -97,6 +119,7 @@ class AvatarService: rows = db.execute(query, params).fetchall() items = [] + global_token = _get_global_token_balance(db) for row in rows: config = {} if row.config: @@ -113,10 +136,10 @@ class AvatarService: "name": row.name, "display_name": row.display_name, "description": row.description or "", - "photo_url": row.photo_url or "", + "photo_url": _resolve_photo_url(row.photo_url), "emoji": row.emoji or "🤖", "status": row.status or "active", - "token_balance": row.token_balance or 0, + "token_balance": global_token or (row.token_balance or 0), "config": config, "owner_nickname": row.owner_nickname or "", "owner_phone": row.owner_phone or "", @@ -155,15 +178,16 @@ class AvatarService: elif isinstance(row.config, dict): config = row.config + global_token = _get_global_token_balance(db) return { "id": row.id, "name": row.name, "display_name": row.display_name, "description": row.description or "", - "photo_url": row.photo_url or "", + "photo_url": _resolve_photo_url(row.photo_url), "emoji": row.emoji or "🤖", "status": row.status or "active", - "token_balance": row.token_balance or 0, + "token_balance": global_token or (row.token_balance or 0), "config": config, "owner_nickname": row.owner_nickname or "", "owner_phone": row.owner_phone or "", diff --git a/frontend/src/views/Avatars.vue b/frontend/src/views/Avatars.vue index d3ea9a4..118a79e 100644 --- a/frontend/src/views/Avatars.vue +++ b/frontend/src/views/Avatars.vue @@ -259,7 +259,7 @@ onUnmounted(() => window.removeEventListener('page-refresh', loadAvatars))