main-web/src/views/login/login.vue

329 lines
11 KiB
Vue

<template>
<div
class="login-container"
:style="{
backgroundImage: `url(${configs.loginBg || '/web-common-resource/img/bg_login.png'})`
}"
>
<div class="login-logo">
<img :src="configs.loginLogo" />
</div>
<div class="login-center">
<div class="desc-content">
<span class="desc-title">{{ configs.promotionalTitle }}</span>
<span class="desc-remark">{{ configs.promotionalContent }}</span>
</div>
<el-form :model="loginForm" ref="loginFormRef" label-position="left" label-width="0px" class="card-box login-form" @keyup.enter="handleUkeyLogin" @submit.prevent>
<el-tabs v-model="activeName">
<el-tab-pane label="云管登录" name="normal">
<div v-if="activeName === 'normal'">
<div class="login-title">账号登录</div>
<el-form-item class="login-form-item" prop="account" :rules="[{ ...required, message: '请输入用户名' }]">
<el-input v-model="loginForm.account" autocomplete="off" placeholder="登录账户">
<template #prefix>
<el-icon>
<icon-ep-user />
</el-icon>
</template>
</el-input>
</el-form-item>
<el-tooltip :visible="capsTooltip" content="大写锁定已打开" placement="right" :manual="true">
<el-form-item class="login-form-item" prop="password" :rules="[{ ...required, message: '请输入密码' }]">
<el-input show-password v-model="loginForm.password" placeholder="密码" @blur="capsTooltip = false" @keyup="checkCapslock">
<template #prefix>
<el-icon><icon-ep-lock /></el-icon>
</template>
</el-input>
</el-form-item>
</el-tooltip>
<el-form-item class="login-form-item">
<div class="operate-region">
<span class="remember">
<el-switch v-model="remember"></el-switch>
<span class="m-l-xs">记住密码</span>
</span>
<a :href="`mailto:${configs.helpInformationLink}`" type="text" class="text-info help-info" :title="configs.helpInformationContent">{{ configs.helpInformationContent }}</a>
</div>
</el-form-item>
<el-button class="login-btn" type="primary" :loading="loading" @click="handleLogin">登录</el-button>
</div>
</el-tab-pane>
<el-tab-pane label="UKEY登录" name="UKEY">
<div v-if="activeName === 'UKEY'">
<el-tooltip :visible="capsTooltip" content="大写锁定已打开" placement="right" :manual="true">
<el-form-item class="login-form-item" prop="ukeyPassword" :rules="[{ ...required, message: '请输入UKEY密码' }]">
<el-input show-password v-model="loginForm.ukeyPassword" placeholder="UKEY密码" @blur="capsTooltip = false" @keyup="checkCapslock" ref="ukeyPasswordInputRef">
<template #prefix>
<el-icon><icon-ep-lock /></el-icon>
</template>
</el-input>
</el-form-item>
</el-tooltip>
<el-button class="login-btn" type="primary" :loading="loading" @click="handleUkeyLogin">登录</el-button>
</div>
</el-tab-pane>
<el-tab-pane label="软KEY登录" name="SKEY">
<div v-if="activeName === 'SKEY'">
<div class="login-title">账号登录</div>
<el-form-item class="login-form-item" prop="account" :rules="[{ ...required, message: '请输入用户名' }]">
<el-input v-model="loginForm.saccount" autocomplete="off" placeholder="登录账户">
<template #prefix>
<el-icon>
<icon-ep-user />
</el-icon>
</template>
</el-input>
</el-form-item>
<el-tooltip :visible="capsTooltip" content="大写锁定已打开" placement="right" :manual="true">
<el-form-item class="login-form-item" prop="password" :rules="[{ ...required, message: '请输入密码' }]">
<el-input show-password v-model="loginForm.spassword" placeholder="密码" @blur="capsTooltip = false" @keyup="checkCapslock">
<template #prefix>
<el-icon><icon-ep-lock /></el-icon>
</template>
</el-input>
</el-form-item>
</el-tooltip>
<el-form-item class="login-form-item">
<div class="operate-region">
<span class="remember">
<el-switch v-model="remember"></el-switch>
<span class="m-l-xs">记住密码</span>
</span>
<a :href="`mailto:${configs.helpInformationLink}`" type="text" class="text-info help-info" :title="configs.helpInformationContent">{{ configs.helpInformationContent }}</a>
</div>
</el-form-item>
<el-button class="login-btn" type="primary" :loading="loading" @click="handleLogin4sKey">登录</el-button>
</div>
</el-tab-pane>
</el-tabs>
</el-form>
</div>
<div class="copyright-info">{{ configs.copyrightInformation }}</div>
</div>
</template>
<script setup lang="ts">
import { decrypt, encrypt } from 'utils/crypto'
import { login } from 'services'
import { useStore } from 'vuex'
import { useRouter, useRoute } from 'vue-router'
import setLoginData from './tools'
import { required } from '@/validate'
import { setUkeyPassword } from 'utils/auth'
import type { FormInstance } from 'element-plus'
const ukeyPasswordInputRef = ref()
onMounted(() => {
if (typeof ukeyPasswordInputRef.value.focus === 'function') ukeyPasswordInputRef.value.focus()
})
const activeName = ref('UKEY')
const loginForm = reactive({
account: '',
password: '',
ukeyPassword: ''
})
const remember = ref(false)
const loading = ref(false)
const capsTooltip = ref(false)
const store = useStore()
const configs = computed(() => store.getters.pageConfig)
const appConfigs = computed(() => store.getters.appConfigs)
const loginFormRef = ref<FormInstance>()
const init = () => {
const local = localStorage.getItem('cmcLoginData')
if (local) {
const obj = JSON.parse(local)
loginForm.account = obj.account
loginForm.password = decrypt(obj.password)
remember.value = true
}
}
init()
const router = useRouter()
const route = useRoute()
function goLogin(data: any) {
setLoginData(data)
if (unref(remember)) {
const obj = {
account: loginForm.account,
password: encrypt(loginForm.password)
}
localStorage.setItem('cmcLoginData', JSON.stringify(obj))
} else {
localStorage.removeItem('cmcLoginData')
}
const { redirect } = route.query
const path = redirect ? (redirect as string).split('/#')[1] : appConfigs.value.homePath
router.replace(path)
localStorage.removeItem('lockData')
}
function handleLogin() {
if (!loginFormRef.value) return
loginFormRef.value.validate(async valid => {
if (valid) {
loading.value = true
const { account, password } = loginForm
const res = await login({
account,
password: encrypt(password),
isManager: true
}).finally(() => {
loading.value = false
})
if (res.success) {
goLogin(res.data)
}
}
})
}
// 软key 登录
function handleLogin4sKey() {
if (!loginFormRef.value) return
loginFormRef.value.validate(async valid => {
if (valid) {
loading.value = true
const { saccount, spassword } = loginForm
const res = await store
.dispatch('skey/Login', {account: saccount, password: spassword})
.finally(() => (loading.value = false))
.catch(() => (loading.value = false))
if (res && res.success) {
console.log('SKEY: 登录成功,云管融合登录接口返回', res)
goLogin(res.data)
} else {
console.log('SKEY: 登录失败,云管融合登录接口返回', res)
}
}
})
// ukey 登录
async function handleUkeyLogin() {
if (!loginFormRef.value) return
loginFormRef.value.validate(async valid => {
if (valid) {
console.log('UKEY: 密码校验通过')
loading.value = true
const res = await store
.dispatch('ukey/Login', loginForm.ukeyPassword)
.finally(() => (loading.value = false))
.catch(() => (loading.value = false))
if (res && res.success) {
console.log('UKEY: 登录成功,云管融合登录接口返回', res)
// 用于保活与监测 ukey 是否拔出
setUkeyPassword(loginForm.ukeyPassword)
goLogin(res.data)
} else {
console.log('UKEY: 登录失败,云管融合登录接口返回', res)
}
}
})
}
function checkCapslock({ shiftKey, key }: { shiftKey: boolean; key: string }) {
if (key && key.length === 1) {
if ((shiftKey && key >= 'a' && key <= 'z') || (!shiftKey && key >= 'A' && key <= 'Z')) {
capsTooltip.value = true
} else {
capsTooltip.value = false
}
}
if (key === 'CapsLock' && unref(capsTooltip) === true) {
capsTooltip.value = false
}
}
</script>
<style lang="scss" scoped>
.login-container {
display: flex;
flex-direction: column;
height: 100vh;
background: url('/web-common-resource/img/bg_login.png') #2d3a4b no-repeat;
background-size: cover;
.login-logo {
padding: 5px 40px;
img {
height: 40px;
}
}
.login-center {
display: flex;
flex: 1;
justify-content: space-around;
align-items: center;
.desc-content {
color: #fff;
display: flex;
flex-direction: column;
margin-top: -150x;
width: 600px;
.desc-title {
font-weight: 700;
font-style: normal;
font-size: 38px;
color: #ffffff;
margin-bottom: 56px;
}
.desc-remark {
line-height: 40px;
font-weight: 400;
font-style: normal;
font-size: 22px;
color: #ffffff;
}
}
.login-form {
box-sizing: border-box;
width: 462px;
padding: 50px 30px;
background: #fff;
font-size: 17px;
.login-title {
font-size: 32px;
text-align: center;
color: #333;
margin-bottom: 50px;
}
.operate-region {
display: flex;
align-items: center;
width: 100%;
.remember {
flex: 1;
text-align: left;
}
}
.login-btn {
margin-top: 20px;
height: 60px;
width: 100%;
}
.help-info {
max-width: 130px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.login-form-item {
:deep(.#{$namespace}-input__wrapper) {
height: 60px;
line-height: 60px;
}
:deep(.#{$namespace}-input__prefix) {
font-size: 20px;
color: #000;
padding: 0 10px;
}
}
}
}
.copyright-info {
padding: 10px 0;
text-align: center;
background: rgba(10, 37, 68, 0.6);
color: #bbbbbb;
}
}
</style>