Files
xSynergy-manage/src/views/login.vue
2025-11-21 16:18:53 +08:00

514 lines
13 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="loginView">
<div class="wrapper-content" >
<div class="login-form">
<div class="selected-rectangle"></div>
<el-form ref="loginRef" class="form-info" :model="loginForm" :rules="loginRules">
<h3 class="title">欢迎登录</h3>
<el-form-item prop="username">
<el-input v-model="loginForm.username" auto-complete="off" placeholder="请输入您的账号" size="large"
type="text"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input v-model="loginForm.password" auto-complete="off" placeholder="请输入密码" size="large"
type="password" @keyup.enter="handleLogin"></el-input>
</el-form-item>
<el-form-item>
<el-button :loading="loading" size="large" class="button-login" type="primary"
@click.prevent="handleLogin">
<span v-if="!loading"> </span>
<span v-else>登录中...</span>
</el-button>
</el-form-item>
</el-form>
<!-- 底部 -->
<!-- <div class="el-login-footer">
<span>{{ $t('Copyright') }}</span>
</div> -->
</div>
</div>
</div>
</template>
<script setup>
import { useUserStore } from '@/stores/modules/user.js'
import { watch, ref, getCurrentInstance, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElNotification,ElMessage } from 'element-plus'
import CryptoJS from 'crypto-js';
import { useMeterStore } from '@/stores/modules/meter'
const userStore = useUserStore()
const router = useRouter()
const route = useRoute()
const { proxy } = getCurrentInstance()
const meterStore = useMeterStore()
const redirect = ref(undefined);
const loginView = ref(true)
// 监听路由变化,获取重定向参数
watch(() => route, (newRoute) => {
redirect.value = newRoute.query && newRoute.query.redirect;
}, { immediate: true });
const loginForm = ref({
username: '',
password: '',
})
const loginRules = {
username: [{ required: true, trigger: 'blur', message: '请输入用户名' }],
password: [{ required: true, trigger: 'blur', message: '请输入密码' }],
}
const loading = ref(false)
function handleLogin() {
proxy.$refs.loginRef.validate((valid) => {
if (valid) {
loading.value = true
if(!localStorage?.getItem('UDID')){
ElMessage({
message: '服务错误,请刷新页面',
type: 'warning',
})
return
}
const secretKey = ((loginForm.value.username + localStorage?.getItem('UDID')).toLowerCase()).replaceAll('-', ''); // 用户名+UDID(32位16进制全小写)
const randomChars = generateRandomChars(6);
const message = `Gx${randomChars}${loginForm.value.password}`;
const ciphertext = CryptoJS.Blowfish.encrypt(message, secretKey).toString();
// 调用action的登录方法
userStore
.login({
// password: loginForm.value.password,
password: ciphertext,
username: loginForm.value.username,
})
.then(async (res) => {
const userInfo = JSON.parse(sessionStorage.getItem('userData'))
await handleLoginSuccess();
})
.catch((e) => {
console.log('登录失败', e)
loading.value = false
})
}
})
requestNotificationPermission()
}
/**
* 处理登录成功后的跳转逻辑
*/
async function handleLoginSuccess() {
try {
// 如果有重定向路径且不是登录页,则跳转到重定向页面
if (redirect.value && redirect.value !== '/login') {
// 确保路由存在,如果不存在则跳转到默认页面
try {
// 解析路径,检查是否是有效路由
const resolved = router.resolve(redirect.value);
if (resolved.matched.length > 0) {
await router.push(redirect.value);
} else {
console.warn('重定向路径无效,跳转到默认页面');
await router.push('/coordinate');
}
} catch (error) {
console.warn('重定向跳转失败,跳转到默认页面:', error);
await router.push('/coordinate');
}
} else {
// 没有重定向或重定向到登录页,跳转到默认页面
await router.push('/coordinate');
}
} catch (error) {
console.error('登录跳转异常:', error);
// 降级处理:跳转到默认页面
await router.push('/coordinate');
} finally {
loading.value = false;
}
}
// 生成随机字符串
function generateRandomChars(length) {
const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
let result = '';
for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
/**
* @description 请求浏览器的通知权限
* @returns {*}
*/
function requestNotificationPermission() {
if ('Notification' in window) {
Notification.requestPermission().then(() => { })
} else {
console.log('浏览器不支持通知')
}
}
onMounted(async () => {
meterStore.initUdid()
});
</script>
<style lang="scss" scoped>
.loginView {
width: 100vw;
height: 100vh;
}
.wrapper-content {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
background-image: url('@/assets/images/loginBg.png');
background-size: cover;
padding: 0 50px;
.content-nav {
display: flex;
justify-content: space-between;
align-items: center;
position: fixed;
top: 0;
z-index: 1111;
width: 100%;
height: 60px;
box-shadow: 0px 2px 5px 0px rgba(153, 153, 153, 0.2);
padding: 0 35px;
background-color: #fff;
.nav-left {
display: flex;
align-items: center;
color: #fff;
box-sizing: border-box;
img {
width: 40px;
height: 40px;
border-radius: 8px;
}
div {
padding-left: 12px;
font-size: 22px;
color: #051435;
}
}
}
}
:deep(.el-input__wrapper) {
border-radius: 35px;
background: #f5f7fa;
font-size: 18px;
border: 1px solid #c9d4e6;
color: #051435;
padding: 0 30px;
input {
height: 50px;
color: #051435;
}
}
:deep(.el-form-item__error) {
font-size: 15px;
font-weight: 20px;
}
// ::v-deep .el-input__inner::placeholder {
// color: #051435;
// }
.login-form {
border-radius: 20px;
width: 600px;
height: 600px;
background-color: rgba(255, 255, 255, .3);
background-size: cover;
display: flex;
align-items: center;
justify-content: flex-end;
position: relative;
.selected-rectangle {
width: 24px;
height: 20px;
border: 4px solid white;
border-radius: 4px;
position: absolute;
top: -11px;
left: 290px;
animation: floatRotate 2s ease-in-out infinite;
transform-origin: center center;
}
@keyframes floatRotate {
0% {
transform: rotate(0deg);
}
25% {
transform: rotate(90deg);
}
50% {
transform: rotate(180deg);
}
75% {
transform: rotate(270deg);
}
100% {
transform: rotate(360deg);
}
}
.el-login-footer {
position: absolute;
bottom: -30px;
left: -5%;
width: 110%;
text-align: center;
color: #687898;
font-family: Arial;
font-size: 16px;
letter-spacing: 1px;
}
.form-info {
margin-right: 50px;
width: 550px;
height: 530px;
border-radius: 25px;
padding: 75px 50px;
box-sizing: border-box;
.el-form-item {
margin-bottom: 0;
}
.title {
position: relative;
text-align: left;
margin: 0 auto;
font-size: 32px;
font-weight: 600;
color: #051435;
line-height: 32px;
}
.button-login {
width: 100%;
height: 50px;
margin-top: 35px;
border-radius: 35px;
font-size: 22px;
background: #00C8C4;
color: #fff;
border: none;
}
.button-ok {
width: 100%;
margin-top: 35px;
display: flex;
align-items: center;
color: #fff;
height: 30px;
cursor: pointer;
img {
width: 20px;
}
span {
margin-left: 13px;
font-size: 16px;
color: #687898;
}
}
:deep(.el-input) {
height: 70px;
display: flex;
align-items: center;
margin-top: 40px;
}
.input-icon {
height: 40px;
width: 32px;
margin-left: 0px;
margin-bottom: 2px;
}
}
}
@media screen and (max-width: 765px) {
.wrapper-content {
padding: 0 20px;
.content-nav {
height: 60px;
padding: 0 15px;
.nav-left {
img {
width: 40px;
height: 40px;
}
div {
padding-left: 10px;
font-size: 16px;
}
}
}
}
:deep(.el-input__wrapper) {
padding: 0 30px;
input {
height: 40px;
color: #051435;
font-size: 16px;
}
}
// ::v-deep .el-input__inner::placeholder {
// color: #051435;
// }
.login-form {
width: 100%;
justify-content: center;
padding: 60px 30px;
height: auto;
.selected-rectangle {
width: 24px;
height: 20px;
border: 4px solid white;
border-radius: 4px;
position: absolute;
top: -11px;
left: 170px;
animation: floatRotate 2s ease-in-out infinite;
transform-origin: center center;
}
.el-login-footer {
font-size: 14px;
}
.form-info {
margin-right: 0;
width: 300px;
height: 400px;
background: #ffffff;
padding: 25px;
height: auto;
.el-form-item {
margin-bottom: 0;
}
.title {
position: relative;
text-align: left;
margin: 0 auto;
font-size: 20px;
font-weight: 600;
color: #051435;
line-height: 32px;
}
.button-login {
height: 40px;
margin-top: 20px;
font-size: 16px;
}
.button-ok {
width: 100%;
margin-top: 20px;
display: flex;
align-items: center;
color: #fff;
height: 30px;
cursor: pointer;
img {
width: 16px;
}
span {
margin-left: 10px;
font-size: 14px;
}
}
:deep(.el-input) {
height: 40px;
display: flex;
align-items: center;
margin-top: 20px;
}
.input-icon {
height: 40px;
width: 32px;
margin-left: 0px;
margin-bottom: 2px;
}
}
}
}
.home-link.modern {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 8px 12px;
color: #606266;
font-size: 14px;
cursor: pointer;
border-radius: 4px;
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}
.home-link.modern:hover {
color: #409EFF;
background-color: rgba(64, 158, 255, 0.1);
}
.home-link.modern i {
font-size: 16px;
transition: transform 0.3s;
}
.home-link.modern:hover i {
transform: translateX(-2px);
}
</style>