From 555dc1c063af59b6236762d7bb62e905022bae5b Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 20 Apr 2025 19:49:16 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E5=A2=9E=E5=8A=A0=E4=B8=AA?= =?UTF-8?q?=E4=BA=BA=E4=B8=AD=E5=BF=83=EF=BC=9A60%=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=8F=B3=E4=BE=A7=E7=9A=84=E7=A4=BE=E4=BA=A4=E7=BB=91=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/_core/profile/index.vue | 8 +-- .../_core/profile/modules/user-social.vue | 60 +++++++++++++++++-- 2 files changed, 59 insertions(+), 9 deletions(-) diff --git a/apps/web-antd/src/views/_core/profile/index.vue b/apps/web-antd/src/views/_core/profile/index.vue index 7b03a4e14..4566b2c8a 100644 --- a/apps/web-antd/src/views/_core/profile/index.vue +++ b/apps/web-antd/src/views/_core/profile/index.vue @@ -13,8 +13,7 @@ import { getUserProfile } from '#/api/system/user/profile'; import { useAuthStore } from '#/store'; const authStore = useAuthStore(); -// const activeName = ref('basicInfo'); -const activeName = ref('userSocial'); +const activeName = ref('basicInfo'); /** 加载个人信息 */ const profile = ref(); @@ -52,9 +51,10 @@ onMounted(loadProfile); - - + + + 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 b9e892f1d..3ddbc2695 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 @@ -4,13 +4,20 @@ import type { SystemSocialUserApi } from '#/api/system/social/user'; import { Button, Card, Image, message, Modal } from 'ant-design-vue'; -import { computed, ref } from 'vue'; +import { computed, ref, onMounted } from 'vue'; +import { useRoute } from 'vue-router'; import { $t } from '#/locales'; import { useVbenVxeGrid } from '#/adapter/vxe-table'; -import { getBindSocialUserList, socialUnbind } from '#/api/system/social/user'; +import { getBindSocialUserList, socialUnbind, socialBind } from '#/api/system/social/user'; +import { socialAuthRedirect } from '#/api/core/auth'; import { DICT_TYPE, getDictLabel } from '#/utils/dict'; import { SystemUserSocialTypeEnum } from '#/utils/constants'; +const route = useRoute() +const emit = defineEmits<{ + (e: 'update:activeName', v: string): void +}>() + /** 已经绑定的平台 */ const bindList = ref([]); const allBindList = computed(() => { @@ -101,10 +108,53 @@ function onUnbind(row: SystemSocialUserApi.SystemSocialUser) { }); } -/** 绑定账号 */ -function onBind(bind: any) { - alert('待实现!'); +/** 绑定账号(跳转授权页面) */ +async function onBind(bind: any) { + const type = bind.type; + if (type <= 0) { + return; + } + try { + // 计算 redirectUri + // tricky: type 需要先 encode 一次,否则钉钉回调会丢失。配合 getUrlValue() 使用 + const redirectUri = location.origin + '/profile?' + encodeURIComponent(`type=${type}`) + + // 进行跳转 + window.location.href = await socialAuthRedirect(type, redirectUri) + } catch (error) { + console.error('社交绑定处理失败:', error); + } } + +/** 监听路由变化,处理社交绑定回调 */ +async function bindSocial() { + // 社交绑定 + const type = Number(getUrlValue('type')) + const code = route.query.code as string + const state = route.query.state as string + if (!code) { + return + } + await socialBind({ type, code, state }) + // 提示成功 + message.success('绑定成功') + emit('update:activeName', 'userSocial') + await gridApi.reload(); + // 清理 URL 参数,避免刷新重复触发 + window.history.replaceState({}, '', location.pathname) +} + +// TODO @芋艿:后续搞到 util 里; +// 双层 encode 需要在回调后进行 decode +function getUrlValue(key: string): string { + const url = new URL(decodeURIComponent(location.href)) + return url.searchParams.get(key) ?? '' +} + +/** 初始化 */ +onMounted(() => { + bindSocial() +})