|
@@ -1,214 +1,260 @@
|
|
-import React, { useState } from 'react';
|
|
|
|
-import { Form, Input, Button, Tabs, message } from 'antd';
|
|
|
|
-import Icon, { LockOutlined, UserOutlined } from '@ant-design/icons';
|
|
|
|
-import styles from './login.module.css';
|
|
|
|
-import { sendCode, loginBySendCode, login } from '../../http/sso';
|
|
|
|
-import LogoIcon from '@src/assets/images/login/logo.svg?react';
|
|
|
|
|
|
+import React, { useState } from "react";
|
|
|
|
+import { Form, Input, Button, Tabs, message } from "antd";
|
|
|
|
+import Icon, { LockOutlined, UserOutlined } from "@ant-design/icons";
|
|
|
|
+import styles from "./login.module.css";
|
|
|
|
+import { sendCode, loginBySendCode, login } from "../../http/sso";
|
|
|
|
+import LogoIcon from "@src/assets/images/login/logo.svg?react";
|
|
|
|
|
|
const LoginPage: React.FC = () => {
|
|
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 [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 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;
|
|
|
|
- }
|
|
|
|
|
|
+ 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((error as Error)?.message || '发送验证码失败,请重试');
|
|
|
|
- } finally {
|
|
|
|
- setSendingCode(false);
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
|
|
+ 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(
|
|
|
|
+ (error as Error)?.message || "发送验证码失败,请重试"
|
|
|
|
+ );
|
|
|
|
+ } 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((error as Error)?.message || '登录失败,请重试');
|
|
|
|
- } finally {
|
|
|
|
- setAccountLoading(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((error as Error)?.message || "登录失败,请重试");
|
|
|
|
+ } finally {
|
|
|
|
+ setAccountLoading(false);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
|
|
- return (
|
|
|
|
- <div className={styles.loginContainer}>
|
|
|
|
- <div className={styles.leftSection}>
|
|
|
|
- <div className={styles.logoSection}>
|
|
|
|
- <Icon component={LogoIcon} />
|
|
|
|
- <span>票圈内容合作平台</span>
|
|
|
|
- </div>
|
|
|
|
- <div className={styles.platformTitle}>票圈内容合作平台</div>
|
|
|
|
- </div>
|
|
|
|
-
|
|
|
|
- <div className={styles.rightSection}>
|
|
|
|
- <div className={styles.loginBox}>
|
|
|
|
- <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>
|
|
|
|
|
|
+ return (
|
|
|
|
+ <div className={styles.loginContainer}>
|
|
|
|
+ <div className={styles.leftSection}>
|
|
|
|
+ <div className={styles.logoSection}>
|
|
|
|
+ <Icon component={LogoIcon} />
|
|
|
|
+ <span>票圈内容合作平台</span>
|
|
|
|
+ </div>
|
|
|
|
+ <div className={styles.platformTitle}>票圈内容合作平台</div>
|
|
|
|
+ </div>
|
|
|
|
|
|
- <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>
|
|
|
|
|
|
+ <div className={styles.rightSection}>
|
|
|
|
+ <div className={styles.loginBox}>
|
|
|
|
+ <div className={styles.tabsContainer}>
|
|
|
|
+ <Tabs
|
|
|
|
+ defaultActiveKey="phone"
|
|
|
|
|
|
- <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>
|
|
|
|
|
|
+ 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
|
|
|
|
+ variant="borderless"
|
|
|
|
+ addonBefore={
|
|
|
|
+ <div
|
|
|
|
+ className={
|
|
|
|
+ styles.phonePrefix
|
|
|
|
+ }
|
|
|
|
+ >
|
|
|
|
+ +86
|
|
|
|
+ </div>
|
|
|
|
+ }
|
|
|
|
+ placeholder="手机号"
|
|
|
|
+ className={
|
|
|
|
+ styles.phoneInput +
|
|
|
|
+ " border-b-[1px] border-b-[#160a19]"
|
|
|
|
+ }
|
|
|
|
+ />
|
|
|
|
+ </Form.Item>
|
|
|
|
|
|
- <Form.Item
|
|
|
|
- name="password"
|
|
|
|
- rules={[{ required: true, message: '请输入密码' }]}
|
|
|
|
- >
|
|
|
|
- <Input.Password
|
|
|
|
- prefix={<LockOutlined />}
|
|
|
|
- placeholder="密码"
|
|
|
|
- />
|
|
|
|
- </Form.Item>
|
|
|
|
|
|
+ <Form.Item
|
|
|
|
+ name="code"
|
|
|
|
+ rules={[
|
|
|
|
+ {
|
|
|
|
+ required: true,
|
|
|
|
+ message: "请输入验证码",
|
|
|
|
+ },
|
|
|
|
+ ]}
|
|
|
|
+ >
|
|
|
|
+ <div className={styles.codeRow}>
|
|
|
|
+ <Input
|
|
|
|
+ variant="borderless"
|
|
|
|
+ placeholder="验证码"
|
|
|
|
+ className={
|
|
|
|
+ styles.codeInput + ' rounded-none border-b-[1px] border-b-[#160a19]'
|
|
|
|
+ }
|
|
|
|
+ />
|
|
|
|
+ <Button
|
|
|
|
+ onClick={handleSendCode}
|
|
|
|
+ disabled={countdown > 0}
|
|
|
|
+ loading={sendingCode}
|
|
|
|
+ type="text"
|
|
|
|
+ className={
|
|
|
|
+ styles.getCodeBtn
|
|
|
|
+ }
|
|
|
|
+ >
|
|
|
|
+ {countdown > 0
|
|
|
|
+ ? `${countdown}s`
|
|
|
|
+ : "获取验证码"}
|
|
|
|
+ </Button>
|
|
|
|
+ </div>
|
|
|
|
+ </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>
|
|
|
|
- );
|
|
|
|
|
|
+ <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
|
|
|
|
+ placeholder="账号"
|
|
|
|
+ variant="borderless"
|
|
|
|
+ className="rounded-none border-b-[1px] border-b-[#160a19]"
|
|
|
|
+ />
|
|
|
|
+ </Form.Item>
|
|
|
|
+
|
|
|
|
+ <Form.Item
|
|
|
|
+ name="password"
|
|
|
|
+ rules={[
|
|
|
|
+ {
|
|
|
|
+ required: true,
|
|
|
|
+ message: "请输入密码",
|
|
|
|
+ },
|
|
|
|
+ ]}
|
|
|
|
+ >
|
|
|
|
+ <Input.Password
|
|
|
|
+ placeholder="密码"
|
|
|
|
+ variant="borderless"
|
|
|
|
+ className="rounded-none border-b-[1px] border-b-[#160a19]"
|
|
|
|
+ />
|
|
|
|
+ </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;
|
|
export default LoginPage;
|