blob: fb85c7056157f781471c0fd0528e831cfbd4f585 [file] [log] [blame]
2081595154f846f912025-06-04 17:35:21 +08001<template>
2 <div class="login-page">
3 <!-- 背景装饰 -->
4 <div class="bg-decoration">
5 <div class="shape shape-1"></div>
6 <div class="shape shape-2"></div>
7 <div class="shape shape-3"></div>
8 </div>
9
10 <!-- 登录表单容器 -->
11 <div class="login-container">
12 <div class="login-card">
13 <!-- 头部信息 -->
14 <div class="login-header">
15 <div class="logo">
16 <el-icon size="48" color="#667eea"><Operation /></el-icon>
17 </div>
18 <h1 class="title">PT Tracker</h1>
19 <p class="subtitle">私有种子分享社区</p>
20 </div>
21
22 <!-- 登录表单 -->
23 <el-form
24 ref="loginFormRef"
25 :model="loginForm"
26 :rules="loginRules"
27 class="login-form"
28 size="large"
29 >
30 <el-form-item prop="username">
31 <el-input
32 v-model="loginForm.username"
33 placeholder="请输入用户名或邮箱"
34 clearable
35 :prefix-icon="User"
36 />
37 </el-form-item>
38
39 <el-form-item prop="password">
40 <el-input
41 v-model="loginForm.password"
42 type="password"
43 placeholder="请输入密码"
44 show-password
45 :prefix-icon="Lock"
46 @keyup.enter="handleLogin"
47 />
48 </el-form-item>
49
50 <el-form-item>
51 <div class="login-options">
52 <el-checkbox v-model="rememberMe">记住登录</el-checkbox>
53 <el-link type="primary" :underline="false">忘记密码?</el-link>
54 </div>
55 </el-form-item>
56
57 <el-form-item>
58 <el-button
59 type="primary"
60 :loading="loading"
61 style="width: 100%"
62 @click="handleLogin"
63 >
64 <span v-if="!loading">登录</span>
65 <span v-else>登录中...</span>
66 </el-button>
67 </el-form-item>
68 </el-form>
69
70 <!-- 底部链接 -->
71 <div class="login-footer">
72 <span class="footer-text">还没有账号?</span>
73 <el-link
74 type="primary"
75 :underline="false"
76 @click="$router.push('/register')"
77 >
78 立即注册
79 </el-link>
80 </div>
81 </div>
82 </div>
83 </div>
84</template>
85
86<script>
87import { ref, reactive } from 'vue'
88import { useRouter } from 'vue-router'
89import { ElMessage } from 'element-plus'
90import { User, Lock, Operation } from '@element-plus/icons-vue'
91
92export default {
93 name: 'LoginView',
94 components: {
95 Operation
96 },
97 setup() {
98 const router = useRouter()
99 const loginFormRef = ref()
100 const loading = ref(false)
101 const rememberMe = ref(false)
102
103 // 表单数据
104 const loginForm = reactive({
105 username: '',
106 password: ''
107 })
108
109 // 验证规则
110 const loginRules = {
111 username: [
112 { required: true, message: '请输入用户名或邮箱', trigger: 'blur' },
113 { min: 3, message: '用户名至少3个字符', trigger: 'blur' }
114 ],
115 password: [
116 { required: true, message: '请输入密码', trigger: 'blur' },
117 { min: 6, message: '密码至少6个字符', trigger: 'blur' }
118 ]
119 }
120
121 // 登录处理
122 const handleLogin = async () => {
123 try {
124 // 表单验证
125 const valid = await loginFormRef.value.validate()
126 if (!valid) return
127
128 loading.value = true
129
130 // 模拟登录API请求
131 await new Promise(resolve => setTimeout(resolve, 1000))
132
133 // 简单的登录验证(实际项目中应该调用后端API)
134 if (loginForm.username === 'admin' && loginForm.password === '123456') {
135 // 登录成功
136 localStorage.setItem('isLoggedIn', 'true')
137 localStorage.setItem('username', loginForm.username)
138 localStorage.setItem('loginTime', new Date().toISOString())
139
140 if (rememberMe.value) {
141 localStorage.setItem('rememberLogin', 'true')
142 }
143
144 ElMessage.success('登录成功!欢迎回来')
145 router.push('/home')
146 } else {
147 ElMessage.error('用户名或密码错误,请重试')
148 }
149
150 } catch (error) {
151 console.error('登录失败:', error)
152 ElMessage.error('登录失败,请稍后重试')
153 } finally {
154 loading.value = false
155 }
156 }
157
158 return {
159 loginFormRef,
160 loginForm,
161 loginRules,
162 loading,
163 rememberMe,
164 handleLogin,
165 User,
166 Lock
167 }
168 }
169}
170</script>
171
172<style lang="scss" scoped>
173.login-page {
174 min-height: 100vh;
175 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
176 position: relative;
177 overflow: hidden;
178 display: flex;
179 align-items: center;
180 justify-content: center;
181 padding: 20px;
182}
183
184// 背景装饰
185.bg-decoration {
186 position: absolute;
187 top: 0;
188 left: 0;
189 width: 100%;
190 height: 100%;
191 overflow: hidden;
192 z-index: 1;
193
194 .shape {
195 position: absolute;
196 border-radius: 50%;
197 background: rgba(255, 255, 255, 0.1);
198 animation: float 6s ease-in-out infinite;
199
200 &.shape-1 {
201 width: 200px;
202 height: 200px;
203 top: 10%;
204 left: 10%;
205 animation-delay: 0s;
206 }
207
208 &.shape-2 {
209 width: 150px;
210 height: 150px;
211 top: 60%;
212 right: 10%;
213 animation-delay: -2s;
214 }
215
216 &.shape-3 {
217 width: 100px;
218 height: 100px;
219 bottom: 20%;
220 left: 20%;
221 animation-delay: -4s;
222 }
223 }
224}
225
226@keyframes float {
227 0%, 100% {
228 transform: translateY(0px) rotate(0deg);
229 }
230 50% {
231 transform: translateY(-20px) rotate(180deg);
232 }
233}
234
235// 登录容器
236.login-container {
237 position: relative;
238 z-index: 10;
239 width: 100%;
240 max-width: 420px;
241}
242
243.login-card {
244 background: rgba(255, 255, 255, 0.95);
245 backdrop-filter: blur(10px);
246 border-radius: 16px;
247 padding: 40px;
248 box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
249 border: 1px solid rgba(255, 255, 255, 0.2);
250
251 .login-header {
252 text-align: center;
253 margin-bottom: 32px;
254
255 .logo {
256 margin-bottom: 16px;
257 }
258
259 .title {
260 font-size: 32px;
261 font-weight: 700;
262 color: #2c3e50;
263 margin-bottom: 8px;
264 letter-spacing: -0.5px;
265 }
266
267 .subtitle {
268 font-size: 15px;
269 color: #7f8c8d;
270 margin: 0;
271 font-weight: 400;
272 }
273 }
274
275 .login-form {
276 .el-form-item {
277 margin-bottom: 24px;
278
279 &:last-child {
280 margin-bottom: 0;
281 }
282 }
283
284 .login-options {
285 display: flex;
286 justify-content: space-between;
287 align-items: center;
288 width: 100%;
289
290 .el-checkbox {
291 :deep(.el-checkbox__label) {
292 font-size: 14px;
293 color: #606266;
294 }
295 }
296
297 .el-link {
298 font-size: 14px;
299 }
300 }
301
302 .el-button {
303 font-size: 16px;
304 font-weight: 500;
305 height: 48px;
306 border-radius: 8px;
307 }
308 }
309
310 .login-footer {
311 text-align: center;
312 margin-top: 24px;
313 padding-top: 24px;
314 border-top: 1px solid #ebeef5;
315
316 .footer-text {
317 color: #909399;
318 font-size: 14px;
319 margin-right: 8px;
320 }
321
322 .el-link {
323 font-size: 14px;
324 font-weight: 500;
325 }
326 }
327}
328
329// 响应式设计
330@media (max-width: 768px) {
331 .login-page {
332 padding: 16px;
333 }
334
335 .login-card {
336 padding: 32px 24px;
337
338 .login-header .title {
339 font-size: 28px;
340 }
341 }
342}
343</style>