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 @@
- 激活账号
+ 绑定班级账号
返回登录
说明
没有找到已绑定的微信账号
- 请用班级邀请码、学号和微信手机号激活你的班级账号。
+ 请用班级邀请码、学号和微信手机号绑定你的班级账号;已在网站激活的账号也可以直接绑定并登录。
邀请码