feat: add dingding login

This commit is contained in:
zhongming4762
2025-07-25 22:02:55 +08:00
parent 5b75e5e917
commit 06ffdf164a
11 changed files with 291 additions and 6 deletions

View File

@@ -0,0 +1,113 @@
<script setup lang="ts">
import { useRoute } from 'vue-router';
import { RiDingding } from '@vben/icons';
import { $t } from '@vben/locales';
import { alert, useVbenModal } from '@vben-core/popup-ui';
import { VbenIconButton } from '@vben-core/shadcn-ui';
import { loadScript } from '@vben-core/shared/utils';
interface Props {
clientId: string;
corpId: string;
// 登录回调地址
redirectUri?: string;
// 是否内嵌二维码登录
isQrCode?: boolean;
}
const props = defineProps<Props>();
const route = useRoute();
const [Modal, modalApi] = useVbenModal({
header: false,
footer: false,
fullscreenButton: false,
class: 'w-[302px] h-[302px] dingding-qrcode-login-modal',
onOpened() {
handleQrCodeLogin();
},
});
const getRedirectUri = () => {
const { redirectUri } = props;
if (redirectUri) {
return redirectUri;
}
return window.location.origin + route.fullPath;
};
/**
* 内嵌二维码登录
*/
const handleQrCodeLogin = async () => {
const { clientId, corpId } = props;
if (!(window as any).DTFrameLogin) {
// 二维码登录 加载资源
await loadScript(
'https://g.alicdn.com/dingding/h5-dingtalk-login/0.21.0/ddlogin.js',
);
}
(window as any).DTFrameLogin(
{
id: 'dingding_qrcode_login_element',
width: 300,
height: 300,
},
{
// 注意redirect_uri 需为完整URL扫码后钉钉会带code跳转到这里
redirect_uri: encodeURIComponent(getRedirectUri()),
client_id: clientId,
scope: 'openid corpid',
response_type: 'code',
state: '1',
prompt: 'consent',
corpId,
},
(loginResult: any) => {
const { redirectUrl } = loginResult;
// 这里可以直接进行重定向
window.location.href = redirectUrl;
},
(errorMsg: string) => {
// 这里一般需要展示登录失败的具体原因
alert(`Login Error: ${errorMsg}`);
},
);
};
const handleLogin = () => {
const { clientId, corpId, isQrCode } = props;
if (isQrCode) {
// 内嵌二维码登录
modalApi.open();
} else {
window.location.href = `https://login.dingtalk.com/oauth2/auth?redirect_uri=${encodeURIComponent(getRedirectUri())}&response_type=code&client_id=${clientId}&scope=openid&corpid=${corpId}&prompt=consent`;
}
};
</script>
<template>
<div>
<VbenIconButton
@click="handleLogin"
:tooltip="$t('authentication.dingdingLogin')"
tooltip-side="top"
>
<RiDingding />
</VbenIconButton>
<Modal>
<div id="dingding_qrcode_login_element"></div>
</Modal>
</div>
</template>
<style>
.dingding-qrcode-login-modal {
.relative {
padding: 0 !important;
}
}
</style>

View File

@@ -1,12 +1,19 @@
<script setup lang="ts">
import { useAppConfig } from '@vben/hooks';
import { MdiGithub, MdiGoogle, MdiQqchat, MdiWechat } from '@vben/icons';
import { $t } from '@vben/locales';
import { VbenIconButton } from '@vben-core/shadcn-ui';
import DingdingLogin from './dingding-login.vue';
defineOptions({
name: 'ThirdPartyLogin',
});
const {
auth: { dingding: dingdingAuthConfig },
} = useAppConfig(import.meta.env, import.meta.env.PROD);
</script>
<template>
@@ -20,18 +27,40 @@ defineOptions({
</div>
<div class="mt-4 flex flex-wrap justify-center">
<VbenIconButton class="mb-3">
<VbenIconButton
:tooltip="$t('authentication.wechatLogin')"
tooltip-side="top"
class="mb-3"
>
<MdiWechat />
</VbenIconButton>
<VbenIconButton class="mb-3">
<VbenIconButton
:tooltip="$t('authentication.qqLogin')"
tooltip-side="top"
class="mb-3"
>
<MdiQqchat />
</VbenIconButton>
<VbenIconButton class="mb-3">
<VbenIconButton
:tooltip="$t('authentication.githubLogin')"
tooltip-side="top"
class="mb-3"
>
<MdiGithub />
</VbenIconButton>
<VbenIconButton class="mb-3">
<VbenIconButton
:tooltip="$t('authentication.googleLogin')"
tooltip-side="top"
class="mb-3"
>
<MdiGoogle />
</VbenIconButton>
<DingdingLogin
v-if="dingdingAuthConfig"
:corp-id="dingdingAuthConfig.corpId"
:client-id="dingdingAuthConfig.clientId"
class="mb-3"
/>
</div>
</div>
</template>

View File

@@ -15,9 +15,22 @@ export function useAppConfig(
? window._VBEN_ADMIN_PRO_APP_CONF_
: (env as VbenAdminProAppConfigRaw);
const { VITE_GLOB_API_URL } = config;
const {
VITE_GLOB_API_URL,
VITE_GLOB_AUTH_DINGDING_CORP_ID,
VITE_GLOB_AUTH_DINGDING_CLIENT_ID,
} = config;
return {
const applicationConfig: ApplicationConfig = {
apiURL: VITE_GLOB_API_URL,
auth: {},
};
if (VITE_GLOB_AUTH_DINGDING_CORP_ID && VITE_GLOB_AUTH_DINGDING_CLIENT_ID) {
applicationConfig.auth.dingding = {
clientId: VITE_GLOB_AUTH_DINGDING_CLIENT_ID,
corpId: VITE_GLOB_AUTH_DINGDING_CORP_ID,
};
}
return applicationConfig;
}