FileManage/web/src/views/login/index.vue
2026-03-06 16:18:09 +08:00

457 lines
12 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>
<div class="login-container" >
<div class="login-container-title">{{title}}</div>
<!-- <div class="login-container-left">
<el-image
:src="loginImg"
fit="cover"
/>
</div> -->
<div class="login-container-content">
<el-form
ref="loginFormRef"
:model="loginData"
:rules="loginRules"
class="login-form"
auto-complete="on"
label-position="left"
>
<!-- <div class="mb-[30px]">
<img src="@/assets/login/logo.png" style="display: inline-block;" alt="">
</div> -->
<div class="title-container">
<h3 class="title">欢迎登录</h3>
</div>
<el-form-item prop="username" style="margin-bottom: 45px;">
<!-- <span class="svg-container">
<img src="@/assets/login/username.png" alt="">
</span> -->
<el-input
ref="username"
clearable
v-model="loginData.username"
:placeholder="$t('login.username')"
name="username"
type="text"
tabindex="1"
auto-complete="on"
/>
</el-form-item>
<el-tooltip
:disabled="capslockTooltipDisabled"
content="Caps lock is On"
placement="right"
>
<el-form-item prop="password" style="margin-bottom:20px;">
<!-- <span class="svg-container">
<img src="@/assets/login/password.png" alt="">
</span> -->
<el-input
ref="passwordRef"
:key="passwordType"
v-model="loginData.password"
:type="passwordType"
:placeholder="$t('login.password')"
name="password"
tabindex="2"
auto-complete="on"
@keyup="checkCapslock"
@blur="capslockTooltipDisabled = true"
@keyup.enter="handleLogin"
/>
<span
class="show-pwd"
@click="showPwd"
>
<svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
</span>
</el-form-item>
</el-tooltip>
<div style="text-align: left;margin-bottom: 40px;">
<el-checkbox
v-model="remember"
:label="$t('login.remember')"
size="large"
/>
</div>
<el-button
size="default"
:loading="loading"
type="primary"
style="width: 100%;height: 50px; margin-bottom: 10px;background-color: rgb(8,186,124);border: none;border-radius: 100px;"
@click.prevent="handleLogin"
>{{ $t('login.login') }}
</el-button>
</el-form>
<div
v-if="showCopyright == true"
class="copyright"
>
<p>{{ $t('login.copyright') }}</p>
<p>{{ $t('login.icp') }}</p>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref, toRefs, watch, nextTick } from 'vue';
import loginImg from '@/assets/images/u287.gif';
// 组件依赖
import { ElForm, ElInput } from 'element-plus';
import router from '@/router';
import SvgIcon from '@/components/SvgIcon/index.vue';
import Cookies from 'js-cookie';
// API依赖
import { useRoute } from 'vue-router';
import { LoginData } from '@/api/auth/types';
//密码加密
import { encrypt,decrypt } from '@/utils/rsaEncrypt';
// 状态管理依赖
import { useUserStore } from '@/store/modules/user';
// 国际化
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const userStore = useUserStore();
const title = userStore.title
const content1 = userStore.content1
const content2 = userStore.content2
const content3 = userStore.content3
const logo = userStore.webApiBaseHttp + "/image/"+ userStore.logo
const bgImg = userStore.webApiBaseHttp + "/image/"+ userStore.bgImg
const route = useRoute();
// 图片验证码
const codeUrl = ref('');
const loginFormRef = ref(ElForm);
const passwordRef = ref(ElInput);
// 记住密码
let remember = ref(false);
const state = reactive({
redirect: '',
loginData: {
username: '',
password: ''
} as LoginData,
loginRules: {
username: [{ required: true, trigger: 'blur', message: t('login.rulesUsername') }],
password: [{ required: true, trigger: 'blur', message: t('login.rulesPassword') }]
},
loginImg: loginImg[0],
loading: false,
passwordType: 'password',
// 大写提示禁用
capslockTooltipDisabled: true,
otherQuery: {},
clientHeight: document.documentElement.clientHeight,
showCopyright: true,
showDialog: false,
cookiePass: ''
});
const {
loginData,
loginRules,
loading,
passwordType,
capslockTooltipDisabled,
showCopyright
} = toRefs(state);
function checkCapslock(e: any) {
const { key } = e;
state.capslockTooltipDisabled =
key && key.length === 1 && key >= 'A' && key <= 'Z';
}
function showPwd() {
if (passwordType.value === 'password') {
passwordType.value = '';
} else {
passwordType.value = 'password';
}
nextTick(() => {
passwordRef.value.focus();
});
}
/**
* 登录
*/
function handleLogin() {
loginFormRef.value.validate((valid: boolean) => {
if (valid) {
const user = {
username: state.loginData.username,
password: state.loginData.password,
};
if (user.password !== state.cookiePass) {
user.password = encrypt(user.password);
}
state.loading = true;
userStore
.login(user)
.then(() => {
Cookies.set('username', user.username);
// debugger
if (remember.value == true) {
Cookies.set('password', user.password);
Cookies.set('rememberMe', String(remember.value));
}
router.push({ path: '/dashboard' || '/', query: state.otherQuery });
state.loading = false;
})
.catch(() => {
// getCode();
state.loading = false;
});
} else {
return false;
}
});
}
watch(
route,
() => {
const query = route.query;
if (query) {
state.redirect = query.redirect as string;
state.otherQuery = getOtherQuery(query);
}
},
{
immediate: true
}
);
function getOtherQuery(query: any) {
return Object.keys(query).reduce((acc: any, cur: any) => {
if (cur !== 'redirect') {
acc[cur] = query[cur];
}
return acc;
}, {});
}
function getCookie() {
const username = Cookies.get('username');
let password = Cookies.get('password');
const rememberMe = Cookies.get('rememberMe');
rememberMe == 'true' ? (remember.value = Boolean(rememberMe)) : false;
// 保存cookie里面的加密后的密码
state.cookiePass = password === undefined ? '' : password;
password = password === undefined ? state.loginData.password : password;
state.loginData = {
username: username === undefined ? state.loginData.username : username,
password: decrypt(password)
};
remember.value = rememberMe === undefined ? false : Boolean(rememberMe)
}
onMounted(() => {
getCookie();
window.onresize = () => {
if (state.clientHeight > document.documentElement.clientHeight) {
state.showCopyright = false;
} else {
state.showCopyright = true;
}
};
});
</script>
<style lang="scss" scoped>
$bg: #fff;
$dark_gray: #889aa4;
$light_gray: #eee;
.login-container-center {
width: 25%;
height:100vh;
// min-height: 400px;
background-color: $bg;
display: flex;
display: -webkit-flex;
align-items: center;
-webkit-align-items: center;
justify-content: center;
}
.login-container {
background: url('../../assets/login/beijings.png') no-repeat;
background-size: cover;
background-position: center center;
min-height: 100%;
width: 100%;
background-color: $bg;
overflow: hidden;
// display: flex;
// display: -webkit-flex;
// align-items: center;
// -webkit-align-items: center;
position: relative;
// justify-content: center;
// -webkit-justify-content: center;
text-align: center;
.login-container-title{
font-size: 60px;
font-weight: 700;
color: #fff;
margin: 0 auto;
margin-top: 2%;
// width: 800px;
letter-spacing: 5px;
}
.login-container-content {
width: 450px;
height: 550px;
background: #fff;
min-width: 350px;
display: flex;
display: -webkit-flex;
justify-content: center;
-webkit-justify-content: center;
align-items: center;
-webkit-align-items: center;
text-align: center;
position: absolute;
left: 69%;
margin-top: 90px;
border-radius: 5px;
.title-container{
font-family: 'Arial Negreta', 'Arial Normal', 'Arial';
font-weight: 700;
font-style: normal;
font-size: 28px;
color: #333333;
margin-bottom: 48px;
.title{
color: #333333;
}
}
}
.login-form {
width: 85%;
margin: 0 auto;
overflow: hidden;
}
.svg-container {
position: absolute;
top: 15px;
left: 5px;
padding: 0 10px;
color: $dark_gray;
vertical-align: text-bottom;
font-size: 24px;
color: #cccccc;
z-index: 2;
}
.svg-container-refresh {
padding-right: 5px;
padding-left: 0;
font-size: 26px;
color: rgb(64, 158, 255);
cursor: pointer;
}
.show-pwd {
position: absolute;
right: 10px;
top: 7px;
font-size: 16px;
color: $dark_gray;
cursor: pointer;
user-select: none;
}
.captcha {
position: absolute;
right: 0;
top: 0;
img {
height: 42px;
cursor: pointer;
vertical-align: middle;
}
}
}
.login-containe-footer{
color: #000000;
font-size: 14px;
position: absolute;
bottom: 20px;
width: 100%;
margin: 0 auto;
left: 0;
// text-align: center;
text-align: left;
padding-left: 40px;
}
.thirdparty-button {
position: absolute;
right: 40px;
bottom: 6px;
}
:deep(.el-input){
height:45px;
}
:deep(.el-form-item__content){
position: relative;
}
:deep(.el-input__wrapper){
padding-left: 0px;
box-shadow:none;
// border-bottom: 1px solid rgb(8,186,124);
border-bottom: 1px solid #dcdfe6;
border-radius: 0px;
}
:deep(.el-button>span){
font-size:18px;
}
:deep(){
.el-form-item.is-error .el-input__wrapper, .el-form-item.is-error .el-input__wrapper.is-focus, .el-form-item.is-error .el-input__wrapper:focus, .el-form-item.is-error .el-input__wrapper:hover, .el-form-item.is-error .el-select__wrapper, .el-form-item.is-error .el-select__wrapper.is-focus, .el-form-item.is-error .el-select__wrapper:focus, .el-form-item.is-error .el-select__wrapper:hover, .el-form-item.is-error .el-textarea__inner, .el-form-item.is-error .el-textarea__inner.is-focus, .el-form-item.is-error .el-textarea__inner:focus, .el-form-item.is-error .el-textarea__inner:hover{
box-shadow:none;
border-bottom: 1px solid red;
}
.el-input__wrapper:hover{
box-shadow:none;
border-bottom: 1px solid rgb(8,186,124);
}
.el-checkbox__input.is-checked .el-checkbox__inner{
background-color: rgb(8,186,124);
border-color: rgb(8,186,124);
}
.el-checkbox__inner:hover {
border-color: rgb(8,186,124);
}
.el-checkbox__input.is-checked+.el-checkbox__label{
color: rgb(8,186,124);
}
}
@media only screen and (max-width: 470px) {
.thirdparty-button {
display: none;
}
}
@media only screen and (max-width: 1366px) {
.title {
margin: 0px auto 20px auto !important;
}
.login-code {
margin-bottom: 0;
}
}
</style>