From d835d1b51f832889929cdf69010034a30ef44d02 Mon Sep 17 00:00:00 2001
From: Junjie <xjj@123>
Date: 星期四, 17 十月 2024 13:57:29 +0800
Subject: [PATCH] #
---
zy-asrs-flow/src/pages/User/Login/index.jsx | 730 +++++++++++++++++++++++++++++++------------------------
1 files changed, 406 insertions(+), 324 deletions(-)
diff --git a/zy-asrs-flow/src/pages/User/Login/index.jsx b/zy-asrs-flow/src/pages/User/Login/index.jsx
index 2338a44..c32f457 100644
--- a/zy-asrs-flow/src/pages/User/Login/index.jsx
+++ b/zy-asrs-flow/src/pages/User/Login/index.jsx
@@ -1,339 +1,421 @@
-import { Footer } from '@/components';
-import { login } from '@/services/ant-design-pro/api';
-import { getFakeCaptcha } from '@/services/ant-design-pro/login';
import {
- LockOutlined,
- MobileOutlined,
- UserOutlined,
+ LockOutlined,
+ MobileOutlined,
+ UserOutlined,
} from '@ant-design/icons';
import {
- LoginForm,
- ProFormCaptcha,
- ProFormCheckbox,
- ProFormText,
+ LoginFormPage,
+ ProConfigProvider,
+ ProFormCaptcha,
+ ProFormCheckbox,
+ ProFormText,
+ ProFormSelect
} from '@ant-design/pro-components';
-import { FormattedMessage, history, SelectLang, useIntl, useModel, Helmet } from '@umijs/max';
-import { Alert, message, Tabs } from 'antd';
-import Settings from '../../../../config/defaultSettings';
-import React, { useState } from 'react';
+import { Button, Divider, Alert, Tabs, message, theme, Form } from 'antd';
+import { useState, useEffect } from 'react';
+import { FormattedMessage, history, SelectLang, useIntl, useModel, request } from '@umijs/max';
import { flushSync } from 'react-dom';
import { createStyles } from 'antd-style';
+import { setToken } from '@/utils/token-util'
+import { PROJECT_NAME } from '@/config/setting'
+import Http from '@/utils/http';
+
+import logo from '/public/img/logo.png'
+import logoBg from '/public/login-bg.mp4'
const useStyles = createStyles(({ token }) => {
- return {
- action: {
- marginLeft: '8px',
- color: 'rgba(0, 0, 0, 0.2)',
- fontSize: '24px',
- verticalAlign: 'middle',
- cursor: 'pointer',
- transition: 'color 0.3s',
- '&:hover': {
- color: token.colorPrimaryActive,
- },
- },
- lang: {
- width: 42,
- height: 42,
- lineHeight: '42px',
- position: 'fixed',
- right: 16,
- borderRadius: token.borderRadius,
- ':hover': {
- backgroundColor: token.colorBgTextHover,
- },
- },
- container: {
- display: 'flex',
- flexDirection: 'column',
- height: '100vh',
- overflow: 'auto',
- backgroundImage:
- "url('https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/V-_oS6r-i7wAAAAAAAAAAAAAFl94AQBr')",
- backgroundSize: '100% 100%',
- },
- };
-});
+ return {
+ lang: {
-const Lang = () => {
- const { styles } = useStyles();
-
- return (
- <div className={styles.lang} data-lang>
- {SelectLang && <SelectLang />}
- </div>
- );
-};
+ }
+ }
+})
const LoginMessage = ({ content }) => {
- return (
- <Alert
- style={{
- marginBottom: 24,
- }}
- message={content}
- type="error"
- showIcon
- />
- );
-};
-
-const Login = () => {
- const [userLoginState, setUserLoginState] = useState({});
- const [type, setType] = useState('account');
- const { initialState, setInitialState } = useModel('@@initialState');
- const { styles } = useStyles();
- const intl = useIntl();
-
- const fetchUserInfo = async () => {
- const userInfo = await initialState?.fetchUserInfo?.();
- if (userInfo) {
- flushSync(() => {
- setInitialState((s) => ({
- ...s,
- currentUser: userInfo,
- }));
- });
- }
- };
-
- const handleSubmit = async (values) => {
- try {
- // 鐧诲綍
- const msg = await login({ ...values, type });
- if (msg.status === 'ok') {
- const defaultLoginSuccessMessage = intl.formatMessage({
- id: 'pages.login.success',
- defaultMessage: '鐧诲綍鎴愬姛锛�',
- });
- message.success(defaultLoginSuccessMessage);
- await fetchUserInfo();
- const urlParams = new URL(window.location.href).searchParams;
- history.push(urlParams.get('redirect') || '/');
- return;
- }
- console.log(msg);
- // 濡傛灉澶辫触鍘昏缃敤鎴烽敊璇俊鎭�
- setUserLoginState(msg);
- } catch (error) {
- const defaultLoginFailureMessage = intl.formatMessage({
- id: 'pages.login.failure',
- defaultMessage: '鐧诲綍澶辫触锛岃閲嶈瘯锛�',
- });
- console.log(error);
- message.error(defaultLoginFailureMessage);
- }
- };
- const { status, type: loginType } = userLoginState;
-
- return (
- <div className={styles.container}>
- <Helmet>
- <title>
- {intl.formatMessage({
- id: 'menu.login',
- defaultMessage: '鐧诲綍椤�',
- })}
- - {Settings.title}
- </title>
- </Helmet>
- <Lang />
- <div
- style={{
- flex: '1',
- padding: '32px 0',
- }}
- >
- <LoginForm
- contentStyle={{
- minWidth: 280,
- maxWidth: '75vw',
- }}
- logo={<img alt="logo" src="/logo.svg" />}
- title="Ant Design"
- subTitle={intl.formatMessage({ id: 'pages.layouts.userLayout.title' })}
- initialValues={{
- autoLogin: true,
- }}
- onFinish={async (values) => {
- await handleSubmit(values);
- }}
- >
- <Tabs
- activeKey={type}
- onChange={setType}
- centered
- items={[
- {
- key: 'account',
- label: intl.formatMessage({
- id: 'pages.login.accountLogin.tab',
- defaultMessage: '璐︽埛瀵嗙爜鐧诲綍',
- }),
- },
- {
- key: 'mobile',
- label: intl.formatMessage({
- id: 'pages.login.phoneLogin.tab',
- defaultMessage: '鎵嬫満鍙风櫥褰�',
- }),
- },
- ]}
- />
-
- {status === 'error' && loginType === 'account' && (
- <LoginMessage
- content={intl.formatMessage({
- id: 'pages.login.accountLogin.errorMessage',
- defaultMessage: '璐︽埛鎴栧瘑鐮侀敊璇�(admin/ant.design)',
- })}
- />
- )}
- {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="璇疯緭鍏ュ瘑鐮侊紒"
- />
- ),
- },
- ]}
- />
- </>
- )}
-
- {status === 'error' && loginType === 'mobile' && <LoginMessage content="楠岃瘉鐮侀敊璇�" />}
- {type === 'mobile' && (
- <>
- <ProFormText
- fieldProps={{
- size: 'large',
- prefix: <MobileOutlined />,
- }}
- name="mobile"
- placeholder={intl.formatMessage({
- id: 'pages.login.phoneNumber.placeholder',
- defaultMessage: '鎵嬫満鍙�',
- })}
- rules={[
- {
- required: true,
- message: (
- <FormattedMessage
- id="pages.login.phoneNumber.required"
- defaultMessage="璇疯緭鍏ユ墜鏈哄彿锛�"
- />
- ),
- },
- {
- pattern: /^1\d{10}$/,
- message: (
- <FormattedMessage
- id="pages.login.phoneNumber.invalid"
- defaultMessage="鎵嬫満鍙锋牸寮忛敊璇紒"
- />
- ),
- },
- ]}
- />
- <ProFormCaptcha
- fieldProps={{
- size: 'large',
- prefix: <LockOutlined />,
- }}
- captchaProps={{
- size: 'large',
- }}
- placeholder={intl.formatMessage({
- id: 'pages.login.captcha.placeholder',
- defaultMessage: '璇疯緭鍏ラ獙璇佺爜',
- })}
- captchaTextRender={(timing, count) => {
- if (timing) {
- return `${count} ${intl.formatMessage({
- id: 'pages.getCaptchaSecondText',
- defaultMessage: '鑾峰彇楠岃瘉鐮�',
- })}`;
- }
- return intl.formatMessage({
- id: 'pages.login.phoneLogin.getVerificationCode',
- defaultMessage: '鑾峰彇楠岃瘉鐮�',
- });
- }}
- name="captcha"
- rules={[
- {
- required: true,
- message: (
- <FormattedMessage
- id="pages.login.captcha.required"
- defaultMessage="璇疯緭鍏ラ獙璇佺爜锛�"
- />
- ),
- },
- ]}
- onGetCaptcha={async (phone) => {
- const result = await getFakeCaptcha({
- phone,
- });
- if (!result) {
- return;
- }
- message.success('鑾峰彇楠岃瘉鐮佹垚鍔燂紒楠岃瘉鐮佷负锛�1234');
- }}
- />
- </>
- )}
- <div
+ return (
+ <Alert
style={{
- marginBottom: 24,
+ marginBottom: 24,
}}
- >
- <ProFormCheckbox noStyle name="autoLogin">
- <FormattedMessage id="pages.login.rememberMe" defaultMessage="鑷姩鐧诲綍" />
- </ProFormCheckbox>
- </div>
- </LoginForm>
- </div>
- <Footer />
- </div>
- );
+ message={content}
+ type="error"
+ showIcon
+ />
+ );
};
-export default Login;
+const Lang = () => {
+ const { styles } = useStyles();
+ return (
+ <div className={styles.lang} data-lang>
+ {SelectLang && <SelectLang />}
+ </div>
+ );
+};
+
+const Page = () => {
+ const intl = useIntl();
+ const { initialState, setInitialState } = useModel('@@initialState');
+ const { token } = theme.useToken();
+
+ const [form] = Form.useForm();
+ const [loginType, setLoginType] = useState('account');
+ const [status, setStatus] = useState(200);
+ const [errDesc, setErrDesc] = useState('');
+ const [rememberMe, setRememberMe] = useState(() => {
+ const storedValue = localStorage.getItem('rememberMe');
+ return storedValue !== null ? JSON.parse(storedValue) : true;
+ });
+ const [rememberData, setRememberData] = useState(() => {
+ const storedValue = localStorage.getItem('rememberData');
+ return storedValue !== null ? JSON.parse(storedValue) : true;
+ });
+ const [hostList, setHostList] = useState([]);
+
+ useEffect(() => {
+ form.setFieldsValue({
+ autoLogin: rememberMe
+ });
+ localStorage.setItem('rememberMe', JSON.stringify(rememberMe));
+ }, [rememberMe])
+
+ useEffect(() => {
+ form.setFieldsValue({
+ username: rememberData.username,
+ password: rememberData.password
+ });
+ localStorage.setItem('rememberData', JSON.stringify(rememberData));
+ }, [rememberData])
+
+ useEffect(() => {
+ const fetchHostList = async () => {
+ const resp = await Http.doGet('api/auth/host');
+ if (resp?.data) {
+ const list = resp.data.map(item => ({
+ label: item.name,
+ value: item.id
+ }));
+ setHostList(list);
+ if (list && list.length > 0) {
+ form.setFieldsValue({
+ hostId: list[0].value
+ });
+ }
+ }
+ }
+ fetchHostList();
+ }, []);
+
+ const fetchUserInfo = async () => {
+ const userInfo = await initialState?.fetchUserInfo?.();
+ if (userInfo) {
+ flushSync(() => {
+ setInitialState((s) => ({
+ ...s,
+ currentUser: userInfo,
+ }));
+ });
+ }
+ };
+
+ const handleSubmit = async (values) => {
+ try {
+ const r = await request('/api/login', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ data: values
+ })
+
+ if (r.code === 200) {
+ localStorage.removeItem("rememberData");
+ if (rememberMe) {
+ setRememberData({
+ username: values.username,
+ password: values.password
+ })
+ }
+ message.success(intl.formatMessage({
+ id: 'login.success',
+ defaultMessage: '鐧诲綍鎴愬姛锛�',
+ }));
+ setToken(r.data.accessToken, values.autoLogin);
+ await fetchUserInfo();
+ const urlParams = new URL(window.location.href).searchParams;
+ history.push(urlParams.get('redirect') || '/');
+ return;
+ }
+ setStatus(r.code);
+ setErrDesc(r.msg);
+ } catch (error) {
+ console.log(error);
+ message.error(intl.formatMessage({
+ id: 'login.failure',
+ defaultMessage: '鐧诲綍澶辫触锛岃閲嶈瘯锛�',
+ }));
+ }
+ }
+
+ return (
+ <div
+ style={{
+ backgroundColor: 'white',
+ height: '100vh',
+ }}
+ >
+ <LoginFormPage
+ form={form}
+ logo={logo}
+ backgroundVideoUrl={logoBg}
+ // title="闄嗘檽娑�"
+ // subTitle="闄嗘檽娑�..."
+ containerStyle={{
+ backgroundColor: 'rgba(0, 0, 0,0.65)',
+ backdropFilter: 'blur(4px)',
+ }}
+ onFinish={async (values) => {
+ await handleSubmit(values);
+ }}
+ initialValue={{
+ }}
+ >
+ <Tabs
+ centered
+ activeKey={loginType}
+ onChange={(activeKey) => setLoginType(activeKey)}
+ >
+ <Tabs.TabPane key={'account'} tab={intl.formatMessage({
+ id: 'login.accountLogin.tab',
+ defaultMessage: '璐︽埛瀵嗙爜鐧诲綍',
+ })} />
+ <Tabs.TabPane key={'phone'} tab={intl.formatMessage({
+ id: 'login.phoneLogin.tab',
+ defaultMessage: '鎵嬫満鍙风櫥褰�',
+ })} />
+ </Tabs>
+ {loginType === 'account' && (
+ <>
+ <ProFormSelect
+ className="centered-select"
+ name="hostId"
+ placeholder={intl.formatMessage({
+ id: 'login.host',
+ defaultMessage: '鏈烘瀯锛�',
+ })}
+ rules={[
+ {
+ required: true,
+ message: intl.formatMessage({
+ id: 'login.rule.host',
+ defaultMessage: '璇烽�夋嫨鏈烘瀯!',
+ }),
+ },
+ ]}
+ options={hostList}
+ />
+ <ProFormText
+ name="username"
+ fieldProps={{
+ size: 'large',
+ prefix: (
+ <UserOutlined
+ style={{
+ color: token.colorText,
+ }}
+ className={'prefixIcon'}
+ />
+ ),
+ }}
+ placeholder={intl.formatMessage({
+ id: 'login.username',
+ defaultMessage: '鐢ㄦ埛鍚�: ',
+ })}
+ rules={[
+ {
+ required: true,
+ message: intl.formatMessage({
+ id: 'login.rule.username',
+ defaultMessage: '璇疯緭鍏ョ敤鎴峰悕!',
+ }),
+ },
+ ]}
+ />
+ <ProFormText.Password
+ name="password"
+ fieldProps={{
+ size: 'large',
+ prefix: (
+ <LockOutlined
+ style={{
+ color: token.colorText,
+ }}
+ className={'prefixIcon'}
+ />
+ ),
+ }}
+ placeholder={intl.formatMessage({
+ id: 'login.password',
+ defaultMessage: '瀵嗙爜: ',
+ })}
+ rules={[
+ {
+ required: true,
+ message: intl.formatMessage({
+ id: 'login.rule.password',
+ defaultMessage: '璇疯緭鍏ュ瘑鐮侊紒!',
+ }),
+ },
+ ]}
+ />
+ </>
+ )}
+ {status !== 200 && loginType === 'account' && (
+ <LoginMessage
+ content={intl.formatMessage({
+ id: 'login.accountLogin.errorMessage',
+ defaultMessage: '璐︽埛鎴栧瘑鐮侀敊璇�',
+ })}
+ />
+ )}
+ {loginType === 'phone' && (
+ <>
+ <ProFormSelect
+ className="centered-select"
+ name="hostId"
+ placeholder={intl.formatMessage({
+ id: 'login.host',
+ defaultMessage: '鏈烘瀯锛�',
+ })}
+ rules={[
+ {
+ required: true,
+ message: intl.formatMessage({
+ id: 'login.rule.host',
+ defaultMessage: '璇烽�夋嫨鏈烘瀯!',
+ }),
+ },
+ ]}
+ options={hostList}
+ />
+ <ProFormText
+ fieldProps={{
+ size: 'large',
+ prefix: (
+ <MobileOutlined
+ style={{
+ color: token.colorText,
+ }}
+ className={'prefixIcon'}
+ />
+ ),
+ }}
+ name="mobile"
+ placeholder={intl.formatMessage({
+ id: 'login.phoneNumber.placeholder',
+ defaultMessage: '鎵嬫満鍙�',
+ })}
+ rules={[
+ {
+ required: true,
+ message:
+ <FormattedMessage
+ id="login.phoneNumber.required"
+ defaultMessage="璇疯緭鍏ユ墜鏈哄彿锛�"
+ />,
+ },
+ {
+ pattern: /^1\d{10}$/,
+ message:
+ <FormattedMessage
+ id="login.phoneNumber.invalid"
+ defaultMessage="鎵嬫満鍙锋牸寮忛敊璇紒"
+ />,
+ },
+ ]}
+ />
+ <ProFormCaptcha
+ fieldProps={{
+ size: 'large',
+ prefix: (
+ <LockOutlined
+ style={{
+ color: token.colorText,
+ }}
+ className={'prefixIcon'}
+ />
+ ),
+ }}
+ captchaProps={{
+ size: 'large',
+ }}
+ placeholder={intl.formatMessage({
+ id: 'login.captcha.placeholder',
+ defaultMessage: '璇疯緭鍏ラ獙璇佺爜',
+ })}
+ captchaTextRender={(timing, count) => {
+ if (timing) {
+ return `${count} ${intl.formatMessage({
+ id: 'pages.getCaptchaSecondText',
+ defaultMessage: 'sec(绉�)',
+ })}`;
+ }
+ return intl.formatMessage({
+ id: 'login.phoneLogin.getVerificationCode',
+ defaultMessage: '鑾峰彇楠岃瘉鐮�',
+ });
+ }}
+ name="captcha"
+ rules={[
+ {
+ required: true,
+ message:
+ <FormattedMessage
+ id="login.captcha.required"
+ defaultMessage="璇疯緭鍏ラ獙璇佺爜锛�"
+ />,
+ },
+ ]}
+ onGetCaptcha={async () => {
+ message.warning(intl.formatMessage({
+ id: 'login.phoneLogin.none',
+ defaultMessage: '鏈紑鍚墜鏈哄彿鐧诲綍',
+ }));
+ }}
+ />
+ </>
+ )}
+ <div
+ style={{
+ display: 'flex',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ marginBlockEnd: 24,
+ }}
+ >
+ <ProFormCheckbox
+ noStyle
+ name="autoLogin"
+ onChange={(e) => {
+ setRememberMe(e.target.checked);
+ }}
+ >
+ {intl.formatMessage({
+ id: 'login.rememberMe',
+ defaultMessage: '鑷姩鐧诲綍',
+ })}
+ </ProFormCheckbox>
+ <Lang />
+ </div>
+ </LoginFormPage>
+ </div>
+ );
+};
+
+export default () => {
+ return (
+ <ProConfigProvider dark>
+ <Page />
+ </ProConfigProvider>
+ );
+};
--
Gitblit v1.9.1