260 lines
8.1 KiB
Vue
260 lines
8.1 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="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>
|