fix(@vben/web-antd): 重构企业微信绑定回调走核心路由

绑定回调从 /profile(动态路由)改为 /auth/social-login(核心路由),
解决页面刷新时动态路由未注册导致回调参数丢失的问题。
social-login.vue 通过 sessionStorage 区分绑定和登录操作,
绑定完成后自动跳转回个人中心。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
lzh
2026-03-23 17:42:24 +08:00
parent 24c3dbc8f1
commit e18b6633a1
2 changed files with 37 additions and 43 deletions

View File

@@ -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();
});

View File

@@ -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<SystemSocialUserApi.SocialUser[]>([]);
@@ -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();
});
</script>