Login.tsx 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import { LoginFormPage, ProFormText } from '@ant-design/pro-components';
  2. import { Alert, Typography, message } from 'antd';
  3. import { Bot, LockKeyhole, UserRound } from 'lucide-react';
  4. import { history } from '@umijs/max';
  5. import { useState } from 'react';
  6. import { apiRequest, jsonOptions, setCsrfToken } from '@/services/api';
  7. import type { AdminUser } from '@/types';
  8. export default function LoginPage() {
  9. const [error, setError] = useState('');
  10. return (
  11. <div className="login-stage">
  12. <span className="login-orbit login-orbit--one" aria-hidden="true" />
  13. <span className="login-orbit login-orbit--two" aria-hidden="true" />
  14. <LoginFormPage
  15. logo={<Bot size={34} color="#168acd" />}
  16. title="Telegram 群管"
  17. subTitle="BOT OPERATIONS / CONTROL PLANE"
  18. containerStyle={{
  19. minHeight: 420,
  20. border: '1px solid rgba(255, 255, 255, 0.7)',
  21. borderRadius: 24,
  22. boxShadow: '0 32px 80px rgba(20, 55, 78, 0.16)',
  23. }}
  24. onFinish={async (values) => {
  25. setError('');
  26. try {
  27. const user = await apiRequest<AdminUser>(
  28. '/auth/login',
  29. jsonOptions('POST', values),
  30. );
  31. setCsrfToken(user.csrf_token);
  32. message.success('登录成功');
  33. history.replace(user.must_change_password ? '/change-password' : '/dashboard');
  34. return true;
  35. } catch (requestError) {
  36. const text = requestError instanceof Error ? requestError.message : '登录失败';
  37. setError(text);
  38. return false;
  39. }
  40. }}
  41. submitter={{ searchConfig: { submitText: '登录' }, submitButtonProps: { block: true } }}
  42. >
  43. {error ? <Alert type="error" showIcon message={error} style={{ marginBottom: 16 }} /> : null}
  44. <ProFormText
  45. name="username"
  46. label="用户名"
  47. initialValue="admin"
  48. fieldProps={{ prefix: <UserRound size={17} />, autoComplete: 'username', size: 'large' }}
  49. rules={[{ required: true, message: '请输入用户名' }]}
  50. />
  51. <ProFormText.Password
  52. name="password"
  53. label="密码"
  54. fieldProps={{ prefix: <LockKeyhole size={17} />, autoComplete: 'current-password', size: 'large' }}
  55. rules={[{ required: true, message: '请输入密码' }]}
  56. />
  57. <Typography.Text type="secondary">
  58. 默认账号 admin;首次登录后必须修改初始密码。
  59. </Typography.Text>
  60. </LoginFormPage>
  61. </div>
  62. );
  63. }