|
@@ -0,0 +1,214 @@
|
|
|
+import React, { useState } from 'react';
|
|
|
+import { Form, Input, Button, Tabs, message } from 'antd';
|
|
|
+import { LockOutlined, UserOutlined } from '@ant-design/icons';
|
|
|
+import styles from './login.module.css';
|
|
|
+import { sendCode, loginBySendCode, login } from '../../http/sso';
|
|
|
+
|
|
|
+const LoginPage: React.FC = () => {
|
|
|
+ const [form] = Form.useForm();
|
|
|
+ const [loading, setLoading] = useState(false);
|
|
|
+ const [sendingCode, setSendingCode] = useState(false);
|
|
|
+ const [countdown, setCountdown] = useState(0);
|
|
|
+ const [accountForm] = Form.useForm();
|
|
|
+ const [accountLoading, setAccountLoading] = useState(false);
|
|
|
+
|
|
|
+ const handlePhoneLogin = async (values: any) => {
|
|
|
+ try {
|
|
|
+ setLoading(true);
|
|
|
+ const { phone, code } = values;
|
|
|
+ const success = await loginBySendCode(phone, code);
|
|
|
+ if (success) {
|
|
|
+ // Redirect will be handled by the login function
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ message.error('登录失败,请重试');
|
|
|
+ } finally {
|
|
|
+ setLoading(false);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleSendCode = async () => {
|
|
|
+ try {
|
|
|
+ const phone = form.getFieldValue('phone');
|
|
|
+ if (!phone) {
|
|
|
+ message.error('请输入手机号');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!/^1[3-9]\d{9}$/.test(phone)) {
|
|
|
+ message.error('请输入正确的手机号');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ setSendingCode(true);
|
|
|
+ const success = await sendCode(phone);
|
|
|
+ if (success) {
|
|
|
+ let count = 60;
|
|
|
+ setCountdown(count);
|
|
|
+ const timer = setInterval(() => {
|
|
|
+ count -= 1;
|
|
|
+ setCountdown(count);
|
|
|
+ if (count <= 0) {
|
|
|
+ clearInterval(timer);
|
|
|
+ setCountdown(0);
|
|
|
+ }
|
|
|
+ }, 1000);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ message.error('发送验证码失败,请重试');
|
|
|
+ } finally {
|
|
|
+ setSendingCode(false);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleAccountLogin = async (values: any) => {
|
|
|
+ try {
|
|
|
+ setAccountLoading(true);
|
|
|
+ const { account, password } = values;
|
|
|
+ const success = await login(account, password);
|
|
|
+ if (success) {
|
|
|
+ // Redirect will be handled by the login function
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ message.error('登录失败,请重试');
|
|
|
+ } finally {
|
|
|
+ setAccountLoading(false);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className={styles.loginContainer}>
|
|
|
+ <div className={styles.leftSection}>
|
|
|
+ <div className={styles.platformTitle}>票圈内容合作平台</div>
|
|
|
+ <div className={styles.illustration}>
|
|
|
+ {/* You can add an illustration image here */}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className={styles.rightSection}>
|
|
|
+ <div className={styles.loginBox}>
|
|
|
+ <h1 className={styles.platformTitle}>票圈内容合作平台</h1>
|
|
|
+
|
|
|
+ <div className={styles.tabsContainer}>
|
|
|
+ <Tabs
|
|
|
+ defaultActiveKey="phone"
|
|
|
+ centered
|
|
|
+ items={[
|
|
|
+ {
|
|
|
+ key: 'phone',
|
|
|
+ label: '验证码登录',
|
|
|
+ children: (
|
|
|
+ <Form
|
|
|
+ form={form}
|
|
|
+ name="phone_login"
|
|
|
+ onFinish={handlePhoneLogin}
|
|
|
+ layout="vertical"
|
|
|
+ size="large"
|
|
|
+ >
|
|
|
+ <Form.Item
|
|
|
+ name="phone"
|
|
|
+ rules={[
|
|
|
+ { required: true, message: '请输入手机号' },
|
|
|
+ { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号' }
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ <Input
|
|
|
+ addonBefore={<div className={styles.phonePrefix}>+86</div>}
|
|
|
+ placeholder="手机号"
|
|
|
+ className={styles.phoneInput}
|
|
|
+ />
|
|
|
+ </Form.Item>
|
|
|
+
|
|
|
+ <Form.Item
|
|
|
+ name="code"
|
|
|
+ rules={[{ required: true, message: '请输入验证码' }]}
|
|
|
+ >
|
|
|
+ <div className={styles.codeRow}>
|
|
|
+ <Input
|
|
|
+ prefix={<LockOutlined />}
|
|
|
+ placeholder="验证码"
|
|
|
+ className={styles.codeInput}
|
|
|
+ />
|
|
|
+ <Button
|
|
|
+ onClick={handleSendCode}
|
|
|
+ disabled={countdown > 0}
|
|
|
+ loading={sendingCode}
|
|
|
+ className={styles.getCodeBtn}
|
|
|
+ >
|
|
|
+ {countdown > 0 ? `${countdown}s` : '获取验证码'}
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </Form.Item>
|
|
|
+
|
|
|
+ <Form.Item>
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ htmlType="submit"
|
|
|
+ block
|
|
|
+ loading={loading}
|
|
|
+ className={styles.loginBtn}
|
|
|
+ >
|
|
|
+ 登录
|
|
|
+ </Button>
|
|
|
+ </Form.Item>
|
|
|
+ </Form>
|
|
|
+ ),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 'account',
|
|
|
+ label: '账号登录',
|
|
|
+ children: (
|
|
|
+ <Form
|
|
|
+ form={accountForm}
|
|
|
+ name="account_login"
|
|
|
+ onFinish={handleAccountLogin}
|
|
|
+ layout="vertical"
|
|
|
+ size="large"
|
|
|
+ >
|
|
|
+ <Form.Item
|
|
|
+ name="account"
|
|
|
+ rules={[{ required: true, message: '请输入账号' }]}
|
|
|
+ >
|
|
|
+ <Input
|
|
|
+ prefix={<UserOutlined />}
|
|
|
+ placeholder="账号"
|
|
|
+ />
|
|
|
+ </Form.Item>
|
|
|
+
|
|
|
+ <Form.Item
|
|
|
+ name="password"
|
|
|
+ rules={[{ required: true, message: '请输入密码' }]}
|
|
|
+ >
|
|
|
+ <Input.Password
|
|
|
+ prefix={<LockOutlined />}
|
|
|
+ placeholder="密码"
|
|
|
+ />
|
|
|
+ </Form.Item>
|
|
|
+
|
|
|
+ <Form.Item>
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ htmlType="submit"
|
|
|
+ block
|
|
|
+ loading={accountLoading}
|
|
|
+ className={styles.loginBtn}
|
|
|
+ >
|
|
|
+ 登录
|
|
|
+ </Button>
|
|
|
+ </Form.Item>
|
|
|
+ </Form>
|
|
|
+ ),
|
|
|
+ }
|
|
|
+ ]}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className={styles.decorationBottom}>
|
|
|
+ {/* You can add a decoration image here */}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+export default LoginPage;
|