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

260 lines
8.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<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="activeName === 'normal' ? handleLogin : handleUkeyLogin">
<el-tabs v-model="activeName">
<el-tab-pane label="云管登录" name="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>
</el-tab-pane>
<el-tab-pane label="UKEY登录待联调" name="UKEY">
<el-tooltip :visible="capsTooltip" content="大写锁定已打开" placement="right" :manual="true">
<el-form-item class="login-form-item" prop="password" :rules="[{ ...required, message: '请输入UKEY密码' }]">
<el-input show-password v-model="loginForm.ukeyPassword" placeholder="UKEY密码" @blur="capsTooltip = false" @keyup="checkCapslock">
<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>
</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 activeName = ref('normal')
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)
}
}
})
}
// ukey 登录
async function handleUkeyLogin() {
if (!loginFormRef.value) return
loginFormRef.value.validate(async valid => {
if (valid) {
loading.value = true
const res = await store.dispatch('ukey/Login', loginForm.ukeyPassword).finally(() => (loading.value = false))
if (res && res.success) {
// 用于保活与监测 ukey 是否拔出
setUkeyPassword(loginForm.ukeyPassword)
goLogin(res.data)
}
}
})
}
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>