blob: 51f323e596a4b727ee14862020ab8bac3e2d3c23 [file] [log] [blame]
Krishya57cc17b2025-05-26 16:43:34 +08001import { useState } from "react";
2import { Link } from "wouter";
3import "./AuthPage.css";
Krishya34493be2025-06-09 22:45:46 +08004// import logo from '../../assets/logo.png';
5import { ReactComponent as LogoIcon } from '../../assets/logo.svg';
6// import backgroundImage from '../../assets/b.png';
Krishya2283d882025-05-27 22:25:19 +08007
Krishya57cc17b2025-05-26 16:43:34 +08008function AuthPage() {
9 const [activeTab, setActiveTab] = useState("login");
10
11 // Login form state
12 const [loginData, setLoginData] = useState({
13 username: "",
14 password: "",
15 rememberMe: false,
16 });
17
18 // Register form state
19 const [registerData, setRegisterData] = useState({
20 username: "",
21 email: "",
22 password: "",
23 confirmPassword: "",
24 inviteCode: "",
Krishya57cc17b2025-05-26 16:43:34 +080025 });
26
27 // Form errors
28 const [errors, setErrors] = useState({
29 login: {},
30 register: {},
31 });
32
Krishya57cc17b2025-05-26 16:43:34 +080033 // Handle login form submission
34 const handleLogin = async (e) => {
Krishyaf66d9592025-06-03 17:41:05 +080035 e.preventDefault();
Krishya57cc17b2025-05-26 16:43:34 +080036
Krishyaf66d9592025-06-03 17:41:05 +080037 const newErrors = {};
38 if (!loginData.username) {
Krishya7096ab12025-06-05 17:15:46 +080039 newErrors.username = "请输入用户名";
Krishyaf66d9592025-06-03 17:41:05 +080040 }
41 if (!loginData.password) {
42 newErrors.password = "请输入密码";
43 }
44
45 if (Object.keys(newErrors).length > 0) {
46 setErrors((prev) => ({ ...prev, login: newErrors }));
47 return;
48 }
49
50 try {
51 const response = await fetch("/echo/user/login", {
52 method: 'POST',
53 headers: {
54 'Content-Type': 'application/json',
55 },
56 body: JSON.stringify({
57 username: loginData.username,
58 password: loginData.password,
59 }),
60 });
61
62 const data = await response.json();
63
64 if (data.msg === "登录成功" && data.user) {
65 // 保存用户信息到 localStorage
66 localStorage.setItem("user", JSON.stringify(data.user));
Krishya8f2fec82025-06-04 21:54:46 +080067 localStorage.setItem("userId", data.user.userId); // 如果有 id 字段
Krishya51f611d2025-06-04 22:25:58 +080068 window.location.href = '/forum';
Krishyaf66d9592025-06-03 17:41:05 +080069 } else {
70 throw new Error(data.msg || "登录失败");
Krishya57cc17b2025-05-26 16:43:34 +080071 }
Krishyaf66d9592025-06-03 17:41:05 +080072 } catch (error) {
73 console.error('登录错误:', error.message);
74 setErrors((prev) => ({
75 ...prev,
76 login: { message: error.message },
77 }));
78 }
79};
Krishya57cc17b2025-05-26 16:43:34 +080080
Krishya57cc17b2025-05-26 16:43:34 +080081
82 // Handle register form submission
83 const handleRegister = async (e) => {
Krishyaf66d9592025-06-03 17:41:05 +080084 e.preventDefault();
Krishya57cc17b2025-05-26 16:43:34 +080085
Krishyaf66d9592025-06-03 17:41:05 +080086 const newErrors = {};
87 if (!registerData.username) {
88 newErrors.username = "请输入用户名";
89 }
90 if (!registerData.email) {
91 newErrors.email = "请输入邮箱";
92 } else if (!/\S+@\S+\.\S+/.test(registerData.email)) {
93 newErrors.email = "邮箱格式不正确";
94 }
95 if (!registerData.password) {
96 newErrors.password = "请输入密码";
97 } else if (registerData.password.length < 6) {
98 newErrors.password = "密码长度至少为6位";
99 }
100 if (registerData.password !== registerData.confirmPassword) {
101 newErrors.confirmPassword = "两次输入的密码不一致";
102 }
Krishya57cc17b2025-05-26 16:43:34 +0800103
Krishyaf66d9592025-06-03 17:41:05 +0800104 if (Object.keys(newErrors).length > 0) {
105 setErrors((prev) => ({ ...prev, register: newErrors }));
106 return;
107 }
108
Krishyaf66d9592025-06-03 17:41:05 +0800109 try {
110 const response = await fetch("/echo/user/register", {
111 method: 'POST',
112 headers: {
113 'Content-Type': 'application/json',
114 },
115 body: JSON.stringify({
116 username: registerData.username,
117 email: registerData.email,
Krishya7096ab12025-06-05 17:15:46 +0800118 password: registerData.password, // 原始密码
119 role: "user",
Krishyaf66d9592025-06-03 17:41:05 +0800120 inviteCode: registerData.inviteCode,
121 }),
122 });
123
124 const data = await response.json();
125
126 if (data.msg === "注册成功") {
127 alert("注册成功,请登录!");
128 setActiveTab("login");
129 } else {
130 throw new Error(data.msg || "注册失败");
Krishya57cc17b2025-05-26 16:43:34 +0800131 }
Krishyaf66d9592025-06-03 17:41:05 +0800132 } catch (error) {
133 console.error("注册错误:", error.message);
134 setErrors((prev) => ({
135 ...prev,
136 register: { message: error.message },
137 }));
138 }
139};
Krishya57cc17b2025-05-26 16:43:34 +0800140
Krishya57cc17b2025-05-26 16:43:34 +0800141
Krishya7096ab12025-06-05 17:15:46 +0800142
Krishya57cc17b2025-05-26 16:43:34 +0800143 // Update login form data
144 const updateLoginData = (field, value) => {
145 setLoginData({
146 ...loginData,
147 [field]: value,
148 });
149 };
150
151 // Update register form data
152 const updateRegisterData = (field, value) => {
153 setRegisterData({
154 ...registerData,
155 [field]: value,
156 });
157 };
Krishya75e43c02025-04-05 21:16:30 +0800158
159 return (
Krishya57cc17b2025-05-26 16:43:34 +0800160 <div className="auth-container">
Krishya7096ab12025-06-05 17:15:46 +0800161 <div className="logo-container">
Krishya34493be2025-06-09 22:45:46 +0800162 <LogoIcon className="site-logo" />
Krishya7096ab12025-06-05 17:15:46 +0800163 </div>
164
Krishya34493be2025-06-09 22:45:46 +0800165 {/* <div className="auth-card"> */}
166 <div className="glass-card">
Krishya57cc17b2025-05-26 16:43:34 +0800167 <div className="auth-header">
168 <div className={`auth-tab ${activeTab === "login" ? "active" : ""}`} onClick={() => setActiveTab("login")}>
169 登录
170 </div>
171 <div className={`auth-tab ${activeTab === "register" ? "active" : ""}`} onClick={() => setActiveTab("register")}>
172 注册
173 </div>
Krishyaf66d9592025-06-03 17:41:05 +0800174
Krishya57cc17b2025-05-26 16:43:34 +0800175 </div>
176
177 <div className="auth-content">
178 {activeTab === "login" ? (
179 <form className="auth-form" onSubmit={handleLogin}>
180 {errors.login.message && <div className="error-message">{errors.login.message}</div>}
181 <div className="form-group">
Krishya7096ab12025-06-05 17:15:46 +0800182 <label htmlFor="login-username">用户名</label>
Krishya57cc17b2025-05-26 16:43:34 +0800183 <input
184 type="text"
185 id="login-username"
186 value={loginData.username}
187 onChange={(e) => updateLoginData("username", e.target.value)}
Krishya7096ab12025-06-05 17:15:46 +0800188 placeholder="请输入用户名"
Krishya57cc17b2025-05-26 16:43:34 +0800189 required
190 />
191 {errors.login.username && <div className="error-message">{errors.login.username}</div>}
192 </div>
193
194 <div className="form-group">
195 <label htmlFor="login-password">密码</label>
196 <input
197 type="password"
198 id="login-password"
199 value={loginData.password}
200 onChange={(e) => updateLoginData("password", e.target.value)}
201 placeholder="请输入密码"
202 required
203 />
204 {errors.login.password && <div className="error-message">{errors.login.password}</div>}
205 </div>
206
207 <div className="form-group-inline">
208 <div className="checkbox-container">
Krishya7096ab12025-06-05 17:15:46 +0800209 {/* <input
Krishya57cc17b2025-05-26 16:43:34 +0800210 type="checkbox"
211 id="remember-me"
212 checked={loginData.rememberMe}
213 onChange={(e) => updateLoginData("rememberMe", e.target.checked)}
Krishya7096ab12025-06-05 17:15:46 +0800214 /> */}
215 {/* <label htmlFor="remember-me">记住我</label> */}
Krishya57cc17b2025-05-26 16:43:34 +0800216 </div>
217 <Link to="/forgot-password" className="forgot-password">
218 忘记密码?
219 </Link>
220 </div>
221
222 <button type="submit" className="auth-button">
223 登录
224 </button>
225 </form>
226 ) : (
227 <form className="auth-form" onSubmit={handleRegister}>
228 {errors.register.message && <div className="error-message">{errors.register.message}</div>}
229 <div className="form-group">
230 <label htmlFor="register-username">用户名</label>
231 <input
232 type="text"
233 id="register-username"
234 value={registerData.username}
235 onChange={(e) => updateRegisterData("username", e.target.value)}
236 placeholder="请输入用户名"
237 required
238 />
239 {errors.register.username && <div className="error-message">{errors.register.username}</div>}
240 </div>
241
242 <div className="form-group">
243 <label htmlFor="register-email">邮箱</label>
244 <input
245 type="email"
246 id="register-email"
247 value={registerData.email}
248 onChange={(e) => updateRegisterData("email", e.target.value)}
249 placeholder="请输入邮箱"
250 required
251 />
252 {errors.register.email && <div className="error-message">{errors.register.email}</div>}
253 </div>
254
255 <div className="form-group">
256 <label htmlFor="register-password">密码</label>
257 <input
258 type="password"
259 id="register-password"
260 value={registerData.password}
261 onChange={(e) => updateRegisterData("password", e.target.value)}
262 placeholder="请输入密码"
263 required
264 />
265 {errors.register.password && <div className="error-message">{errors.register.password}</div>}
266 </div>
267
268 <div className="form-group">
269 <label htmlFor="register-confirm-password">确认密码</label>
270 <input
271 type="password"
272 id="register-confirm-password"
273 value={registerData.confirmPassword}
274 onChange={(e) => updateRegisterData("confirmPassword", e.target.value)}
275 placeholder="请再次输入密码"
276 required
277 />
278 {errors.register.confirmPassword && (
279 <div className="error-message">{errors.register.confirmPassword}</div>
280 )}
281 </div>
282
283 <div className="form-group">
284 <label htmlFor="register-inviteCode">邀请码</label>
285 <input
286 type="text"
287 id="register-inviteCode"
288 value={registerData.inviteCode}
289 onChange={(e) => updateRegisterData("inviteCode", e.target.value)}
290 placeholder="请输入邀请码"
291 />
292 {errors.register.inviteCode && <div className="error-message">{errors.register.inviteCode}</div>}
293 </div>
294
295 <button type="submit" className="auth-button">
296 注册
297 </button>
298 </form>
299 )}
300 </div>
301 </div>
Krishya75e43c02025-04-05 21:16:30 +0800302 </div>
303 );
Krishya57cc17b2025-05-26 16:43:34 +0800304}
Krishya75e43c02025-04-05 21:16:30 +0800305
306export default AuthPage;