feat: add platform authentication methods and improve QR code handling
This commit is contained in:
parent
0eb1cf701e
commit
f744e8b109
@ -31,8 +31,30 @@ const putAuthSetting: (auth_type: string, data: any, loading?: Ref<boolean>) =>
|
||||
return put(`${prefix}/${auth_type}/info`, data, undefined, loading)
|
||||
}
|
||||
|
||||
const platformPrefix = '/chat_user/auth/platform'
|
||||
const getPlatformInfo: (loading?: Ref<boolean>) => Promise<Result<any>> = (loading) => {
|
||||
return get(`${platformPrefix}/source`, undefined, loading)
|
||||
}
|
||||
|
||||
const updateConfig: (data: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||
data,
|
||||
loading
|
||||
) => {
|
||||
return post(`${platformPrefix}/source`, data, undefined, loading)
|
||||
}
|
||||
|
||||
const validateConnection: (data: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||
data,
|
||||
loading
|
||||
) => {
|
||||
return put(`${platformPrefix}/source`, data, undefined, loading)
|
||||
}
|
||||
|
||||
export default {
|
||||
getAuthSetting,
|
||||
postAuthSetting,
|
||||
putAuthSetting
|
||||
putAuthSetting,
|
||||
getPlatformInfo,
|
||||
updateConfig,
|
||||
validateConnection
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Result } from '@/request/Result'
|
||||
import {Result} from '@/request/Result'
|
||||
import {
|
||||
get,
|
||||
post,
|
||||
@ -9,17 +9,17 @@ import {
|
||||
download,
|
||||
exportFile,
|
||||
} from '@/request/chat/index'
|
||||
import { type ChatProfile } from '@/api/type/chat'
|
||||
import { type Ref } from 'vue'
|
||||
import type { ResetPasswordRequest } from '@/api/type/user.ts'
|
||||
import {type ChatProfile} from '@/api/type/chat'
|
||||
import {type Ref} from 'vue'
|
||||
import type {ResetPasswordRequest} from '@/api/type/user.ts'
|
||||
|
||||
import useStore from '@/stores'
|
||||
import type { LoginRequest } from '@/api/type/user'
|
||||
import type {LoginRequest} from '@/api/type/user'
|
||||
|
||||
const prefix: any = { _value: '/workspace/' }
|
||||
const prefix: any = {_value: '/workspace/'}
|
||||
Object.defineProperty(prefix, 'value', {
|
||||
get: function () {
|
||||
const { user } = useStore()
|
||||
const {user} = useStore()
|
||||
return this._value + user.getWorkspaceId() + '/application'
|
||||
},
|
||||
})
|
||||
@ -51,7 +51,7 @@ const chatProfile: (assessToken: string, loading?: Ref<boolean>) => Promise<Resu
|
||||
assessToken,
|
||||
loading,
|
||||
) => {
|
||||
return get('/profile', { access_token: assessToken }, loading)
|
||||
return get('/profile', {access_token: assessToken}, loading)
|
||||
}
|
||||
/**
|
||||
* 匿名认证
|
||||
@ -63,7 +63,7 @@ const anonymousAuthentication: (
|
||||
assessToken: string,
|
||||
loading?: Ref<boolean>,
|
||||
) => Promise<Result<any>> = (assessToken, loading) => {
|
||||
return post('/auth/anonymous', { access_token: assessToken }, {}, loading)
|
||||
return post('/auth/anonymous', {access_token: assessToken}, {}, loading)
|
||||
}
|
||||
/**
|
||||
* 密码认证
|
||||
@ -77,7 +77,7 @@ const passwordAuthentication: (
|
||||
password: string,
|
||||
loading?: Ref<boolean>,
|
||||
) => Promise<Result<any>> = (assessToken, password, loading) => {
|
||||
return post('auth/password', { access_token: assessToken, password: password }, {}, loading)
|
||||
return post('auth/password', {access_token: assessToken, password: password}, {}, loading)
|
||||
}
|
||||
/**
|
||||
* 获取应用相关信息
|
||||
@ -122,38 +122,40 @@ const getCaptcha: (loading?: Ref<boolean>) => Promise<Result<any>> = (loading) =
|
||||
* 获取二维码类型
|
||||
*/
|
||||
const getQrType: (loading?: Ref<boolean>) => Promise<Result<any>> = (loading) => {
|
||||
return get('qr_type', undefined, loading)
|
||||
return get('auth/qr_type', undefined, loading)
|
||||
}
|
||||
|
||||
const getQrSource: (loading?: Ref<boolean>) => Promise<Result<any>> = (loading) => {
|
||||
return get('qr_type/source', undefined, loading)
|
||||
return get('auth/qr_type/source', undefined, loading)
|
||||
}
|
||||
|
||||
const getDingCallback: (code: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||
const getDingCallback: (code: string, accessToken: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||
code,
|
||||
accessToken,
|
||||
loading,
|
||||
) => {
|
||||
return get('dingtalk', { code }, loading)
|
||||
return get('auth/dingtalk', {code, accessToken: accessToken}, loading)
|
||||
}
|
||||
|
||||
const getDingOauth2Callback: (code: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||
code,
|
||||
loading,
|
||||
) => {
|
||||
return get('dingtalk/oauth2', { code }, loading)
|
||||
return get('auth/dingtalk/oauth2', {code}, loading)
|
||||
}
|
||||
|
||||
const getWecomCallback: (code: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||
const getWecomCallback: (code: string, accessToken: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||
code,
|
||||
accessToken,
|
||||
loading,
|
||||
) => {
|
||||
return get('wecom', { code }, loading)
|
||||
return get('auth/wecom', {code, accessToken: accessToken}, loading)
|
||||
}
|
||||
const getLarkCallback: (code: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||
code,
|
||||
loading,
|
||||
) => {
|
||||
return get('lark/oauth2', { code }, loading)
|
||||
return get('auth/lark/oauth2', {code}, loading)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -274,17 +276,17 @@ const deleteChat: (chat_id: string, loading?: Ref<boolean>) => Promise<Result<an
|
||||
chat_id,
|
||||
loading,
|
||||
) => {
|
||||
return del(`historical_conversation/${chat_id}`,undefined,undefined ,loading)
|
||||
return del(`historical_conversation/${chat_id}`, undefined, undefined, loading)
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param loading
|
||||
* @returns
|
||||
*
|
||||
* @param loading
|
||||
* @returns
|
||||
*/
|
||||
const clearChat: (loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||
loading
|
||||
) => {
|
||||
return del(`historical_conversation/clear`,undefined,undefined, loading)
|
||||
return del(`historical_conversation/clear`, undefined, undefined, loading)
|
||||
}
|
||||
/**
|
||||
*
|
||||
|
||||
@ -103,6 +103,14 @@ const batchSync: (sync_type: string, loading?: Ref<boolean>) => Promise<Result<a
|
||||
) => {
|
||||
return post(`${prefix}/sync/${sync_type}`, undefined, undefined, loading)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取同步类型
|
||||
*/
|
||||
const getSyncType: (loading?: Ref<boolean>) => Promise<Result<any>> = (loading) => {
|
||||
return get(`${prefix}/sync_types`, undefined, loading)
|
||||
}
|
||||
|
||||
export default {
|
||||
getUserManage,
|
||||
putUserManage,
|
||||
@ -112,5 +120,6 @@ export default {
|
||||
getChatUserList,
|
||||
batchAddGroup,
|
||||
batchDelete,
|
||||
batchSync
|
||||
batchSync,
|
||||
getSyncType
|
||||
}
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import {defineStore} from 'pinia'
|
||||
import ChatAPI from '@/api/chat/chat'
|
||||
import type { ChatProfile, ChatUserProfile } from '@/api/type/chat'
|
||||
import type { LoginRequest } from '@/api/type/user'
|
||||
import type { Ref } from 'vue'
|
||||
import { getBrowserLang } from '@/locales/index'
|
||||
import type {ChatProfile, ChatUserProfile} from '@/api/type/chat'
|
||||
import type {LoginRequest} from '@/api/type/user'
|
||||
import type {Ref} from 'vue'
|
||||
import {getBrowserLang} from '@/locales/index'
|
||||
import LoginApi from "@/api/user/login.ts";
|
||||
import useUserStore from "@/stores/modules/user.ts";
|
||||
|
||||
interface ChatUser {
|
||||
// 用户id
|
||||
id: string
|
||||
}
|
||||
|
||||
interface Chat {
|
||||
chat_profile?: ChatProfile
|
||||
application?: any
|
||||
@ -16,6 +19,7 @@ interface Chat {
|
||||
token?: string
|
||||
accessToken?: string
|
||||
}
|
||||
|
||||
const useChatUserStore = defineStore('chat-user', {
|
||||
state: (): Chat => ({
|
||||
chat_profile: undefined,
|
||||
@ -111,6 +115,41 @@ const useChatUserStore = defineStore('chat-user', {
|
||||
return true
|
||||
})
|
||||
},
|
||||
async dingCallback(code: string, accessToken: string) {
|
||||
return ChatAPI.getDingCallback(code, accessToken).then((ok) => {
|
||||
this.setToken(ok.data.token)
|
||||
return this.token
|
||||
})
|
||||
},
|
||||
async dingOauth2Callback(code: string) {
|
||||
return ChatAPI.getDingOauth2Callback(code).then((ok) => {
|
||||
this.setToken(ok.data.token)
|
||||
return this.token
|
||||
})
|
||||
},
|
||||
async wecomCallback(code: string, accessToken: string) {
|
||||
return ChatAPI.getWecomCallback(code, accessToken).then((ok) => {
|
||||
this.setToken(ok.data.token)
|
||||
return this.token
|
||||
})
|
||||
},
|
||||
async larkCallback(code: string) {
|
||||
return ChatAPI.getLarkCallback(code).then((ok) => {
|
||||
this.setToken(ok.data.token)
|
||||
return this.token
|
||||
})
|
||||
},
|
||||
async getQrType() {
|
||||
return ChatAPI.getQrType().then((ok) => {
|
||||
return ok.data
|
||||
})
|
||||
},
|
||||
async getQrSource() {
|
||||
return ChatAPI.getQrSource().then((ok) => {
|
||||
return ok.data
|
||||
})
|
||||
},
|
||||
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@ -10,9 +10,9 @@
|
||||
class="mr-8"
|
||||
style="background: none"
|
||||
>
|
||||
<img :src="chatUser.chat_profile?.icon" alt="" />
|
||||
<img :src="chatUser.chat_profile?.icon" alt=""/>
|
||||
</el-avatar>
|
||||
<LogoIcon v-else height="32px" class="mr-8" />
|
||||
<LogoIcon v-else height="32px" class="mr-8"/>
|
||||
<h4>{{ chatUser.chat_profile?.application_name }}</h4>
|
||||
</div>
|
||||
</template>
|
||||
@ -29,9 +29,9 @@
|
||||
class="mr-8"
|
||||
style="background: none"
|
||||
>
|
||||
<img :src="chatUser.chat_profile?.icon" alt="" />
|
||||
<img :src="chatUser.chat_profile?.icon" alt=""/>
|
||||
</el-avatar>
|
||||
<LogoIcon v-else height="32px" class="mr-8" />
|
||||
<LogoIcon v-else height="32px" class="mr-8"/>
|
||||
<h4>{{ chatUser.chat_profile?.application_name }}</h4>
|
||||
</div>
|
||||
</template>
|
||||
@ -104,7 +104,7 @@
|
||||
</el-button>
|
||||
</div>
|
||||
<div v-if="showQrCodeTab">
|
||||
<QrCodeTab :tabs="orgOptions" />
|
||||
<QrCodeTab :tabs="orgOptions"/>
|
||||
</div>
|
||||
<div class="login-gradient-divider lighter mt-24" v-if="modeList.length > 1">
|
||||
<span>{{ $t('views.login.moreMethod') }}</span>
|
||||
@ -123,7 +123,7 @@
|
||||
'font-size': item === 'OAUTH2' ? '8px' : '10px',
|
||||
color: theme.themeInfo?.theme,
|
||||
}"
|
||||
>{{ item }}</span
|
||||
>{{ item }}</span
|
||||
>
|
||||
</el-button>
|
||||
<el-button
|
||||
@ -133,7 +133,7 @@
|
||||
class="login-button-circle color-secondary"
|
||||
@click="changeMode('QR_CODE')"
|
||||
>
|
||||
<img src="@/assets/icon_qr_outlined.svg" width="25px" />
|
||||
<img src="@/assets/icon_qr_outlined.svg" width="25px"/>
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="item === 'LOCAL' && loginMode != 'LOCAL'"
|
||||
@ -150,29 +150,29 @@
|
||||
</UserLoginLayout>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, onBeforeMount } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import type { LoginRequest } from '@/api/type/login'
|
||||
import {onMounted, ref, onBeforeMount} from 'vue'
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import type {FormInstance, FormRules} from 'element-plus'
|
||||
import type {LoginRequest} from '@/api/type/login'
|
||||
import LoginContainer from '@/layout/login-layout/LoginContainer.vue'
|
||||
import UserLoginLayout from '@/layout/login-layout/UserLoginLayout.vue'
|
||||
import loginApi from '@/api/chat/chat.ts'
|
||||
import { t, getBrowserLang } from '@/locales'
|
||||
import {t, getBrowserLang} from '@/locales'
|
||||
import useStore from '@/stores'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import QrCodeTab from '@/views/login/scanCompinents/QrCodeTab.vue'
|
||||
import { MsgConfirm, MsgError } from '@/utils/message.ts'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
import QrCodeTab from '@/views/chat/user-login/scanCompinents/QrCodeTab.vue'
|
||||
import {MsgConfirm, MsgError} from '@/utils/message.ts'
|
||||
import PasswordAuth from '@/views/chat/auth/component/password.vue'
|
||||
import { isAppIcon } from '@/utils/common'
|
||||
import {isAppIcon} from '@/utils/common'
|
||||
|
||||
const router = useRouter()
|
||||
const { theme, chatUser } = useStore()
|
||||
const { locale } = useI18n({ useScope: 'global' })
|
||||
const {theme, chatUser} = useStore()
|
||||
const {locale} = useI18n({useScope: 'global'})
|
||||
const loading = ref<boolean>(false)
|
||||
const route = useRoute()
|
||||
const identifyCode = ref<string>('')
|
||||
const {
|
||||
params: { accessToken },
|
||||
params: {accessToken},
|
||||
} = route as any
|
||||
const loginFormRef = ref<FormInstance>()
|
||||
const loginForm = ref<LoginRequest>({
|
||||
@ -211,7 +211,7 @@ const loginHandle = () => {
|
||||
chatUser.ldapLogin(loginForm.value).then((ok) => {
|
||||
router.push({
|
||||
name: 'chat',
|
||||
params: { accessToken: chatUser.accessToken },
|
||||
params: {accessToken: chatUser.accessToken},
|
||||
query: route.query,
|
||||
})
|
||||
})
|
||||
@ -219,7 +219,7 @@ const loginHandle = () => {
|
||||
chatUser.login(loginForm.value).then((ok) => {
|
||||
router.push({
|
||||
name: 'chat',
|
||||
params: { accessToken: chatUser.accessToken },
|
||||
params: {accessToken: chatUser.accessToken},
|
||||
query: route.query,
|
||||
})
|
||||
})
|
||||
@ -239,7 +239,7 @@ onBeforeMount(() => {
|
||||
})
|
||||
|
||||
const modeList = ref<string[]>([])
|
||||
//const QrList = ref<any[]>([''])
|
||||
const QrList = ref<any[]>([''])
|
||||
const loginMode = ref('')
|
||||
const showQrCodeTab = ref(false)
|
||||
|
||||
@ -300,7 +300,8 @@ function redirectAuth(authType: string, needMessage: boolean = false) {
|
||||
.then(() => {
|
||||
window.location.href = url
|
||||
})
|
||||
.catch(() => {})
|
||||
.catch(() => {
|
||||
})
|
||||
} else {
|
||||
console.log('url', url)
|
||||
window.location.href = url
|
||||
@ -340,6 +341,25 @@ onBeforeMount(() => {
|
||||
if (modeList.value.length == 1 && ['CAS', 'OIDC', 'OAuth2'].includes(modeList.value[0])) {
|
||||
redirectAuth(modeList.value[0])
|
||||
}
|
||||
// 这里的modeList 是oauth2 cas ldap oidc 这四个 还会有 lark wecom dingtalk
|
||||
// 获取到的 modeList中除'CAS', 'OIDC', 'OAuth2' LOCAL之外的登录方式
|
||||
QrList.value = modeList.value.filter((item) => !['CAS', 'OIDC', 'OAuth2', 'LOCAL', 'LDAP'].includes(item))
|
||||
// modeList需要去掉lark wecom dingtalk
|
||||
modeList.value = modeList.value.filter((item) => !['lark', 'wecom', 'dingtalk'].includes(item))
|
||||
if (QrList.value.length > 0) {
|
||||
modeList.value.push('QR_CODE')
|
||||
QrList.value.forEach((item) => {
|
||||
orgOptions.value.push({
|
||||
key: item,
|
||||
value:
|
||||
item === 'wecom'
|
||||
? t('views.system.authentication.scanTheQRCode.wecom')
|
||||
: item === 'dingtalk'
|
||||
? t('views.system.authentication.scanTheQRCode.dingtalk')
|
||||
: t('views.system.authentication.scanTheQRCode.lark'),
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -15,7 +15,8 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, defineAsyncComponent } from 'vue'
|
||||
import useStore from '@/stores'
|
||||
import useStore from "@/stores";
|
||||
const { chatUser } = useStore()
|
||||
|
||||
interface Tab {
|
||||
key: string
|
||||
@ -40,10 +41,9 @@ const props = defineProps<{ tabs: Tab[] }>()
|
||||
const activeKey = ref('')
|
||||
const allConfigs = ref<PlatformConfig[]>([])
|
||||
const config = ref<Config>({ app_key: '', app_secret: '' })
|
||||
const { login } = useStore()
|
||||
async function getPlatformInfo() {
|
||||
try {
|
||||
return await login.getQrSource()
|
||||
return await chatUser.getQrSource()
|
||||
} catch (error) {
|
||||
return []
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="flex-center mb-16">
|
||||
<img src="@/assets/logo/logo_dingtalk.svg" alt="" width="24px" class="mr-4" />
|
||||
<img src="@/assets/logo/logo_dingtalk.svg" alt="" width="24px" class="mr-4"/>
|
||||
<h2>{{ $t('views.system.authentication.scanTheQRCode.dingtalkQrCode') }}</h2>
|
||||
</div>
|
||||
<div class="ding-talk-qrName">
|
||||
@ -9,11 +9,11 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useScriptTag } from '@vueuse/core'
|
||||
import { ref, watch } from 'vue'
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import {useScriptTag} from '@vueuse/core'
|
||||
import {ref, watch} from 'vue'
|
||||
import useStore from '@/stores'
|
||||
import { MsgError } from '@/utils/message'
|
||||
import {MsgError} from '@/utils/message'
|
||||
// 声明 DTFrameLogin 和 QRLogin 的类型
|
||||
declare global {
|
||||
interface Window {
|
||||
@ -70,10 +70,15 @@ const props = defineProps<{
|
||||
}>()
|
||||
|
||||
const router = useRouter()
|
||||
const { login } = useStore()
|
||||
const { load } = useScriptTag('https://g.alicdn.com/dingding/h5-dingtalk-login/0.21.0/ddlogin.js')
|
||||
const {chatUser} = useStore()
|
||||
const {load} = useScriptTag('https://g.alicdn.com/dingding/h5-dingtalk-login/0.21.0/ddlogin.js')
|
||||
const isConfigReady = ref(false)
|
||||
|
||||
const route = useRoute()
|
||||
const {
|
||||
params: {accessToken},
|
||||
} = route as any
|
||||
|
||||
const initActive = async () => {
|
||||
try {
|
||||
await load(true)
|
||||
@ -97,19 +102,21 @@ const initActive = async () => {
|
||||
{
|
||||
redirect_uri: redirectUri,
|
||||
client_id: data.appKey,
|
||||
scope: 'openid corpid',
|
||||
scope: 'openid',
|
||||
response_type: 'code',
|
||||
state: 'fit2cloud-ding-qr',
|
||||
state: 'fit2cloud-ding-chat-qr',
|
||||
prompt: 'consent',
|
||||
corpId: data.corp_id
|
||||
},
|
||||
(loginResult) => {
|
||||
console.log(loginResult)
|
||||
const authCode = loginResult.authCode
|
||||
login.dingCallback(authCode).then(() => {
|
||||
router.push({ name: 'home' })
|
||||
chatUser.dingCallback(authCode, accessToken).then(() => {
|
||||
router.push({name: 'home'})
|
||||
})
|
||||
},
|
||||
(errorMsg: string) => {
|
||||
console.log(errorMsg)
|
||||
MsgError(errorMsg)
|
||||
}
|
||||
)
|
||||
@ -126,7 +133,7 @@ watch(
|
||||
initActive()
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
{immediate: true}
|
||||
)
|
||||
</script>
|
||||
|
||||
|
||||
@ -1,16 +1,22 @@
|
||||
<template>
|
||||
<div class="flex-center mb-16">
|
||||
<img src="@/assets/logo/logo_lark.svg " alt="" width="24px" class="mr-4" />
|
||||
<img src="@/assets/logo/logo_lark.svg " alt="" width="24px" class="mr-4"/>
|
||||
<h2>{{ $t('views.system.authentication.scanTheQRCode.larkQrCode') }}</h2>
|
||||
</div>
|
||||
<div id="lark-qr" class="lark-qrName"></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useScriptTag } from '@vueuse/core'
|
||||
import { onMounted } from 'vue'
|
||||
import {useScriptTag} from '@vueuse/core'
|
||||
import {onMounted} from 'vue'
|
||||
import {useRoute} from "vue-router";
|
||||
|
||||
const { load } = useScriptTag(
|
||||
const route = useRoute()
|
||||
const {
|
||||
params: {accessToken},
|
||||
} = route as any
|
||||
|
||||
const {load} = useScriptTag(
|
||||
'https://lf-package-cn.feishucdn.com/obj/feishu-static/lark/passport/qrcode/LarkSSOSDKWebQRCode-1.0.3.js'
|
||||
)
|
||||
|
||||
@ -33,7 +39,8 @@ const initActive = async () => {
|
||||
appSecret: props.config.app_secret
|
||||
}
|
||||
|
||||
const redirectUrl = encodeURIComponent(`${window.location.origin}/api/feishu`)
|
||||
const redirectUrl = encodeURIComponent(`${window.location.origin}/chat/api/auth/lark?accessToken=${accessToken}`)
|
||||
//const redirectUrl = encodeURIComponent(`http://127.0.0.1:8080/chat/api/auth/lark?accessToken=${accessToken}`)
|
||||
const url = `https://passport.feishu.cn/suite/passport/oauth/authorize?client_id=${data.agentId}&redirect_uri=${redirectUrl}&response_type=code&state=fit2cloud-lark-qr`
|
||||
|
||||
const QRLoginObj = window.QRLogin({
|
||||
@ -47,7 +54,7 @@ const initActive = async () => {
|
||||
window.addEventListener('message', async (event: any) => {
|
||||
if (QRLoginObj.matchOrigin(event.origin) && QRLoginObj.matchData(event.data)) {
|
||||
const loginTmpCode = event.data.tmp_code
|
||||
window.location.href = `${url}&tmp_code=${loginTmpCode}`
|
||||
window.location.replace(`${url}&tmp_code=${loginTmpCode}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useRouter } from 'vue-router'
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import * as ww from '@wecom/jssdk'
|
||||
import {
|
||||
WWLoginLangType,
|
||||
@ -16,10 +16,13 @@ import { MsgError } from '@/utils/message'
|
||||
import useStore from '@/stores'
|
||||
import { getBrowserLang } from '@/locales'
|
||||
const router = useRouter()
|
||||
|
||||
const route = useRoute()
|
||||
const {
|
||||
params: {accessToken},
|
||||
} = route as any
|
||||
const wwLogin = ref({})
|
||||
const obj = ref<any>({ isWeComLogin: false })
|
||||
const { login } = useStore()
|
||||
const { chatUser } = useStore()
|
||||
|
||||
const props = defineProps<{
|
||||
config: {
|
||||
@ -53,7 +56,7 @@ const init = async () => {
|
||||
},
|
||||
onCheckWeComLogin: obj.value,
|
||||
async onLoginSuccess({ code }: any) {
|
||||
login.wecomCallback(code).then(() => {
|
||||
chatUser.wecomCallback(code, accessToken).then(() => {
|
||||
setTimeout(() => {
|
||||
router.push({ name: 'home' })
|
||||
})
|
||||
|
||||
@ -52,7 +52,7 @@ template
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue'
|
||||
import { ElForm } from 'element-plus'
|
||||
import platformApi from '@/api/system/platform-source'
|
||||
import platformApi from '@/api/chat-user/auth-setting.ts'
|
||||
import { MsgError, MsgSuccess } from '@/utils/message'
|
||||
import { t } from '@/locales'
|
||||
|
||||
|
||||
@ -89,7 +89,7 @@
|
||||
import { reactive, ref, onMounted } from 'vue'
|
||||
import { copyClick } from '@/utils/clipboard'
|
||||
import EditModel from './EditModal.vue'
|
||||
import platformApi from '@/api/system/platform-source'
|
||||
import platformApi from '@/api/chat-user/auth-setting.ts'
|
||||
import { MsgError, MsgSuccess } from '@/utils/message'
|
||||
import { t } from '@/locales'
|
||||
|
||||
@ -148,7 +148,7 @@ function createPlatform(key: string, name: string): Platform {
|
||||
|
||||
return {
|
||||
key,
|
||||
logoSrc: new URL(`../../../assets/logo/logo_${logo}.svg`, import.meta.url).href,
|
||||
logoSrc: new URL(`../../../../assets/logo/logo_${logo}.svg`, import.meta.url).href,
|
||||
name,
|
||||
isActive: false,
|
||||
isValid: false,
|
||||
|
||||
@ -17,7 +17,7 @@ import { useRouter } from 'vue-router'
|
||||
import LDAP from './component/LDAP.vue'
|
||||
import CAS from './component/CAS.vue'
|
||||
import OIDC from './component/OIDC.vue'
|
||||
//import SCAN from './component/SCAN.vue'
|
||||
import SCAN from './component/SCAN.vue'
|
||||
import OAuth2 from './component/OAuth2.vue'
|
||||
import { t } from '@/locales'
|
||||
|
||||
@ -43,11 +43,11 @@ const tabList = [
|
||||
name: 'OAuth2',
|
||||
component: OAuth2,
|
||||
},
|
||||
// {
|
||||
// label: t('views.system.authentication.scanTheQRCode.title'),
|
||||
// name: 'SCAN',
|
||||
// component: SCAN,
|
||||
// },
|
||||
{
|
||||
label: t('views.system.authentication.scanTheQRCode.title'),
|
||||
name: 'SCAN',
|
||||
component: SCAN,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
|
||||
@ -9,8 +9,12 @@
|
||||
require-asterisk-position="right">
|
||||
<el-form-item :label="$t('views.userManage.source.label')" prop="sync_type">
|
||||
<el-select v-model="form.sync_type" :placeholder="$t('common.selectPlaceholder')">
|
||||
<el-option :label="t('views.userManage.source.local')" value="LOCAL">
|
||||
</el-option>
|
||||
<el-option
|
||||
v-for="option in syncTypeOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@ -31,6 +35,14 @@ import type {FormInstance} from 'element-plus'
|
||||
import {MsgError, MsgSuccess} from '@/utils/message'
|
||||
import {t} from '@/locales'
|
||||
import userManageApi from '@/api/system/chat-user'
|
||||
import systemChatUserApi from '@/api/system/chat-user'
|
||||
|
||||
const syncTypeOptions = ref<Array<{ label: string; value: string }>>([
|
||||
{label: t('views.userManage.source.local'), value: 'LOCAL'},
|
||||
{label: t('views.system.authentication.scanTheQRCode.wecom'), value: 'wecom'},
|
||||
{label: 'LDAP', value: 'LDAP'},
|
||||
{label: t('views.system.authentication.scanTheQRCode.lark'), value: 'lark'},
|
||||
])
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'refresh'): void;
|
||||
@ -48,9 +60,18 @@ const form = ref<{
|
||||
|
||||
function open() {
|
||||
form.value = {...defaultForm}
|
||||
getSyncType()
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
async function getSyncType() {
|
||||
return systemChatUserApi.getSyncType().then((res) => {
|
||||
if (res.data && res.data.length > 0) {
|
||||
syncTypeOptions.value = syncTypeOptions.value.filter(option => res.data.includes(option.value))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
|
||||
const rules = reactive({
|
||||
@ -65,9 +86,9 @@ const submit = async (formEl: FormInstance | undefined) => {
|
||||
userManageApi.batchSync(form.value.sync_type, loading).then((res) => {
|
||||
if (res.data) {
|
||||
const count = res.data.success_count
|
||||
let ErrorMsg = ''
|
||||
if (res.data.conflict_users && res.data.conflict_users.length > 0) {
|
||||
// 遍历res.data.conflict_users, 他是一个数组里面是对象
|
||||
let ErrorMsg = ''
|
||||
res.data.conflict_users.forEach((item: any) => {
|
||||
if (item.type === 'username') {
|
||||
ErrorMsg += '\n\n' + t('views.chatUser.syncMessage.usernameExist') + " [ " + item.users.join(',') + '\n' + ' ]'
|
||||
@ -76,10 +97,10 @@ const submit = async (formEl: FormInstance | undefined) => {
|
||||
ErrorMsg += '\n\n' + t('views.chatUser.syncMessage.nicknameExist') + " [ " + item.users.join(',') + '\n' + ' ]'
|
||||
}
|
||||
})
|
||||
MsgSuccess(t('views.chatUser.syncMessage.title', {count: count}) + ErrorMsg)
|
||||
emit('refresh')
|
||||
dialogVisible.value = false
|
||||
}
|
||||
MsgSuccess(t('views.chatUser.syncMessage.title', {count: count}) + ErrorMsg)
|
||||
emit('refresh')
|
||||
dialogVisible.value = false
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
import { RoleTypeEnum } from '@/enums/system'
|
||||
import { t } from '@/locales'
|
||||
import {RoleTypeEnum} from '@/enums/system'
|
||||
import {t} from '@/locales'
|
||||
import useStore from '@/stores'
|
||||
import {computed} from "vue";
|
||||
|
||||
const { user } = useStore()
|
||||
export const roleTypeMap: any = {
|
||||
const {user} = useStore()
|
||||
export const roleTypeMap = computed(() => ({
|
||||
...(user.is_admin()
|
||||
? {
|
||||
[RoleTypeEnum.ADMIN]: t('views.role.systemAdmin'),
|
||||
}
|
||||
[RoleTypeEnum.ADMIN]: t('views.role.systemAdmin'),
|
||||
}
|
||||
: {}),
|
||||
[RoleTypeEnum.USER]: t('views.role.user'),
|
||||
[RoleTypeEnum.WORKSPACE_MANAGE]: t('views.role.workspaceAdmin'),
|
||||
}
|
||||
}))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user