feat(invite): 支持已登录用户直接加入应用

- 后端accept接口code参数改为可选,支持通过Authorization头识别登录用户
- 已登录用户加入时不再弹手机号授权,前端调用新增的doJoinAppForLoggedInUser方法
- 未注册用户仍通过手机号授权码code加入,调用doJoinAppForNewUser方法
- 拆分前端加入逻辑,新增handleConfirmJoin统一处理已登录加入流程
- 优化按钮交互,已登录状态下按钮变为普通点击,移除协议强制勾选
- 错误处理和状态提示完善,加入成功后自动跳转首页
This commit is contained in:
2026-04-12 11:56:11 +08:00
parent 6084cd5a5b
commit 2ae30ac692
3 changed files with 108 additions and 14 deletions

View File

@@ -129,8 +129,7 @@ const InvitePage: React.FC = () => {
/**
* 已登录用户:点击「确认加入」
* 不弹手机号授权,直接用 wx.login() 获取 code 调加入接口
* 不强制要求勾选协议
* 后端已改造支持已登录用户直接加入(不传 code从 Authorization 头识别用户)
*/
const handleConfirmJoin = async () => {
const accessToken = Taro.getStorageSync('access_token');
@@ -141,10 +140,8 @@ const InvitePage: React.FC = () => {
try {
setAuthLoading(true);
// 用 wx.login() 获取 code后端需要 code 识别用户身份)
const wxRes = await Taro.login();
if (!wxRes.code) throw new Error('获取微信登录凭证失败');
await doJoinApp(wxRes.code, accessToken);
// 已登录用户不传 code后端从 Authorization 头识别用户
await doJoinAppForLoggedInUser(accessToken);
} catch (err: any) {
console.error('确认加入失败:', err);
Taro.showToast({ title: err.message || '加入失败,请重试', icon: 'none' });
@@ -209,7 +206,7 @@ const InvitePage: React.FC = () => {
const wxRes = await Taro.login();
if (!wxRes.code) throw new Error('获取微信登录凭证失败');
await doJoinApp(wxRes.code, access_token);
await doJoinAppForNewUser(wxRes.code, access_token);
} catch (err: any) {
console.error('手机号授权登录失败:', err);
Taro.showToast({ title: err.message || '授权失败,请重试', icon: 'none' });
@@ -219,13 +216,43 @@ const InvitePage: React.FC = () => {
};
/**
* 调用加入接口(统一入口
* @param wxCode wx.login() 或 getPhoneNumber 获取的 code后端用于识别用户
* @param accessToken 登录 token加到 Authorization 头,双重验证)
* 已登录用户调用加入接口(不传 code后端从 Authorization 头识别用户
*/
const doJoinApp = async (wxCode: string, accessToken: string) => {
const doJoinAppForLoggedInUser = async (accessToken: string) => {
const inviteToken = Taro.getStorageSync('invite_token') || token;
console.log('doJoinApp, inviteToken:', inviteToken, 'wxCode:', wxCode ? '有' : '无', 'accessToken:', accessToken ? '有' : '无');
console.log('doJoinAppForLoggedInUser, inviteToken:', inviteToken, 'accessToken:', accessToken ? '有' : '无');
const res = await Taro.request({
url: `${INVITE_API_URL}/api/_app/developer/invite/accept`,
method: 'POST',
data: {
token: inviteToken,
// 已登录用户不传 code后端从 Authorization 头识别用户
},
header: {
'content-type': 'application/json',
TenantId,
Authorization: `Bearer ${accessToken}`,
},
});
console.log('加入应用接口响应:', res);
if (res.data.code === 200 || res.data.code === 0) {
Taro.removeStorageSync('invite_token');
Taro.showToast({ title: '加入成功', icon: 'success', duration: 1500 });
setTimeout(() => Taro.switchTab({ url: '/pages/index/index' }), 1500);
} else {
throw new Error(res.data.message || '加入失败');
}
};
/**
* 未注册用户调用加入接口(传 code后端用 code 获取手机号创建用户)
*/
const doJoinAppForNewUser = async (wxCode: string, accessToken: string) => {
const inviteToken = Taro.getStorageSync('invite_token') || token;
console.log('doJoinAppForNewUser, inviteToken:', inviteToken, 'wxCode:', wxCode ? '有' : '无', 'accessToken:', accessToken ? '有' : '无');
const res = await Taro.request({
url: `${INVITE_API_URL}/api/_app/developer/invite/accept`,
@@ -431,7 +458,7 @@ const InvitePage: React.FC = () => {
boxShadow: '0 0 30px rgba(59, 130, 246, 0.4)',
}}>
{isLoggedIn ? (
/* 已登录:普通按钮,不弹手机号授权,用 wx.login() 获取 code */
/* 已登录:普通按钮,不弹手机号授权,直接调后端 */
<Button
onClick={handleConfirmJoin}
disabled={authLoading}