Files
sunProduct/src/views/login.vue
2026-04-08 08:56:37 +08:00

251 lines
7.3 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">
<el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
<div class="title-box">
<div class="line"></div>
<div class="subtitle">
<div>WELCOME</div>
<div>智慧物业后台管理系统</div>
</div>
</div>
<el-form-item prop="username">
<el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" :placeholder="proxy.$t('login.username')">
<template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
type="password"
size="large"
auto-complete="off"
:placeholder="proxy.$t('login.password')"
@keyup.enter="handleLogin"
>
<template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template>
</el-input>
</el-form-item>
<div class="remberBox">
<el-checkbox v-model="loginForm.rememberMe" style="color: #fff">{{ proxy.$t('login.rememberPassword') }}</el-checkbox>
<div>忘记密码?</div>
</div>
<el-form-item style="width: 100%">
<el-button :loading="loading" size="large" type="primary" style="width: 100%" @click.prevent="handleLogin">
<span v-if="!loading">{{ proxy.$t('login.login') }}</span>
<span v-else>{{ proxy.$t('login.logging') }}</span>
</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script setup lang="ts">
import { authRouterUrl } from '@/api/system/social/auth';
import { useUserStore } from '@/store/modules/user';
import { LoginData, TenantVO } from '@/api/types';
import { to } from 'await-to-js';
import { getCodeImg, getTenantList } from '@/api/login';
import { HttpStatus } from '@/enums/RespEnum';
import { useI18n } from 'vue-i18n';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const title = import.meta.env.VITE_APP_TITLE;
const userStore = useUserStore();
const router = useRouter();
const { t } = useI18n();
const loginForm = ref<LoginData>({
tenantId: '000000',
username: '',
password: '',
rememberMe: false,
code: '',
uuid: ''
} as LoginData);
const loginRules: ElFormRules = {
tenantId: [{ required: true, trigger: 'blur', message: t('login.rule.tenantId.required') }],
username: [{ required: true, trigger: 'blur', message: t('login.rule.username.required') }],
password: [{ required: true, trigger: 'blur', message: t('login.rule.password.required') }],
code: [{ required: true, trigger: 'change', message: t('login.rule.code.required') }]
};
const codeUrl = ref('');
const loading = ref(false);
// 验证码开关
const captchaEnabled = ref(true);
// 租户开关
const tenantEnabled = ref(true);
// 注册开关
const register = ref(false);
const redirect = ref('/');
const loginRef = ref<ElFormInstance>();
// 租户列表
const tenantList = ref<TenantVO[]>([]);
watch(
() => router.currentRoute.value,
(newRoute: any) => {
redirect.value = newRoute.query && newRoute.query.redirect && decodeURIComponent(newRoute.query.redirect);
},
{ immediate: true }
);
const handleLogin = () => {
loginRef.value?.validate(async (valid: boolean, fields: any) => {
if (valid) {
loading.value = true;
// 勾选了需要记住密码设置在 localStorage 中设置记住用户名和密码
if (loginForm.value.rememberMe) {
localStorage.setItem('tenantId', String(loginForm.value.tenantId));
localStorage.setItem('username', String(loginForm.value.username));
localStorage.setItem('password', String(loginForm.value.password));
localStorage.setItem('rememberMe', String(loginForm.value.rememberMe));
} else {
// 否则移除
localStorage.removeItem('tenantId');
localStorage.removeItem('username');
localStorage.removeItem('password');
localStorage.removeItem('rememberMe');
}
// 调用action的登录方法
const [err] = await to(userStore.login(loginForm.value));
if (!err) {
const redirectUrl = redirect.value || '/';
await router.push(redirectUrl);
loading.value = false;
} else {
loading.value = false;
// 重新获取验证码
if (captchaEnabled.value) {
await getCode();
}
}
} else {
}
});
};
/**
* 获取验证码
*/
const getCode = async () => {
const res = await getCodeImg();
const { data } = res;
captchaEnabled.value = data.captchaEnabled === undefined ? true : data.captchaEnabled;
if (captchaEnabled.value) {
// 刷新验证码时清空输入框
loginForm.value.code = '';
codeUrl.value = 'data:image/gif;base64,' + data.img;
loginForm.value.uuid = data.uuid;
}
};
const getLoginData = () => {
const tenantId = localStorage.getItem('tenantId');
const username = localStorage.getItem('username');
const password = localStorage.getItem('password');
const rememberMe = localStorage.getItem('rememberMe');
loginForm.value = {
tenantId: tenantId === null ? String(loginForm.value.tenantId) : tenantId,
username: username === null ? String(loginForm.value.username) : username,
password: password === null ? String(loginForm.value.password) : String(password),
rememberMe: rememberMe === null ? false : Boolean(rememberMe)
} as LoginData;
};
/**
* 获取租户列表
*/
const initTenantList = async () => {
const { data } = await getTenantList(false);
tenantEnabled.value = data.tenantEnabled === undefined ? true : data.tenantEnabled;
if (tenantEnabled.value) {
tenantList.value = data.voList;
if (tenantList.value != null && tenantList.value.length !== 0) {
loginForm.value.tenantId = tenantList.value[0].tenantId;
}
}
};
/**
* 第三方登录
* @param type
*/
const doSocialLogin = (type: string) => {
authRouterUrl(type, loginForm.value.tenantId).then((res: any) => {
if (res.code === HttpStatus.SUCCESS) {
// 获取授权地址跳转
window.location.href = res.data;
} else {
ElMessage.error(res.msg);
}
});
};
onMounted(() => {
getCode();
initTenantList();
getLoginData();
});
</script>
<style lang="scss" scoped>
.login {
display: flex;
color: #fff !important;
justify-content: center;
align-items: center;
height: 100%;
background-image: url('../assets/images/login-background.jpg');
background-size: cover;
background-position: center;
}
.title-box {
display: flex;
align-items: center;
margin-bottom: 40px;
.line {
margin-right: 18px;
width: 1px;
height: 69px;
background-color: rgba(255, 255, 255, 1);
border: 3px solid rgba(255, 255, 255, 1);
}
.subtitle {
color: rgba(255, 255, 255, 1);
font-size: 28px;
text-align: left;
div {
height: 39px;
line-height: 39px;
}
}
}
.login-form {
width: 368px;
height: 393px;
padding: 30px;
border-radius: 10px;
background: linear-gradient(180deg, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0.3) 100%);
.input-icon {
height: 40px;
width: 23px;
margin-left: 0px;
margin-right: 16px;
color: #1a75ff;
}
.remberBox {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 18px;
}
}
</style>