From 45eb50fd77ad91a7cce4b68a4e1924f71b0938fa Mon Sep 17 00:00:00 2001
From: vincentlu <t1341870251@gmail.com>
Date: 星期二, 11 二月 2025 13:14:10 +0800
Subject: [PATCH] #
---
rsf-admin/src/page/login/Login.jsx | 189 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 189 insertions(+), 0 deletions(-)
diff --git a/rsf-admin/src/page/login/Login.jsx b/rsf-admin/src/page/login/Login.jsx
new file mode 100644
index 0000000..0eedaad
--- /dev/null
+++ b/rsf-admin/src/page/login/Login.jsx
@@ -0,0 +1,189 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import { useLocation } from 'react-router-dom';
+import {
+ Box,
+ CircularProgress,
+ Typography,
+ Button,
+ TextField,
+ Stack,
+ Autocomplete,
+ InputAdornment,
+ IconButton,
+} from '@mui/material';
+import {
+ useTranslate,
+ useLogin,
+ useNotify,
+} from 'react-admin';
+import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form";
+import ProviderChoices from "./ProviderChoices";
+import Visibility from '@mui/icons-material/Visibility';
+import VisibilityOff from '@mui/icons-material/VisibilityOff';
+
+const Login = (props) => {
+ const translate = useTranslate();
+ const notify = useNotify();
+ const login = useLogin();
+ const location = useLocation();
+ const { tenantList } = props;
+
+ const { control, handleSubmit, watch, setValue, getValues } = useForm();
+
+ const [loading, setLoading] = useState(false);
+ const [showPassword, setShowPassword] = useState(false);
+
+ const username = watch('username');
+ const password = watch('password');
+ const tenantId = watch('tenantId');
+
+ useEffect(() => {
+ if (tenantList.length > 0 && !tenantId) {
+ const rememberTenantId = localStorage.getItem('remember_tenantId');
+ if (rememberTenantId && tenantList.some(t => t.id === Number(rememberTenantId))) {
+ setValue('tenantId', Number(rememberTenantId));
+ } else {
+ 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) => {
+ const newTenantId = newValue ? newValue.id : '';
+ onChange(newTenantId);
+ localStorage.setItem('remember_tenantId', newTenantId);
+ }}
+ 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("page.login.username")}
+ variant="standard"
+ disabled={loading}
+ autoFocus
+ autoComplete="off"
+ />
+ )}
+ />
+
+ <Controller
+ name="password"
+ control={control}
+ defaultValue=""
+ rules={{ required: true }}
+ render={({ field }) => (
+ <TextField
+ {...field}
+ label={translate("page.login.password")}
+ type={showPassword ? 'text' : 'password'}
+ variant="standard"
+ disabled={loading}
+ autoComplete="off"
+ InputProps={{
+ endAdornment: (
+ <InputAdornment position="end">
+ <IconButton
+ aria-label="toggle password visibility"
+ onClick={() => setShowPassword((show) => !show)}
+ onMouseDown={(event) => { event.preventDefault() }}
+ edge="end"
+ >
+ {showPassword ? <VisibilityOff /> : <Visibility />}
+ </IconButton>
+ </InputAdornment>
+ ),
+ }}
+ />
+ )}
+ />
+
+ <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>
+
+ <ProviderChoices type="LOG IN" />
+ </Box >
+ </>
+ )
+}
+
+export default Login;
\ No newline at end of file
--
Gitblit v1.9.1