blob: 1aa7b24f6fc5762db4f99c7d99af485342d6d8a7 [file] [log] [blame]
Krishya57cc17b2025-05-26 16:43:34 +08001// import React, { useState } from 'react';
2// import Login from '../../components/Auth/Login';
3// import Register from '../../components/Auth/Register';
Krishya75e43c02025-04-05 21:16:30 +08004
Krishya57cc17b2025-05-26 16:43:34 +08005// const AuthPage = () => {
6// const [isRegister, setIsRegister] = useState(false);
7
8// return (
9// <div>
10// {isRegister ? (
11// <Register onLoginClick={() => setIsRegister(false)} />
12// ) : (
13// <Login onRegisterClick={() => setIsRegister(true)} />
14// )}
15// </div>
16// );
17// };
18
19// export default AuthPage;
20
21
22
23import { useState } from "react";
24import { Link } from "wouter";
25import "./AuthPage.css";
26import CryptoJS from "crypto-js";
27
Krishya2283d882025-05-27 22:25:19 +080028
Krishya57cc17b2025-05-26 16:43:34 +080029function AuthPage() {
30 const [activeTab, setActiveTab] = useState("login");
31
32 // Login form state
33 const [loginData, setLoginData] = useState({
34 username: "",
35 password: "",
36 rememberMe: false,
37 });
38
39 // Register form state
40 const [registerData, setRegisterData] = useState({
41 username: "",
42 email: "",
43 password: "",
44 confirmPassword: "",
45 inviteCode: "",
46 agreeTerms: false,
47 });
48
49 // Form errors
50 const [errors, setErrors] = useState({
51 login: {},
52 register: {},
53 });
54
55 const hashPassword = (password) => {
56 return CryptoJS.SHA256(password).toString(CryptoJS.enc.Hex);
57 };
58
59 // Handle login form submission
60 const handleLogin = async (e) => {
61 e.preventDefault();
62
63 // 客户端验证
64 const newErrors = {};
65 if (!loginData.username) {
66 newErrors.username = "请输入用户名或邮箱";
67 }
68 if (!loginData.password) {
69 newErrors.password = "请输入密码";
70 }
71
72 if (Object.keys(newErrors).length > 0) {
73 setErrors((prev) => ({ ...prev, login: newErrors }));
74 return;
75 }
76
77 // 加密密码
78 const hashedPassword = hashPassword(loginData.password);
79
80 try {
Krishya2283d882025-05-27 22:25:19 +080081 const response = await fetch(`/echo/user/login`, {
Krishya57cc17b2025-05-26 16:43:34 +080082 method: 'POST',
83 headers: {
84 'Content-Type': 'application/json',
85 },
86 body: JSON.stringify({
87 username: loginData.username,
88 password: hashedPassword,
89 }),
90 });
91
92 if (!response.ok) {
93 throw new Error('登录失败');
94 }
95
96 const data = await response.json();
97
98 if (data.code !== 0 || !data.result) {
99 throw new Error(data.msg || '登录失败');
100 }
101
102 console.log('登录成功:', data);
103 localStorage.setItem('token', data.rows.token);
104 localStorage.setItem('userId', data.rows.userId);
105 window.location.href = '/';
106 } catch (error) {
107 console.error('登录错误:', error.message);
108 setErrors((prev) => ({
109 ...prev,
110 login: { message: error.message },
111 }));
112 throw error;
113 }
114 };
115
116 // Handle register form submission
117 const handleRegister = async (e) => {
118 e.preventDefault();
119
120 // 客户端验证
121 const newErrors = {};
122 if (!registerData.username) {
123 newErrors.username = "请输入用户名";
124 }
125 if (!registerData.email) {
126 newErrors.email = "请输入邮箱";
127 } else if (!/\S+@\S+\.\S+/.test(registerData.email)) {
128 newErrors.email = "邮箱格式不正确";
129 }
130 if (!registerData.password) {
131 newErrors.password = "请输入密码";
132 } else if (registerData.password.length < 6) {
133 newErrors.password = "密码长度至少为6位";
134 }
135 if (registerData.password !== registerData.confirmPassword) {
136 newErrors.confirmPassword = "两次输入的密码不一致";
137 }
138 if (!registerData.agreeTerms) {
139 newErrors.agreeTerms = "请同意用户协议和隐私政策";
140 }
141
142 if (Object.keys(newErrors).length > 0) {
143 setErrors({ ...errors, register: newErrors });
144 return;
145 }
146
147 // 加密密码
148 const hashedPassword = hashPassword(registerData.password);
149
150 try {
Krishya2283d882025-05-27 22:25:19 +0800151 const response = await fetch(`/echo/user/register`, {
Krishya57cc17b2025-05-26 16:43:34 +0800152 method: 'POST',
153 headers: {
154 'Content-Type': 'application/json',
155 },
156 body: JSON.stringify({
157 username: registerData.username,
158 email: registerData.email,
159 password: hashedPassword,
160 inviteCode: registerData.inviteCode,
161 }),
162 });
163
164 if (!response.ok) {
165 throw new Error('注册失败');
166 }
167
168 const data = await response.json();
169 if (data.code !== 0 || !data.result) {
170 throw new Error(data.msg || '注册失败');
171 }
172
173 console.log('注册成功:', data);
174 setActiveTab('login');
175 alert('注册成功,请登录!');
176 } catch (error) {
177 console.error('注册错误:', error.message);
178 setErrors((prev) => ({
179 ...prev,
180 register: { message: error.message },
181 }));
182 }
183 };
184
185 // Update login form data
186 const updateLoginData = (field, value) => {
187 setLoginData({
188 ...loginData,
189 [field]: value,
190 });
191 };
192
193 // Update register form data
194 const updateRegisterData = (field, value) => {
195 setRegisterData({
196 ...registerData,
197 [field]: value,
198 });
199 };
Krishya75e43c02025-04-05 21:16:30 +0800200
201 return (
Krishya57cc17b2025-05-26 16:43:34 +0800202 <div className="auth-container">
203 <div className="auth-card">
204 <div className="auth-header">
205 <div className={`auth-tab ${activeTab === "login" ? "active" : ""}`} onClick={() => setActiveTab("login")}>
206 登录
207 </div>
208 <div className={`auth-tab ${activeTab === "register" ? "active" : ""}`} onClick={() => setActiveTab("register")}>
209 注册
210 </div>
211 </div>
212
213 <div className="auth-content">
214 {activeTab === "login" ? (
215 <form className="auth-form" onSubmit={handleLogin}>
216 {errors.login.message && <div className="error-message">{errors.login.message}</div>}
217 <div className="form-group">
218 <label htmlFor="login-username">用户名/邮箱</label>
219 <input
220 type="text"
221 id="login-username"
222 value={loginData.username}
223 onChange={(e) => updateLoginData("username", e.target.value)}
224 placeholder="请输入用户名或邮箱"
225 required
226 />
227 {errors.login.username && <div className="error-message">{errors.login.username}</div>}
228 </div>
229
230 <div className="form-group">
231 <label htmlFor="login-password">密码</label>
232 <input
233 type="password"
234 id="login-password"
235 value={loginData.password}
236 onChange={(e) => updateLoginData("password", e.target.value)}
237 placeholder="请输入密码"
238 required
239 />
240 {errors.login.password && <div className="error-message">{errors.login.password}</div>}
241 </div>
242
243 <div className="form-group-inline">
244 <div className="checkbox-container">
245 <input
246 type="checkbox"
247 id="remember-me"
248 checked={loginData.rememberMe}
249 onChange={(e) => updateLoginData("rememberMe", e.target.checked)}
250 />
251 <label htmlFor="remember-me">记住我</label>
252 </div>
253 <Link to="/forgot-password" className="forgot-password">
254 忘记密码?
255 </Link>
256 </div>
257
258 <button type="submit" className="auth-button">
259 登录
260 </button>
261 </form>
262 ) : (
263 <form className="auth-form" onSubmit={handleRegister}>
264 {errors.register.message && <div className="error-message">{errors.register.message}</div>}
265 <div className="form-group">
266 <label htmlFor="register-username">用户名</label>
267 <input
268 type="text"
269 id="register-username"
270 value={registerData.username}
271 onChange={(e) => updateRegisterData("username", e.target.value)}
272 placeholder="请输入用户名"
273 required
274 />
275 {errors.register.username && <div className="error-message">{errors.register.username}</div>}
276 </div>
277
278 <div className="form-group">
279 <label htmlFor="register-email">邮箱</label>
280 <input
281 type="email"
282 id="register-email"
283 value={registerData.email}
284 onChange={(e) => updateRegisterData("email", e.target.value)}
285 placeholder="请输入邮箱"
286 required
287 />
288 {errors.register.email && <div className="error-message">{errors.register.email}</div>}
289 </div>
290
291 <div className="form-group">
292 <label htmlFor="register-password">密码</label>
293 <input
294 type="password"
295 id="register-password"
296 value={registerData.password}
297 onChange={(e) => updateRegisterData("password", e.target.value)}
298 placeholder="请输入密码"
299 required
300 />
301 {errors.register.password && <div className="error-message">{errors.register.password}</div>}
302 </div>
303
304 <div className="form-group">
305 <label htmlFor="register-confirm-password">确认密码</label>
306 <input
307 type="password"
308 id="register-confirm-password"
309 value={registerData.confirmPassword}
310 onChange={(e) => updateRegisterData("confirmPassword", e.target.value)}
311 placeholder="请再次输入密码"
312 required
313 />
314 {errors.register.confirmPassword && (
315 <div className="error-message">{errors.register.confirmPassword}</div>
316 )}
317 </div>
318
319 <div className="form-group">
320 <label htmlFor="register-inviteCode">邀请码</label>
321 <input
322 type="text"
323 id="register-inviteCode"
324 value={registerData.inviteCode}
325 onChange={(e) => updateRegisterData("inviteCode", e.target.value)}
326 placeholder="请输入邀请码"
327 />
328 {errors.register.inviteCode && <div className="error-message">{errors.register.inviteCode}</div>}
329 </div>
330
331 <button type="submit" className="auth-button">
332 注册
333 </button>
334 </form>
335 )}
336 </div>
337 </div>
Krishya75e43c02025-04-05 21:16:30 +0800338 </div>
339 );
Krishya57cc17b2025-05-26 16:43:34 +0800340}
Krishya75e43c02025-04-05 21:16:30 +0800341
342export default AuthPage;