From 69e6338722560e5950ad07f1873672afb0469116 Mon Sep 17 00:00:00 2001 From: aaron <> Date: Sat, 23 May 2026 14:52:29 +0800 Subject: [PATCH] 1 --- backend/app/api/wechat.py | 40 ++++++++++++++++++++++++++++--- miniprogram/pages/bind/index.js | 3 ++- miniprogram/pages/bind/index.wxml | 6 ++--- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/backend/app/api/wechat.py b/backend/app/api/wechat.py index 9ac2dd7..873d150 100644 --- a/backend/app/api/wechat.py +++ b/backend/app/api/wechat.py @@ -5,7 +5,7 @@ from sqlalchemy.orm import selectinload from app.core.deps import get_current_user from app.db.database import get_db -from app.db.models import ClassMembership, User +from app.db.models import ClassMembership, Class_, User from app.schemas.user import TokenResponse, build_user_out from app.schemas.wechat import ( WeChatBindRequest, @@ -28,6 +28,31 @@ from app.services.wechat_service import ( router = APIRouter(prefix="/api/wechat", tags=["wechat"]) +async def _find_approved_member_for_wechat_bind( + db: AsyncSession, + invite_code: str, + student_id: str, +) -> tuple[User, int] | None: + result = await db.execute( + select(User, ClassMembership.class_id) + .join(ClassMembership, ClassMembership.user_id == User.id) + .join(Class_, Class_.id == ClassMembership.class_id) + .options( + selectinload(User.memberships), + selectinload(User.memberships).selectinload(ClassMembership.class_), + ) + .where( + Class_.invite_code == invite_code, + User.student_id == student_id, + User.status == "approved", + ) + ) + row = result.first() + if row is None: + return None + return row[0], row[1] + + @router.post("/login", response_model=WeChatLoginResponse) async def wechat_login(req: WeChatLoginRequest, db: AsyncSession = Depends(get_db)): session = await exchange_code_for_session(req.code) @@ -60,12 +85,21 @@ async def wechat_bind(req: WeChatBindRequest, db: AsyncSession = Depends(get_db) req.invite_code.strip().upper(), req.student_id.strip(), ) + approved_target = None if activation_target is None: - raise HTTPException(status_code=400, detail="邀请码或学号无效,或账号已激活") + approved_target = await _find_approved_member_for_wechat_bind( + db, + req.invite_code.strip().upper(), + req.student_id.strip(), + ) + if activation_target is None and approved_target is None: + raise HTTPException(status_code=400, detail="邀请码或学号无效") - user, class_id = activation_target + user, class_id = activation_target or approved_target if existing is not None and existing.id != user.id: raise HTTPException(status_code=400, detail="该微信已绑定其他账号") + if user.wechat_openid and user.wechat_openid != openid: + raise HTTPException(status_code=400, detail="该账号已绑定其他微信") if user.phone and user.phone != phone: raise HTTPException(status_code=400, detail="手机号与预留手机号不一致") diff --git a/miniprogram/pages/bind/index.js b/miniprogram/pages/bind/index.js index 92ba772..9a71d78 100644 --- a/miniprogram/pages/bind/index.js +++ b/miniprogram/pages/bind/index.js @@ -126,7 +126,8 @@ Page({ phone_code: phoneCode }); saveSession(res.token, res.user); - wx.switchTab({ url: "/pages/home/index" }); + wx.showToast({ title: "绑定成功", icon: "success" }); + setTimeout(() => wx.switchTab({ url: "/pages/home/index" }), 500); } catch (error) { wx.showToast({ title: error.message || "绑定失败", icon: "none" }); } finally { diff --git a/miniprogram/pages/bind/index.wxml b/miniprogram/pages/bind/index.wxml index 0745103..44176fd 100644 --- a/miniprogram/pages/bind/index.wxml +++ b/miniprogram/pages/bind/index.wxml @@ -15,7 +15,7 @@ 微信快捷登录 - 已绑定微信的同学可直接进入班级空间;未绑定账号会进入激活流程。 + 已绑定微信的同学可直接进入班级空间;未绑定微信的账号会进入绑定流程。 @@ -37,13 +37,13 @@ - 激活账号 + 绑定班级账号 返回登录 说明 没有找到已绑定的微信账号 - 请用班级邀请码、学号和微信手机号激活你的班级账号。 + 请用班级邀请码、学号和微信手机号绑定你的班级账号;已在网站激活的账号也可以直接绑定并登录。 邀请码