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)
|
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 {
|
export default {
|
||||||
getAuthSetting,
|
getAuthSetting,
|
||||||
postAuthSetting,
|
postAuthSetting,
|
||||||
putAuthSetting
|
putAuthSetting,
|
||||||
|
getPlatformInfo,
|
||||||
|
updateConfig,
|
||||||
|
validateConnection
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Result } from '@/request/Result'
|
import {Result} from '@/request/Result'
|
||||||
import {
|
import {
|
||||||
get,
|
get,
|
||||||
post,
|
post,
|
||||||
@ -9,17 +9,17 @@ import {
|
|||||||
download,
|
download,
|
||||||
exportFile,
|
exportFile,
|
||||||
} from '@/request/chat/index'
|
} from '@/request/chat/index'
|
||||||
import { type ChatProfile } from '@/api/type/chat'
|
import {type ChatProfile} from '@/api/type/chat'
|
||||||
import { type Ref } from 'vue'
|
import {type Ref} from 'vue'
|
||||||
import type { ResetPasswordRequest } from '@/api/type/user.ts'
|
import type {ResetPasswordRequest} from '@/api/type/user.ts'
|
||||||
|
|
||||||
import useStore from '@/stores'
|
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', {
|
Object.defineProperty(prefix, 'value', {
|
||||||
get: function () {
|
get: function () {
|
||||||
const { user } = useStore()
|
const {user} = useStore()
|
||||||
return this._value + user.getWorkspaceId() + '/application'
|
return this._value + user.getWorkspaceId() + '/application'
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -51,7 +51,7 @@ const chatProfile: (assessToken: string, loading?: Ref<boolean>) => Promise<Resu
|
|||||||
assessToken,
|
assessToken,
|
||||||
loading,
|
loading,
|
||||||
) => {
|
) => {
|
||||||
return get('/profile', { access_token: assessToken }, loading)
|
return get('/profile', {access_token: assessToken}, loading)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 匿名认证
|
* 匿名认证
|
||||||
@ -63,7 +63,7 @@ const anonymousAuthentication: (
|
|||||||
assessToken: string,
|
assessToken: string,
|
||||||
loading?: Ref<boolean>,
|
loading?: Ref<boolean>,
|
||||||
) => Promise<Result<any>> = (assessToken, loading) => {
|
) => 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,
|
password: string,
|
||||||
loading?: Ref<boolean>,
|
loading?: Ref<boolean>,
|
||||||
) => Promise<Result<any>> = (assessToken, password, loading) => {
|
) => 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) => {
|
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) => {
|
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,
|
code,
|
||||||
|
accessToken,
|
||||||
loading,
|
loading,
|
||||||
) => {
|
) => {
|
||||||
return get('dingtalk', { code }, loading)
|
return get('auth/dingtalk', {code, accessToken: accessToken}, loading)
|
||||||
}
|
}
|
||||||
|
|
||||||
const getDingOauth2Callback: (code: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
const getDingOauth2Callback: (code: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
code,
|
code,
|
||||||
loading,
|
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,
|
code,
|
||||||
|
accessToken,
|
||||||
loading,
|
loading,
|
||||||
) => {
|
) => {
|
||||||
return get('wecom', { code }, loading)
|
return get('auth/wecom', {code, accessToken: accessToken}, loading)
|
||||||
}
|
}
|
||||||
const getLarkCallback: (code: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
const getLarkCallback: (code: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
code,
|
code,
|
||||||
loading,
|
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,
|
chat_id,
|
||||||
loading,
|
loading,
|
||||||
) => {
|
) => {
|
||||||
return del(`historical_conversation/${chat_id}`,undefined,undefined ,loading)
|
return del(`historical_conversation/${chat_id}`, undefined, undefined, loading)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param loading
|
* @param loading
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const clearChat: (loading?: Ref<boolean>) => Promise<Result<any>> = (
|
const clearChat: (loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||||
loading
|
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)
|
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 {
|
export default {
|
||||||
getUserManage,
|
getUserManage,
|
||||||
putUserManage,
|
putUserManage,
|
||||||
@ -112,5 +120,6 @@ export default {
|
|||||||
getChatUserList,
|
getChatUserList,
|
||||||
batchAddGroup,
|
batchAddGroup,
|
||||||
batchDelete,
|
batchDelete,
|
||||||
batchSync
|
batchSync,
|
||||||
|
getSyncType
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,17 @@
|
|||||||
import { defineStore } from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import ChatAPI from '@/api/chat/chat'
|
import ChatAPI from '@/api/chat/chat'
|
||||||
import type { ChatProfile, ChatUserProfile } from '@/api/type/chat'
|
import type {ChatProfile, ChatUserProfile} from '@/api/type/chat'
|
||||||
import type { LoginRequest } from '@/api/type/user'
|
import type {LoginRequest} from '@/api/type/user'
|
||||||
import type { Ref } from 'vue'
|
import type {Ref} from 'vue'
|
||||||
import { getBrowserLang } from '@/locales/index'
|
import {getBrowserLang} from '@/locales/index'
|
||||||
|
import LoginApi from "@/api/user/login.ts";
|
||||||
|
import useUserStore from "@/stores/modules/user.ts";
|
||||||
|
|
||||||
interface ChatUser {
|
interface ChatUser {
|
||||||
// 用户id
|
// 用户id
|
||||||
id: string
|
id: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Chat {
|
interface Chat {
|
||||||
chat_profile?: ChatProfile
|
chat_profile?: ChatProfile
|
||||||
application?: any
|
application?: any
|
||||||
@ -16,6 +19,7 @@ interface Chat {
|
|||||||
token?: string
|
token?: string
|
||||||
accessToken?: string
|
accessToken?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const useChatUserStore = defineStore('chat-user', {
|
const useChatUserStore = defineStore('chat-user', {
|
||||||
state: (): Chat => ({
|
state: (): Chat => ({
|
||||||
chat_profile: undefined,
|
chat_profile: undefined,
|
||||||
@ -111,6 +115,41 @@ const useChatUserStore = defineStore('chat-user', {
|
|||||||
return true
|
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"
|
class="mr-8"
|
||||||
style="background: none"
|
style="background: none"
|
||||||
>
|
>
|
||||||
<img :src="chatUser.chat_profile?.icon" alt="" />
|
<img :src="chatUser.chat_profile?.icon" alt=""/>
|
||||||
</el-avatar>
|
</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>
|
<h4>{{ chatUser.chat_profile?.application_name }}</h4>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -29,9 +29,9 @@
|
|||||||
class="mr-8"
|
class="mr-8"
|
||||||
style="background: none"
|
style="background: none"
|
||||||
>
|
>
|
||||||
<img :src="chatUser.chat_profile?.icon" alt="" />
|
<img :src="chatUser.chat_profile?.icon" alt=""/>
|
||||||
</el-avatar>
|
</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>
|
<h4>{{ chatUser.chat_profile?.application_name }}</h4>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -104,7 +104,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="showQrCodeTab">
|
<div v-if="showQrCodeTab">
|
||||||
<QrCodeTab :tabs="orgOptions" />
|
<QrCodeTab :tabs="orgOptions"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="login-gradient-divider lighter mt-24" v-if="modeList.length > 1">
|
<div class="login-gradient-divider lighter mt-24" v-if="modeList.length > 1">
|
||||||
<span>{{ $t('views.login.moreMethod') }}</span>
|
<span>{{ $t('views.login.moreMethod') }}</span>
|
||||||
@ -123,7 +123,7 @@
|
|||||||
'font-size': item === 'OAUTH2' ? '8px' : '10px',
|
'font-size': item === 'OAUTH2' ? '8px' : '10px',
|
||||||
color: theme.themeInfo?.theme,
|
color: theme.themeInfo?.theme,
|
||||||
}"
|
}"
|
||||||
>{{ item }}</span
|
>{{ item }}</span
|
||||||
>
|
>
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
@ -133,7 +133,7 @@
|
|||||||
class="login-button-circle color-secondary"
|
class="login-button-circle color-secondary"
|
||||||
@click="changeMode('QR_CODE')"
|
@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>
|
||||||
<el-button
|
<el-button
|
||||||
v-if="item === 'LOCAL' && loginMode != 'LOCAL'"
|
v-if="item === 'LOCAL' && loginMode != 'LOCAL'"
|
||||||
@ -150,29 +150,29 @@
|
|||||||
</UserLoginLayout>
|
</UserLoginLayout>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, ref, onBeforeMount } from 'vue'
|
import {onMounted, ref, onBeforeMount} from 'vue'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import {useRoute, useRouter} from 'vue-router'
|
||||||
import type { FormInstance, FormRules } from 'element-plus'
|
import type {FormInstance, FormRules} from 'element-plus'
|
||||||
import type { LoginRequest } from '@/api/type/login'
|
import type {LoginRequest} from '@/api/type/login'
|
||||||
import LoginContainer from '@/layout/login-layout/LoginContainer.vue'
|
import LoginContainer from '@/layout/login-layout/LoginContainer.vue'
|
||||||
import UserLoginLayout from '@/layout/login-layout/UserLoginLayout.vue'
|
import UserLoginLayout from '@/layout/login-layout/UserLoginLayout.vue'
|
||||||
import loginApi from '@/api/chat/chat.ts'
|
import loginApi from '@/api/chat/chat.ts'
|
||||||
import { t, getBrowserLang } from '@/locales'
|
import {t, getBrowserLang} from '@/locales'
|
||||||
import useStore from '@/stores'
|
import useStore from '@/stores'
|
||||||
import { useI18n } from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
import QrCodeTab from '@/views/login/scanCompinents/QrCodeTab.vue'
|
import QrCodeTab from '@/views/chat/user-login/scanCompinents/QrCodeTab.vue'
|
||||||
import { MsgConfirm, MsgError } from '@/utils/message.ts'
|
import {MsgConfirm, MsgError} from '@/utils/message.ts'
|
||||||
import PasswordAuth from '@/views/chat/auth/component/password.vue'
|
import PasswordAuth from '@/views/chat/auth/component/password.vue'
|
||||||
import { isAppIcon } from '@/utils/common'
|
import {isAppIcon} from '@/utils/common'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { theme, chatUser } = useStore()
|
const {theme, chatUser} = useStore()
|
||||||
const { locale } = useI18n({ useScope: 'global' })
|
const {locale} = useI18n({useScope: 'global'})
|
||||||
const loading = ref<boolean>(false)
|
const loading = ref<boolean>(false)
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const identifyCode = ref<string>('')
|
const identifyCode = ref<string>('')
|
||||||
const {
|
const {
|
||||||
params: { accessToken },
|
params: {accessToken},
|
||||||
} = route as any
|
} = route as any
|
||||||
const loginFormRef = ref<FormInstance>()
|
const loginFormRef = ref<FormInstance>()
|
||||||
const loginForm = ref<LoginRequest>({
|
const loginForm = ref<LoginRequest>({
|
||||||
@ -211,7 +211,7 @@ const loginHandle = () => {
|
|||||||
chatUser.ldapLogin(loginForm.value).then((ok) => {
|
chatUser.ldapLogin(loginForm.value).then((ok) => {
|
||||||
router.push({
|
router.push({
|
||||||
name: 'chat',
|
name: 'chat',
|
||||||
params: { accessToken: chatUser.accessToken },
|
params: {accessToken: chatUser.accessToken},
|
||||||
query: route.query,
|
query: route.query,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -219,7 +219,7 @@ const loginHandle = () => {
|
|||||||
chatUser.login(loginForm.value).then((ok) => {
|
chatUser.login(loginForm.value).then((ok) => {
|
||||||
router.push({
|
router.push({
|
||||||
name: 'chat',
|
name: 'chat',
|
||||||
params: { accessToken: chatUser.accessToken },
|
params: {accessToken: chatUser.accessToken},
|
||||||
query: route.query,
|
query: route.query,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -239,7 +239,7 @@ onBeforeMount(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const modeList = ref<string[]>([])
|
const modeList = ref<string[]>([])
|
||||||
//const QrList = ref<any[]>([''])
|
const QrList = ref<any[]>([''])
|
||||||
const loginMode = ref('')
|
const loginMode = ref('')
|
||||||
const showQrCodeTab = ref(false)
|
const showQrCodeTab = ref(false)
|
||||||
|
|
||||||
@ -300,7 +300,8 @@ function redirectAuth(authType: string, needMessage: boolean = false) {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
window.location.href = url
|
window.location.href = url
|
||||||
})
|
})
|
||||||
.catch(() => {})
|
.catch(() => {
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
console.log('url', url)
|
console.log('url', url)
|
||||||
window.location.href = url
|
window.location.href = url
|
||||||
@ -340,6 +341,25 @@ onBeforeMount(() => {
|
|||||||
if (modeList.value.length == 1 && ['CAS', 'OIDC', 'OAuth2'].includes(modeList.value[0])) {
|
if (modeList.value.length == 1 && ['CAS', 'OIDC', 'OAuth2'].includes(modeList.value[0])) {
|
||||||
redirectAuth(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>
|
</script>
|
||||||
|
|||||||
@ -15,7 +15,8 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, ref, defineAsyncComponent } from 'vue'
|
import { onMounted, ref, defineAsyncComponent } from 'vue'
|
||||||
import useStore from '@/stores'
|
import useStore from "@/stores";
|
||||||
|
const { chatUser } = useStore()
|
||||||
|
|
||||||
interface Tab {
|
interface Tab {
|
||||||
key: string
|
key: string
|
||||||
@ -40,10 +41,9 @@ const props = defineProps<{ tabs: Tab[] }>()
|
|||||||
const activeKey = ref('')
|
const activeKey = ref('')
|
||||||
const allConfigs = ref<PlatformConfig[]>([])
|
const allConfigs = ref<PlatformConfig[]>([])
|
||||||
const config = ref<Config>({ app_key: '', app_secret: '' })
|
const config = ref<Config>({ app_key: '', app_secret: '' })
|
||||||
const { login } = useStore()
|
|
||||||
async function getPlatformInfo() {
|
async function getPlatformInfo() {
|
||||||
try {
|
try {
|
||||||
return await login.getQrSource()
|
return await chatUser.getQrSource()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex-center mb-16">
|
<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>
|
<h2>{{ $t('views.system.authentication.scanTheQRCode.dingtalkQrCode') }}</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="ding-talk-qrName">
|
<div class="ding-talk-qrName">
|
||||||
@ -9,11 +9,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useRouter } from 'vue-router'
|
import {useRoute, useRouter} from 'vue-router'
|
||||||
import { useScriptTag } from '@vueuse/core'
|
import {useScriptTag} from '@vueuse/core'
|
||||||
import { ref, watch } from 'vue'
|
import {ref, watch} from 'vue'
|
||||||
import useStore from '@/stores'
|
import useStore from '@/stores'
|
||||||
import { MsgError } from '@/utils/message'
|
import {MsgError} from '@/utils/message'
|
||||||
// 声明 DTFrameLogin 和 QRLogin 的类型
|
// 声明 DTFrameLogin 和 QRLogin 的类型
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
@ -70,10 +70,15 @@ const props = defineProps<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { login } = useStore()
|
const {chatUser} = useStore()
|
||||||
const { load } = useScriptTag('https://g.alicdn.com/dingding/h5-dingtalk-login/0.21.0/ddlogin.js')
|
const {load} = useScriptTag('https://g.alicdn.com/dingding/h5-dingtalk-login/0.21.0/ddlogin.js')
|
||||||
const isConfigReady = ref(false)
|
const isConfigReady = ref(false)
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const {
|
||||||
|
params: {accessToken},
|
||||||
|
} = route as any
|
||||||
|
|
||||||
const initActive = async () => {
|
const initActive = async () => {
|
||||||
try {
|
try {
|
||||||
await load(true)
|
await load(true)
|
||||||
@ -97,19 +102,21 @@ const initActive = async () => {
|
|||||||
{
|
{
|
||||||
redirect_uri: redirectUri,
|
redirect_uri: redirectUri,
|
||||||
client_id: data.appKey,
|
client_id: data.appKey,
|
||||||
scope: 'openid corpid',
|
scope: 'openid',
|
||||||
response_type: 'code',
|
response_type: 'code',
|
||||||
state: 'fit2cloud-ding-qr',
|
state: 'fit2cloud-ding-chat-qr',
|
||||||
prompt: 'consent',
|
prompt: 'consent',
|
||||||
corpId: data.corp_id
|
corpId: data.corp_id
|
||||||
},
|
},
|
||||||
(loginResult) => {
|
(loginResult) => {
|
||||||
|
console.log(loginResult)
|
||||||
const authCode = loginResult.authCode
|
const authCode = loginResult.authCode
|
||||||
login.dingCallback(authCode).then(() => {
|
chatUser.dingCallback(authCode, accessToken).then(() => {
|
||||||
router.push({ name: 'home' })
|
router.push({name: 'home'})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
(errorMsg: string) => {
|
(errorMsg: string) => {
|
||||||
|
console.log(errorMsg)
|
||||||
MsgError(errorMsg)
|
MsgError(errorMsg)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -126,7 +133,7 @@ watch(
|
|||||||
initActive()
|
initActive()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{immediate: true}
|
||||||
)
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -1,16 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex-center mb-16">
|
<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>
|
<h2>{{ $t('views.system.authentication.scanTheQRCode.larkQrCode') }}</h2>
|
||||||
</div>
|
</div>
|
||||||
<div id="lark-qr" class="lark-qrName"></div>
|
<div id="lark-qr" class="lark-qrName"></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useScriptTag } from '@vueuse/core'
|
import {useScriptTag} from '@vueuse/core'
|
||||||
import { onMounted } from 'vue'
|
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'
|
'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
|
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 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({
|
const QRLoginObj = window.QRLogin({
|
||||||
@ -47,7 +54,7 @@ const initActive = async () => {
|
|||||||
window.addEventListener('message', async (event: any) => {
|
window.addEventListener('message', async (event: any) => {
|
||||||
if (QRLoginObj.matchOrigin(event.origin) && QRLoginObj.matchData(event.data)) {
|
if (QRLoginObj.matchOrigin(event.origin) && QRLoginObj.matchData(event.data)) {
|
||||||
const loginTmpCode = event.data.tmp_code
|
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>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useRouter } from 'vue-router'
|
import {useRoute, useRouter} from 'vue-router'
|
||||||
import * as ww from '@wecom/jssdk'
|
import * as ww from '@wecom/jssdk'
|
||||||
import {
|
import {
|
||||||
WWLoginLangType,
|
WWLoginLangType,
|
||||||
@ -16,10 +16,13 @@ import { MsgError } from '@/utils/message'
|
|||||||
import useStore from '@/stores'
|
import useStore from '@/stores'
|
||||||
import { getBrowserLang } from '@/locales'
|
import { getBrowserLang } from '@/locales'
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
const {
|
||||||
|
params: {accessToken},
|
||||||
|
} = route as any
|
||||||
const wwLogin = ref({})
|
const wwLogin = ref({})
|
||||||
const obj = ref<any>({ isWeComLogin: false })
|
const obj = ref<any>({ isWeComLogin: false })
|
||||||
const { login } = useStore()
|
const { chatUser } = useStore()
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
config: {
|
config: {
|
||||||
@ -53,7 +56,7 @@ const init = async () => {
|
|||||||
},
|
},
|
||||||
onCheckWeComLogin: obj.value,
|
onCheckWeComLogin: obj.value,
|
||||||
async onLoginSuccess({ code }: any) {
|
async onLoginSuccess({ code }: any) {
|
||||||
login.wecomCallback(code).then(() => {
|
chatUser.wecomCallback(code, accessToken).then(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
router.push({ name: 'home' })
|
router.push({ name: 'home' })
|
||||||
})
|
})
|
||||||
|
|||||||
@ -52,7 +52,7 @@ template
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, ref } from 'vue'
|
import { reactive, ref } from 'vue'
|
||||||
import { ElForm } from 'element-plus'
|
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 { MsgError, MsgSuccess } from '@/utils/message'
|
||||||
import { t } from '@/locales'
|
import { t } from '@/locales'
|
||||||
|
|
||||||
|
|||||||
@ -89,7 +89,7 @@
|
|||||||
import { reactive, ref, onMounted } from 'vue'
|
import { reactive, ref, onMounted } from 'vue'
|
||||||
import { copyClick } from '@/utils/clipboard'
|
import { copyClick } from '@/utils/clipboard'
|
||||||
import EditModel from './EditModal.vue'
|
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 { MsgError, MsgSuccess } from '@/utils/message'
|
||||||
import { t } from '@/locales'
|
import { t } from '@/locales'
|
||||||
|
|
||||||
@ -148,7 +148,7 @@ function createPlatform(key: string, name: string): Platform {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
key,
|
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,
|
name,
|
||||||
isActive: false,
|
isActive: false,
|
||||||
isValid: false,
|
isValid: false,
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import { useRouter } from 'vue-router'
|
|||||||
import LDAP from './component/LDAP.vue'
|
import LDAP from './component/LDAP.vue'
|
||||||
import CAS from './component/CAS.vue'
|
import CAS from './component/CAS.vue'
|
||||||
import OIDC from './component/OIDC.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 OAuth2 from './component/OAuth2.vue'
|
||||||
import { t } from '@/locales'
|
import { t } from '@/locales'
|
||||||
|
|
||||||
@ -43,11 +43,11 @@ const tabList = [
|
|||||||
name: 'OAuth2',
|
name: 'OAuth2',
|
||||||
component: OAuth2,
|
component: OAuth2,
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// label: t('views.system.authentication.scanTheQRCode.title'),
|
label: t('views.system.authentication.scanTheQRCode.title'),
|
||||||
// name: 'SCAN',
|
name: 'SCAN',
|
||||||
// component: SCAN,
|
component: SCAN,
|
||||||
// },
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -9,8 +9,12 @@
|
|||||||
require-asterisk-position="right">
|
require-asterisk-position="right">
|
||||||
<el-form-item :label="$t('views.userManage.source.label')" prop="sync_type">
|
<el-form-item :label="$t('views.userManage.source.label')" prop="sync_type">
|
||||||
<el-select v-model="form.sync_type" :placeholder="$t('common.selectPlaceholder')">
|
<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-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
@ -31,6 +35,14 @@ import type {FormInstance} from 'element-plus'
|
|||||||
import {MsgError, MsgSuccess} from '@/utils/message'
|
import {MsgError, MsgSuccess} from '@/utils/message'
|
||||||
import {t} from '@/locales'
|
import {t} from '@/locales'
|
||||||
import userManageApi from '@/api/system/chat-user'
|
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<{
|
const emit = defineEmits<{
|
||||||
(e: 'refresh'): void;
|
(e: 'refresh'): void;
|
||||||
@ -48,9 +60,18 @@ const form = ref<{
|
|||||||
|
|
||||||
function open() {
|
function open() {
|
||||||
form.value = {...defaultForm}
|
form.value = {...defaultForm}
|
||||||
|
getSyncType()
|
||||||
dialogVisible.value = true
|
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 formRef = ref<FormInstance>();
|
||||||
|
|
||||||
const rules = reactive({
|
const rules = reactive({
|
||||||
@ -65,9 +86,9 @@ const submit = async (formEl: FormInstance | undefined) => {
|
|||||||
userManageApi.batchSync(form.value.sync_type, loading).then((res) => {
|
userManageApi.batchSync(form.value.sync_type, loading).then((res) => {
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
const count = res.data.success_count
|
const count = res.data.success_count
|
||||||
|
let ErrorMsg = ''
|
||||||
if (res.data.conflict_users && res.data.conflict_users.length > 0) {
|
if (res.data.conflict_users && res.data.conflict_users.length > 0) {
|
||||||
// 遍历res.data.conflict_users, 他是一个数组里面是对象
|
// 遍历res.data.conflict_users, 他是一个数组里面是对象
|
||||||
let ErrorMsg = ''
|
|
||||||
res.data.conflict_users.forEach((item: any) => {
|
res.data.conflict_users.forEach((item: any) => {
|
||||||
if (item.type === 'username') {
|
if (item.type === 'username') {
|
||||||
ErrorMsg += '\n\n' + t('views.chatUser.syncMessage.usernameExist') + " [ " + item.users.join(',') + '\n' + ' ]'
|
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' + ' ]'
|
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 {RoleTypeEnum} from '@/enums/system'
|
||||||
import { t } from '@/locales'
|
import {t} from '@/locales'
|
||||||
import useStore from '@/stores'
|
import useStore from '@/stores'
|
||||||
|
import {computed} from "vue";
|
||||||
|
|
||||||
const { user } = useStore()
|
const {user} = useStore()
|
||||||
export const roleTypeMap: any = {
|
export const roleTypeMap = computed(() => ({
|
||||||
...(user.is_admin()
|
...(user.is_admin()
|
||||||
? {
|
? {
|
||||||
[RoleTypeEnum.ADMIN]: t('views.role.systemAdmin'),
|
[RoleTypeEnum.ADMIN]: t('views.role.systemAdmin'),
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
[RoleTypeEnum.USER]: t('views.role.user'),
|
[RoleTypeEnum.USER]: t('views.role.user'),
|
||||||
[RoleTypeEnum.WORKSPACE_MANAGE]: t('views.role.workspaceAdmin'),
|
[RoleTypeEnum.WORKSPACE_MANAGE]: t('views.role.workspaceAdmin'),
|
||||||
}
|
}))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user