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

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,8 +2,10 @@ from collections.abc import Mapping
from typing import Optional
from sqlalchemy import text
from sqlalchemy.exc import IntegrityError
from app.dao import BaseDAO
from app.db_compat import inserted_primary_key
class ParentDAO(BaseDAO):
@@ -23,8 +25,9 @@ class ParentDAO(BaseDAO):
),
{"openid": openid, "unionid": unionid, "nickname": nickname, "avatar_url": avatar_url},
)
user_id = inserted_primary_key(result)
self.commit()
return int(self.db.execute(text("SELECT last_insert_rowid()")).scalar_one())
return user_id
def get_by_id(self, user_id: int) -> Optional[Mapping]:
return (
@@ -67,6 +70,49 @@ class ParentDAO(BaseDAO):
)
self.commit()
def set_avatar_file_key(self, user_id: int, avatar_file_key: str) -> None:
self.db.execute(
text(
"""
UPDATE parents
SET avatar_file_key = :avatar_file_key,
avatar_url = NULL
WHERE user_id = :user_id
"""
),
{"user_id": user_id, "avatar_file_key": avatar_file_key},
)
self.commit()
def update_from_wechat_login(
self,
user_id: int,
unionid: Optional[str] = None,
nickname: Optional[str] = None,
avatar_url: Optional[str] = None,
) -> None:
self.db.execute(
text(
"""
UPDATE parents
SET unionid = CASE
WHEN unionid IS NULL AND :unionid IS NOT NULL THEN :unionid
ELSE unionid
END,
nickname = COALESCE(:nickname, nickname),
avatar_url = COALESCE(:avatar_url, avatar_url)
WHERE user_id = :user_id
"""
),
{
"user_id": user_id,
"unionid": unionid,
"nickname": nickname,
"avatar_url": avatar_url,
},
)
self.commit()
def upsert(
self,
openid: str,
@@ -74,27 +120,18 @@ class ParentDAO(BaseDAO):
nickname: Optional[str] = None,
avatar_url: Optional[str] = None,
) -> int:
from app.settings import settings
existing = self.get_by_openid(openid)
if existing:
self.update(existing["user_id"], nickname, avatar_url)
return existing["user_id"]
self.update_from_wechat_login(existing["user_id"], unionid, nickname, avatar_url)
return int(existing["user_id"])
if settings.db_type == "sqlite":
try:
return self.create(openid, unionid, nickname, avatar_url)
self.db.execute(
text(
"""
INSERT INTO parents (openid, unionid, nickname, avatar_url, status)
VALUES (:openid, :unionid, :nickname, :avatar_url, 1)
ON DUPLICATE KEY UPDATE
user_id = LAST_INSERT_ID(user_id),
updated_at = CURRENT_TIMESTAMP
"""
),
{"openid": openid, "unionid": unionid, "nickname": nickname, "avatar_url": avatar_url},
)
self.commit()
return int(self.db.execute(text("SELECT LAST_INSERT_ID()")).scalar_one())
except IntegrityError:
self.db.rollback()
existing = self.get_by_openid(openid)
if not existing:
raise
if unionid or nickname or avatar_url:
self.update_from_wechat_login(existing["user_id"], unionid, nickname, avatar_url)
return int(existing["user_id"])