diff --git a/react-ui/src/pages/User/Login/login.tsx b/react-ui/src/pages/User/Login/login.tsx new file mode 100644 index 00000000..9ef18148 --- /dev/null +++ b/react-ui/src/pages/User/Login/login.tsx @@ -0,0 +1,221 @@ +import { clearSessionToken, setSessionToken } from '@/access'; +import { getCaptchaImg, login } from '@/services/system/auth'; +import { parseJsonText } from '@/utils'; +import { safeInvoke } from '@/utils/functional'; +import LocalStorage from '@/utils/localStorage'; +import { to } from '@/utils/promise'; +import { history, useModel } from '@umijs/max'; +import { Button, Checkbox, Flex, Form, Image, Input, message, type InputRef } from 'antd'; +import CryptoJS from 'crypto-js'; +import { useEffect, useRef, useState } from 'react'; +import { flushSync } from 'react-dom'; +import styles from './login.less'; + +const VERSION = 1; +const AESKEY = 'OPENSOURCETECHNOLOGYCENTER'; + +const LoginInputPrefix = ({ icon }: { icon: string }) => { + return ( +
+ +
+
+ ); +}; + +const Login = () => { + const { initialState, setInitialState } = useModel('@@initialState'); + const [captchaCode, setCaptchaCode] = useState(''); + const [uuid, setUuid] = useState(''); + const [form] = Form.useForm(); + const captchaInputRef = useRef(null); + + useEffect(() => { + getCaptchaCode(); + const autoLogin = LocalStorage.getItem(LocalStorage.rememberPasswordKey) ?? 'false'; + if (autoLogin === 'true') { + const userStorage = LocalStorage.getItem(LocalStorage.loginUserKey); + const userJson = safeInvoke((text: string) => + CryptoJS.AES.decrypt(text, AESKEY).toString(CryptoJS.enc.Utf8), + )(userStorage); + const user = safeInvoke(parseJsonText)(userJson); + if (user && typeof user === 'object' && user.version === VERSION) { + const { username, password } = user; + form.setFieldsValue({ username: username, password: password, autoLogin: true }); + } else { + form.setFieldsValue({ username: '', password: '', autoLogin: true }); + LocalStorage.removeItem(LocalStorage.loginUserKey); + } + } else { + form.setFieldsValue({ username: '', password: '', autoLogin: false }); + } + }, []); + const getCaptchaCode = async () => { + const [res] = await to(getCaptchaImg()); + if (res) { + const imgdata = `data:image/png;base64,${res.img}`; + setCaptchaCode(imgdata); + setUuid(res.uuid); + } + }; + + const fetchUserInfo = async () => { + const userInfo = await initialState?.fetchUserInfo?.(); + if (userInfo) { + flushSync(() => { + setInitialState((s) => ({ + ...s, + currentUser: userInfo, + })); + }); + } + }; + + // 登录 + const handleSubmit = async (values: API.LoginParams) => { + const [res, error] = await to(login({ ...values, uuid })); + if (res && res.data) { + const current = new Date(); + const expireTime = current.setTime(current.getTime() + 1000 * 12 * 60 * 60); + const { access_token } = res.data; + setSessionToken(access_token, access_token, expireTime); + message.success('登录成功!'); + + LocalStorage.setItem(LocalStorage.rememberPasswordKey, values.autoLogin ? 'true' : 'false'); + if (values.autoLogin) { + const user = { + username: values.username, + password: values.password, + version: VERSION, + }; + const encrypted = CryptoJS.AES.encrypt(JSON.stringify(user), AESKEY).toString(); + LocalStorage.setItem(LocalStorage.loginUserKey, encrypted); + } else { + LocalStorage.removeItem(LocalStorage.loginUserKey); + } + + await fetchUserInfo(); + const urlParams = new URL(window.location.href).searchParams; + history.push(urlParams.get('redirect') || '/'); + } else { + if (error?.data?.code === 500 && error?.data?.msg === '验证码错误') { + captchaInputRef.current?.focus({ + cursor: 'all', + }); + } + + clearSessionToken(); + getCaptchaCode(); + } + }; + + return ( +
+
+
+ + 智能材料科研平台 +
+
+ 智能材料科研平台 + +
+
+ 大语言模型运维 统一管理平台 +
+ +
+
+
+
+ 欢迎登录 + 智能材料科研平台 +
+
+
账号登录
+
+
+ + } + allowClear + /> + + + + } + allowClear + /> + + + +
+ + + } + ref={captchaInputRef} + allowClear + /> + +
+ 验证码 getCaptchaCode()} + /> +
+ + + 记住密码 + + + + + +
+
+
+
+
+
+ ); +}; + +export default Login;