gaoluyang
2026-06-24 c0cb161bb52ce0fbdce5c66ec391d107c75e2452
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
<script setup lang="ts">
import { useRoute } from 'vue-router';
 
import { SvgDingDingIcon } from '..\..\..\..\..\icons\src';
import { $t } from '..\..\..\..\..\locales\src';
 
import { alert, useVbenModal } from '..\..\..\..\..\@core\ui-kit\popup-ui\src';
import { VbenIconButton } from '..\..\..\..\..\@core\ui-kit\shadcn-ui\src';
import { loadScript } from '..\..\..\..\..\@core\base\shared\src\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: 'size-75.5 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"
    >
      <SvgDingDingIcon />
    </VbenIconButton>
    <Modal>
      <div id="dingding_qrcode_login_element"></div>
    </Modal>
  </div>
</template>
 
<style>
.dingding-qrcode-login-modal {
  .relative {
    padding: 0 !important;
  }
}
</style>