From bb45d484db8daa9b6633c892e110a8dc8844d6e8 Mon Sep 17 00:00:00 2001
From: vincentlu <t1341870251@gmail.com>
Date: 星期一, 10 二月 2025 15:16:35 +0800
Subject: [PATCH] #

---
 rsf-framework/src/main/resources/templates/react-admin/ReactCreate.txt                       |    2 
 rsf-server/src/main/java/com/vincent/rsf/server/system/controller/param/TenantInitParam.java |   20 ++
 rsf-admin/src/page/host/HostCreate.jsx                                                       |    2 
 rsf-admin/src/page/user/UserCreate.jsx                                                       |    2 
 rsf-admin/src/page/role/RoleCreate.jsx                                                       |    2 
 rsf-admin/src/page/config/ConfigCreate.jsx                                                   |    2 
 rsf-admin/src/themes/themes.jsx                                                              |    2 
 rsf-admin/src/i18n/zh.js                                                                     |   17 +
 rsf-admin/src/i18n/en.js                                                                     |   17 +
 rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java                      |   26 --
 rsf-admin/src/page/tenant/TenantCreate.jsx                                                   |  400 ++++++++++++++++++++++++++++++++++++--------
 rsf-server/src/main/java/com/vincent/rsf/server/system/controller/TenantController.java      |   11 +
 12 files changed, 401 insertions(+), 102 deletions(-)

diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js
index 0390e96..e356675 100644
--- a/rsf-admin/src/i18n/en.js
+++ b/rsf-admin/src/i18n/en.js
@@ -244,12 +244,29 @@
                 confirmNewPwd: 'Confirm Password',
                 resetBtn: 'Reset',
                 tip: {
+                    usernameLimit: 'Only 3-20 English letters or numbers are allowed. No special characters.',
                     pwdInputLimit: "New Password must be 6-13 characters long and include both letters and numbers.",
                     pwdNotSameAsOld: "New Password cannot be the same as the Current Password.",
                     pwdNotMatch: "New Password and Confirm Password do not match.",
                 }
             }
         },
+        tenant: {
+            create: {
+                title: {
+                    basic: 'Basic Information',
+                    root: 'Add Administrator',
+                    confirm: 'Confirm',
+                },
+                btn: {
+                    next: 'Next Step',
+                    back: 'Back Step',
+                },
+                tip: {
+                    onlyEn: 'Only 3-20 English letters are allowed.'
+                },
+            },
+        },
     }
 };
 
diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js
index 60efdde..9490a9c 100644
--- a/rsf-admin/src/i18n/zh.js
+++ b/rsf-admin/src/i18n/zh.js
@@ -244,12 +244,29 @@
                 confirmNewPwd: '纭鏂板瘑鐮�',
                 resetBtn: '閲嶇疆瀵嗙爜',
                 tip: {
+                    usernameLimit: '浠呭厑璁歌緭鍏� 3-20 涓嫳鏂囧瓧姣嶆垨鏁板瓧锛屼笉鑳藉寘鍚壒娈婂瓧绗�',
                     pwdInputLimit: "瀵嗙爜蹇呴』涓�6-13浣�,涓斿繀椤诲寘鍚瓧姣嶅拰鏁板瓧",
                     pwdNotSameAsOld: "鏂板瘑鐮佷笉鑳戒笌褰撳墠瀵嗙爜鐩稿悓",
                     pwdNotMatch: "纭瀵嗙爜涓嶄竴鑷�",
                 }
             }
         },
+        tenant: {
+            create: {
+                title: {
+                    basic: '鍩虹淇℃伅',
+                    root: '娣诲姞绠$悊鍛�',
+                    confirm: '纭',
+                },
+                btn: {
+                    next: '涓嬩竴姝�',
+                    back: '涓婁竴姝�',
+                },
+                tip: {
+                    onlyEn: '浠呭厑璁歌緭鍏� 3-20 涓嫳鏂囧瓧姣�'
+                },
+            },
+        },
     }
 };
 
diff --git a/rsf-admin/src/page/config/ConfigCreate.jsx b/rsf-admin/src/page/config/ConfigCreate.jsx
index a3fe657..079e40e 100644
--- a/rsf-admin/src/page/config/ConfigCreate.jsx
+++ b/rsf-admin/src/page/config/ConfigCreate.jsx
@@ -79,7 +79,7 @@
                                 <DialogCloseButton onClose={handleClose} />
                             </Box>
                         </DialogTitle>
-                        <DialogContent>
+                        <DialogContent sx={{ mt: 2 }}>
                             <Grid container rowSpacing={2} columnSpacing={2}>
                                 {/* <Grid item xs={6} display="flex" gap={1}>
                                     <TextInput
diff --git a/rsf-admin/src/page/host/HostCreate.jsx b/rsf-admin/src/page/host/HostCreate.jsx
index dbf0182..8061e95 100644
--- a/rsf-admin/src/page/host/HostCreate.jsx
+++ b/rsf-admin/src/page/host/HostCreate.jsx
@@ -80,7 +80,7 @@
                                 <DialogCloseButton onClose={handleClose} />
                             </Box>
                         </DialogTitle>
-                        <DialogContent>
+                        <DialogContent sx={{ mt: 2 }}>
                             <Grid container rowSpacing={2} columnSpacing={2}>
                                 <Grid item xs={12} display="flex" gap={1}>
                                     <TextInput
diff --git a/rsf-admin/src/page/role/RoleCreate.jsx b/rsf-admin/src/page/role/RoleCreate.jsx
index dd2bce1..0ded77a 100644
--- a/rsf-admin/src/page/role/RoleCreate.jsx
+++ b/rsf-admin/src/page/role/RoleCreate.jsx
@@ -79,7 +79,7 @@
                                 <DialogCloseButton onClose={handleClose} />
                             </Box>
                         </DialogTitle>
-                        <DialogContent>
+                        <DialogContent sx={{ mt: 2 }}>
                             <Grid container rowSpacing={2} columnSpacing={2}>
                                 <Grid item xs={6} display="flex" gap={1}>
                                     <TextInput
diff --git a/rsf-admin/src/page/tenant/TenantCreate.jsx b/rsf-admin/src/page/tenant/TenantCreate.jsx
index 37e3d05..4e0dea7 100644
--- a/rsf-admin/src/page/tenant/TenantCreate.jsx
+++ b/rsf-admin/src/page/tenant/TenantCreate.jsx
@@ -23,100 +23,354 @@
     Stack,
     Grid,
     Box,
+    Stepper,
+    Step,
+    StepLabel,
+    StepContent,
+    Button,
+    TextField,
+    InputAdornment,
+    IconButton,
 } from '@mui/material';
+import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form";
+import { matchPath, useLocation } from 'react-router';
 import DialogCloseButton from "../components/DialogCloseButton";
 import StatusSelectInput from "../components/StatusSelectInput";
 import MemoInput from "../components/MemoInput";
+import Visibility from '@mui/icons-material/Visibility';
+import VisibilityOff from '@mui/icons-material/VisibilityOff';
 
 const TenantCreate = (props) => {
     const { open, setOpen } = props;
-
     const translate = useTranslate();
     const notify = useNotify();
+    const {
+        control,
+        handleSubmit,
+        watch,
+        setValue,
+        getValues,
+        reset,
+        formState: {
+            errors,
+            isDirty,
+        },
+        trigger
+    } = useForm();
+
+    const passwordVal = watch('password');
+
+    const [activeStep, setActiveStep] = useState(0);
+    const [showPassword, setShowPassword] = useState(false);
+
+    const validateCurrentStep = async () => {
+        let fieldsToValidate = [];
+        if (activeStep === 0) {
+            fieldsToValidate = ['name', 'flag'];
+        } else if (activeStep === 1) {
+            fieldsToValidate = ['username', 'email', 'password', 'confirmPassword'];
+        } else if (activeStep === 2) {
+            fieldsToValidate = ['memo'];
+        }
+        return await trigger(fieldsToValidate);
+    };
+
+    const handleNext = async () => {
+        const isValid = await validateCurrentStep();
+        if (!isValid) {
+            return;
+        }
+        setActiveStep(prev => prev + 1);
+    };
+
+    const handleBack = () => {
+        setActiveStep(prev => prev - 1);
+    };
 
     const handleClose = (event, reason) => {
         if (reason !== "backdropClick") {
+            setActiveStep(0);
             setOpen(false);
+            reset();
         }
     };
 
-    const handleSuccess = async (data) => {
-        setOpen(false);
-        notify('common.response.success');
-    };
+    const onSubmit = (data) => {
+        console.log(data);
+        return;
 
-    const handleError = async (error) => {
-        notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
-    };
+        // setOpen(false);
+        reset();
+        // notify('common.response.success');
+
+        // notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
+    }
 
     return (
         <>
-            <CreateBase
-                record={{}}
-                transform={(data) => {
-                    return data;
-                }}
-                mutationOptions={{ onSuccess: handleSuccess, onError: handleError }}
+            <Dialog
+                open={open}
+                onClose={handleClose}
+                aria-labelledby="form-dialog-title"
+                fullWidth
+                disableRestoreFocus
+                maxWidth="md"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
             >
-                <Dialog
-                    open={open}
-                    onClose={handleClose}
-                    aria-labelledby="form-dialog-title"
-                    fullWidth
-                    disableRestoreFocus
-                    maxWidth="md"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
-                >
-                    <Form>
-                        <DialogTitle id="form-dialog-title" sx={{
-                            position: 'sticky',
-                            top: 0,
-                            backgroundColor: 'background.paper',
-                            zIndex: 1000
-                        }}
-                        >
-                            {translate('create.title')}
-                            <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
-                                <DialogCloseButton onClose={handleClose} />
-                            </Box>
-                        </DialogTitle>
-                        <DialogContent>
-                            <Grid container rowSpacing={2} columnSpacing={2}>
-                                <Grid item xs={6} display="flex" gap={1}>
-                                    <TextInput
-                                        label="table.field.tenant.name"
-                                        source="name"
-                                        parse={v => v}
-                                        autoFocus
-                                        validate={required()}
-                                    />
-                                </Grid>
-                                <Grid item xs={6} display="flex" gap={1}>
-                                    <TextInput
-                                        label="table.field.tenant.flag"
-                                        source="flag"
-                                        parse={v => v}
-                                        autoFocus
-                                        validate={required()}
-                                    />
-                                </Grid>
-                                <Grid item xs={6} display="flex" gap={1}>
-                                    <StatusSelectInput />
-                                </Grid>
-                                <Grid item xs={12} display="flex" gap={1}>
-                                    <Stack direction="column" spacing={1} width={'100%'}>
-                                        <MemoInput />
-                                    </Stack>
-                                </Grid>
-                            </Grid>
-                        </DialogContent>
-                        <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
-                            <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }}  >
-                                <SaveButton />
-                            </Toolbar>
-                        </DialogActions>
-                    </Form>
-                </Dialog>
-            </CreateBase>
+                <DialogTitle id="form-dialog-title" sx={{
+                    position: 'sticky',
+                    top: 0,
+                    backgroundColor: 'background.paper',
+                    zIndex: 1000
+                }}>
+                    {translate('create.title')}
+                    <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
+                        <DialogCloseButton onClose={handleClose} />
+                    </Box>
+                </DialogTitle>
+                <DialogContent sx={{ mt: 2 }}>
+                    {open && (
+                        <form noValidate onSubmit={handleSubmit(onSubmit)} >
+                            <Stepper activeStep={activeStep} orientation="vertical">
+                                <Step>
+                                    <StepLabel>{translate('page.tenant.create.title.basic')}</StepLabel>
+                                    <StepContent>
+                                        <Stack spacing={3} mt={2} direction='column' width={'50%'}>
+                                            <Controller
+                                                name="name"
+                                                control={control}
+                                                defaultValue=""
+                                                rules={{ required: true }}
+                                                parse={v => v}
+                                                render={({ field, fieldState: { error } }) => (
+                                                    <TextField
+                                                        {...field}
+                                                        label={translate('table.field.tenant.name')}
+                                                        variant="outlined"
+                                                        autoComplete="off"
+                                                        error={!!error}
+                                                        helperText={error ? translate('ra.validation.required') : ""}
+                                                    />
+                                                )}
+                                            />
+                                            <Controller
+                                                name="flag"
+                                                control={control}
+                                                defaultValue=""
+                                                rules={{
+                                                    required: {
+                                                        value: true,
+                                                        message: translate('ra.validation.required')
+                                                    },
+                                                    pattern: {
+                                                        value: /^[A-Za-z]{3,20}$/,
+                                                        message: translate('page.tenant.create.tip.onlyEn'),
+                                                    }
+                                                }}
+                                                parse={v => v}
+                                                render={({ field, fieldState: { error } }) => (
+                                                    <TextField
+                                                        {...field}
+                                                        label={translate('table.field.tenant.flag')}
+                                                        variant="outlined"
+                                                        autoComplete="off"
+                                                        error={!!error}
+                                                        helperText={error ? error.message : ""}
+                                                    />
+                                                )}
+                                            />
+                                        </Stack>
+                                        <Box sx={{ mt: 3 }}>
+                                            <Button onClick={handleNext} variant="contained">
+                                                {translate('page.tenant.create.btn.next')}
+                                            </Button>
+                                            <Button disabled={activeStep === 0} onClick={handleBack}>
+                                                {translate('page.tenant.create.btn.back')}
+                                            </Button>
+                                        </Box>
+                                    </StepContent>
+                                </Step>
+
+                                <Step>
+                                    <StepLabel>{translate('page.tenant.create.title.root')}</StepLabel>
+                                    <StepContent>
+                                        <Stack spacing={3} mt={2} direction='column' width={'50%'}>
+                                            <Controller
+                                                name="username"
+                                                control={control}
+                                                defaultValue=""
+                                                rules={{
+                                                    required: {
+                                                        value: true,
+                                                        message: translate('ra.validation.required')
+                                                    },
+                                                    pattern: {
+                                                        value: /^[A-Za-z0-9]{3,20}$/,
+                                                        message: translate('page.settings.resetPwd.tip.usernameLimit'),
+                                                    },
+                                                }}
+                                                parse={v => v}
+                                                render={({ field, fieldState: { error } }) => (
+                                                    <TextField
+                                                        {...field}
+                                                        label={translate('table.field.user.username')}
+                                                        variant="outlined"
+                                                        autoComplete="off"
+                                                        error={!!error}
+                                                        helperText={error ? error.message : ""}
+                                                    />
+                                                )}
+                                            />
+                                            <Controller
+                                                name="email"
+                                                control={control}
+                                                defaultValue=""
+                                                rules={{
+                                                    required: false,
+                                                    pattern: {
+                                                        value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
+                                                        message: translate("ra.validation.email"),
+                                                    },
+                                                }}
+                                                render={({ field, fieldState: { error } }) => (
+                                                    <TextField
+                                                        {...field}
+                                                        label={translate('table.field.user.email')}
+                                                        variant="outlined"
+                                                        autoComplete="off"
+                                                        error={!!error}
+                                                        helperText={error ? error.message : ""}
+                                                    />
+                                                )}
+                                            />
+                                            <Controller
+                                                name="password"
+                                                control={control}
+                                                defaultValue=""
+                                                rules={{
+                                                    required: {
+                                                        value: true,
+                                                        message: translate('ra.validation.required'),
+                                                    },
+                                                    pattern: {
+                                                        value: /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{6,13}$/,
+                                                        message: translate('page.settings.resetPwd.tip.pwdInputLimit'),
+                                                    },
+                                                }}
+                                                render={({ field, fieldState: { error } }) => (
+                                                    <TextField
+                                                        {...field}
+                                                        label={translate('page.settings.resetPwd.newPwd')}
+                                                        type={showPassword ? 'text' : 'password'}
+                                                        variant="outlined"
+                                                        autoComplete="off"
+                                                        error={!!error}
+                                                        helperText={error ? error.message : ""}
+                                                        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>
+                                                            ),
+                                                        }}
+                                                    />
+                                                )}
+                                            />
+                                            <Controller
+                                                name="confirmPassword"
+                                                control={control}
+                                                defaultValue=""
+                                                rules={{
+                                                    required: translate('ra.validation.required'),
+                                                    validate: value =>
+                                                        value === passwordVal || translate('page.settings.resetPwd.tip.pwdNotMatch'),
+                                                }}
+                                                render={({ field, fieldState: { error } }) => (
+                                                    <TextField
+                                                        {...field}
+                                                        label={translate('page.settings.resetPwd.confirmNewPwd')}
+                                                        type={showPassword ? 'text' : 'password'}
+                                                        variant="outlined"
+                                                        autoComplete="off"
+                                                        error={!!error}
+                                                        helperText={error?.message || ""}
+                                                        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>
+                                                            ),
+                                                        }}
+                                                    />
+                                                )}
+                                            />
+                                        </Stack>
+                                        <Box sx={{ mt: 3 }}>
+                                            <Button onClick={handleNext} variant="contained">
+                                                {translate('page.tenant.create.btn.next')}
+                                            </Button>
+                                            <Button onClick={handleBack}>
+                                                {translate('page.tenant.create.btn.back')}
+                                            </Button>
+                                        </Box>
+                                    </StepContent>
+                                </Step>
+
+                                <Step>
+                                    <StepLabel>{translate('page.tenant.create.title.confirm')}</StepLabel>
+                                    <StepContent>
+                                        <Stack spacing={3} mt={2} direction='column' width={'50%'}>
+                                            <Controller
+                                                name="memo"
+                                                control={control}
+                                                defaultValue=""
+                                                rules={{ required: false }}
+                                                parse={v => v}
+                                                render={({ field, fieldState: { error } }) => (
+                                                    <TextField
+                                                        {...field}
+                                                        label={translate('common.field.memo')}
+                                                        variant="outlined"
+                                                        autoComplete="off"
+                                                        fullWidth
+                                                        multiline
+                                                        minRows={2}
+                                                        error={!!error}
+                                                        helperText={error ? translate('ra.validation.required') : ""}
+                                                    />
+                                                )}
+                                            />
+                                        </Stack>
+                                        <Box sx={{ mt: 3 }}>
+                                            <Button type="submit" variant="contained">
+                                                {translate('ra.action.save')}
+                                            </Button>
+                                            <Button onClick={handleBack}>
+                                                {translate('page.tenant.create.btn.back')}
+                                            </Button>
+                                        </Box>
+                                    </StepContent>
+                                </Step>
+                            </Stepper>
+                        </form>
+                    )}
+                </DialogContent>
+                <DialogActions sx={{ height: 10, position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
+                </DialogActions>
+            </Dialog>
         </>
     )
 }
diff --git a/rsf-admin/src/page/user/UserCreate.jsx b/rsf-admin/src/page/user/UserCreate.jsx
index c0c9a04..c2d8e08 100644
--- a/rsf-admin/src/page/user/UserCreate.jsx
+++ b/rsf-admin/src/page/user/UserCreate.jsx
@@ -107,7 +107,7 @@
                                 <DialogCloseButton onClose={handleClose} />
                             </Box>
                         </DialogTitle>
-                        <DialogContent>
+                        <DialogContent sx={{ mt: 2 }}>
                             <Grid container rowSpacing={2} columnSpacing={2}>
                                 <Grid item xs={6} display="flex" gap={1}>
                                     <TextInput
diff --git a/rsf-admin/src/themes/themes.jsx b/rsf-admin/src/themes/themes.jsx
index 05856c1..093fe0f 100644
--- a/rsf-admin/src/themes/themes.jsx
+++ b/rsf-admin/src/themes/themes.jsx
@@ -11,7 +11,6 @@
 import { DEFAULT_THEME_NAME } from '@/config/setting';
 
 import { softDarkTheme, softLightTheme } from './softTheme';
-import { chiptuneTheme } from './chiptuneTheme';
 import { rsfLightTheme, rsfDarkTheme } from './rsfTheme';
 
 export const themes = [
@@ -21,5 +20,4 @@
     { name: 'nano', light: nanoLightTheme, dark: nanoDarkTheme },
     // { name: 'radiant', light: radiantLightTheme, dark: radiantDarkTheme },
     // { name: 'house', light: houseLightTheme, dark: houseDarkTheme },
-    // { name: 'chiptune', light: chiptuneTheme },
 ];
diff --git a/rsf-framework/src/main/resources/templates/react-admin/ReactCreate.txt b/rsf-framework/src/main/resources/templates/react-admin/ReactCreate.txt
index d461fb6..9760184 100644
--- a/rsf-framework/src/main/resources/templates/react-admin/ReactCreate.txt
+++ b/rsf-framework/src/main/resources/templates/react-admin/ReactCreate.txt
@@ -82,7 +82,7 @@
                                 <DialogCloseButton onClose={handleClose} />
                             </Box>
                         </DialogTitle>
-                        <DialogContent>
+                        <DialogContent sx={{ mt: 2 }}>
                             <Grid container rowSpacing={2} columnSpacing={2}>
 @{REACTCREATECONTENT}
                                 <Grid item xs={6} display="flex" gap={1}>
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java b/rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java
index 65fa3ef..60e6d14 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java
@@ -11,11 +11,11 @@
 
     public static void main(String[] args) throws Exception {
         ReactGenerator generator = new ReactGenerator();
-        generator.backendPrefixPath = "zy-acs-manager/";
-        generator.frontendPrefixPath = "zy-acs-flow/";
+        generator.backendPrefixPath = "rsf-server/";
+        generator.frontendPrefixPath = "rsf-admin/";
 
         generator.sqlOsType = SqlOsType.MYSQL;
-        generator.url="localhost:3306/react_admin_dev";
+        generator.url="localhost:3306/rsf";
         generator.username="root";
         generator.password="xltys1995";
 //        generator.url="47.97.1.152:51433;databasename=jkasrs";
@@ -46,22 +46,4 @@
  */
 
 }
-/**
- *
- * TRUNCATE man_bus;
- * TRUNCATE man_task;
- * TRUNCATE man_travel;
- * TRUNCATE man_segment;
- * TRUNCATE man_jam;
- * TRUNCATE man_action;
- *
- * TRUNCATE man_code;
- * TRUNCATE man_code_gap;
- * TRUNCATE man_route;
- *
- * TRUNCATE man_func_sta;
- * TRUNCATE man_loc;
- * TRUNCATE man_sta;
- * TRUNCATE man_nav_map;
- *
- */
+
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/TenantController.java b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/TenantController.java
index 8c0639d..ff30c51 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/TenantController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/TenantController.java
@@ -9,6 +9,7 @@
 import com.vincent.rsf.server.common.domain.KeyValVo;
 import com.vincent.rsf.server.common.domain.PageParam;
 import com.vincent.rsf.server.common.utils.ExcelUtil;
+import com.vincent.rsf.server.system.controller.param.TenantInitParam;
 import com.vincent.rsf.server.system.entity.Tenant;
 import com.vincent.rsf.server.system.service.TenantService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -62,6 +63,16 @@
         return R.ok("Save Success").add(tenant);
     }
 
+    @PreAuthorize("hasAuthority('system:tenant:save')")
+    @OperationLog("Init Tenant")
+    @PostMapping("/tenant/init")
+    public R init(@RequestBody TenantInitParam param) {
+        
+
+
+        return R.ok("Initialize Success");
+    }
+
     @PreAuthorize("hasAuthority('system:tenant:update')")
     @OperationLog("Update Tenant")
     @PostMapping("/tenant/update")
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/param/TenantInitParam.java b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/param/TenantInitParam.java
new file mode 100644
index 0000000..af77d0a
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/param/TenantInitParam.java
@@ -0,0 +1,20 @@
+package com.vincent.rsf.server.system.controller.param;
+
+import lombok.Data;
+
+@Data
+public class TenantInitParam {
+
+    private String name;
+
+    private String flag;
+
+    private String username;
+
+    private String password;
+
+    private String email;
+
+    private String memo;
+
+}

--
Gitblit v1.9.1