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