1
This commit is contained in:
parent
02c35c146d
commit
69e6338722
@ -5,7 +5,7 @@ from sqlalchemy.orm import selectinload
|
|||||||
|
|
||||||
from app.core.deps import get_current_user
|
from app.core.deps import get_current_user
|
||||||
from app.db.database import get_db
|
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.user import TokenResponse, build_user_out
|
||||||
from app.schemas.wechat import (
|
from app.schemas.wechat import (
|
||||||
WeChatBindRequest,
|
WeChatBindRequest,
|
||||||
@ -28,6 +28,31 @@ from app.services.wechat_service import (
|
|||||||
router = APIRouter(prefix="/api/wechat", tags=["wechat"])
|
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)
|
@router.post("/login", response_model=WeChatLoginResponse)
|
||||||
async def wechat_login(req: WeChatLoginRequest, db: AsyncSession = Depends(get_db)):
|
async def wechat_login(req: WeChatLoginRequest, db: AsyncSession = Depends(get_db)):
|
||||||
session = await exchange_code_for_session(req.code)
|
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.invite_code.strip().upper(),
|
||||||
req.student_id.strip(),
|
req.student_id.strip(),
|
||||||
)
|
)
|
||||||
|
approved_target = None
|
||||||
if activation_target is 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:
|
if existing is not None and existing.id != user.id:
|
||||||
raise HTTPException(status_code=400, detail="该微信已绑定其他账号")
|
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:
|
if user.phone and user.phone != phone:
|
||||||
raise HTTPException(status_code=400, detail="手机号与预留手机号不一致")
|
raise HTTPException(status_code=400, detail="手机号与预留手机号不一致")
|
||||||
|
|
||||||
|
|||||||
@ -126,7 +126,8 @@ Page({
|
|||||||
phone_code: phoneCode
|
phone_code: phoneCode
|
||||||
});
|
});
|
||||||
saveSession(res.token, res.user);
|
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) {
|
} catch (error) {
|
||||||
wx.showToast({ title: error.message || "绑定失败", icon: "none" });
|
wx.showToast({ title: error.message || "绑定失败", icon: "none" });
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
<view wx:if="{{isWechatLogin}}" class="login-method">
|
<view wx:if="{{isWechatLogin}}" class="login-method">
|
||||||
<view class="wechat-symbol">微</view>
|
<view class="wechat-symbol">微</view>
|
||||||
<view class="login-title">微信快捷登录</view>
|
<view class="login-title">微信快捷登录</view>
|
||||||
<view class="login-copy">已绑定微信的同学可直接进入班级空间;未绑定账号会进入激活流程。</view>
|
<view class="login-copy">已绑定微信的同学可直接进入班级空间;未绑定微信的账号会进入绑定流程。</view>
|
||||||
<button class="button login-primary" loading="{{loading}}" bindtap="loginWithWechatTap">使用微信登录</button>
|
<button class="button login-primary" loading="{{loading}}" bindtap="loginWithWechatTap">使用微信登录</button>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@ -37,13 +37,13 @@
|
|||||||
|
|
||||||
<view wx:elif="{{isActivateMode}}" class="section">
|
<view wx:elif="{{isActivateMode}}" class="section">
|
||||||
<view class="section-head">
|
<view class="section-head">
|
||||||
<view class="section-title">激活账号</view>
|
<view class="section-title">绑定班级账号</view>
|
||||||
<view class="section-action" bindtap="backToLogin">返回登录</view>
|
<view class="section-action" bindtap="backToLogin">返回登录</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="card">
|
<view class="card">
|
||||||
<view class="muted">说明</view>
|
<view class="muted">说明</view>
|
||||||
<view class="card-title">没有找到已绑定的微信账号</view>
|
<view class="card-title">没有找到已绑定的微信账号</view>
|
||||||
<view class="muted">请用班级邀请码、学号和微信手机号激活你的班级账号。</view>
|
<view class="muted">请用班级邀请码、学号和微信手机号绑定你的班级账号;已在网站激活的账号也可以直接绑定并登录。</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="card">
|
<view class="card">
|
||||||
<view class="muted">邀请码</view>
|
<view class="muted">邀请码</view>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user