|
@@ -1,275 +1,280 @@
|
|
|
-import Footer from '@/components/Footer';
|
|
|
-import { login } from '@/services/ant-design-pro/api';
|
|
|
-import { getFakeCaptcha } from '@/services/ant-design-pro/login';
|
|
|
-import {
|
|
|
- LockOutlined,
|
|
|
- MobileOutlined,
|
|
|
- UserOutlined,
|
|
|
-} from '@ant-design/icons';
|
|
|
-import {
|
|
|
- LoginForm,
|
|
|
- ProFormCaptcha,
|
|
|
- ProFormCheckbox,
|
|
|
- ProFormText,
|
|
|
-} from '@ant-design/pro-components';
|
|
|
-import { useEmotionCss } from '@ant-design/use-emotion-css';
|
|
|
-import { FormattedMessage, history, useIntl, useModel, Helmet } from '@umijs/max';
|
|
|
-import { Alert, message, Tabs } from 'antd';
|
|
|
-import Settings from '../../../../config/defaultSettings';
|
|
|
-import React, { useState } from 'react';
|
|
|
-import { flushSync } from 'react-dom';
|
|
|
-
|
|
|
-
|
|
|
-const LoginMessage: React.FC<{
|
|
|
- content: string;
|
|
|
-}> = ({ content }) => {
|
|
|
- return (
|
|
|
- <Alert
|
|
|
- style={{
|
|
|
- marginBottom: 24,
|
|
|
- }}
|
|
|
- message={content}
|
|
|
- type="error"
|
|
|
- showIcon
|
|
|
- />
|
|
|
- );
|
|
|
-};
|
|
|
-
|
|
|
-const Login: React.FC = () => {
|
|
|
- const [userLoginState, setUserLoginState] = useState<API.Result>({});
|
|
|
- const [type, setType] = useState<string>('mobile');
|
|
|
- const { initialState, setInitialState } = useModel('@@initialState');
|
|
|
-
|
|
|
- const containerClassName = useEmotionCss(() => {
|
|
|
- return {
|
|
|
- display: 'flex',
|
|
|
- flexDirection: 'column',
|
|
|
- height: '100vh',
|
|
|
- overflow: 'auto',
|
|
|
- backgroundImage:
|
|
|
- "url('https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/V-_oS6r-i7wAAAAAAAAAAAAAFl94AQBr')",
|
|
|
- backgroundSize: '100% 100%',
|
|
|
- };
|
|
|
- });
|
|
|
-
|
|
|
- const intl = useIntl();
|
|
|
-
|
|
|
- const fetchUserInfo = async () => {
|
|
|
- const userInfo = await initialState?.fetchUserInfo?.();
|
|
|
- if (userInfo) {
|
|
|
- console.log('userInfo--->', userInfo)
|
|
|
- flushSync(() => {
|
|
|
- setInitialState((s) => ({
|
|
|
- ...s,
|
|
|
- currentUser: {
|
|
|
- avatar: `https://xsgames.co/randomusers/avatar.php?g=pixel&key=${Math.floor(Math.random() * 10)}`,
|
|
|
- ...userInfo
|
|
|
- },
|
|
|
- }));
|
|
|
- });
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- const handleSubmit = async (values: API.LoginParams) => {
|
|
|
- try {
|
|
|
- const { savePhone, ...value } = values
|
|
|
- // 登录
|
|
|
- const msg = await login({ ...value });
|
|
|
- if (msg.success) {
|
|
|
- localStorage.setItem('Admin-Token', msg?.data?.token)
|
|
|
- const defaultLoginSuccessMessage = intl.formatMessage({
|
|
|
- id: 'pages.login.success',
|
|
|
- defaultMessage: '登录成功!',
|
|
|
- });
|
|
|
- if (savePhone) {
|
|
|
- localStorage.setItem('MOBILE', values.mobile as string)
|
|
|
- }
|
|
|
- message.success(defaultLoginSuccessMessage);
|
|
|
- await fetchUserInfo();
|
|
|
- const urlParams = new URL(window.location.href).searchParams;
|
|
|
- history.push(urlParams.get('redirect') || '/');
|
|
|
- return;
|
|
|
- }
|
|
|
- // 如果失败去设置用户错误信息
|
|
|
- setUserLoginState(msg);
|
|
|
- } catch (error) {
|
|
|
- const defaultLoginFailureMessage = intl.formatMessage({
|
|
|
- id: 'pages.login.failure',
|
|
|
- defaultMessage: '登录失败,请重试!',
|
|
|
- });
|
|
|
- console.log(error);
|
|
|
- message.error(defaultLoginFailureMessage);
|
|
|
- }
|
|
|
- };
|
|
|
- const { success = true } = userLoginState;
|
|
|
-
|
|
|
- return (
|
|
|
- <div className={containerClassName}>
|
|
|
- <Helmet>
|
|
|
- <title>
|
|
|
- {intl.formatMessage({
|
|
|
- id: 'menu.login',
|
|
|
- defaultMessage: '登录页',
|
|
|
- })}
|
|
|
- - {Settings.title}
|
|
|
- </title>
|
|
|
- </Helmet>
|
|
|
- <div
|
|
|
- style={{
|
|
|
- flex: '1',
|
|
|
- padding: '32px 0',
|
|
|
- }}
|
|
|
- >
|
|
|
- <LoginForm
|
|
|
- contentStyle={{
|
|
|
- minWidth: 280,
|
|
|
- maxWidth: '75vw',
|
|
|
- }}
|
|
|
- // logo={<img alt="logo" src="/logo.svg" />}
|
|
|
- title="趣程素材库"
|
|
|
- subTitle={<span style={{ display: 'inline-block', height: 16 }}>{/** intl.formatMessage({ id: 'pages.layouts.userLayout.title' }) */}</span>}
|
|
|
- initialValues={{
|
|
|
- savePhone: true,
|
|
|
- mobile: localStorage.getItem('MOBILE') || null
|
|
|
- }}
|
|
|
- onFinish={async (values) => {
|
|
|
- await handleSubmit(values as API.LoginParams);
|
|
|
- }}
|
|
|
-
|
|
|
- >
|
|
|
- {/* <Tabs
|
|
|
- activeKey={type}
|
|
|
- onChange={setType}
|
|
|
- centered
|
|
|
- items={[
|
|
|
- {
|
|
|
- key: 'account',
|
|
|
- label: '账户密码登录',
|
|
|
- },
|
|
|
- {
|
|
|
- key: 'mobile',
|
|
|
- label: '手机号登录',
|
|
|
- },
|
|
|
- ]}
|
|
|
- /> */}
|
|
|
-
|
|
|
- {!success && type === 'account' && (
|
|
|
- <LoginMessage content={'账户或密码错误'} />
|
|
|
- )}
|
|
|
- {type === 'account' && (
|
|
|
- <>
|
|
|
- <ProFormText
|
|
|
- name="username"
|
|
|
- fieldProps={{
|
|
|
- size: 'large',
|
|
|
- prefix: <UserOutlined />,
|
|
|
- }}
|
|
|
- placeholder={intl.formatMessage({
|
|
|
- id: 'pages.login.username.placeholder',
|
|
|
- defaultMessage: '用户名: admin or user',
|
|
|
- })}
|
|
|
- rules={[
|
|
|
- {
|
|
|
- required: true,
|
|
|
- message: (
|
|
|
- <FormattedMessage
|
|
|
- id="pages.login.username.required"
|
|
|
- defaultMessage="请输入用户名!"
|
|
|
- />
|
|
|
- ),
|
|
|
- },
|
|
|
- ]}
|
|
|
- />
|
|
|
- <ProFormText.Password
|
|
|
- name="password"
|
|
|
- fieldProps={{
|
|
|
- size: 'large',
|
|
|
- prefix: <LockOutlined />,
|
|
|
- }}
|
|
|
- placeholder={intl.formatMessage({
|
|
|
- id: 'pages.login.password.placeholder',
|
|
|
- defaultMessage: '密码: ant.design',
|
|
|
- })}
|
|
|
- rules={[
|
|
|
- {
|
|
|
- required: true,
|
|
|
- message: (
|
|
|
- <FormattedMessage
|
|
|
- id="pages.login.password.required"
|
|
|
- defaultMessage="请输入密码!"
|
|
|
- />
|
|
|
- ),
|
|
|
- },
|
|
|
- ]}
|
|
|
- />
|
|
|
- </>
|
|
|
- )}
|
|
|
-
|
|
|
- {!success && type === 'mobile' && <LoginMessage content="验证码错误" />}
|
|
|
- {type === 'mobile' && (
|
|
|
- <>
|
|
|
- <ProFormText
|
|
|
- fieldProps={{
|
|
|
- size: 'large',
|
|
|
- prefix: <MobileOutlined />,
|
|
|
- }}
|
|
|
- name="mobile"
|
|
|
- placeholder='手机号'
|
|
|
- rules={[
|
|
|
- {
|
|
|
- required: true,
|
|
|
- message: "请输入手机号!",
|
|
|
- },
|
|
|
- {
|
|
|
- pattern: /^1\d{10}$/,
|
|
|
- message: "手机号格式错误!",
|
|
|
- },
|
|
|
- ]}
|
|
|
- />
|
|
|
- <ProFormCaptcha
|
|
|
- fieldProps={{
|
|
|
- size: 'large',
|
|
|
- prefix: <LockOutlined />,
|
|
|
- }}
|
|
|
- phoneName="mobile"
|
|
|
- captchaProps={{
|
|
|
- size: 'large',
|
|
|
- }}
|
|
|
- placeholder='请输入验证码'
|
|
|
- captchaTextRender={(timing, count) => {
|
|
|
- if (timing) {
|
|
|
- return `${count} 获取验证码`;
|
|
|
- }
|
|
|
- return '获取验证码';
|
|
|
- }}
|
|
|
- name="code"
|
|
|
- rules={[
|
|
|
- {
|
|
|
- required: true,
|
|
|
- message: "请输入验证码!",
|
|
|
- },
|
|
|
- ]}
|
|
|
- onGetCaptcha={async (mobile) => {
|
|
|
- const result: any = await getFakeCaptcha({
|
|
|
- mobile,
|
|
|
- smsType: 'SMS_REG_LOGIN'
|
|
|
- });
|
|
|
- if (!result?.success) {
|
|
|
- throw new Error();
|
|
|
- }
|
|
|
- message.success('获取验证码成功!');
|
|
|
- }}
|
|
|
- />
|
|
|
- </>
|
|
|
- )}
|
|
|
- <div style={{ marginBottom: 24 }} >
|
|
|
- <ProFormCheckbox noStyle name="savePhone">保存手机号</ProFormCheckbox>
|
|
|
- </div>
|
|
|
- </LoginForm>
|
|
|
- </div>
|
|
|
- <Footer />
|
|
|
- </div>
|
|
|
- );
|
|
|
-};
|
|
|
-
|
|
|
-export default Login;
|
|
|
+import Footer from '@/components/Footer';
|
|
|
+import { login } from '@/services/ant-design-pro/api';
|
|
|
+import { getFakeCaptcha } from '@/services/ant-design-pro/login';
|
|
|
+import { LockOutlined, MobileOutlined, UserOutlined } from '@ant-design/icons';
|
|
|
+import {
|
|
|
+ LoginForm,
|
|
|
+ ProFormCaptcha,
|
|
|
+ ProFormCheckbox,
|
|
|
+ ProFormText,
|
|
|
+} from '@ant-design/pro-components';
|
|
|
+import { useEmotionCss } from '@ant-design/use-emotion-css';
|
|
|
+import { FormattedMessage, Helmet, history, useIntl, useModel } from '@umijs/max';
|
|
|
+import { Alert, message } from 'antd';
|
|
|
+import React, { useState } from 'react';
|
|
|
+import { flushSync } from 'react-dom';
|
|
|
+import Settings from '../../../../config/defaultSettings';
|
|
|
+
|
|
|
+const LoginMessage: React.FC<{
|
|
|
+ content: string;
|
|
|
+}> = ({ content }) => {
|
|
|
+ return (
|
|
|
+ <Alert
|
|
|
+ style={{
|
|
|
+ marginBottom: 24,
|
|
|
+ }}
|
|
|
+ message={content}
|
|
|
+ type="error"
|
|
|
+ showIcon
|
|
|
+ />
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+const Login: React.FC = () => {
|
|
|
+ const [userLoginState, setUserLoginState] = useState<API.Result>({});
|
|
|
+ const [type, setType] = useState<string>('mobile');
|
|
|
+ const { initialState, setInitialState } = useModel('@@initialState');
|
|
|
+
|
|
|
+ const containerClassName = useEmotionCss(() => {
|
|
|
+ return {
|
|
|
+ display: 'flex',
|
|
|
+ flexDirection: 'column',
|
|
|
+ height: '100vh',
|
|
|
+ overflow: 'auto',
|
|
|
+ backgroundImage:
|
|
|
+ "url('https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/V-_oS6r-i7wAAAAAAAAAAAAAFl94AQBr')",
|
|
|
+ backgroundSize: '100% 100%',
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ const intl = useIntl();
|
|
|
+
|
|
|
+ const fetchUserInfo = async () => {
|
|
|
+ const userInfo = await initialState?.fetchUserInfo?.();
|
|
|
+ if (userInfo) {
|
|
|
+ console.log('userInfo--->', userInfo);
|
|
|
+ flushSync(() => {
|
|
|
+ setInitialState((s) => ({
|
|
|
+ ...s,
|
|
|
+ currentUser: {
|
|
|
+ avatar: `https://xsgames.co/randomusers/avatar.php?g=pixel&key=${Math.floor(
|
|
|
+ Math.random() * 10,
|
|
|
+ )}`,
|
|
|
+ ...userInfo,
|
|
|
+ },
|
|
|
+ }));
|
|
|
+ });
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleSubmit = async (values: API.LoginParams) => {
|
|
|
+ try {
|
|
|
+ const { savePhone, ...value } = values;
|
|
|
+ // 登录
|
|
|
+ const msg = await login({ ...value });
|
|
|
+ if (msg.success) {
|
|
|
+ localStorage.setItem('Admin-Token', msg?.data?.token);
|
|
|
+ const defaultLoginSuccessMessage = intl.formatMessage({
|
|
|
+ id: 'pages.login.success',
|
|
|
+ defaultMessage: '登录成功!',
|
|
|
+ });
|
|
|
+ if (savePhone) {
|
|
|
+ localStorage.setItem('MOBILE', values.mobile as string);
|
|
|
+ }
|
|
|
+ message.success(defaultLoginSuccessMessage);
|
|
|
+ await fetchUserInfo();
|
|
|
+ const urlParams = new URL(window.location.href).searchParams;
|
|
|
+ history.push(urlParams.get('redirect') || '/');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 如果失败去设置用户错误信息
|
|
|
+ setUserLoginState(msg);
|
|
|
+ } catch (error) {
|
|
|
+ const defaultLoginFailureMessage = intl.formatMessage({
|
|
|
+ id: 'pages.login.failure',
|
|
|
+ defaultMessage: '登录失败,请重试!',
|
|
|
+ });
|
|
|
+ console.log(error);
|
|
|
+ message.error(defaultLoginFailureMessage);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const { success = true } = userLoginState;
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className={containerClassName}>
|
|
|
+ <Helmet>
|
|
|
+ <title>
|
|
|
+ {intl.formatMessage({
|
|
|
+ id: 'menu.login',
|
|
|
+ defaultMessage: '登录页',
|
|
|
+ })}
|
|
|
+ - {Settings.title}
|
|
|
+ </title>
|
|
|
+ </Helmet>
|
|
|
+ <div
|
|
|
+ style={{
|
|
|
+ flex: '1',
|
|
|
+ padding: '32px 0',
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <LoginForm
|
|
|
+ contentStyle={{
|
|
|
+ minWidth: 280,
|
|
|
+ maxWidth: '75vw',
|
|
|
+ }}
|
|
|
+ // logo={<img alt="logo" src="/logo.svg" />}
|
|
|
+ title="趣程素材库"
|
|
|
+ subTitle={
|
|
|
+ <span style={{ display: 'inline-block', height: 16 }}>
|
|
|
+ {/** intl.formatMessage({ id: 'pages.layouts.userLayout.title' }) */}
|
|
|
+ </span>
|
|
|
+ }
|
|
|
+ initialValues={{
|
|
|
+ savePhone: true,
|
|
|
+ mobile: localStorage.getItem('MOBILE') || null,
|
|
|
+ }}
|
|
|
+ onFinish={async (values) => {
|
|
|
+ await handleSubmit(values as API.LoginParams);
|
|
|
+ }}
|
|
|
+ submitter={{
|
|
|
+ searchConfig: {
|
|
|
+ submitText: '注册/登录',
|
|
|
+ },
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {/* <Tabs
|
|
|
+ activeKey={type}
|
|
|
+ onChange={setType}
|
|
|
+ centered
|
|
|
+ items={[
|
|
|
+ {
|
|
|
+ key: 'account',
|
|
|
+ label: '账户密码登录',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 'mobile',
|
|
|
+ label: '手机号登录',
|
|
|
+ },
|
|
|
+ ]}
|
|
|
+ /> */}
|
|
|
+
|
|
|
+ {!success && type === 'account' && <LoginMessage content={'账户或密码错误'} />}
|
|
|
+ {type === 'account' && (
|
|
|
+ <>
|
|
|
+ <ProFormText
|
|
|
+ name="username"
|
|
|
+ fieldProps={{
|
|
|
+ size: 'large',
|
|
|
+ prefix: <UserOutlined />,
|
|
|
+ }}
|
|
|
+ placeholder={intl.formatMessage({
|
|
|
+ id: 'pages.login.username.placeholder',
|
|
|
+ defaultMessage: '用户名: admin or user',
|
|
|
+ })}
|
|
|
+ rules={[
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: (
|
|
|
+ <FormattedMessage
|
|
|
+ id="pages.login.username.required"
|
|
|
+ defaultMessage="请输入用户名!"
|
|
|
+ />
|
|
|
+ ),
|
|
|
+ },
|
|
|
+ ]}
|
|
|
+ />
|
|
|
+ <ProFormText.Password
|
|
|
+ name="password"
|
|
|
+ fieldProps={{
|
|
|
+ size: 'large',
|
|
|
+ prefix: <LockOutlined />,
|
|
|
+ }}
|
|
|
+ placeholder={intl.formatMessage({
|
|
|
+ id: 'pages.login.password.placeholder',
|
|
|
+ defaultMessage: '密码: ant.design',
|
|
|
+ })}
|
|
|
+ rules={[
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: (
|
|
|
+ <FormattedMessage
|
|
|
+ id="pages.login.password.required"
|
|
|
+ defaultMessage="请输入密码!"
|
|
|
+ />
|
|
|
+ ),
|
|
|
+ },
|
|
|
+ ]}
|
|
|
+ />
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+
|
|
|
+ {!success && type === 'mobile' && <LoginMessage content="验证码错误" />}
|
|
|
+ {type === 'mobile' && (
|
|
|
+ <>
|
|
|
+ <ProFormText
|
|
|
+ fieldProps={{
|
|
|
+ size: 'large',
|
|
|
+ prefix: <MobileOutlined />,
|
|
|
+ }}
|
|
|
+ name="mobile"
|
|
|
+ placeholder="手机号"
|
|
|
+ rules={[
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请输入手机号!',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ pattern: /^1\d{10}$/,
|
|
|
+ message: '手机号格式错误!',
|
|
|
+ },
|
|
|
+ ]}
|
|
|
+ />
|
|
|
+ <ProFormCaptcha
|
|
|
+ fieldProps={{
|
|
|
+ size: 'large',
|
|
|
+ prefix: <LockOutlined />,
|
|
|
+ }}
|
|
|
+ phoneName="mobile"
|
|
|
+ captchaProps={{
|
|
|
+ size: 'large',
|
|
|
+ }}
|
|
|
+ placeholder="请输入验证码"
|
|
|
+ captchaTextRender={(timing, count) => {
|
|
|
+ if (timing) {
|
|
|
+ return `${count} 获取验证码`;
|
|
|
+ }
|
|
|
+ return '获取验证码';
|
|
|
+ }}
|
|
|
+ name="code"
|
|
|
+ rules={[
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请输入验证码!',
|
|
|
+ },
|
|
|
+ ]}
|
|
|
+ onGetCaptcha={async (mobile) => {
|
|
|
+ const result: any = await getFakeCaptcha({
|
|
|
+ mobile,
|
|
|
+ smsType: 'SMS_REG_LOGIN',
|
|
|
+ });
|
|
|
+ if (!result?.success) {
|
|
|
+ throw new Error();
|
|
|
+ }
|
|
|
+ message.success('获取验证码成功!');
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ <div style={{ marginBottom: 24 }}>
|
|
|
+ <ProFormCheckbox noStyle name="savePhone">
|
|
|
+ 保存手机号
|
|
|
+ </ProFormCheckbox>
|
|
|
+ </div>
|
|
|
+ </LoginForm>
|
|
|
+ </div>
|
|
|
+ <Footer />
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+export default Login;
|