samlax12 commited on
Commit
ba1c27f
·
verified ·
1 Parent(s): 6972bfb

Update templates/login.html

Browse files
Files changed (1) hide show
  1. templates/login.html +504 -504
templates/login.html CHANGED
@@ -1,505 +1,505 @@
1
- <!DOCTYPE html>
2
- <html lang="zh-CN">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
7
- <title>教育AI助手平台 - 登录</title>
8
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
9
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
10
- <style>
11
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
12
-
13
- :root {
14
- /* 优雅的配色方案 */
15
- --primary-color: #0f2d49;
16
- --primary-light: #234a70;
17
- --secondary-color: #4a6cfd;
18
- --secondary-light: #7b91ff;
19
- --tertiary-color: #f7f9fe;
20
- --success-color: #10b981;
21
- --success-light: rgba(16, 185, 129, 0.1);
22
- --warning-color: #f59e0b;
23
- --warning-light: rgba(245, 158, 11, 0.1);
24
- --info-color: #0ea5e9;
25
- --info-light: rgba(14, 165, 233, 0.1);
26
- --danger-color: #ef4444;
27
- --danger-light: rgba(239, 68, 68, 0.1);
28
- --neutral-50: #f9fafb;
29
- --neutral-100: #f3f4f6;
30
- --neutral-200: #e5e7eb;
31
- --neutral-300: #d1d5db;
32
- --neutral-400: #9ca3af;
33
- --neutral-500: #6b7280;
34
- --neutral-600: #4b5563;
35
- --neutral-700: #374151;
36
- --neutral-800: #1f2937;
37
- --neutral-900: #111827;
38
-
39
- /* 样式变量 */
40
- --border-radius-sm: 0.25rem;
41
- --border-radius: 0.375rem;
42
- --border-radius-lg: 0.5rem;
43
- --border-radius-xl: 0.75rem;
44
- --border-radius-2xl: 1rem;
45
- --card-shadow: 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 2px rgba(0, 0, 0, 0.1);
46
- --card-shadow-hover: 0 10px 20px rgba(0, 0, 0, 0.05), 0 6px 6px rgba(0, 0, 0, 0.1);
47
- --card-shadow-lg: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
48
- --transition-base: all 0.2s ease-in-out;
49
- --transition-smooth: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
50
- --font-family: 'Inter', 'PingFang SC', 'Helvetica Neue', 'Microsoft YaHei', sans-serif;
51
- }
52
-
53
- /* 基础样式 */
54
- body {
55
- font-family: var(--font-family);
56
- background-color: var(--neutral-50);
57
- color: var(--neutral-800);
58
- margin: 0;
59
- padding: 0;
60
- min-height: 100vh;
61
- display: flex;
62
- align-items: center;
63
- justify-content: center;
64
- -webkit-font-smoothing: antialiased;
65
- -moz-osx-font-smoothing: grayscale;
66
- }
67
-
68
- h1, h2, h3, h4, h5, h6 {
69
- font-weight: 600;
70
- color: var(--neutral-900);
71
- }
72
-
73
- .text-gradient {
74
- background: linear-gradient(135deg, var(--secondary-color), var(--secondary-light));
75
- -webkit-background-clip: text;
76
- -webkit-text-fill-color: transparent;
77
- background-clip: text;
78
- color: transparent;
79
- }
80
-
81
- /* 登录容器样式 */
82
- .login-container {
83
- width: 100%;
84
- max-width: 450px;
85
- padding: 2.5rem;
86
- background-color: white;
87
- border-radius: var(--border-radius-xl);
88
- box-shadow: var(--card-shadow-lg);
89
- transition: var(--transition-smooth);
90
- position: relative;
91
- overflow: hidden;
92
- }
93
-
94
- .login-container::before {
95
- content: '';
96
- position: absolute;
97
- top: 0;
98
- left: 0;
99
- width: 100%;
100
- height: 4px;
101
- background: linear-gradient(to right, var(--secondary-color), var(--secondary-light));
102
- border-radius: 4px 4px 0 0;
103
- }
104
-
105
- .login-header {
106
- text-align: center;
107
- margin-bottom: 2.5rem;
108
- }
109
-
110
- .login-header h1 {
111
- font-size: 1.75rem;
112
- font-weight: 700;
113
- margin-bottom: 0.5rem;
114
- background: linear-gradient(45deg, var(--primary-color), var(--secondary-color));
115
- -webkit-background-clip: text;
116
- -webkit-text-fill-color: transparent;
117
- letter-spacing: -0.01em;
118
- }
119
-
120
- .login-header p {
121
- color: var(--neutral-600);
122
- margin-bottom: 0;
123
- font-size: 0.95rem;
124
- }
125
-
126
- .user-type-switch {
127
- margin-bottom: 2rem;
128
- }
129
-
130
- .user-type-switch .btn-group {
131
- width: 100%;
132
- box-shadow: var(--card-shadow);
133
- border-radius: var(--border-radius-lg);
134
- padding: 0.25rem;
135
- background-color: var(--neutral-100);
136
- }
137
-
138
- .user-type-switch .btn {
139
- flex: 1;
140
- background: transparent;
141
- border: none;
142
- padding: 0.75rem 1rem;
143
- font-weight: 500;
144
- color: var(--neutral-700);
145
- border-radius: var(--border-radius);
146
- transition: var(--transition-base);
147
- }
148
-
149
- .user-type-switch .btn:hover {
150
- color: var(--primary-color);
151
- }
152
-
153
- .user-type-switch .btn.active {
154
- background: white;
155
- color: var(--secondary-color);
156
- box-shadow: var(--card-shadow);
157
- }
158
-
159
- /* 表单样式 */
160
- .form-floating {
161
- margin-bottom: 1.25rem;
162
- }
163
-
164
- .form-floating > .form-control {
165
- padding: 1rem 1rem;
166
- height: calc(3.5rem + 2px);
167
- border-radius: var(--border-radius-lg);
168
- border: 1px solid var(--neutral-200);
169
- font-size: 0.95rem;
170
- transition: var(--transition-base);
171
- }
172
-
173
- .form-floating > .form-control:focus {
174
- border-color: var(--secondary-color);
175
- box-shadow: 0 0 0 3px rgba(74, 108, 253, 0.1);
176
- }
177
-
178
- .form-floating > label {
179
- padding: 1rem;
180
- color: var(--neutral-500);
181
- }
182
-
183
- .form-check {
184
- display: flex;
185
- align-items: center;
186
- margin-bottom: 1.5rem;
187
- }
188
-
189
- .form-check-input {
190
- width: 1.25em;
191
- height: 1.25em;
192
- margin-right: 0.75rem;
193
- background-color: white;
194
- border: 1px solid var(--neutral-300);
195
- border-radius: 0.25em;
196
- transition: all 0.15s ease-in-out;
197
- }
198
-
199
- .form-check-input:checked {
200
- background-color: var(--secondary-color);
201
- border-color: var(--secondary-color);
202
- }
203
-
204
- .form-check-label {
205
- color: var(--neutral-700);
206
- font-size: 0.95rem;
207
- }
208
-
209
- /* 按钮样式 */
210
- .btn-primary {
211
- background: linear-gradient(to right, var(--secondary-color), var(--secondary-light));
212
- border: none;
213
- width: 100%;
214
- padding: 0.85rem;
215
- font-weight: 500;
216
- border-radius: var(--border-radius-lg);
217
- transition: var(--transition-base);
218
- }
219
-
220
- .btn-primary:hover, .btn-primary:focus {
221
- background: linear-gradient(to right, var(--secondary-light), var(--secondary-color));
222
- box-shadow: 0 4px 10px rgba(74, 108, 253, 0.3);
223
- transform: translateY(-1px);
224
- }
225
-
226
- .btn-outline-primary {
227
- color: var(--secondary-color);
228
- border-color: var(--secondary-color);
229
- background-color: transparent;
230
- }
231
-
232
- .btn-outline-primary:hover, .btn-outline-primary:focus {
233
- background-color: var(--secondary-color);
234
- border-color: var(--secondary-color);
235
- color: white;
236
- box-shadow: 0 4px 10px rgba(74, 108, 253, 0.2);
237
- }
238
-
239
- /* 学生说明部分 */
240
- .student-instructions {
241
- margin-top: 1.5rem;
242
- padding: 1.25rem;
243
- background-color: var(--neutral-50);
244
- border-radius: var(--border-radius-lg);
245
- border: 1px solid var(--neutral-200);
246
- font-size: 0.95rem;
247
- color: var(--neutral-700);
248
- transition: var(--transition-smooth);
249
- }
250
-
251
- .student-instructions p {
252
- margin-bottom: 0.75rem;
253
- }
254
-
255
- .student-instructions p:last-child {
256
- margin-bottom: 0;
257
- }
258
-
259
- .student-instructions strong {
260
- color: var(--neutral-900);
261
- }
262
-
263
- /* 页脚样式 */
264
- .login-footer {
265
- text-align: center;
266
- margin-top: 2rem;
267
- color: var(--neutral-500);
268
- font-size: 0.85rem;
269
- }
270
-
271
- /* 动画效果 */
272
- @keyframes fadeIn {
273
- from { opacity: 0; transform: translateY(8px); }
274
- to { opacity: 1; transform: translateY(0); }
275
- }
276
-
277
- .fade-in {
278
- opacity: 0;
279
- animation: fadeIn 0.4s ease-out forwards;
280
- }
281
-
282
- /* 输入组样式 */
283
- .input-group {
284
- position: relative;
285
- }
286
-
287
- .input-group .form-control {
288
- padding-right: 3.5rem;
289
- border-radius: var(--border-radius-lg);
290
- }
291
-
292
- .input-group .btn {
293
- position: absolute;
294
- right: 0;
295
- top: 0;
296
- bottom: 0;
297
- z-index: 5;
298
- border-radius: 0 var(--border-radius-lg) var(--border-radius-lg) 0;
299
- color: var(--neutral-700);
300
- background-color: var(--neutral-100);
301
- border: 1px solid var(--neutral-200);
302
- border-left: none;
303
- transition: var(--transition-base);
304
- }
305
-
306
- .input-group .btn:hover, .input-group .btn:focus {
307
- background-color: var(--neutral-200);
308
- }
309
- </style>
310
- </head>
311
- <body>
312
- <div class="login-container fade-in">
313
- <div class="login-header">
314
- <h1>AI 助教平台</h1>
315
- <p id="login-subtitle">教师端登录</p>
316
- </div>
317
-
318
- <div class="user-type-switch">
319
- <div class="btn-group" role="group" id="user-type-buttons">
320
- <button type="button" class="btn active" id="teacher-button">教师</button>
321
- <button type="button" class="btn" id="student-button">学生</button>
322
- </div>
323
- </div>
324
-
325
- <form id="login-form">
326
- <div class="form-floating">
327
- <input type="text" class="form-control" id="username" placeholder="用户名" required>
328
- <label for="username">用户名</label>
329
- </div>
330
-
331
- <div class="form-floating">
332
- <input type="password" class="form-control" id="password" placeholder="密码" required>
333
- <label for="password">密码</label>
334
- </div>
335
-
336
- <div class="form-check">
337
- <input class="form-check-input" type="checkbox" id="remember-me">
338
- <label class="form-check-label" for="remember-me">
339
- 记住我
340
- </label>
341
- </div>
342
-
343
- <div id="student-instructions" class="student-instructions" style="display: none;">
344
- <p><strong>学生登录说明:</strong></p>
345
- <p>您也可以直接使用教师分享的链接访问AI助手,无需登录。</p>
346
- <div class="input-group mt-3">
347
- <input type="text" class="form-control" id="access-token" placeholder="输入访问令牌">
348
- <button class="btn" type="button" id="access-button">
349
- <i class="bi bi-arrow-right"></i>
350
- </button>
351
- </div>
352
- </div>
353
-
354
- <button type="submit" class="btn btn-primary mt-3">
355
- <i class="bi bi-box-arrow-in-right me-2"></i>登录
356
- </button>
357
- </form>
358
-
359
- <div class="login-footer">
360
- © 2025 教育AI助手平台 版权所有
361
- </div>
362
- </div>
363
-
364
- <script>
365
- // 硬编码用户
366
- const users = {
367
- teachers: [
368
- { username: 'teacher', password: '123456', name: '李志刚' },
369
- { username: 'admin', password: 'admin123', name: '管理员' }
370
- ],
371
- students: [
372
- { username: 'student1', password: '123456', name: '张三' },
373
- { username: 'student2', password: '123456', name: '李四' }
374
- ]
375
- };
376
-
377
- // DOM元素
378
- const teacherButton = document.getElementById('teacher-button');
379
- const studentButton = document.getElementById('student-button');
380
- const loginSubtitle = document.getElementById('login-subtitle');
381
- const studentInstructions = document.getElementById('student-instructions');
382
- const loginForm = document.getElementById('login-form');
383
- const accessButton = document.getElementById('access-button');
384
-
385
- // 切换用户类型
386
- teacherButton.addEventListener('click', function() {
387
- teacherButton.classList.add('active');
388
- studentButton.classList.remove('active');
389
- loginSubtitle.textContent = '教师端登录';
390
- studentInstructions.style.display = 'none';
391
- });
392
-
393
- studentButton.addEventListener('click', function() {
394
- studentButton.classList.add('active');
395
- teacherButton.classList.remove('active');
396
- loginSubtitle.textContent = '学生端登录';
397
- studentInstructions.style.display = 'block';
398
- });
399
-
400
- // 处理登录表单提交
401
- // 处理登录表单提交
402
- loginForm.addEventListener('submit', async function(e) {
403
- e.preventDefault();
404
-
405
- const username = document.getElementById('username').value;
406
- const password = document.getElementById('password').value;
407
- const isTeacher = teacherButton.classList.contains('active');
408
-
409
- try {
410
- const response = await fetch('/api/auth/login', {
411
- method: 'POST',
412
- headers: {
413
- 'Content-Type': 'application/json'
414
- },
415
- body: JSON.stringify({
416
- username: username,
417
- password: password,
418
- type: isTeacher ? 'teacher' : 'student'
419
- })
420
- });
421
-
422
- const data = await response.json();
423
-
424
- if (data.success) {
425
- // 登录成功,重定向到相应页面
426
- window.location.href = isTeacher ? '/index.html' : '/student_portal.html';
427
- } else {
428
- showAlert('用户名或密码错误', 'danger');
429
- }
430
- } catch (error) {
431
- console.error('登录失败:', error);
432
- showAlert('登录请求失败,请重试', 'danger');
433
- }
434
- });
435
- // 处理访问令牌
436
- accessButton.addEventListener('click', function() {
437
- const token = document.getElementById('access-token').value.trim();
438
-
439
- if (token) {
440
- // 简单验证令牌格式
441
- if (token.length >= 32) {
442
- // 这里应该向服务器验证令牌有效性,这里简化处理
443
- // 直接从URL中提取agent_id (假设格式为: [agent_id]?token=[token])
444
- if (token.includes('?token=')) {
445
- window.location.href = '/student/' + token;
446
- } else {
447
- // 假设这是一个纯token,需要输入Agent ID
448
- const agentId = prompt('请输入Agent ID');
449
- if (agentId) {
450
- window.location.href = `/student/${agentId}?token=${token}`;
451
- }
452
- }
453
- } else {
454
- showAlert('无效的访问令牌格式', 'warning');
455
- }
456
- } else {
457
- showAlert('请输入访问令牌', 'warning');
458
- }
459
- });
460
-
461
- // 显示提示信息
462
- function showAlert(message, type) {
463
- // 移除现有的提示
464
- const existingAlert = document.querySelector('.alert');
465
- if (existingAlert) {
466
- existingAlert.remove();
467
- }
468
-
469
- // 创建新提示
470
- const alert = document.createElement('div');
471
- alert.className = `alert alert-${type} fade-in`;
472
- alert.role = 'alert';
473
- alert.style.marginBottom = '1.5rem';
474
- alert.innerHTML = `
475
- <i class="bi ${type === 'danger' ? 'bi-exclamation-triangle' : 'bi-info-circle'} me-2"></i>
476
- ${message}
477
- `;
478
-
479
- // 添加到表单上方
480
- loginForm.insertAdjacentElement('beforebegin', alert);
481
-
482
- // 3秒后自动移除
483
- setTimeout(() => {
484
- alert.style.opacity = '0';
485
- setTimeout(() => alert.remove(), 300);
486
- }, 3000);
487
- }
488
-
489
- // 页面加载时检查是否已经登录
490
- // window.addEventListener('DOMContentLoaded', function() {
491
- // const currentUser = localStorage.getItem('currentUser');
492
-
493
- // if (currentUser) {
494
- // const userData = JSON.parse(currentUser);
495
-
496
- // if (userData.type === 'teacher') {
497
- // window.location.href = '/index.html';
498
- // } else if (userData.type === 'student') {
499
- // window.location.href = '/student_portal.html';
500
- // }
501
- // }
502
- // });
503
- </script>
504
- </body>
505
  </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
7
+ <title>教育AI助手平台 - 登录</title>
8
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
9
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
10
+ <style>
11
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
12
+
13
+ :root {
14
+ /* 优雅的配色方案 */
15
+ --primary-color: #0f2d49;
16
+ --primary-light: #234a70;
17
+ --secondary-color: #4a6cfd;
18
+ --secondary-light: #7b91ff;
19
+ --tertiary-color: #f7f9fe;
20
+ --success-color: #10b981;
21
+ --success-light: rgba(16, 185, 129, 0.1);
22
+ --warning-color: #f59e0b;
23
+ --warning-light: rgba(245, 158, 11, 0.1);
24
+ --info-color: #0ea5e9;
25
+ --info-light: rgba(14, 165, 233, 0.1);
26
+ --danger-color: #ef4444;
27
+ --danger-light: rgba(239, 68, 68, 0.1);
28
+ --neutral-50: #f9fafb;
29
+ --neutral-100: #f3f4f6;
30
+ --neutral-200: #e5e7eb;
31
+ --neutral-300: #d1d5db;
32
+ --neutral-400: #9ca3af;
33
+ --neutral-500: #6b7280;
34
+ --neutral-600: #4b5563;
35
+ --neutral-700: #374151;
36
+ --neutral-800: #1f2937;
37
+ --neutral-900: #111827;
38
+
39
+ /* 样式变量 */
40
+ --border-radius-sm: 0.25rem;
41
+ --border-radius: 0.375rem;
42
+ --border-radius-lg: 0.5rem;
43
+ --border-radius-xl: 0.75rem;
44
+ --border-radius-2xl: 1rem;
45
+ --card-shadow: 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 2px rgba(0, 0, 0, 0.1);
46
+ --card-shadow-hover: 0 10px 20px rgba(0, 0, 0, 0.05), 0 6px 6px rgba(0, 0, 0, 0.1);
47
+ --card-shadow-lg: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
48
+ --transition-base: all 0.2s ease-in-out;
49
+ --transition-smooth: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
50
+ --font-family: 'Inter', 'PingFang SC', 'Helvetica Neue', 'Microsoft YaHei', sans-serif;
51
+ }
52
+
53
+ /* 基础样式 */
54
+ body {
55
+ font-family: var(--font-family);
56
+ background-color: var(--neutral-50);
57
+ color: var(--neutral-800);
58
+ margin: 0;
59
+ padding: 0;
60
+ min-height: 100vh;
61
+ display: flex;
62
+ align-items: center;
63
+ justify-content: center;
64
+ -webkit-font-smoothing: antialiased;
65
+ -moz-osx-font-smoothing: grayscale;
66
+ }
67
+
68
+ h1, h2, h3, h4, h5, h6 {
69
+ font-weight: 600;
70
+ color: var(--neutral-900);
71
+ }
72
+
73
+ .text-gradient {
74
+ background: linear-gradient(135deg, var(--secondary-color), var(--secondary-light));
75
+ -webkit-background-clip: text;
76
+ -webkit-text-fill-color: transparent;
77
+ background-clip: text;
78
+ color: transparent;
79
+ }
80
+
81
+ /* 登录容器样式 */
82
+ .login-container {
83
+ width: 100%;
84
+ max-width: 450px;
85
+ padding: 2.5rem;
86
+ background-color: white;
87
+ border-radius: var(--border-radius-xl);
88
+ box-shadow: var(--card-shadow-lg);
89
+ transition: var(--transition-smooth);
90
+ position: relative;
91
+ overflow: hidden;
92
+ }
93
+
94
+ .login-container::before {
95
+ content: '';
96
+ position: absolute;
97
+ top: 0;
98
+ left: 0;
99
+ width: 100%;
100
+ height: 4px;
101
+ background: linear-gradient(to right, var(--secondary-color), var(--secondary-light));
102
+ border-radius: 4px 4px 0 0;
103
+ }
104
+
105
+ .login-header {
106
+ text-align: center;
107
+ margin-bottom: 2.5rem;
108
+ }
109
+
110
+ .login-header h1 {
111
+ font-size: 1.75rem;
112
+ font-weight: 700;
113
+ margin-bottom: 0.5rem;
114
+ background: linear-gradient(45deg, var(--primary-color), var(--secondary-color));
115
+ -webkit-background-clip: text;
116
+ -webkit-text-fill-color: transparent;
117
+ letter-spacing: -0.01em;
118
+ }
119
+
120
+ .login-header p {
121
+ color: var(--neutral-600);
122
+ margin-bottom: 0;
123
+ font-size: 0.95rem;
124
+ }
125
+
126
+ .user-type-switch {
127
+ margin-bottom: 2rem;
128
+ }
129
+
130
+ .user-type-switch .btn-group {
131
+ width: 100%;
132
+ box-shadow: var(--card-shadow);
133
+ border-radius: var(--border-radius-lg);
134
+ padding: 0.25rem;
135
+ background-color: var(--neutral-100);
136
+ }
137
+
138
+ .user-type-switch .btn {
139
+ flex: 1;
140
+ background: transparent;
141
+ border: none;
142
+ padding: 0.75rem 1rem;
143
+ font-weight: 500;
144
+ color: var(--neutral-700);
145
+ border-radius: var(--border-radius);
146
+ transition: var(--transition-base);
147
+ }
148
+
149
+ .user-type-switch .btn:hover {
150
+ color: var(--primary-color);
151
+ }
152
+
153
+ .user-type-switch .btn.active {
154
+ background: white;
155
+ color: var(--secondary-color);
156
+ box-shadow: var(--card-shadow);
157
+ }
158
+
159
+ /* 表单样式 */
160
+ .form-floating {
161
+ margin-bottom: 1.25rem;
162
+ }
163
+
164
+ .form-floating > .form-control {
165
+ padding: 1rem 1rem;
166
+ height: calc(3.5rem + 2px);
167
+ border-radius: var(--border-radius-lg);
168
+ border: 1px solid var(--neutral-200);
169
+ font-size: 0.95rem;
170
+ transition: var(--transition-base);
171
+ }
172
+
173
+ .form-floating > .form-control:focus {
174
+ border-color: var(--secondary-color);
175
+ box-shadow: 0 0 0 3px rgba(74, 108, 253, 0.1);
176
+ }
177
+
178
+ .form-floating > label {
179
+ padding: 1rem;
180
+ color: var(--neutral-500);
181
+ }
182
+
183
+ .form-check {
184
+ display: flex;
185
+ align-items: center;
186
+ margin-bottom: 1.5rem;
187
+ }
188
+
189
+ .form-check-input {
190
+ width: 1.25em;
191
+ height: 1.25em;
192
+ margin-right: 0.75rem;
193
+ background-color: white;
194
+ border: 1px solid var(--neutral-300);
195
+ border-radius: 0.25em;
196
+ transition: all 0.15s ease-in-out;
197
+ }
198
+
199
+ .form-check-input:checked {
200
+ background-color: var(--secondary-color);
201
+ border-color: var(--secondary-color);
202
+ }
203
+
204
+ .form-check-label {
205
+ color: var(--neutral-700);
206
+ font-size: 0.95rem;
207
+ }
208
+
209
+ /* 按钮样式 */
210
+ .btn-primary {
211
+ background: linear-gradient(to right, var(--secondary-color), var(--secondary-light));
212
+ border: none;
213
+ width: 100%;
214
+ padding: 0.85rem;
215
+ font-weight: 500;
216
+ border-radius: var(--border-radius-lg);
217
+ transition: var(--transition-base);
218
+ }
219
+
220
+ .btn-primary:hover, .btn-primary:focus {
221
+ background: linear-gradient(to right, var(--secondary-light), var(--secondary-color));
222
+ box-shadow: 0 4px 10px rgba(74, 108, 253, 0.3);
223
+ transform: translateY(-1px);
224
+ }
225
+
226
+ .btn-outline-primary {
227
+ color: var(--secondary-color);
228
+ border-color: var(--secondary-color);
229
+ background-color: transparent;
230
+ }
231
+
232
+ .btn-outline-primary:hover, .btn-outline-primary:focus {
233
+ background-color: var(--secondary-color);
234
+ border-color: var(--secondary-color);
235
+ color: white;
236
+ box-shadow: 0 4px 10px rgba(74, 108, 253, 0.2);
237
+ }
238
+
239
+ /* 学生说明部分 */
240
+ .student-instructions {
241
+ margin-top: 1.5rem;
242
+ padding: 1.25rem;
243
+ background-color: var(--neutral-50);
244
+ border-radius: var(--border-radius-lg);
245
+ border: 1px solid var(--neutral-200);
246
+ font-size: 0.95rem;
247
+ color: var(--neutral-700);
248
+ transition: var(--transition-smooth);
249
+ }
250
+
251
+ .student-instructions p {
252
+ margin-bottom: 0.75rem;
253
+ }
254
+
255
+ .student-instructions p:last-child {
256
+ margin-bottom: 0;
257
+ }
258
+
259
+ .student-instructions strong {
260
+ color: var(--neutral-900);
261
+ }
262
+
263
+ /* 页脚样式 */
264
+ .login-footer {
265
+ text-align: center;
266
+ margin-top: 2rem;
267
+ color: var(--neutral-500);
268
+ font-size: 0.85rem;
269
+ }
270
+
271
+ /* 动画效果 */
272
+ @keyframes fadeIn {
273
+ from { opacity: 0; transform: translateY(8px); }
274
+ to { opacity: 1; transform: translateY(0); }
275
+ }
276
+
277
+ .fade-in {
278
+ opacity: 0;
279
+ animation: fadeIn 0.4s ease-out forwards;
280
+ }
281
+
282
+ /* 输入组样式 */
283
+ .input-group {
284
+ position: relative;
285
+ }
286
+
287
+ .input-group .form-control {
288
+ padding-right: 3.5rem;
289
+ border-radius: var(--border-radius-lg);
290
+ }
291
+
292
+ .input-group .btn {
293
+ position: absolute;
294
+ right: 0;
295
+ top: 0;
296
+ bottom: 0;
297
+ z-index: 5;
298
+ border-radius: 0 var(--border-radius-lg) var(--border-radius-lg) 0;
299
+ color: var(--neutral-700);
300
+ background-color: var(--neutral-100);
301
+ border: 1px solid var(--neutral-200);
302
+ border-left: none;
303
+ transition: var(--transition-base);
304
+ }
305
+
306
+ .input-group .btn:hover, .input-group .btn:focus {
307
+ background-color: var(--neutral-200);
308
+ }
309
+ </style>
310
+ </head>
311
+ <body>
312
+ <div class="login-container fade-in">
313
+ <div class="login-header">
314
+ <h1>AI助教开发平台</h1>
315
+ <p id="login-subtitle">教师端登录</p>
316
+ </div>
317
+
318
+ <div class="user-type-switch">
319
+ <div class="btn-group" role="group" id="user-type-buttons">
320
+ <button type="button" class="btn active" id="teacher-button">教师</button>
321
+ <button type="button" class="btn" id="student-button">学生</button>
322
+ </div>
323
+ </div>
324
+
325
+ <form id="login-form">
326
+ <div class="form-floating">
327
+ <input type="text" class="form-control" id="username" placeholder="用户名" required>
328
+ <label for="username">用户名</label>
329
+ </div>
330
+
331
+ <div class="form-floating">
332
+ <input type="password" class="form-control" id="password" placeholder="密码" required>
333
+ <label for="password">密码</label>
334
+ </div>
335
+
336
+ <div class="form-check">
337
+ <input class="form-check-input" type="checkbox" id="remember-me">
338
+ <label class="form-check-label" for="remember-me">
339
+ 记住我
340
+ </label>
341
+ </div>
342
+
343
+ <div id="student-instructions" class="student-instructions" style="display: none;">
344
+ <p><strong>学生登录说明:</strong></p>
345
+ <p>您也可以直接使用教师分享的链接访问AI助手,无需登录。</p>
346
+ <div class="input-group mt-3">
347
+ <input type="text" class="form-control" id="access-token" placeholder="输入访问令牌">
348
+ <button class="btn" type="button" id="access-button">
349
+ <i class="bi bi-arrow-right"></i>
350
+ </button>
351
+ </div>
352
+ </div>
353
+
354
+ <button type="submit" class="btn btn-primary mt-3">
355
+ <i class="bi bi-box-arrow-in-right me-2"></i>登录
356
+ </button>
357
+ </form>
358
+
359
+ <div class="login-footer">
360
+ © 2025 教育AI助手开发平台 版权所有
361
+ </div>
362
+ </div>
363
+
364
+ <script>
365
+ // 硬编码用户
366
+ const users = {
367
+ teachers: [
368
+ { username: 'teacher', password: '123456', name: '李志刚' },
369
+ { username: 'admin', password: 'admin123', name: '管理员' }
370
+ ],
371
+ students: [
372
+ { username: 'student1', password: '123456', name: '张三' },
373
+ { username: 'student2', password: '123456', name: '李四' }
374
+ ]
375
+ };
376
+
377
+ // DOM元素
378
+ const teacherButton = document.getElementById('teacher-button');
379
+ const studentButton = document.getElementById('student-button');
380
+ const loginSubtitle = document.getElementById('login-subtitle');
381
+ const studentInstructions = document.getElementById('student-instructions');
382
+ const loginForm = document.getElementById('login-form');
383
+ const accessButton = document.getElementById('access-button');
384
+
385
+ // 切换用户类型
386
+ teacherButton.addEventListener('click', function() {
387
+ teacherButton.classList.add('active');
388
+ studentButton.classList.remove('active');
389
+ loginSubtitle.textContent = '教师端登录';
390
+ studentInstructions.style.display = 'none';
391
+ });
392
+
393
+ studentButton.addEventListener('click', function() {
394
+ studentButton.classList.add('active');
395
+ teacherButton.classList.remove('active');
396
+ loginSubtitle.textContent = '学生端登录';
397
+ studentInstructions.style.display = 'block';
398
+ });
399
+
400
+ // 处理登录表单提交
401
+ // 处理登录表单提交
402
+ loginForm.addEventListener('submit', async function(e) {
403
+ e.preventDefault();
404
+
405
+ const username = document.getElementById('username').value;
406
+ const password = document.getElementById('password').value;
407
+ const isTeacher = teacherButton.classList.contains('active');
408
+
409
+ try {
410
+ const response = await fetch('/api/auth/login', {
411
+ method: 'POST',
412
+ headers: {
413
+ 'Content-Type': 'application/json'
414
+ },
415
+ body: JSON.stringify({
416
+ username: username,
417
+ password: password,
418
+ type: isTeacher ? 'teacher' : 'student'
419
+ })
420
+ });
421
+
422
+ const data = await response.json();
423
+
424
+ if (data.success) {
425
+ // 登录成功,重定向到相应页面
426
+ window.location.href = isTeacher ? '/index.html' : '/student_portal.html';
427
+ } else {
428
+ showAlert('用户名或密码错误', 'danger');
429
+ }
430
+ } catch (error) {
431
+ console.error('登录失败:', error);
432
+ showAlert('登录请求失败,请重试', 'danger');
433
+ }
434
+ });
435
+ // 处理访问令牌
436
+ accessButton.addEventListener('click', function() {
437
+ const token = document.getElementById('access-token').value.trim();
438
+
439
+ if (token) {
440
+ // 简单验证令牌格式
441
+ if (token.length >= 32) {
442
+ // 这里应该向服务器验证令牌有效性,这里简化处理
443
+ // 直接从URL中提取agent_id (假设格式为: [agent_id]?token=[token])
444
+ if (token.includes('?token=')) {
445
+ window.location.href = '/student/' + token;
446
+ } else {
447
+ // 假设这是一个纯token,需要输入Agent ID
448
+ const agentId = prompt('请输入Agent ID');
449
+ if (agentId) {
450
+ window.location.href = `/student/${agentId}?token=${token}`;
451
+ }
452
+ }
453
+ } else {
454
+ showAlert('无效的访问令牌格式', 'warning');
455
+ }
456
+ } else {
457
+ showAlert('请输入访问令牌', 'warning');
458
+ }
459
+ });
460
+
461
+ // 显示提示信息
462
+ function showAlert(message, type) {
463
+ // 移除现有的提示
464
+ const existingAlert = document.querySelector('.alert');
465
+ if (existingAlert) {
466
+ existingAlert.remove();
467
+ }
468
+
469
+ // 创建新提示
470
+ const alert = document.createElement('div');
471
+ alert.className = `alert alert-${type} fade-in`;
472
+ alert.role = 'alert';
473
+ alert.style.marginBottom = '1.5rem';
474
+ alert.innerHTML = `
475
+ <i class="bi ${type === 'danger' ? 'bi-exclamation-triangle' : 'bi-info-circle'} me-2"></i>
476
+ ${message}
477
+ `;
478
+
479
+ // 添加到表单上方
480
+ loginForm.insertAdjacentElement('beforebegin', alert);
481
+
482
+ // 3秒后自动移除
483
+ setTimeout(() => {
484
+ alert.style.opacity = '0';
485
+ setTimeout(() => alert.remove(), 300);
486
+ }, 3000);
487
+ }
488
+
489
+ // 页面加载时检查是否已经登录
490
+ // window.addEventListener('DOMContentLoaded', function() {
491
+ // const currentUser = localStorage.getItem('currentUser');
492
+
493
+ // if (currentUser) {
494
+ // const userData = JSON.parse(currentUser);
495
+
496
+ // if (userData.type === 'teacher') {
497
+ // window.location.href = '/index.html';
498
+ // } else if (userData.type === 'student') {
499
+ // window.location.href = '/student_portal.html';
500
+ // }
501
+ // }
502
+ // });
503
+ </script>
504
+ </body>
505
  </html>