From 7a00868dc7730b83dc1e3d232b9f2e2b43ad237a Mon Sep 17 00:00:00 2001
From: vincentlu <t1341870251@gmail.com>
Date: 星期五, 07 二月 2025 14:51:29 +0800
Subject: [PATCH] #
---
/dev/null | 261 --------------
rsf-server/src/main/java/com/vincent/rsf/server/system/service/impl/UserLoginServiceImpl.java | 1
rsf-admin/src/page/login/index.jsx | 247 ++++---------
rsf-admin/src/page/login/Register.jsx | 161 ++++++++
rsf-admin/src/page/login/index2.jsx | 195 ++++++++++
rsf-admin/src/i18n/zh.js | 1
rsf-admin/src/page/login/Login.jsx | 159 ++++++++
rsf-admin/src/i18n/en.js | 1
rsf-admin/src/App.jsx | 2
9 files changed, 599 insertions(+), 429 deletions(-)
diff --git a/rsf-admin/src/App.jsx b/rsf-admin/src/App.jsx
index 6d3a10a..00924d9 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/index1";
+import Login from "./page/login";
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/i18n/en.js b/rsf-admin/src/i18n/en.js
index 7dae7d3..fe4509a 100644
--- a/rsf-admin/src/i18n/en.js
+++ b/rsf-admin/src/i18n/en.js
@@ -223,6 +223,7 @@
tenant: 'Tenant',
button: {
login: 'LOG IN',
+ register: 'REGISTER',
},
},
}
diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js
index bf5b646..016d04c 100644
--- a/rsf-admin/src/i18n/zh.js
+++ b/rsf-admin/src/i18n/zh.js
@@ -223,6 +223,7 @@
tenant: '绉熸埛',
button: {
login: 'LOG IN',
+ register: 'REGISTER',
},
},
}
diff --git a/rsf-admin/src/page/login/Login.jsx b/rsf-admin/src/page/login/Login.jsx
new file mode 100644
index 0000000..e30af97
--- /dev/null
+++ b/rsf-admin/src/page/login/Login.jsx
@@ -0,0 +1,159 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import { useLocation } from 'react-router-dom';
+import {
+ Box,
+ CircularProgress,
+ Typography,
+ Button,
+ TextField,
+ Stack,
+ Autocomplete
+} from '@mui/material';
+import {
+ useTranslate,
+ useLogin,
+ useNotify,
+} from 'react-admin';
+import { useForm, Controller } from 'react-hook-form';
+
+const Login = (props) => {
+ const translate = useTranslate();
+ const notify = useNotify();
+ const login = useLogin();
+ const location = useLocation();
+ const { tenantList } = props;
+
+ const { control, watch, handleSubmit, setValue } = useForm();
+
+ const [loading, setLoading] = useState(false);
+
+ const username = watch('username');
+ const password = watch('password');
+ const tenantId = watch('tenantId');
+
+ useEffect(() => {
+ if (tenantList.length > 0 && !tenantId) {
+ setValue('tenantId', tenantList[0].id);
+ }
+ }, [tenantList, setValue]);
+
+ const onSubmit = (data) => {
+ setLoading(true);
+ login(
+ data,
+ 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,
+ },
+ }
+ );
+ });
+ };
+
+ return (
+ <>
+ <Box
+ p={2}
+ display="flex"
+ flexDirection='column'
+ component="form" onSubmit={handleSubmit(onSubmit)} noValidate
+ >
+ <Stack spacing={2}>
+ <Controller
+ name="tenantId"
+ control={control}
+ rules={{ required: true }}
+ defaultValue={tenantList.length > 0 ? tenantList[0].id : ''}
+ render={({ field: { onChange, value, ref } }) => {
+ const selectedTenant = tenantList.find(tenant => tenant.id === value) || null;
+ return (
+ <Autocomplete
+ options={tenantList}
+ getOptionLabel={(option) => option.name}
+ value={selectedTenant}
+ onChange={(_, newValue) => {
+ onChange(newValue ? newValue.id : '');
+ }}
+ renderInput={(params) => (
+ <TextField
+ {...params}
+ label={translate("page.login.tenant")}
+ variant="standard"
+ inputRef={ref}
+ />
+ )}
+ />
+ );
+ }}
+ />
+
+ <Controller
+ name="username"
+ control={control}
+ defaultValue=""
+ rules={{ required: true }}
+ render={({ field }) => (
+ <TextField
+ {...field}
+ label={translate('ra.auth.username')}
+ variant="standard"
+ disabled={loading}
+ autoFocus
+ />
+ )}
+ />
+
+ <Controller
+ name="password"
+ control={control}
+ defaultValue=""
+ rules={{ required: true }}
+ render={({ field }) => (
+ <TextField
+ {...field}
+ label={translate('ra.auth.password')}
+ type="password"
+ variant="standard"
+ disabled={loading}
+
+ />
+ )}
+ />
+
+ <Box mt={10}></Box>
+
+ <Button
+ type="submit"
+ variant="contained"
+ disabled={loading || !(tenantId && username && password)}
+ sx={{
+ backgroundColor: "#3D4BA7"
+ }}
+ >
+ {loading && <CircularProgress size={25} thickness={2} />}
+ {translate('page.login.button.login')}
+ </Button>
+
+ </Stack>
+ <Box mt={1} mb={1} sx={{ textAlign: 'center' }}>or</Box>
+ </Box >
+ </>
+ )
+}
+
+export default Login;
\ No newline at end of file
diff --git a/rsf-admin/src/page/login/Register.jsx b/rsf-admin/src/page/login/Register.jsx
new file mode 100644
index 0000000..832081f
--- /dev/null
+++ b/rsf-admin/src/page/login/Register.jsx
@@ -0,0 +1,161 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import { useLocation } from 'react-router-dom';
+import {
+ Box,
+ CircularProgress,
+ Typography,
+ Button,
+ TextField,
+ Stack,
+ Autocomplete
+} from '@mui/material';
+import {
+ useTranslate,
+ useLogin,
+ useNotify,
+} from 'react-admin';
+import { useForm, Controller } from 'react-hook-form';
+
+const Register = (props) => {
+ const translate = useTranslate();
+ const notify = useNotify();
+ const login = useLogin();
+ const location = useLocation();
+ const { tab, tenantList } = props;
+
+ const { control, watch, handleSubmit, setValue } = useForm();
+
+ const [loading, setLoading] = useState(false);
+
+ const username = watch('username');
+ const password = watch('password');
+ const tenantId = watch('tenantId');
+
+ useEffect(() => {
+ if (tenantList.length > 0 && !tenantId) {
+ setValue('tenantId', tenantList[0].id);
+ }
+ }, [tenantList, setValue]);
+
+ const onSubmit = (data) => {
+ console.log(data);
+ setLoading(true);
+ // js native confirm && root
+ login(
+ data,
+ 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,
+ },
+ }
+ );
+ });
+ };
+
+ return (
+ <>
+ <Box
+ p={2}
+ display="flex"
+ flexDirection='column'
+ component="form" onSubmit={handleSubmit(onSubmit)} noValidate
+ >
+ <Stack spacing={2}>
+ <Controller
+ name="tenantId"
+ control={control}
+ rules={{ required: true }}
+ defaultValue={tenantList.length > 0 ? tenantList[0].id : ''}
+ render={({ field: { onChange, value, ref } }) => {
+ const selectedTenant = tenantList.find(tenant => tenant.id === value) || null;
+ return (
+ <Autocomplete
+ options={tenantList}
+ getOptionLabel={(option) => option.name}
+ value={selectedTenant}
+ onChange={(_, newValue) => {
+ onChange(newValue ? newValue.id : '');
+ }}
+ renderInput={(params) => (
+ <TextField
+ {...params}
+ label={translate("page.login.tenant")}
+ variant="standard"
+ inputRef={ref}
+ />
+ )}
+ />
+ );
+ }}
+ />
+
+ <Controller
+ name="username"
+ control={control}
+ defaultValue=""
+ rules={{ required: true }}
+ render={({ field }) => (
+ <TextField
+ {...field}
+ label={translate('ra.auth.username')}
+ variant="standard"
+ disabled={loading}
+ autoFocus
+ />
+ )}
+ />
+
+ <Controller
+ name="password"
+ control={control}
+ defaultValue=""
+ rules={{ required: true }}
+ render={({ field }) => (
+ <TextField
+ {...field}
+ label={translate('ra.auth.password')}
+ type="password"
+ variant="standard"
+ disabled={loading}
+
+ />
+ )}
+ />
+
+ <Box mt={10}></Box>
+
+ <Button
+ type="submit"
+ variant="contained"
+ disabled={loading || !(tenantId && username && password)}
+ sx={{
+ backgroundColor: "#3D4BA7"
+ }}
+ >
+ {loading && <CircularProgress size={25} thickness={2} />}
+ {translate('page.login.button.register')}
+ </Button>
+
+ </Stack>
+ <Box mt={1} mb={1} sx={{ textAlign: 'center' }}>or</Box>
+ </Box >
+ </>
+ )
+}
+
+export default Register;
\ No newline at end of file
diff --git a/rsf-admin/src/page/login/index.jsx b/rsf-admin/src/page/login/index.jsx
index 634211a..5c56eaf 100644
--- a/rsf-admin/src/page/login/index.jsx
+++ b/rsf-admin/src/page/login/index.jsx
@@ -1,195 +1,108 @@
-import * as React from 'react';
-import { useState } from 'react';
-import { useLocation } from 'react-router-dom';
+import React, { useState, useRef, useEffect, useMemo } from "react";
import {
- Avatar,
Box,
- Button,
+ AppBar,
Card,
- CardActions,
+ Toolbar,
CircularProgress,
+ Typography,
+ Tabs,
+ Tab,
} from '@mui/material';
-import LockIcon from '@mui/icons-material/Lock';
import {
- Form,
- required,
- TextInput,
useTranslate,
useLogin,
useNotify,
- SelectInput,
} from 'react-admin';
import { LOGIN_BACKGROUND } from '@/config/setting';
import { tenants } from '@/api/auth';
+import Login from "./Login";
+import Register from "./Register";
-const Login = () => {
- const [loading, setLoading] = useState(false);
+const Index = () => {
const translate = useTranslate();
- const notify = useNotify();
- const login = useLogin();
- const location = useLocation();
+ const [tab, setTab] = useState(0)
+ const [tenantList, setTenantList] = useState([]);
- const [tenantList, setTenantList] = React.useState([]);
- const [tenantId, setTenantId] = React.useState(null);
-
- React.useEffect(() => {
+ useEffect(() => {
tenants().then(data => {
setTenantList(data);
- if (data.length > 0) {
- setTenantId(data[0].id);
- }
})
}, []);
- React.useEffect(() => {
- console.log(tenantId);
- }, [tenantId]);
-
- const handleSubmit = (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,
- },
- }
- );
- });
- };
-
return (
- <Form onSubmit={handleSubmit} noValidate>
- {/* https://unsplash.com/ */}
- <Box
- sx={{
- display: 'flex',
- flexDirection: 'column',
- minHeight: '100vh',
- alignItems: 'center',
- justifyContent: 'flex-start',
- // justifyContent: 'center',
- background: `url(/login_bg.jpg)`,
- backgroundRepeat: 'no-repeat',
- backgroundSize: 'cover',
+ <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,
}}
>
- <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>
+ {LOGIN_BACKGROUND === 'media' && (
+ <source src="/login_bg.mp4" type="video/mp4" />
+ )}
+ </video>
- <Card sx={{
- minWidth: 300,
- marginTop: '6em',
- zIndex: 1
- }}>
- <Box
- sx={{
- margin: '1em',
- display: 'flex',
- justifyContent: 'center',
- }}
- >
- <Avatar sx={{ bgcolor: 'secondary.main' }}>
- <LockIcon />
- </Avatar>
- </Box>
- <Box
- sx={{
- marginTop: '1em',
- display: 'flex',
- justifyContent: 'center',
- color: theme => theme.palette.grey[500],
- }}
- >
- Hint: root / 123456
- </Box>
- <Box sx={{ padding: '0 1em 1em 1em' }}>
- <Box sx={{ marginTop: '1em' }}>
- <SelectInput
- label="page.login.tenant"
- source="tenantId"
- choices={tenantList.map(item => ({
- id: item.id,
- name: item.name
- }))}
- validate={required()}
- value={tenantId}
- onChange={e => setTenantId(e.target.value)}
- />
- </Box>
- <Box sx={{ marginTop: '.1em' }}>
- <TextInput
- autoFocus
- source="username"
- label={translate('ra.auth.username')}
- disabled={loading}
- validate={required()}
- />
- </Box>
- <Box sx={{ marginTop: '.1em' }}>
- <TextInput
- source="password"
- label={translate('ra.auth.password')}
- type="password"
- disabled={loading}
- validate={required()}
- />
- </Box>
- </Box>
- <CardActions sx={{ padding: '0 1em 1em 1em' }}>
- <Button
- variant="contained"
- type="submit"
- color="primary"
- disabled={loading}
- fullWidth
- >
- {loading && (
- <CircularProgress size={25} thickness={2} />
- )}
- {translate('ra.auth.sign_in')}
- </Button>
- </CardActions>
- </Card>
- </Box>
- </Form>
+ <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>
+
+ {tab === 0 && <Login tenantList={tenantList} />}
+ {tab === 1 && <Register tenantList={tenantList} />}
+
+ <Box mt={1} mb={1} sx={{ textAlign: 'center' }}>
+ <Typography variant="caption" align="center">rsf - sever</Typography>
+ </Box>
+ </Card>
+ </Box >
);
};
-export default Login;
+export default Index;
diff --git a/rsf-admin/src/page/login/index1.jsx b/rsf-admin/src/page/login/index1.jsx
deleted file mode 100644
index bd9ff5e..0000000
--- a/rsf-admin/src/page/login/index1.jsx
+++ /dev/null
@@ -1,261 +0,0 @@
-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;
diff --git a/rsf-admin/src/page/login/index2.jsx b/rsf-admin/src/page/login/index2.jsx
new file mode 100644
index 0000000..634211a
--- /dev/null
+++ b/rsf-admin/src/page/login/index2.jsx
@@ -0,0 +1,195 @@
+import * as React from 'react';
+import { useState } from 'react';
+import { useLocation } from 'react-router-dom';
+import {
+ Avatar,
+ Box,
+ Button,
+ Card,
+ CardActions,
+ CircularProgress,
+} from '@mui/material';
+import LockIcon from '@mui/icons-material/Lock';
+import {
+ Form,
+ required,
+ TextInput,
+ useTranslate,
+ useLogin,
+ useNotify,
+ SelectInput,
+} from 'react-admin';
+import { LOGIN_BACKGROUND } from '@/config/setting';
+import { tenants } from '@/api/auth';
+
+const Login = () => {
+ const [loading, setLoading] = useState(false);
+ const translate = useTranslate();
+
+ const notify = useNotify();
+ const login = useLogin();
+ const location = useLocation();
+
+ const [tenantList, setTenantList] = React.useState([]);
+ const [tenantId, setTenantId] = React.useState(null);
+
+ React.useEffect(() => {
+ tenants().then(data => {
+ setTenantList(data);
+ if (data.length > 0) {
+ setTenantId(data[0].id);
+ }
+ })
+ }, []);
+
+ React.useEffect(() => {
+ console.log(tenantId);
+ }, [tenantId]);
+
+ const handleSubmit = (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,
+ },
+ }
+ );
+ });
+ };
+
+ return (
+ <Form onSubmit={handleSubmit} noValidate>
+ {/* https://unsplash.com/ */}
+ <Box
+ sx={{
+ display: 'flex',
+ flexDirection: 'column',
+ minHeight: '100vh',
+ alignItems: 'center',
+ justifyContent: 'flex-start',
+ // justifyContent: 'center',
+ background: `url(/login_bg.jpg)`,
+ 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={{
+ minWidth: 300,
+ marginTop: '6em',
+ zIndex: 1
+ }}>
+ <Box
+ sx={{
+ margin: '1em',
+ display: 'flex',
+ justifyContent: 'center',
+ }}
+ >
+ <Avatar sx={{ bgcolor: 'secondary.main' }}>
+ <LockIcon />
+ </Avatar>
+ </Box>
+ <Box
+ sx={{
+ marginTop: '1em',
+ display: 'flex',
+ justifyContent: 'center',
+ color: theme => theme.palette.grey[500],
+ }}
+ >
+ Hint: root / 123456
+ </Box>
+ <Box sx={{ padding: '0 1em 1em 1em' }}>
+ <Box sx={{ marginTop: '1em' }}>
+ <SelectInput
+ label="page.login.tenant"
+ source="tenantId"
+ choices={tenantList.map(item => ({
+ id: item.id,
+ name: item.name
+ }))}
+ validate={required()}
+ value={tenantId}
+ onChange={e => setTenantId(e.target.value)}
+ />
+ </Box>
+ <Box sx={{ marginTop: '.1em' }}>
+ <TextInput
+ autoFocus
+ source="username"
+ label={translate('ra.auth.username')}
+ disabled={loading}
+ validate={required()}
+ />
+ </Box>
+ <Box sx={{ marginTop: '.1em' }}>
+ <TextInput
+ source="password"
+ label={translate('ra.auth.password')}
+ type="password"
+ disabled={loading}
+ validate={required()}
+ />
+ </Box>
+ </Box>
+ <CardActions sx={{ padding: '0 1em 1em 1em' }}>
+ <Button
+ variant="contained"
+ type="submit"
+ color="primary"
+ disabled={loading}
+ fullWidth
+ >
+ {loading && (
+ <CircularProgress size={25} thickness={2} />
+ )}
+ {translate('ra.auth.sign_in')}
+ </Button>
+ </CardActions>
+ </Card>
+ </Box>
+ </Form>
+ );
+};
+
+export default Login;
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/system/service/impl/UserLoginServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/system/service/impl/UserLoginServiceImpl.java
index 3d7b485..a2bc7c8 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/system/service/impl/UserLoginServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/system/service/impl/UserLoginServiceImpl.java
@@ -23,6 +23,7 @@
userLogin.setUserId(userId);
userLogin.setToken(token);
userLogin.setType(type);
+ userLogin.setTenantId(tenantId);
userLogin.setIp(IpTools.gainRealIp(request));
userLogin.setMemo(memo);
baseMapper.insert(userLogin);
--
Gitblit v1.9.1