Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 

84 строки
2.4 KiB

  1. import React, { useState } from 'react';
  2. export default function LoginForm({ apiUrl, onSuccess, onError }) {
  3. const [username, setUsername] = useState('');
  4. const [password, setPassword] = useState('');
  5. const [loading, setLoading] = useState(false);
  6. const [error, setError] = useState('');
  7. const handleSubmit = async (e) => {
  8. e.preventDefault();
  9. setError('');
  10. if (!username.trim() || !password.trim()) {
  11. const msg = '请输入用户名和密码';
  12. setError(msg);
  13. onError?.({ message: msg });
  14. return;
  15. }
  16. setLoading(true);
  17. try {
  18. const res = await fetch(`${apiUrl}/api/user/login`, {
  19. method: 'POST',
  20. headers: { 'Content-Type': 'application/json' },
  21. body: JSON.stringify({ username: username.trim(), password }),
  22. });
  23. const data = await res.json();
  24. if (data.success) {
  25. if (data.data?.require_2fa) {
  26. const msg = '此账户启用了两步验证,暂不支持通过 Widget 登录';
  27. setError(msg);
  28. onError?.({ message: msg });
  29. return;
  30. }
  31. onSuccess?.(data.data);
  32. } else {
  33. const msg = data.message || '登录失败';
  34. setError(msg);
  35. onError?.({ message: msg });
  36. }
  37. } catch (err) {
  38. const msg = '网络错误,请检查网络连接';
  39. setError(msg);
  40. onError?.({ message: msg });
  41. } finally {
  42. setLoading(false);
  43. }
  44. };
  45. return (
  46. <form className="naw-form" onSubmit={handleSubmit}>
  47. <div className="naw-field">
  48. <label className="naw-label">用户名或邮箱</label>
  49. <input
  50. className="naw-input"
  51. type="text"
  52. placeholder="请输入用户名或邮箱地址"
  53. value={username}
  54. onChange={(e) => setUsername(e.target.value)}
  55. autoComplete="username"
  56. disabled={loading}
  57. />
  58. </div>
  59. <div className="naw-field">
  60. <label className="naw-label">密码</label>
  61. <input
  62. className="naw-input"
  63. type="password"
  64. placeholder="请输入密码"
  65. value={password}
  66. onChange={(e) => setPassword(e.target.value)}
  67. autoComplete="current-password"
  68. disabled={loading}
  69. />
  70. </div>
  71. <p className="naw-error-msg">{error}</p>
  72. <button className="naw-button" type="submit" disabled={loading}>
  73. {loading ? '登录中...' : '登录'}
  74. </button>
  75. </form>
  76. );
  77. }