134 lines
3.6 KiB
Vue
134 lines
3.6 KiB
Vue
<template>
|
|
<div class="login-page">
|
|
<div class="login-left">
|
|
<div class="brand">
|
|
<div class="brand-icon">A</div>
|
|
<h1>AirLabs Project</h1>
|
|
<p>内容组 · 项目管理系统</p>
|
|
</div>
|
|
<div class="brand-features">
|
|
<div class="feature"><span class="dot blue"></span>项目进度实时追踪</div>
|
|
<div class="feature"><span class="dot green"></span>成本自动核算分摊</div>
|
|
<div class="feature"><span class="dot orange"></span>损耗与效率分析</div>
|
|
</div>
|
|
</div>
|
|
<div class="login-right">
|
|
<div class="login-card">
|
|
<h2>登录</h2>
|
|
<p class="login-desc">使用你的账号登录系统</p>
|
|
<el-form :model="form" @submit.prevent="handleLogin" class="login-form">
|
|
<el-form-item>
|
|
<el-input v-model="form.username" placeholder="用户名" size="large" />
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-input v-model="form.password" placeholder="密码" type="password" size="large" show-password />
|
|
</el-form-item>
|
|
<el-button type="primary" size="large" :loading="loading" @click="handleLogin" class="login-btn">
|
|
登 录
|
|
</el-button>
|
|
</el-form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { reactive, ref } from 'vue'
|
|
import { useRouter } from 'vue-router'
|
|
import { useAuthStore } from '../stores/auth'
|
|
import { ElMessage } from 'element-plus'
|
|
|
|
const router = useRouter()
|
|
const authStore = useAuthStore()
|
|
const loading = ref(false)
|
|
const form = reactive({ username: '', password: '' })
|
|
|
|
async function handleLogin() {
|
|
if (!form.username || !form.password) {
|
|
ElMessage.warning('请输入用户名和密码')
|
|
return
|
|
}
|
|
loading.value = true
|
|
try {
|
|
await authStore.login(form.username, form.password)
|
|
ElMessage.success(`欢迎回来,${authStore.user?.name || ''}`)
|
|
router.push('/')
|
|
} catch {
|
|
// 错误已在拦截器处理
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.login-page {
|
|
min-height: 100vh;
|
|
display: flex;
|
|
}
|
|
|
|
/* 左侧品牌区 */
|
|
.login-left {
|
|
flex: 1;
|
|
background: linear-gradient(135deg, #3370FF 0%, #2451B8 100%);
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
padding: 80px;
|
|
color: #fff;
|
|
}
|
|
.brand { margin-bottom: 48px; }
|
|
.brand-icon {
|
|
width: 48px; height: 48px;
|
|
border-radius: 12px;
|
|
background: rgba(255,255,255,0.2);
|
|
display: flex; align-items: center; justify-content: center;
|
|
font-size: 22px; font-weight: 700;
|
|
margin-bottom: 24px;
|
|
backdrop-filter: blur(10px);
|
|
}
|
|
.brand h1 { font-size: 32px; font-weight: 700; margin-bottom: 8px; }
|
|
.brand p { font-size: 16px; opacity: 0.8; }
|
|
.brand-features { display: flex; flex-direction: column; gap: 16px; }
|
|
.feature {
|
|
display: flex; align-items: center; gap: 12px;
|
|
font-size: 15px; opacity: 0.9;
|
|
}
|
|
.dot {
|
|
width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
|
|
}
|
|
.dot.blue { background: #7EB8FF; }
|
|
.dot.green { background: #7DECA2; }
|
|
.dot.orange { background: #FFB967; }
|
|
|
|
/* 右侧登录区 */
|
|
.login-right {
|
|
width: 480px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: var(--bg-page);
|
|
}
|
|
.login-card {
|
|
width: 360px;
|
|
}
|
|
.login-card h2 {
|
|
font-size: 24px;
|
|
font-weight: 700;
|
|
color: var(--text-primary);
|
|
margin-bottom: 8px;
|
|
}
|
|
.login-desc {
|
|
font-size: 14px;
|
|
color: var(--text-secondary);
|
|
margin-bottom: 32px;
|
|
}
|
|
.login-form .el-form-item { margin-bottom: 20px; }
|
|
.login-btn {
|
|
width: 100%;
|
|
height: 44px !important;
|
|
font-size: 15px !important;
|
|
border-radius: var(--radius-sm) !important;
|
|
}
|
|
</style>
|