小程序后端接入微信登录与家长头像能力

This commit is contained in:
stu2not
2026-04-16 18:19:19 +08:00
parent db888df50f
commit 2526365af1
10 changed files with 515 additions and 77 deletions

View File

@@ -2,12 +2,14 @@ from collections.abc import Mapping
from typing import Optional
from app.dao.parent import ParentDAO
from app.service import get_db_session
from app.service.avatar_storage import AvatarStorageService
from app.settings import settings
class ParentService:
def __init__(self, db):
def __init__(self, db, avatar_storage: AvatarStorageService | None = None):
self.dao = ParentDAO(db)
self.avatar_storage = avatar_storage or AvatarStorageService()
def create(
self,
@@ -17,10 +19,10 @@ class ParentService:
avatar_url: Optional[str] = None,
) -> Mapping:
user_id = self.dao.upsert(openid, unionid, nickname, avatar_url)
return self.dao.get_by_id(user_id)
return self.get(user_id)
def get(self, user_id: int) -> Optional[Mapping]:
return self.dao.get_by_id(user_id)
return self._present_parent(self.dao.get_by_id(user_id))
def update(
self,
@@ -30,4 +32,71 @@ class ParentService:
phone: Optional[str] = None,
) -> Mapping:
self.dao.update(user_id, nickname, avatar_url, phone)
return self.dao.get_by_id(user_id)
return self.get(user_id)
def upload_avatar(
self,
*,
user_id: int,
filename: str | None,
content_type: str | None,
content: bytes,
) -> Optional[Mapping]:
existing = self.dao.get_by_id(user_id)
if not existing:
return None
stored = self.avatar_storage.upload_avatar(
user_id=user_id,
filename=filename,
content_type=content_type,
content=content,
)
old_avatar_file_key = existing.get("avatar_file_key")
try:
self.dao.set_avatar_file_key(user_id, stored.file_key)
except Exception:
try:
self.avatar_storage.delete_avatar(stored.file_key)
except Exception:
pass
raise
if old_avatar_file_key and old_avatar_file_key != stored.file_key:
try:
self.avatar_storage.delete_avatar(old_avatar_file_key)
except Exception:
pass
return self.get(user_id)
def get_avatar_download(self, user_id: int) -> Optional[dict]:
parent = self.dao.get_by_id(user_id)
if not parent:
return None
avatar_file_key = parent.get("avatar_file_key")
if avatar_file_key:
return {
"avatar_url": self.avatar_storage.get_avatar_url(avatar_file_key),
"expires_in": settings.cos_avatar_url_expire_seconds,
}
avatar_url = parent.get("avatar_url")
if avatar_url:
return {
"avatar_url": avatar_url,
"expires_in": None,
}
return None
def _present_parent(self, parent: Optional[Mapping]) -> Optional[dict]:
if not parent:
return None
data = dict(parent)
avatar_file_key = data.get("avatar_file_key")
if avatar_file_key:
data["avatar_url"] = self.avatar_storage.get_avatar_url(avatar_file_key)
return data