| 1234567891011121314151617181920212223242526272829303132333435363738394041 |
- """用户头像 URL 解析(sys_user.avatar 可能存 MinIO 相对路径或完整 URL)"""
- from typing import Optional
- from app.core.config import settings
- from app.core.storage import storage
- def resolve_avatar_display_url(raw: Optional[str]) -> Optional[str]:
- """服务端内部拼完整 URL(邮件等);Web API 应返回库中原始路径。"""
- if raw is None:
- return None
- s = str(raw).strip()
- if not s:
- return None
- lower = s.lower()
- if lower.startswith("http://") or lower.startswith("https://") or s.startswith("/"):
- return s
- try:
- return storage.get_url(s.lstrip("/"))
- except Exception:
- base = (settings.MINIO_BASE_URL or settings.LOCAL_STORAGE_URL or "").rstrip("/")
- if base:
- return f"{base}/{s.lstrip('/')}"
- return s
- def extract_avatar_storage_key(full_url: str) -> str:
- """从 upload 返回值或历史完整 URL 中提取 avatar/ 相对路径。"""
- u = (full_url or "").strip()
- if not u:
- return ""
- base_url = (settings.MINIO_BASE_URL or "").rstrip("/")
- if base_url and u.startswith(base_url + "/"):
- return u[len(base_url) + 1 :].lstrip("/")
- marker = "/avatar/"
- idx = u.lower().find(marker)
- if idx >= 0:
- return f"avatar/{u[idx + len(marker) :].lstrip('/')}"
- if not u.lower().startswith("http") and not u.startswith("/"):
- return u.lstrip("/")
- return u
|