From 4ef0f81629b10732a2eec7fcb5aa14093e2f06d1 Mon Sep 17 00:00:00 2001 From: Pine Date: Thu, 27 Aug 2026 20:26:34 +0800 Subject: [PATCH] =?UTF-8?q?feat(auth):=20/auth/me=20=E4=B8=8E=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E5=93=8D=E5=BA=94=E6=9A=B4=E9=9C=B2=20wxBound/wxMiniB?= =?UTF-8?q?ound=20=E7=BB=91=E5=AE=9A=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - UserProfile schema 增加 wxBound/wxMiniBound(LoginResponse/ProfileResponse 继承) - to_profile 补 wx_openid/wx_mini_openid 判定,web/admin 正确识别手机号+小程序绑定 --- app/api/schemas/auth.py | 2 ++ app/infrastructure/repositories.py | 36 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/app/api/schemas/auth.py b/app/api/schemas/auth.py index 886443b..785585f 100644 --- a/app/api/schemas/auth.py +++ b/app/api/schemas/auth.py @@ -76,6 +76,8 @@ class UserProfile(BaseModel): name: str = "" # 别名 = nickname(小程序契约:显示名 / 报名资料姓名) phone: str = "" # 已绑定手机号 phoneBound: bool = False # 是否已绑手机(小程序「已绑定手机」徽标/绑定门槛) + wxBound: bool = False # 是否已绑定微信开放平台 openid + wxMiniBound: bool = False # 是否已绑定小程序 openid(各端口共享) account: str = "" company: str = "" room: str = "" diff --git a/app/infrastructure/repositories.py b/app/infrastructure/repositories.py index 035c7db..6a1c1f2 100644 --- a/app/infrastructure/repositories.py +++ b/app/infrastructure/repositories.py @@ -101,6 +101,14 @@ PROFILE_FIELDS = ( "company_avatar", "opc_status", "topics", + "gender", + "birthday", + "phone", + "email", + "id_card", + "ethnicity", + "grad_school_major", + "grad_time", ) @@ -173,6 +181,10 @@ def _user_to_dict(u: User) -> dict: "email": u.email, "gender": u.gender, "birthday": u.birthday, + "id_card": u.id_card, + "ethnicity": u.ethnicity, + "grad_school_major": u.grad_school_major, + "grad_time": u.grad_time, "source": u.source, "auth_type": u.auth_type, "register_ip": u.register_ip, @@ -243,6 +255,12 @@ class UserRepository: async def list(self) -> list[dict]: return [_user_to_dict(u) for u in await self.session.scalars(select(User).order_by(User.created_at))] + async def list_by_park(self, park_id: str) -> list[dict]: + """本园区用户(park_id 命中,含富资料)。""" + return [_user_to_dict(u) for u in await self.session.scalars( + select(User).where(User.park_id == park_id).order_by(User.created_at.desc()) + )] + async def delete(self, user_id: str) -> bool: """硬删除用户(含其身份/会话在级联范围内由 DB 层处理)。""" u = await self.session.get(User, user_id) @@ -279,6 +297,14 @@ class UserRepository: register_ip: str = "", opc_status: str = "", topics: str = "", + id_card: str = "", + ethnicity: str = "", + grad_school_major: str = "", + grad_time: str = "", + affiliation: str = "", + park_id: str = "", + park_name: str = "", + account_type: str = "opc_default", compute_provisioned: bool = False, compute_username: str = "", compute_quota: int = 0, @@ -315,6 +341,14 @@ class UserRepository: register_ip=register_ip, opc_status=opc_status, topics=topics, + id_card=id_card, + ethnicity=ethnicity, + grad_school_major=grad_school_major, + grad_time=grad_time, + affiliation=affiliation, + park_id=park_id, + park_name=park_name, + account_type=account_type, last_login_ip=register_ip, last_login_at=now, compute_provisioned=compute_provisioned, @@ -558,6 +592,8 @@ class UserRepository: profile["name"] = user.get("nickname") or user.get("username", "") profile["phone"] = user.get("phone", "") profile["phoneBound"] = bool(user.get("phone", "")) + profile["wxBound"] = bool(user.get("wx_openid", "")) + profile["wxMiniBound"] = bool(user.get("wx_mini_openid", "")) profile["status"] = user.get("opc_status", "") profile["topics"] = _parse_topics(user.get("topics", "")) profile["role"] = user.get("role", "opc_member")