maxkb/ui/src/views/login/index.vue
wxg0103 76f3afbc7a fix: 修复双击ldap结果跳转到oidc的缺陷
--bug=1048233 --user=王孝刚 【用户登录】登录首页-点击LDAP两下,会提示跳转至认证源页面登录 https://www.tapd.cn/57709429/s/1599607
2024-10-28 17:22:13 +08:00

276 lines
7.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<login-layout v-if="user.isEnterprise() ? user.themeInfo : true" v-loading="loading">
<LoginContainer :subTitle="user.themeInfo?.slogan || '欢迎使用 MaxKB 智能知识库问答系统'">
<h2 class="mb-24" v-if="!showQrCodeTab">{{ loginMode || '普通登录' }}</h2>
<div v-if="!showQrCodeTab">
<el-form
class="login-form"
:rules="rules"
:model="loginForm"
ref="loginFormRef"
@keyup.enter="login"
>
<div class="mb-24">
<el-form-item prop="username">
<el-input
size="large"
class="input-item"
v-model="loginForm.username"
placeholder="请输入用户名"
>
</el-input>
</el-form-item>
</div>
<div class="mb-24">
<el-form-item prop="password">
<el-input
type="password"
size="large"
class="input-item"
v-model="loginForm.password"
placeholder="请输入密码"
show-password
>
</el-input>
</el-form-item>
</div>
</el-form>
<el-button size="large" type="primary" class="w-full" @click="login">登录</el-button>
<div class="operate-container flex-between mt-12">
<!-- <el-button class="register" @click="router.push('/register')" link type="primary">
注册
</el-button> -->
<el-button
class="forgot-password"
@click="router.push('/forgot_password')"
link
type="primary"
>
忘记密码?
</el-button>
</div>
</div>
<div v-if="showQrCodeTab">
<QrCodeTab :tabs="orgOptions" />
</div>
<div class="login-gradient-divider lighter mt-24" v-if="modeList.length > 1">
<span>更多登录方式</span>
</div>
<div class="text-center mt-16">
<template v-for="item in modeList">
<el-button
v-if="item !== '' && loginMode !== item && item !== 'QR_CODE'"
circle
:key="item"
class="login-button-circle color-secondary"
@click="changeMode(item)"
>{{ item }}
</el-button>
<el-button
v-if="item === 'QR_CODE' && loginMode !== item"
circle
:key="item"
class="login-button-circle color-secondary"
@click="changeMode('QR_CODE')"
>
<img src="@/assets/icon_qr_outlined.svg" width="25px" />
</el-button>
<el-button
v-if="item === '' && loginMode !== ''"
circle
:key="item"
class="login-button-circle color-secondary"
style="font-size: 24px"
icon="UserFilled"
@click="changeMode('')"
/>
</template>
</div>
</LoginContainer>
</login-layout>
</template>
<script setup lang="ts">
import { onMounted, ref, onBeforeMount } from 'vue'
import type { LoginRequest } from '@/api/type/user'
import { useRouter } from 'vue-router'
import type { FormInstance, FormRules } from 'element-plus'
import useStore from '@/stores'
import authApi from '@/api/auth-setting'
import { MsgConfirm, MsgSuccess } from '@/utils/message'
import { t } from '@/locales'
import QrCodeTab from '@/views/login/components/QrCodeTab.vue'
const loading = ref<boolean>(false)
const { user } = useStore()
const router = useRouter()
const loginForm = ref<LoginRequest>({
username: '',
password: ''
})
const rules = ref<FormRules<LoginRequest>>({
username: [
{
required: true,
message: '请输入用户名',
trigger: 'blur'
}
],
password: [
{
required: true,
message: '请输入密码',
trigger: 'blur'
}
]
})
const loginFormRef = ref<FormInstance>()
const modeList = ref<string[]>([''])
const QrList = ref<any[]>([''])
const loginMode = ref('')
const showQrCodeTab = ref(false)
interface qrOption {
key: string
value: string
}
const orgOptions = ref<qrOption[]>([])
function redirectAuth(authType: string) {
if (authType === 'LDAP' || authType === '') {
return
}
authApi.getAuthSetting(authType, loading).then((res: any) => {
if (!res.data) {
return
}
MsgConfirm(`${t('login.jump_tip')}`, t(''), {
confirmButtonText: t('login.jump'),
cancelButtonText: t('views.applicationOverview.appInfo.APIKeyDialog.cancel'),
confirmButtonClass: ''
})
.then(() => {
if (!res.data.config_data) {
return
}
const config = res.data.config_data
const redirectUrl = eval(`\`${config.redirectUrl}\``)
let url
if (authType === 'CAS') {
url = `${config.ldpUri}?service=${encodeURIComponent(redirectUrl)}`
}
if (authType === 'OIDC') {
url = `${config.authEndpoint}?client_id=${config.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=openid+profile+email`
}
if (url) {
window.location.href = url
}
})
.catch(() => {})
})
}
function changeMode(val: string) {
loginMode.value = val === 'LDAP' ? val : ''
if (val === 'QR_CODE') {
loginMode.value = val
showQrCodeTab.value = true
return
}
showQrCodeTab.value = false
loginForm.value = {
username: '',
password: ''
}
redirectAuth(val)
loginFormRef.value?.clearValidate()
}
const login = () => {
loginFormRef.value?.validate().then(() => {
loading.value = true
user
.login(loginMode.value, loginForm.value.username, loginForm.value.password)
.then(() => {
router.push({ name: 'home' })
})
.finally(() => (loading.value = false))
})
}
onMounted(() => {
user.asyncGetProfile().then((res) => {
if (user.isEnterprise()) {
loading.value = true
user
.getAuthType()
.then((res) => {
//如果结果包含LDAP把LDAP放在第一个
const ldapIndex = res.indexOf('LDAP')
if (ldapIndex !== -1) {
const [ldap] = res.splice(ldapIndex, 1)
res.unshift(ldap)
}
modeList.value = [...modeList.value, ...res]
})
.finally(() => (loading.value = false))
user
.getQrType()
.then((res) => {
if (res.length > 0) {
modeList.value = ['QR_CODE', ...modeList.value]
QrList.value = res
QrList.value.forEach((item) => {
orgOptions.value.push({
key: item,
value: item === 'wecom' ? '企业微信' : item === 'dingtalk' ? '钉钉' : '飞书'
})
})
}
})
.finally(() => (loading.value = false))
}
})
})
onBeforeMount(() => {
if (user.isEnterprise()) {
user.theme(loading)
}
})
</script>
<style lang="scss" scope>
.login-gradient-divider {
position: relative;
text-align: center;
color: var(--el-color-info);
::before {
content: '';
width: 25%;
height: 1px;
background: linear-gradient(90deg, rgba(222, 224, 227, 0) 0%, #dee0e3 100%);
position: absolute;
left: 16px;
top: 50%;
}
::after {
content: '';
width: 25%;
height: 1px;
background: linear-gradient(90deg, #dee0e3 0%, rgba(222, 224, 227, 0) 100%);
position: absolute;
right: 16px;
top: 50%;
}
}
.login-button-circle {
padding: 20px !important;
margin: 0 4px;
width: 32px;
height: 32px;
text-align: center;
}
</style>