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