From e18b6633a1618a316adc3837fadb9507d5284ed5 Mon Sep 17 00:00:00 2001 From: lzh Date: Mon, 23 Mar 2026 17:42:24 +0800 Subject: [PATCH] =?UTF-8?q?fix(@vben/web-antd):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E4=BC=81=E4=B8=9A=E5=BE=AE=E4=BF=A1=E7=BB=91=E5=AE=9A=E5=9B=9E?= =?UTF-8?q?=E8=B0=83=E8=B5=B0=E6=A0=B8=E5=BF=83=E8=B7=AF=E7=94=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 绑定回调从 /profile(动态路由)改为 /auth/social-login(核心路由), 解决页面刷新时动态路由未注册导致回调参数丢失的问题。 social-login.vue 通过 sessionStorage 区分绑定和登录操作, 绑定完成后自动跳转回个人中心。 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../_core/authentication/social-login.vue | 36 +++++++++++++-- .../_core/profile/modules/user-social.vue | 44 ++----------------- 2 files changed, 37 insertions(+), 43 deletions(-) diff --git a/apps/web-antd/src/views/_core/authentication/social-login.vue b/apps/web-antd/src/views/_core/authentication/social-login.vue index 1052a9a18..a5847c81c 100644 --- a/apps/web-antd/src/views/_core/authentication/social-login.vue +++ b/apps/web-antd/src/views/_core/authentication/social-login.vue @@ -12,12 +12,15 @@ import { $t } from '@vben/locales'; import { useAccessStore } from '@vben/stores'; import { getUrlValue } from '@vben/utils'; +import { message } from 'ant-design-vue'; + import { checkCaptcha, getCaptcha, getTenantByWebsite, getTenantSimpleList, } from '#/api/core/auth'; +import { socialBind } from '#/api/system/social/user'; import { useAuthStore } from '#/store'; defineOptions({ name: 'SocialLogin' }); @@ -69,11 +72,35 @@ async function fetchTenantList() { } } -/** 尝试登录:当账号已经绑定,socialLogin 会直接获得 token */ +/** 尝试登录或绑定 */ const socialType = Number(getUrlValue('type')); const redirect = getUrlValue('redirect'); const socialCode = query?.code as string; const socialState = query?.state as string; + +// 检查是否为绑定操作(从个人中心发起) +const bindAction = sessionStorage.getItem('socialBindAction'); +const bindType = sessionStorage.getItem('socialBindType'); + +async function tryBind() { + const type = Number(bindType); + sessionStorage.removeItem('socialBindAction'); + sessionStorage.removeItem('socialBindType'); + if (!type || !socialCode) { + message.error('绑定失败:缺少参数'); + await router.replace('/profile'); + return; + } + try { + await socialBind({ type, code: socialCode, state: socialState }); + message.success('绑定成功'); + } catch (error) { + console.error('社交绑定失败:', error); + message.error('绑定失败,请重试'); + } + await router.replace('/profile'); +} + async function tryLogin() { // 用于登录后,基于 redirect 的重定向 if (redirect) { @@ -125,10 +152,13 @@ async function handleVerifySuccess({ captchaVerification }: any) { } } -/** 组件挂载时获取租户信息 */ +/** 组件挂载时:绑定操作走绑定流程,否则走登录流程 */ onMounted(async () => { + if (bindAction === 'bind') { + await tryBind(); + return; + } await fetchTenantList(); - await tryLogin(); }); diff --git a/apps/web-antd/src/views/_core/profile/modules/user-social.vue b/apps/web-antd/src/views/_core/profile/modules/user-social.vue index d2621cdd9..41ad0401a 100644 --- a/apps/web-antd/src/views/_core/profile/modules/user-social.vue +++ b/apps/web-antd/src/views/_core/profile/modules/user-social.vue @@ -2,29 +2,21 @@ import type { SystemSocialUserApi } from '#/api/system/social/user'; import { computed, onMounted, ref } from 'vue'; -import { useRoute } from 'vue-router'; import { confirm } from '@vben/common-ui'; import { DICT_TYPE, SystemUserSocialTypeEnum } from '@vben/constants'; import { getDictLabel } from '@vben/hooks'; import { $t } from '@vben/locales'; -import { formatDateTime, getUrlValue } from '@vben/utils'; +import { formatDateTime } from '@vben/utils'; import { Avatar, Button, Image, message, Tag, Tooltip } from 'ant-design-vue'; import { socialAuthRedirect } from '#/api/core/auth'; import { getBindSocialUserList, - socialBind, socialUnbind, } from '#/api/system/social/user'; -const emit = defineEmits<{ - (e: 'update:activeName', v: string): void; -}>(); - -const route = useRoute(); - /** 已经绑定的平台 */ const bindList = ref([]); @@ -77,47 +69,19 @@ async function onBind(bind: SocialBindItem) { return; } try { - // 将 type 存入 sessionStorage,避免放入 redirect_uri 导致参数被截断 + // 标记为绑定操作,回调走 /auth/social-login(核心路由,始终可用) sessionStorage.setItem('socialBindType', String(type)); - const redirectUri = `${location.origin}/profile`; + sessionStorage.setItem('socialBindAction', 'bind'); + const redirectUri = `${location.origin}/auth/social-login`; window.location.href = await socialAuthRedirect(type, redirectUri); } catch (error) { console.error('社交绑定处理失败:', error); } } -/** 监听路由变化,处理社交绑定回调 */ -async function bindSocial() { - const code = route.query.code as string; - const state = route.query.state as string; - if (!code) { - return; - } - // 优先从 sessionStorage 获取 type,兼容从 URL 参数获取 - const storedType = sessionStorage.getItem('socialBindType'); - const type = storedType ? Number(storedType) : Number(getUrlValue('type')); - sessionStorage.removeItem('socialBindType'); - if (!type) { - message.error('绑定失败:缺少社交平台类型'); - return; - } - try { - await socialBind({ type, code, state }); - message.success('绑定成功'); - emit('update:activeName', 'userSocial'); - await loadBindList(); - } catch (error) { - console.error('社交绑定失败:', error); - message.error('绑定失败,请重试'); - } finally { - window.history.replaceState({}, '', location.pathname); - } -} - /** 初始化 */ onMounted(async () => { await loadBindList(); - await bindSocial(); });