From 54d6fc96a8ef1e9903a7362c97a00e504c174ab3 Mon Sep 17 00:00:00 2001 From: vincentlu <t1341870251@gmail.com> Date: 星期五, 07 二月 2025 13:13:42 +0800 Subject: [PATCH] # --- rsf-admin/src/config/authProvider.js | 5 rsf-admin/src/i18n/zh.js | 3 rsf-admin/src/i18n/en.js | 3 rsf-admin/src/page/login/index1.jsx | 261 ++++++++++++++++++++++++++++++++++++++++++++++++++++ rsf-admin/src/App.jsx | 2 5 files changed, 270 insertions(+), 4 deletions(-) diff --git a/rsf-admin/src/App.jsx b/rsf-admin/src/App.jsx index 00924d9..6d3a10a 100644 --- a/rsf-admin/src/App.jsx +++ b/rsf-admin/src/App.jsx @@ -16,7 +16,7 @@ import DataProvider from "./config/dataProvider"; import Dashboard from "./page/dashboard/Dashboard"; import Settings from "./page/settings/Settings"; -import Login from "./page/login"; +import Login from "./page/login/index1"; import * as Common from './utils/common' import { themes } from './themes/themes'; import { SPA_NAME, SPA_VERSION, DEFAULT_THEME_NAME, DEFAULT_THEME_MODE, DATA_PROVIDER_SPRING } from "./config/setting"; diff --git a/rsf-admin/src/config/authProvider.js b/rsf-admin/src/config/authProvider.js index 7436b8e..1c440e7 100644 --- a/rsf-admin/src/config/authProvider.js +++ b/rsf-admin/src/config/authProvider.js @@ -6,12 +6,11 @@ const AuthProvider = { // login - login: async ({ username, password }) => { - + login: async ({ username, password, tenantId }) => { const { accessToken, user } = await login({ username: username, password: password, - tenantId: 1, + tenantId: tenantId, }); if (user && accessToken) { diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js index d8ea362..7dae7d3 100644 --- a/rsf-admin/src/i18n/en.js +++ b/rsf-admin/src/i18n/en.js @@ -221,6 +221,9 @@ page: { login: { tenant: 'Tenant', + button: { + login: 'LOG IN', + }, }, } }; diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js index 522cd05..bf5b646 100644 --- a/rsf-admin/src/i18n/zh.js +++ b/rsf-admin/src/i18n/zh.js @@ -221,6 +221,9 @@ page: { login: { tenant: '绉熸埛', + button: { + login: 'LOG IN', + }, }, } }; diff --git a/rsf-admin/src/page/login/index1.jsx b/rsf-admin/src/page/login/index1.jsx new file mode 100644 index 0000000..bd9ff5e --- /dev/null +++ b/rsf-admin/src/page/login/index1.jsx @@ -0,0 +1,261 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { useLocation } from 'react-router-dom'; +import { + Box, + AppBar, + Card, + Toolbar, + CircularProgress, + Typography, + Tabs, + Tab, + Button +} from '@mui/material'; +import { + Form, + required, + TextInput, + useTranslate, + useLogin, + useNotify, + SelectInput, +} from 'react-admin'; +import { useForm, Controller } from 'react-hook-form'; +import { LOGIN_BACKGROUND } from '@/config/setting'; +import { tenants } from '@/api/auth'; + +const Login = () => { + const translate = useTranslate(); + + const [tab, setTab] = useState(0) + + const [tenantList, setTenantList] = useState([]); + + useEffect(() => { + tenants().then(data => { + setTenantList(data); + }) + }, []); + + return ( + <Box + sx={{ + display: 'flex', + flexDirection: 'column', + minHeight: '100vh', + alignItems: 'center', + justifyContent: 'flex-start', + // justifyContent: 'center', + background: `url(/login_bg.jpg)`, // https://unsplash.com/ + backgroundRepeat: 'no-repeat', + backgroundSize: 'cover', + } + } + > + <video + autoPlay + loop + muted + style={{ + position: 'fixed', + top: 0, + left: 0, + width: '100%', + height: '100%', + // objectFit: 'cover', + // objectFit: 'contain', + objectFit: 'fill', + // objectFit: 'scale-down', + zIndex: 0, + }} + > + {LOGIN_BACKGROUND === 'media' && ( + <source src="/login_bg.mp4" type="video/mp4" /> + )} + </video> + + <Card sx={{ + width: 400, + marginTop: '6em', + zIndex: 1 + }}> + <div> + <AppBar position="static" sx={{ backgroundColor: '#3D4BA7' }}> + <Toolbar> + <Typography variant="h6" color="inherit">Welcome</Typography> + </Toolbar> + </AppBar> + </div> + + <Tabs + value={tab} + onChange={(event, value) => { + setTab(value); + }} + indicatorColor="primary" + textColor="primary" + variant="fullWidth" + > + <Tab label="Login" sx={{ fontSize: '.8em' }} /> + <Tab label="Register" sx={{ fontSize: '.8em' }} /> + </Tabs> + + <LoginForm + tab={tab} + tenantList={tenantList} + /> + + <RegisterForm + tab={tab} + tenantList={tenantList} + /> + + <Box mt={1} mb={1} sx={{ textAlign: 'center' }}> + <Typography variant="caption" align="center">rsf - sever</Typography> + </Box> + </Card> + </Box > + ); +}; + +const LoginForm = (props) => { + const translate = useTranslate(); + const notify = useNotify(); + const login = useLogin(); + const location = useLocation(); + + const { tab, tenantList } = props; + + const [loading, setLoading] = useState(false); + const [tenantId, setTenantId] = useState(null); + const [username, setUsername] = useState(''); + const [password, setPassword] = useState(''); + const [btnDisable, setBtnDisable] = useState(true); + + useEffect(() => { + if (tenantList.length > 0) { + setTenantId(tenantList[0].id); + } + setBtnDisable(!(tenantId && username && password)) + }, [tenantList, username, password]); + + const handleSubmit = (auth) => { + console.log(auth); + + setLoading(true); + // js native confirm && root + login( + auth, + location.state ? (location.state).nextPathname : '/' + ).catch((error) => { + setLoading(false); + notify( + typeof error === 'string' + ? error + : typeof error === 'undefined' || !error.message + ? 'ra.auth.sign_in_error' + : error.message, + { + type: 'error', + messageArgs: { + _: + typeof error === 'string' + ? error + : error && error.message + ? error.message + : undefined, + }, + } + ); + + setUsername(auth.username) + }); + }; + + return ( + <> + <Form + onSubmit={handleSubmit} + noValidate + > + <Box + hidden={tab !== 0} + p={2} + display="flex" + justifyContent="center" + flexDirection='column' + > + <Box width="60%"> + <SelectInput + label="page.login.tenant" + source="tenantId" + variant="standard" + choices={tenantList.map(item => ({ + id: item.id, + name: item.name + }))} + validate={required()} + defaultValue={tenantId} + onChange={e => setTenantId(e.target.value)} + sx={{ marginTop: 0, marginBottom: 0 }} + /> + </Box> + + <TextInput + label={translate('ra.auth.username')} + source="username" + variant="standard" + disabled={loading} + validate={required()} + value={username} + onChange={e => setUsername(e.target.value)} + autoFocus + sx={{ marginTop: 0, marginBottom: 0 }} + /> + <TextInput + label={translate('ra.auth.password')} + source="password" + variant="standard" + type="password" + disabled={loading} + validate={required()} + value={password} + onChange={e => setPassword(e.target.value)} + sx={{ marginTop: 0, marginBottom: 0 }} + /> + <Button + variant="contained" + type="submit" + disabled={loading || btnDisable} + fullWidth + sx={{ + backgroundColor: "#3D4BA7" + }} + > + {loading && ( + <CircularProgress size={25} thickness={2} /> + )} + {translate('page.login.button.login')} + </Button> + + <Box mt={1} mb={1} sx={{ textAlign: 'center' }}>or</Box> + </Box > + </Form> + </> + ) +} + +const RegisterForm = (props) => { + + return ( + <> + <Box + hidden={props.tab !== 1} + > + Register + </Box > + </> + ) +} + +export default Login; -- Gitblit v1.9.1