275 lines
6.9 KiB
Vue
275 lines
6.9 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="handleLogin"
|
||
|
>
|
||
|
<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-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 type { FormInstance } from "element-plus";
|
||
|
|
||
|
const loginForm = reactive({
|
||
|
account: "",
|
||
|
password: ""
|
||
|
});
|
||
|
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
|
||
|
});
|
||
|
if (res.success) {
|
||
|
goLogin(res.data);
|
||
|
}
|
||
|
loading.value = false;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
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>
|