Files
xSynergy-manage/src/components/Login/index.vue
2025-10-20 17:41:54 +08:00

241 lines
6.7 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="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>
</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 { useMeterStore } from '@/stores/modules/meter'
import CryptoJS from 'crypto-js';
const userStore = useUserStore()
const router = useRouter()
const { proxy } = getCurrentInstance()
const redirect = ref(undefined);
const emit = defineEmits(['loginSuccess'])
const meterStore = useMeterStore()
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: ciphertext,
// password: loginForm.value.password,
username: loginForm.value.username,
})
.then(async (res) => {
const userInfo = JSON.parse(sessionStorage.getItem('userData'))
emit('loginSuccess', userInfo)
})
.catch((e) => {
console.log('登录失败', e)
loading.value = false
})
}
})
requestNotificationPermission()
}
// 生成随机字符串
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(() => {
meterStore.initUdid()
})
</script>
<style lang="scss" scoped>
.wrapper-content {
display: flex;
justify-content: center;
align-items: center;
height: calc(100vh - 60px);
padding: 0 40px;
background: linear-gradient(135deg, #f5f7fa 0%, #eef1f6 100%);
}
.login-form {
width: 100%;
max-width: 520px;
background: #fff;
border-radius: 20px;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);
padding: 60px 50px;
display: flex;
flex-direction: column;
align-items: stretch;
position: relative;
.form-info {
width: 100%;
.title {
font-size: 28px;
font-weight: 600;
color: #051435;
margin-bottom: 40px;
}
.el-form-item {
margin-bottom: 28px;
}
:deep(.el-input__wrapper) {
border-radius: 40px;
background: #f8f9fb;
border: 1px solid #dbe1ec;
padding: 0 22px;
transition: border-color 0.25s ease;
input {
height: 48px;
font-size: 16px;
color: #051435;
}
&:hover,
&.is-focus {
border-color: #00c8c4;
box-shadow: 0 0 0 2px rgba(0, 200, 196, 0.15);
}
}
:deep(.el-form-item__error) {
font-size: 13px;
margin-top: 6px;
color: #f56c6c;
}
.button-login {
width: 100%;
height: 50px;
margin-top: 10px;
border-radius: 35px;
font-size: 18px;
font-weight: 500;
background: linear-gradient(135deg, #00c8c4, #00a5a1);
border: none;
color: #fff;
letter-spacing: 1px;
transition: background 0.3s ease, transform 0.2s ease;
&:hover {
background: linear-gradient(135deg, #00a5a1, #008f8b);
transform: translateY(-2px);
}
&:active {
transform: translateY(0);
}
}
}
}
/* 移动端优化 */
@media screen and (max-width: 768px) {
.wrapper-content {
padding: 20px;
}
.login-form {
padding: 40px 25px;
max-width: 100%;
.form-info {
.title {
font-size: 22px;
margin-bottom: 30px;
}
.button-login {
height: 44px;
font-size: 16px;
}
:deep(.el-input__wrapper) {
padding: 0 18px;
input {
height: 42px;
font-size: 15px;
}
}
}
}
}
</style>