feat(系统管理): 新增钉钉登陆

This commit is contained in:
guoyuqi 2024-06-04 20:12:40 +08:00 committed by Craftsman
parent 74c44e8459
commit c2df6e04e2
6 changed files with 81 additions and 16 deletions

View File

@ -12,7 +12,9 @@ public class FilterChainUtils {
filterChainDefinitionMap.put("/ldap/login", "anon");
filterChainDefinitionMap.put("/authentication/get-list", "anon");
filterChainDefinitionMap.put("/we_com/info", "anon");
filterChainDefinitionMap.put("/ding_talk/info", "anon");
filterChainDefinitionMap.put("/sso/callback/we_com", "anon");
filterChainDefinitionMap.put("/auth", "anon");
filterChainDefinitionMap.put("/setting/get/platform/param", "anon");
filterChainDefinitionMap.put("/signout", "anon");
filterChainDefinitionMap.put("/is-login", "anon");

View File

@ -7,8 +7,10 @@ import {
DisableLocalConfigUrl,
EnableAPIKEYUrl,
EnableLocalConfigUrl,
GeDingInfoUrl,
GetAPIKEYListUrl,
getAuthenticationUrl,
GetDingCallbackUrl,
GetInfoUrl,
GetLocalConfigUrl,
GetMenuListUrl,
@ -46,7 +48,7 @@ import type {
UpdateLocalConfigParams,
UpdatePswParams,
} from '@/models/user';
import { WecomInfo } from '@/models/user';
import { DingInfo, WecomInfo } from '@/models/user';
import type { RouteRecordNormalized } from 'vue-router';
@ -83,6 +85,16 @@ export function getWeComCallback(code: string) {
);
}
export function getDingInfo() {
return MSR.get<DingInfo>({ url: GeDingInfoUrl }, { ignoreCancelToken: true, errorMessageMode: 'none' });
}
export function getDingCallback(code: string) {
return MSR.get<LoginRes>(
{ url: GetDingCallbackUrl, params: { code } },
{ ignoreCancelToken: true, errorMessageMode: 'none' }
);
}
export function logout() {
return MSR.get<LoginRes>({ url: LogoutUrl });
}

View File

@ -29,3 +29,5 @@ export const GetPlatformOrgOptionUrl = '/user/platform/switch-option'; // 个人
export const GetWeComInfoUrl = '/we_com/info'; // 获取企业微信登陆的配置信息
export const GetWeComCallbackUrl = '/sso/callback/we_com'; // 获取企业微信登陆的回调信息
export const GetPlatformParamUrl = '/setting/get/platform/param';
export const GeDingInfoUrl = '/ding_talk/info'; // 获取企业微信登陆的配置信息
export const GetDingCallbackUrl = '/auth'; // 获取企业微信登陆的回调信息

View File

@ -21,6 +21,13 @@ export interface WecomInfo {
callBack?: string;
}
// 企业微信对接信息
export interface DingInfo {
agentId?: string;
state?: string;
callBack?: string;
}
// 更新本地执行配置
export interface UpdateLocalConfigParams {
id: string;

View File

@ -3,16 +3,32 @@
</template>
<script lang="ts" setup>
import { useRouter } from 'vue-router';
import { useScriptTag } from '@vueuse/core';
import { Message } from '@arco-design/web-vue';
import { getProjectInfo } from '@/api/modules/project-management/basicInfo';
import { getDingCallback, getDingInfo } from '@/api/modules/user';
import { useI18n } from '@/hooks/useI18n';
import { NO_PROJECT_ROUTE_NAME, NO_RESOURCE_ROUTE_NAME } from '@/router/constants';
import { useAppStore, useUserStore } from '@/store';
import useLicenseStore from '@/store/modules/setting/license';
import { setLoginExpires } from '@/utils/auth';
import { getFirstRouteNameByPermission, routerNameHasPermission } from '@/utils/permission';
const { t } = useI18n();
const userStore = useUserStore();
const appStore = useAppStore();
const licenseStore = useLicenseStore();
const router = useRouter();
const { load } = useScriptTag('https://g.alicdn.com/dingding/h5-dingtalk-login/0.21.0/ddlogin.js');
const a = encodeURIComponent('https://s0my5tnf41e2.ngrok.xiaomiqiu123.top/');
const url = `https://login.dingtalk.com/oauth2/auth?redirect_uri=${a}&response_type=code&client_id=dinglsfxhodjquu4gq2x&scope=openid&state=dddd&prompt=consent`;
const initActive = async () => {
const data = await getDingInfo();
await load(true);
const url = encodeURIComponent(data.callBack ? data.callBack : '');
window.DTFrameLogin(
{
id: 'ding-talk-qr',
@ -20,17 +36,42 @@
height: 300,
},
{
redirect_uri: a,
client_id: 'dinglsfxhodjquu4gq2x',
redirect_uri: url,
client_id: data.agentId ? data.agentId : '',
scope: 'openid',
response_type: 'code',
state: 'xxxxxxxxx',
state: 'fit2cloud-ding-qr',
prompt: 'consent',
},
(loginResult) => {
async (loginResult) => {
const { redirectUrl, authCode, state } = loginResult;
//
window.location.href = redirectUrl;
const dingCallback = getDingCallback(authCode);
userStore.qrCodeLogin(await dingCallback);
Message.success(t('login.form.login.success'));
const { redirect, ...othersQuery } = router.currentRoute.value.query;
const redirectHasPermission =
redirect &&
![NO_RESOURCE_ROUTE_NAME, NO_PROJECT_ROUTE_NAME].includes(redirect as string) &&
routerNameHasPermission(redirect as string, router.getRoutes());
const currentRouteName = getFirstRouteNameByPermission(router.getRoutes());
const [res] = await Promise.all([getProjectInfo(appStore.currentProjectId), licenseStore.getValidateLicense()]); // license license
if (!res || res.deleted) {
router.push({
name: NO_PROJECT_ROUTE_NAME,
});
}
if (res) {
appStore.setCurrentMenuConfig(res?.moduleIds || []);
}
setLoginExpires();
router.push({
name: redirectHasPermission ? (redirect as string) : currentRouteName,
query: {
...othersQuery,
orgId: appStore.currentOrgId,
pId: appStore.currentProjectId,
},
});
// 使code
console.log(authCode);
},

View File

@ -1,10 +1,10 @@
<template>
<a-tabs v-model:active-key="activeName" class="tabPlatform" @change="handleClick">
<a-tab-pane key="wecom" :title="t('project.messageManagement.WE_COM')" class="font-[16px]"></a-tab-pane>
<a-tab-pane key="dingtalk" :title="t('project.messageManagement.DING_TALK')" class="font-[16px]"></a-tab-pane>
<a-radio-group v-model:active-key="activeName" type="button" class="tabPlatform" @change="handleClick">
<a-radio value="wecom">{{ t('project.messageManagement.WE_COM') }}</a-radio>
<a-radio value="dingtalk">{{ t('project.messageManagement.DING_TALK') }}</a-radio>
<!-- <a-tab-pane key="lark" :title="t('project.messageManagement.LARK')"></a-tab-pane>
<a-tab-pane key="larksuite" :title="t('project.messageManagement.LARK_SUITE')"></a-tab-pane>-->
</a-tabs>
</a-radio-group>
<div v-if="activeName === 'wecom'" class="login-qrcode">
<div class="qrcode">
<wecom-qr v-if="activeName === 'wecom'" />
@ -56,7 +56,7 @@
}
}
};
function handleClick(val: string | number) {
function handleClick(val: string | number | boolean) {
if (typeof val === 'string') {
activeName.value = val;
}
@ -84,6 +84,7 @@
overflow: hidden;
border-radius: 8px;
background: #ffffff;
flex-direction: column;
}
.title {
display: flex;