项目初始化

This commit is contained in:
leilei
2025-09-19 17:24:46 +08:00
commit 293951a610
107 changed files with 10222 additions and 0 deletions

View File

@@ -0,0 +1,206 @@
<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'
import { watch, ref, getCurrentInstance } from 'vue'
import { useRoute, useRouter } from 'vue-router'
const userStore = useUserStore()
const router = useRouter()
const { proxy } = getCurrentInstance()
const redirect = ref(undefined);
const emit = defineEmits(['loginSuccess'])
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
// 调用action的登录方法
userStore
.login({
password: loginForm.value.password,
username: loginForm.value.username,
})
.then(async (res) => {
const userInfo = JSON.parse(localStorage.getItem('userData'))
emit('loginSuccess', userInfo)
})
.catch((e) => {
console.log('登录失败', e)
loading.value = false
})
}
})
requestNotificationPermission()
}
/**
* @description 请求浏览器的通知权限
* @returns {*}
*/
function requestNotificationPermission() {
if ('Notification' in window) {
Notification.requestPermission().then(() => { })
} else {
console.log('浏览器不支持通知')
}
}
</script>
<style lang="scss" scoped>
.wrapper-content {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
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>