|
@@ -1,11 +1,12 @@
|
|
|
import { useAdminLogin, useSendSmsCode, useSmsLogin } from '@/services/login/LoginController';
|
|
|
+import { useFetchSystemDictionary } from '@/services/system/SystemController';
|
|
|
import { AesEncode } from '@/utils/crypto';
|
|
|
import { setLocalStorageItem } from '@/utils/storage';
|
|
|
-import { LockOutlined, UserOutlined } from '@ant-design/icons';
|
|
|
-import { useNavigate } from '@umijs/max';
|
|
|
-import { Button, Divider, Flex, Form, Input, message, Space } from 'antd';
|
|
|
-import md5 from 'js-md5';
|
|
|
-import React, { useState } from 'react';
|
|
|
+import { LockOutlined, MailOutlined, UserOutlined } from '@ant-design/icons';
|
|
|
+import { useModel, useNavigate } from '@umijs/max';
|
|
|
+import { Button, Divider, Flex, Form, Input, message } from 'antd';
|
|
|
+import { md5 } from 'js-md5';
|
|
|
+import React, { useEffect, useRef, useState } from 'react';
|
|
|
import style from './index.less';
|
|
|
|
|
|
type FieldType = {
|
|
@@ -20,7 +21,7 @@ type AdminLoginForm = {
|
|
|
};
|
|
|
|
|
|
type AdminLoginFormProps = {
|
|
|
- loginCallback: () => void;
|
|
|
+ loginCallback: (param: PublicResponseBody<any>) => void;
|
|
|
formCallback: (param: AdminLoginForm) => void;
|
|
|
};
|
|
|
|
|
@@ -29,50 +30,72 @@ const AdminLoginForm: React.FC<AdminLoginFormProps> = ({ loginCallback, formCall
|
|
|
const [form] = Form.useForm();
|
|
|
const [loadingState, setLoadingState] = useState(false);
|
|
|
|
|
|
- const useLoginDeep = async () => {
|
|
|
- try {
|
|
|
- setLoadingState(true);
|
|
|
- const result = await useAdminLogin({
|
|
|
- username: AesEncode(form.getFieldValue('username')),
|
|
|
- // username: form.getFieldValue('username'),
|
|
|
- password: AesEncode(md5(form.getFieldValue('password')).toUpperCase()),
|
|
|
- });
|
|
|
-
|
|
|
- setLoadingState(false);
|
|
|
- console.log('登录结果', result);
|
|
|
- // @ts-ignore
|
|
|
- loginCallback(result);
|
|
|
- // @ts-ignore
|
|
|
- formCallback(
|
|
|
+ const useLoginDeep = () => {
|
|
|
+ form.validateFields().then(async () => {
|
|
|
+ try {
|
|
|
+ setLoadingState(true);
|
|
|
+ const result = await useAdminLogin({
|
|
|
+ username: AesEncode(form.getFieldValue('username')),
|
|
|
+ password: AesEncode(md5(form.getFieldValue('password')).toUpperCase()),
|
|
|
+ });
|
|
|
+
|
|
|
+ setLoadingState(false);
|
|
|
+ console.log('登录结果', result);
|
|
|
// @ts-ignore
|
|
|
- Object.assign({}, result.data, {
|
|
|
- username: form.getFieldValue('username'),
|
|
|
- password: form.getFieldValue('password'),
|
|
|
- }),
|
|
|
- );
|
|
|
- } catch (error) {
|
|
|
- setLoadingState(false);
|
|
|
- message.error('登录错误, 请重试');
|
|
|
- }
|
|
|
+ loginCallback(result);
|
|
|
+ // @ts-ignore
|
|
|
+ formCallback(
|
|
|
+ // @ts-ignore
|
|
|
+ Object.assign({}, result.data, {
|
|
|
+ username: form.getFieldValue('username'),
|
|
|
+ password: form.getFieldValue('password'),
|
|
|
+ }),
|
|
|
+ );
|
|
|
+ } catch (error) {
|
|
|
+ setLoadingState(false);
|
|
|
+ message.error('登录错误, 请重试');
|
|
|
+ }
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
return (
|
|
|
<>
|
|
|
- <Form form={form} name="login" style={{ maxWidth: 600, width: '100%' }}>
|
|
|
- <Form.Item<FieldType> name="username">
|
|
|
+ <div className={style.admin_login_title}>账号登录</div>
|
|
|
+ <Form
|
|
|
+ form={form}
|
|
|
+ name="login"
|
|
|
+ style={{ maxWidth: 600, width: '100%', paddingBottom: '24px' }}
|
|
|
+ >
|
|
|
+ <Form.Item<FieldType>
|
|
|
+ name="username"
|
|
|
+ rules={[{ required: true, message: '请输入账号' }]}
|
|
|
+ >
|
|
|
<Input
|
|
|
+ style={{
|
|
|
+ backgroundColor: '#f6f7fb',
|
|
|
+ border: '0.5px solid #14172f inset',
|
|
|
+ fontSize: '12px',
|
|
|
+ }}
|
|
|
size="large"
|
|
|
prefix={<UserOutlined style={{ color: 'rgba(0, 0, 0, 0.25)' }} />}
|
|
|
- placeholder="Please input username"
|
|
|
+ placeholder="请输入您的账号"
|
|
|
allowClear
|
|
|
/>
|
|
|
</Form.Item>
|
|
|
|
|
|
- <Form.Item<FieldType> name="password">
|
|
|
+ <Form.Item<FieldType>
|
|
|
+ name="password"
|
|
|
+ rules={[{ required: true, message: '请输入密码' }]}
|
|
|
+ >
|
|
|
<Input.Password
|
|
|
+ style={{
|
|
|
+ backgroundColor: '#f6f7fb',
|
|
|
+ border: '0.5px solid #14172f inset',
|
|
|
+ fontSize: '12px',
|
|
|
+ }}
|
|
|
size="large"
|
|
|
prefix={<LockOutlined style={{ color: 'rgba(0, 0, 0, 0.25)' }} />}
|
|
|
- placeholder="Please input password"
|
|
|
+ placeholder="请输入您的密码"
|
|
|
allowClear
|
|
|
/>
|
|
|
</Form.Item>
|
|
@@ -85,7 +108,7 @@ const AdminLoginForm: React.FC<AdminLoginFormProps> = ({ loginCallback, formCall
|
|
|
onClick={useLoginDeep}
|
|
|
loading={loadingState}
|
|
|
>
|
|
|
- 登录
|
|
|
+ 下一步
|
|
|
</Button>
|
|
|
</Form>
|
|
|
</>
|
|
@@ -96,7 +119,7 @@ type SmsLoginFormProps = {
|
|
|
username: string;
|
|
|
password: string;
|
|
|
phone: string;
|
|
|
- loginCallback: () => void;
|
|
|
+ loginCallback: (param: PublicResponseBody<any>) => void;
|
|
|
};
|
|
|
|
|
|
/** 短信验证码区域组件 */
|
|
@@ -106,11 +129,19 @@ const SmsLoginForm: React.FC<SmsLoginFormProps> = ({
|
|
|
phone,
|
|
|
loginCallback,
|
|
|
}) => {
|
|
|
- const [smsCode, setSmsCode] = useState<string>('');
|
|
|
const [smsCountDown, setSmsCountDown] = useState<number>(-1);
|
|
|
const [loadingState, setLoadingState] = useState(false);
|
|
|
const [form] = Form.useForm();
|
|
|
- let smsCountDownInterval = null;
|
|
|
+ let timerRef = useRef<NodeJS.Timeout | null>(null);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ return () => {
|
|
|
+ if (timerRef.current) {
|
|
|
+ clearInterval(timerRef.current);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }, []);
|
|
|
+
|
|
|
const sendSmsCode = async () => {
|
|
|
console.log({ username, password });
|
|
|
const result = await useSendSmsCode({
|
|
@@ -120,11 +151,18 @@ const SmsLoginForm: React.FC<SmsLoginFormProps> = ({
|
|
|
|
|
|
if (result.code === 0) {
|
|
|
setSmsCountDown(60);
|
|
|
- smsCountDownInterval = setInterval(() => {
|
|
|
- setSmsCountDown((prev) => prev - 1);
|
|
|
- if (smsCountDown === -1) {
|
|
|
- clearInterval(smsCountDownInterval);
|
|
|
- }
|
|
|
+ if (timerRef.current) {
|
|
|
+ clearInterval(timerRef.current);
|
|
|
+ }
|
|
|
+ timerRef.current = setInterval(() => {
|
|
|
+ setSmsCountDown((prev) => {
|
|
|
+ const nextCount = prev - 1;
|
|
|
+ if (nextCount <= 0) {
|
|
|
+ clearInterval(timerRef.current!);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ return nextCount;
|
|
|
+ });
|
|
|
}, 1000);
|
|
|
message.success(result.msg);
|
|
|
} else {
|
|
@@ -134,45 +172,62 @@ const SmsLoginForm: React.FC<SmsLoginFormProps> = ({
|
|
|
console.log('发送验证码结果', result);
|
|
|
};
|
|
|
|
|
|
- const confirmLogin = async () => {
|
|
|
- setLoadingState(true);
|
|
|
-
|
|
|
- console.log('formapds', form.getFieldValue('smsCode'));
|
|
|
-
|
|
|
- try {
|
|
|
- const res = await useSmsLogin({
|
|
|
- username: AesEncode(username),
|
|
|
- password: AesEncode(md5(password).toUpperCase()),
|
|
|
- smsCode: AesEncode(form.getFieldValue('smsCode')),
|
|
|
- });
|
|
|
-
|
|
|
- console.log('短信登录结果', res);
|
|
|
-
|
|
|
- setLoadingState(false);
|
|
|
-
|
|
|
- loginCallback(res);
|
|
|
- } catch (error) {
|
|
|
- setLoadingState(false);
|
|
|
- message.error('登录错误, 请重试');
|
|
|
- }
|
|
|
+ const confirmLogin = () => {
|
|
|
+ form.validateFields().then(async () => {
|
|
|
+ setLoadingState(true);
|
|
|
+ console.log('formapds', form.getFieldValue('smsCode'));
|
|
|
+ try {
|
|
|
+ const res = await useSmsLogin({
|
|
|
+ username: AesEncode(username),
|
|
|
+ password: AesEncode(md5(password).toUpperCase()),
|
|
|
+ smsCode: AesEncode(form.getFieldValue('smsCode')),
|
|
|
+ });
|
|
|
+ console.log('短信登录结果', res);
|
|
|
+ setLoadingState(false);
|
|
|
+ loginCallback(res);
|
|
|
+ } catch (error) {
|
|
|
+ setLoadingState(false);
|
|
|
+ message.error('登录错误, 请重试');
|
|
|
+ }
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
return (
|
|
|
- <Flex justify="center" align="center" vertical gap={16}>
|
|
|
- 短信验证码已发送至手机: {phone}, 请输入:
|
|
|
- <Form form={form}>
|
|
|
- <Form.Item name="smsCode">
|
|
|
- <Space size="large">
|
|
|
- <Input maxLength={4} placeholder="请输入短信验证码" />
|
|
|
- {/* <Input placeholder="请输入短信验证码" allowClear></Input> */}
|
|
|
- <Button type="primary" disabled={smsCountDown > 0} onClick={sendSmsCode}>
|
|
|
- {smsCountDown < 0 ? '点击获取验证码' : `${smsCountDown}s后重新发送`}
|
|
|
- </Button>
|
|
|
- </Space>
|
|
|
+ <Flex justify="center" align="flex-start" vertical gap={16} style={{ width: '100%' }}>
|
|
|
+ <span className={style['sms_login_title']}>请输入绑定手机({phone})短信验证码</span>
|
|
|
+ <Form form={form} style={{ width: '100%' }}>
|
|
|
+ <Form.Item
|
|
|
+ name="smsCode"
|
|
|
+ rules={[{ required: true, message: '短信验证码不可为空' }]}
|
|
|
+ >
|
|
|
+ <Input
|
|
|
+ prefix={<MailOutlined />}
|
|
|
+ maxLength={4}
|
|
|
+ placeholder="请输入短信验证码"
|
|
|
+ name="smsCode"
|
|
|
+ style={{
|
|
|
+ backgroundColor: '#f6f7fb',
|
|
|
+ fontSize: '12px',
|
|
|
+ height: '40px',
|
|
|
+ boxSizing: 'border-box',
|
|
|
+ width: '100%',
|
|
|
+ }}
|
|
|
+ />
|
|
|
</Form.Item>
|
|
|
+ <Flex justify="flex-end">
|
|
|
+ <Button type="primary" disabled={smsCountDown > 0} onClick={sendSmsCode}>
|
|
|
+ {smsCountDown < 0 ? '点击获取验证码' : `${smsCountDown}s后重新发送`}
|
|
|
+ </Button>
|
|
|
+ </Flex>
|
|
|
</Form>
|
|
|
- <Button type="primary" onClick={confirmLogin} block loading={loadingState}>
|
|
|
- 确认登录
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ onClick={confirmLogin}
|
|
|
+ block
|
|
|
+ loading={loadingState}
|
|
|
+ style={{ height: '40px' }}
|
|
|
+ >
|
|
|
+ 登录
|
|
|
</Button>
|
|
|
</Flex>
|
|
|
);
|
|
@@ -189,7 +244,7 @@ const LoginWrapper = ({ loginCompleteCallback }) => {
|
|
|
const [password, setPassword] = useState('');
|
|
|
const [phone, setPhone] = useState('');
|
|
|
|
|
|
- const syncFormInformation = (form) => {
|
|
|
+ const syncFormInformation = (form: AdminLoginForm) => {
|
|
|
console.log('同步登录表单信息', form);
|
|
|
if (form) {
|
|
|
setUsername(form.username);
|
|
@@ -202,12 +257,15 @@ const LoginWrapper = ({ loginCompleteCallback }) => {
|
|
|
console.log('子组件触发父组件事件', data);
|
|
|
|
|
|
if ([0, 3].includes(data.code)) {
|
|
|
- const { mainAccount, main, loginName, token, admUserId } = data.data;
|
|
|
+ const { mainAccount, main, token, admUserId, admUserName, receiveStatus } = data.data;
|
|
|
setLocalStorageItem('__BIZ_ID', admUserId);
|
|
|
setLocalStorageItem('TOKEN', token);
|
|
|
- setLocalStorageItem('IS_CHILD', !main);
|
|
|
+ setLocalStorageItem('IS_MAIN', main);
|
|
|
setLocalStorageItem('MAIN_ACCOUNT', mainAccount);
|
|
|
- setLocalStorageItem('LOGIN_NAME', loginName);
|
|
|
+ setLocalStorageItem('LOGIN_NAME', admUserName);
|
|
|
+ if (!main) {
|
|
|
+ setLocalStorageItem('RECEIVE_STATUS', receiveStatus);
|
|
|
+ }
|
|
|
loginCompleteCallback(data);
|
|
|
} else if ([2].includes(data.code)) {
|
|
|
setSmsAreaVisible(true);
|
|
@@ -231,21 +289,52 @@ const LoginWrapper = ({ loginCompleteCallback }) => {
|
|
|
|
|
|
const LoginPage: React.FC = () => {
|
|
|
const navigate = useNavigate();
|
|
|
+ const { setIsMainAccount, setName, setReceiveStatus } = useModel('global');
|
|
|
+ const { refresh } = useModel('@@initialState');
|
|
|
|
|
|
- const onLoginPass = (data) => {
|
|
|
- console.log('接收到跳转信息', data);
|
|
|
+ const onLoginPass = async (data: PublicResponseBody<any>) => {
|
|
|
+ setName(data.data.admUserName);
|
|
|
+ setIsMainAccount(data.data.main);
|
|
|
+ setReceiveStatus(data.data.receiveStatus);
|
|
|
+
|
|
|
+ await refresh();
|
|
|
+
|
|
|
+ // 在登录成功后获取一次系统字典
|
|
|
+ useFetchSystemDictionary().then((res) => {
|
|
|
+ console.log('System dictionary', res);
|
|
|
+ // 整理字典数据
|
|
|
+ const dictionary: Record<string, Record<string, string>> = {};
|
|
|
+ res.data &&
|
|
|
+ res.data.forEach(({ type, code, msg }) => {
|
|
|
+ if (!(type in dictionary)) {
|
|
|
+ dictionary[type] = {};
|
|
|
+ }
|
|
|
+ dictionary[type][code] = msg;
|
|
|
+ });
|
|
|
+ setLocalStorageItem('SYSTEM_DICTIONARY', dictionary);
|
|
|
+ });
|
|
|
navigate('/home', { replace: true });
|
|
|
};
|
|
|
return (
|
|
|
- <Flex className={style.container} align="center" justify="center">
|
|
|
+ <Flex
|
|
|
+ className={style.container}
|
|
|
+ align="center"
|
|
|
+ justify="center"
|
|
|
+ style={{ minHeight: '100vh' }} // 确保登录页面占满整个视口高度
|
|
|
+ >
|
|
|
<Flex
|
|
|
- align="center"
|
|
|
+ align="flex-start" // 调整为center以获得更好的垂直对齐效果
|
|
|
justify="center"
|
|
|
vertical
|
|
|
- style={{ width: '400px', height: '100vh' }}
|
|
|
+ className={style['login_panel_wrapper']}
|
|
|
+ style={{
|
|
|
+ padding: '2rem', // 增加内边距提升视觉体验
|
|
|
+ borderRadius: '8px', // 添加圆角使面板更现代
|
|
|
+ boxShadow: '0 4px 12px rgba(0, 0, 0, 0.1)', // 添加阴影提升层次感
|
|
|
+ }}
|
|
|
>
|
|
|
<div className={style.title}>惠融易客商户后台</div>
|
|
|
- <Divider />
|
|
|
+ <Divider style={{ margin: '1.5rem 0' }} /> {/* 调整分割线间距 */}
|
|
|
<LoginWrapper loginCompleteCallback={onLoginPass} />
|
|
|
</Flex>
|
|
|
</Flex>
|