dvc890 commited on
Commit
58efa17
·
verified ·
1 Parent(s): b3e6ac4

Update pages/Login.tsx

Browse files
Files changed (1) hide show
  1. pages/Login.tsx +93 -26
pages/Login.tsx CHANGED
@@ -1,6 +1,6 @@
1
 
2
  import React, { useState } from 'react';
3
- import { GraduationCap, Lock, User as UserIcon, AlertCircle } from 'lucide-react';
4
  import { User, UserRole } from '../types';
5
  import { api } from '../services/api';
6
 
@@ -9,46 +9,94 @@ interface LoginProps {
9
  }
10
 
11
  export const Login: React.FC<LoginProps> = ({ onLogin }) => {
12
- const [username, setUsername] = useState('admin');
13
- const [password, setPassword] = useState('admin');
 
 
 
14
  const [error, setError] = useState('');
15
  const [loading, setLoading] = useState(false);
 
16
 
17
  const handleSubmit = async (e: React.FormEvent) => {
18
  e.preventDefault();
19
  setError('');
 
20
  setLoading(true);
21
 
22
  try {
23
- const user = await api.auth.login(username, password);
24
- onLogin(user);
25
- } catch (err) {
26
- setError('用户名或密码错误。尝试 admin/admin');
27
- } finally {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  setLoading(false);
29
  }
30
  };
31
 
32
  return (
33
  <div className="min-h-screen bg-gray-100 flex items-center justify-center p-4">
34
- <div className="max-w-md w-full bg-white rounded-2xl shadow-xl overflow-hidden">
35
- <div className="bg-blue-600 p-8 text-center">
36
- <div className="inline-flex p-3 bg-white/20 rounded-full mb-4 backdrop-blur-sm">
37
- <GraduationCap className="h-10 w-10 text-white" />
 
 
 
 
 
38
  </div>
39
- <h2 className="text-3xl font-bold text-white mb-2">智慧校园</h2>
40
- <p className="text-blue-100">学校综合教务管理系统</p>
41
  </div>
42
 
43
  <div className="p-8">
44
- <form onSubmit={handleSubmit} className="space-y-6">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  {error && (
46
- <div className="bg-red-50 text-red-600 p-3 rounded-lg text-sm flex items-center">
47
- <AlertCircle size={16} className="mr-2" />
48
  {error}
49
  </div>
50
  )}
51
 
 
 
 
 
 
 
 
52
  <div className="space-y-2">
53
  <label className="text-sm font-medium text-gray-700">用户名</label>
54
  <div className="relative">
@@ -60,7 +108,7 @@ export const Login: React.FC<LoginProps> = ({ onLogin }) => {
60
  required
61
  value={username}
62
  onChange={(e) => setUsername(e.target.value)}
63
- className="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500 transition-colors"
64
  placeholder="请输入用户名"
65
  />
66
  </div>
@@ -77,25 +125,44 @@ export const Login: React.FC<LoginProps> = ({ onLogin }) => {
77
  required
78
  value={password}
79
  onChange={(e) => setPassword(e.target.value)}
80
- className="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500 transition-colors"
81
  placeholder="请输入密码"
82
  />
83
  </div>
84
  </div>
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  <button
87
  type="submit"
88
  disabled={loading}
89
- className={`w-full flex justify-center py-3 px-4 border border-transparent rounded-lg shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-all ${loading ? 'opacity-70 cursor-not-allowed' : ''}`}
90
  >
91
- {loading ? '登录中...' : '登 录'}
 
92
  </button>
93
 
94
- <div className="text-center text-xs text-gray-400 mt-4">
95
- <p>演示账号:</p>
96
- <p>管理员: admin / admin</p>
97
- <p>教师: teacher / teacher</p>
98
- </div>
 
 
99
  </form>
100
  </div>
101
  </div>
 
1
 
2
  import React, { useState } from 'react';
3
+ import { GraduationCap, Lock, User as UserIcon, AlertCircle, ArrowRight } from 'lucide-react';
4
  import { User, UserRole } from '../types';
5
  import { api } from '../services/api';
6
 
 
9
  }
10
 
11
  export const Login: React.FC<LoginProps> = ({ onLogin }) => {
12
+ const [isRegistering, setIsRegistering] = useState(false);
13
+ const [username, setUsername] = useState('');
14
+ const [password, setPassword] = useState('');
15
+ const [role, setRole] = useState<UserRole>(UserRole.ADMIN); // Default to Admin for easy testing
16
+
17
  const [error, setError] = useState('');
18
  const [loading, setLoading] = useState(false);
19
+ const [successMsg, setSuccessMsg] = useState('');
20
 
21
  const handleSubmit = async (e: React.FormEvent) => {
22
  e.preventDefault();
23
  setError('');
24
+ setSuccessMsg('');
25
  setLoading(true);
26
 
27
  try {
28
+ if (isRegistering) {
29
+ // Register Logic
30
+ await api.auth.register({ username, password, role });
31
+ setSuccessMsg('注册成功!正在自动登录...');
32
+ // Auto login after register
33
+ setTimeout(async () => {
34
+ const user = await api.auth.login(username, password);
35
+ onLogin(user);
36
+ }, 1500);
37
+ } else {
38
+ // Login Logic
39
+ const user = await api.auth.login(username, password);
40
+ onLogin(user);
41
+ }
42
+ } catch (err: any) {
43
+ console.error(err);
44
+ if (isRegistering) {
45
+ setError('注册失败: 用户名可能已存在');
46
+ } else {
47
+ setError('用户名或密码错误');
48
+ }
49
  setLoading(false);
50
  }
51
  };
52
 
53
  return (
54
  <div className="min-h-screen bg-gray-100 flex items-center justify-center p-4">
55
+ <div className="max-w-md w-full bg-white rounded-2xl shadow-xl overflow-hidden transition-all duration-300">
56
+ <div className="bg-blue-600 p-8 text-center relative overflow-hidden">
57
+ <div className="absolute inset-0 bg-gradient-to-br from-blue-600 to-indigo-700 opacity-90"></div>
58
+ <div className="relative z-10">
59
+ <div className="inline-flex p-3 bg-white/20 rounded-full mb-4 backdrop-blur-sm shadow-inner">
60
+ <GraduationCap className="h-10 w-10 text-white" />
61
+ </div>
62
+ <h2 className="text-3xl font-bold text-white mb-2">智慧校园</h2>
63
+ <p className="text-blue-100">学校综合教务管理系统</p>
64
  </div>
 
 
65
  </div>
66
 
67
  <div className="p-8">
68
+ <div className="mb-6 flex justify-center">
69
+ <div className="bg-gray-100 p-1 rounded-lg flex text-sm font-medium">
70
+ <button
71
+ onClick={() => { setIsRegistering(false); setError(''); }}
72
+ className={`px-6 py-2 rounded-md transition-all ${!isRegistering ? 'bg-white text-blue-600 shadow-sm' : 'text-gray-500 hover:text-gray-700'}`}
73
+ >
74
+ 登录
75
+ </button>
76
+ <button
77
+ onClick={() => { setIsRegistering(true); setError(''); }}
78
+ className={`px-6 py-2 rounded-md transition-all ${isRegistering ? 'bg-white text-blue-600 shadow-sm' : 'text-gray-500 hover:text-gray-700'}`}
79
+ >
80
+ 注册新账号
81
+ </button>
82
+ </div>
83
+ </div>
84
+
85
+ <form onSubmit={handleSubmit} className="space-y-5">
86
  {error && (
87
+ <div className="bg-red-50 text-red-600 p-3 rounded-lg text-sm flex items-center animate-in fade-in slide-in-from-top-2">
88
+ <AlertCircle size={16} className="mr-2 flex-shrink-0" />
89
  {error}
90
  </div>
91
  )}
92
 
93
+ {successMsg && (
94
+ <div className="bg-green-50 text-green-600 p-3 rounded-lg text-sm flex items-center animate-in fade-in slide-in-from-top-2">
95
+ <div className="mr-2 h-2 w-2 bg-green-500 rounded-full animate-pulse"></div>
96
+ {successMsg}
97
+ </div>
98
+ )}
99
+
100
  <div className="space-y-2">
101
  <label className="text-sm font-medium text-gray-700">用户名</label>
102
  <div className="relative">
 
108
  required
109
  value={username}
110
  onChange={(e) => setUsername(e.target.value)}
111
+ className="block w-full pl-10 pr-3 py-2.5 border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500 transition-colors bg-gray-50 focus:bg-white"
112
  placeholder="请输入用户名"
113
  />
114
  </div>
 
125
  required
126
  value={password}
127
  onChange={(e) => setPassword(e.target.value)}
128
+ className="block w-full pl-10 pr-3 py-2.5 border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500 transition-colors bg-gray-50 focus:bg-white"
129
  placeholder="请输入密码"
130
  />
131
  </div>
132
  </div>
133
 
134
+ {isRegistering && (
135
+ <div className="space-y-2 animate-in fade-in slide-in-from-top-2">
136
+ <label className="text-sm font-medium text-gray-700">选择角色</label>
137
+ <select
138
+ value={role}
139
+ onChange={(e) => setRole(e.target.value as UserRole)}
140
+ className="block w-full px-3 py-2.5 border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500 transition-colors bg-white"
141
+ >
142
+ <option value={UserRole.ADMIN}>管理员 (拥有所有权限)</option>
143
+ <option value={UserRole.TEACHER}>教师</option>
144
+ <option value={UserRole.STUDENT}>学生</option>
145
+ </select>
146
+ <p className="text-xs text-gray-500 mt-1">* 仅用于演示,实际生产环境应禁止直接注册管理员</p>
147
+ </div>
148
+ )}
149
+
150
  <button
151
  type="submit"
152
  disabled={loading}
153
+ className={`w-full flex justify-center py-3 px-4 border border-transparent rounded-lg shadow-lg shadow-blue-200 text-sm font-bold text-white bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-all transform hover:scale-[1.02] active:scale-[0.98] ${loading ? 'opacity-70 cursor-not-allowed' : ''}`}
154
  >
155
+ {loading ? '处理中...' : (isRegistering ? '立即注册' : '登 录')}
156
+ {!loading && <ArrowRight size={16} className="ml-2" />}
157
  </button>
158
 
159
+ {!isRegistering && (
160
+ <div className="text-center text-xs text-gray-400 mt-4 border-t border-gray-100 pt-4">
161
+ <p className="mb-1">演示账号 (如果数据库已初始化):</p>
162
+ <span className="bg-gray-100 px-2 py-1 rounded mr-2">admin / admin</span>
163
+ <span className="bg-gray-100 px-2 py-1 rounded">teacher / teacher</span>
164
+ </div>
165
+ )}
166
  </form>
167
  </div>
168
  </div>