From cb8536b77509a38e04594bc57fb93555c048c30b Mon Sep 17 00:00:00 2001 From: vincentlu <t1341870251@gmail.com> Date: 星期六, 08 二月 2025 15:52:30 +0800 Subject: [PATCH] # --- rsf-admin/src/api/auth/index.js | 18 ++ rsf-server/src/main/java/com/vincent/rsf/server/system/controller/AuthController.java | 21 +- rsf-admin/src/page/user/UserCreate.jsx | 6 rsf-admin/src/page/settings/BaseSettings.jsx | 251 ++++++++++++++++++++++++++++++++++++----- rsf-admin/src/page/login/Login.jsx | 4 rsf-admin/src/page/user/UserEdit.jsx | 6 rsf-admin/src/page/settings/index.jsx | 14 + rsf-admin/src/page/user/UserList.jsx | 6 8 files changed, 265 insertions(+), 61 deletions(-) diff --git a/rsf-admin/src/api/auth/index.js b/rsf-admin/src/api/auth/index.js index 2d73737..b3a2cc8 100644 --- a/rsf-admin/src/api/auth/index.js +++ b/rsf-admin/src/api/auth/index.js @@ -22,4 +22,20 @@ return res.data.data; } return Promise.reject(new Error(res.data.msg)); -} \ No newline at end of file +} + +export async function queryUserInfo(_params) { + const res = await request.get('/auth/user', _params); + if (res.data.code === 200) { + return res.data.data; + } + return Promise.reject(new Error(res.data.msg)); +} + +export async function updateUserInfo(_params) { + const res = await request.post('/auth/user', _params); + if (res.data.code === 200) { + return res.data; + } + return Promise.reject(new Error(res.data.msg)); +} diff --git a/rsf-admin/src/page/login/Login.jsx b/rsf-admin/src/page/login/Login.jsx index fe3123a..aa0ccbe 100644 --- a/rsf-admin/src/page/login/Login.jsx +++ b/rsf-admin/src/page/login/Login.jsx @@ -16,7 +16,7 @@ useLogin, useNotify, } from 'react-admin'; -import { useForm, Controller } from 'react-hook-form'; +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'; @@ -28,7 +28,7 @@ const location = useLocation(); const { tenantList } = props; - const { control, watch, handleSubmit, setValue } = useForm(); + const { control, handleSubmit, watch, setValue, getValues } = useForm(); const [loading, setLoading] = useState(false); const [showPassword, setShowPassword] = useState(false); diff --git a/rsf-admin/src/page/settings/BaseSettings.jsx b/rsf-admin/src/page/settings/BaseSettings.jsx index 78edbda..95c5a7f 100644 --- a/rsf-admin/src/page/settings/BaseSettings.jsx +++ b/rsf-admin/src/page/settings/BaseSettings.jsx @@ -1,57 +1,238 @@ import React, { useState, useRef, useEffect, useMemo } from "react"; -import { useNavigate } from 'react-router-dom'; import { - Edit, - SimpleForm, - FormDataConsumer, useTranslate, - TextInput, - NumberInput, - BooleanInput, - SaveButton, - SelectInput, - Toolbar, - Labeled, - NumberField, - required, - useRecordContext, - useTheme, - useAuthProvider, + useNotify, } from 'react-admin'; -import { useWatch, useFormContext } from "react-hook-form"; +import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form"; import { Stack, Grid, Box, Typography, - Card, - CardContent, + TextField, + Button, + FormControl, + InputLabel, + Select, + MenuItem, + FormHelperText, + CircularProgress, } from '@mui/material'; +import { updateUserInfo } from '@/api/auth'; const BaseSettings = (props) => { - const { children, value, ...other } = props; + const translate = useTranslate(); + const notify = useNotify(); + const { children, value, userInfo } = props; + + const { control, handleSubmit, watch, setValue, getValues, formState: { isDirty } } = useForm(); + const [loading, setLoading] = useState(false); + + useEffect(() => { + if (userInfo) { + setValue("username", userInfo.username || "", { shouldDirty: false }); + setValue("nickname", userInfo.nickname || "", { shouldDirty: false }); + setValue("sex", userInfo.sex ?? "", { shouldDirty: false }); + setValue("code", userInfo.code || "", { shouldDirty: false }); + setValue("phone", userInfo.phone || "", { shouldDirty: false }); + setValue("email", userInfo.email || "", { shouldDirty: false }); + setValue("realName", userInfo.realName || "", { shouldDirty: false }); + setValue("idCard", userInfo.idCard || "", { shouldDirty: false }); + } + }, [userInfo, setValue]) + + const onSubmit = (data) => { + setLoading(true); + updateUserInfo({ id: userInfo.id, ...data }).then(res => { + setLoading(false); + const { code, msg, data } = res; + if (code === 200) { + notify(msg, { type: 'success', messageArgs: { _: msg } }); + } else { + notify(msg, { type: 'error', messageArgs: { _: msg } }); + } + }).catch((error) => { + setLoading(false); + notify(error.message, { type: 'error', messageArgs: { _: error.message } }); + console.error(error); + }) + } return ( <Box hidden={value !== 0} - sx={{ p: 3 }} - {...other} + sx={{ + p: 3, + flex: 1, + overflow: 'auto', + }} > - <Grid container spacing={6}> - <Grid item xs={12}> - {/* https://github.com/themeselection/materio-mui-nextjs-admin-template-free/blob/main/javascript-version/src/views/account-settings/account/AccountDetails.jsx */} - <Card> - <CardContent className='mbe-5'> - <Typography> - Base Settings - </Typography> - </CardContent> - </Card> + {/* https://github.com/themeselection/materio-mui-nextjs-admin-template-free/blob/main/javascript-version/src/views/account-settings/account/AccountDetails.jsx */} + <form onSubmit={handleSubmit(onSubmit)} noValidate> + <Stack + direction='column' + spacing={3} + sx={{ + width: '30%', + pt: 1 + }} + > + <Controller + name="username" + control={control} + defaultValue="" + rules={{ required: true }} + render={({ field, fieldState: { error } }) => ( + <TextField + {...field} + label={translate('table.field.user.username')} + variant="outlined" + autoComplete="off" + helperText={error ? translate('ra.validation.required') : ""} + disabled + /> + )} + /> + <Controller + name="nickname" + control={control} + defaultValue="" + rules={{ required: true }} + render={({ field, fieldState: { error } }) => ( + <TextField + {...field} + label={translate('table.field.user.nickname')} + variant="outlined" + autoComplete="off" + error={!!error} + helperText={error ? translate('ra.validation.required') : ""} + /> + )} + /> + <Controller + name="sex" + control={control} + defaultValue="" + rules={{ required: true }} + render={({ field, fieldState: { error } }) => ( + <FormControl fullWidth variant="outlined" error={!!error}> + <InputLabel>{translate('table.field.user.sex')}</InputLabel> + <Select + {...field} + label={translate('table.field.user.sex')} + > + <MenuItem value={0}> + <em>{translate('table.field.user.sexes.unknown')}</em> + </MenuItem> + <MenuItem value={1}>{translate('table.field.user.sexes.male')}</MenuItem> + <MenuItem value={2}>{translate('table.field.user.sexes.female')}</MenuItem> + </Select> + {error && <FormHelperText>{translate('ra.validation.required')}</FormHelperText>} + </FormControl> + )} + /> + <Controller + name="code" + control={control} + defaultValue="" + rules={{ required: false }} + render={({ field, fieldState: { error } }) => ( + <TextField + {...field} + label={translate('table.field.user.code')} + variant="outlined" + autoComplete="off" + error={!!error} + helperText={error ? translate('ra.validation.required') : ""} + /> + )} + /> + <Controller + name="phone" + control={control} + defaultValue="" + rules={{ required: false }} + render={({ field, fieldState: { error } }) => ( + <TextField + {...field} + label={translate('table.field.user.phone')} + variant="outlined" + autoComplete="off" + error={!!error} + helperText={error ? translate('ra.validation.required') : ""} + /> + )} + /> + <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="realName" + control={control} + defaultValue="" + rules={{ required: false }} + render={({ field, fieldState: { error } }) => ( + <TextField + {...field} + label={translate('table.field.user.realName')} + variant="outlined" + autoComplete="off" + error={!!error} + helperText={error ? translate('ra.validation.required') : ""} + /> + )} + /> + <Controller + name="idCard" + control={control} + defaultValue="" + rules={{ required: false }} + render={({ field, fieldState: { error } }) => ( + <TextField + {...field} + label={translate('table.field.user.idCard')} + variant="outlined" + autoComplete="off" + error={!!error} + helperText={error ? translate('ra.validation.required') : ""} + /> + )} + /> + <Button + type="submit" + variant="contained" + disabled={loading || !isDirty} + sx={{ + alignSelf: 'flex-start', + width: '120px' + }} + > + {loading && <CircularProgress size={25} thickness={2} />} + {translate('ra.action.save')} + </Button> + </Stack> + </form> - </Grid> - </Grid> </Box> - ) } diff --git a/rsf-admin/src/page/settings/index.jsx b/rsf-admin/src/page/settings/index.jsx index 63e48b6..bc2364c 100644 --- a/rsf-admin/src/page/settings/index.jsx +++ b/rsf-admin/src/page/settings/index.jsx @@ -21,15 +21,17 @@ import { useWatch, useFormContext } from "react-hook-form"; import { Stack, Grid, Box, Typography, Card, CardContent, Tabs, Tab } from '@mui/material'; import * as Common from '@/utils/common'; -import { } from '@/config/setting'; import BaseSettings from "./BaseSettings"; +import { queryUserInfo } from '@/api/auth'; const Index = () => { const authProvider = useAuthProvider(); const navigate = useNavigate(); const translate = useTranslate(); const theme = useTheme(); - const [value, setValue] = React.useState(0); + + const [value, setValue] = useState(0); + const [userInfo, setUserInfo] = useState(null); useEffect(() => { authProvider.checkAuth().catch(() => { @@ -38,7 +40,10 @@ }, [authProvider, navigate]); useEffect(() => { - }, [value]); + queryUserInfo().then(res => { + setUserInfo(res); + }) + }, []); return ( <> @@ -50,7 +55,7 @@ flexGrow: 1, bgcolor: 'background.paper', display: 'flex', - height: 224, + // height: 224, border: `1px solid #${theme[0] === 'light' ? 'ddd' : '333'}`, borderRadius: 2 }} @@ -82,6 +87,7 @@ </Tabs> <BaseSettings value={value} + userInfo={userInfo} /> <SecuritySettings value={value} diff --git a/rsf-admin/src/page/user/UserCreate.jsx b/rsf-admin/src/page/user/UserCreate.jsx index 5a129ed..c0c9a04 100644 --- a/rsf-admin/src/page/user/UserCreate.jsx +++ b/rsf-admin/src/page/user/UserCreate.jsx @@ -155,9 +155,9 @@ label="table.field.user.sex" source="sex" choices={[ - { id: 0, name: '鏈煡' }, - { id: 1, name: '鐢�' }, - { id: 2, name: '濂�' }, + { id: 0, name: 'table.field.user.sexes.unknown' }, + { id: 1, name: 'table.field.user.sexes.male' }, + { id: 2, name: 'table.field.user.sexes.female' }, ]} /> </Grid> diff --git a/rsf-admin/src/page/user/UserEdit.jsx b/rsf-admin/src/page/user/UserEdit.jsx index b5b48b1..f040af2 100644 --- a/rsf-admin/src/page/user/UserEdit.jsx +++ b/rsf-admin/src/page/user/UserEdit.jsx @@ -134,9 +134,9 @@ label="table.field.user.sex" source="sex" choices={[ - { id: 0, name: '鏈煡' }, - { id: 1, name: '鐢�' }, - { id: 2, name: '濂�' }, + { id: 0, name: 'table.field.user.sexes.unknown' }, + { id: 1, name: 'table.field.user.sexes.male' }, + { id: 2, name: 'table.field.user.sexes.female' }, ]} /> <TextInput diff --git a/rsf-admin/src/page/user/UserList.jsx b/rsf-admin/src/page/user/UserList.jsx index 63f81bd..25fd5bd 100644 --- a/rsf-admin/src/page/user/UserList.jsx +++ b/rsf-admin/src/page/user/UserList.jsx @@ -88,9 +88,9 @@ <TextInput source="code" label="table.field.user.code" />, <SelectInput source="sex" label="table.field.user.sex" choices={[ - { id: 0, name: '鏈煡' }, - { id: 1, name: '鐢�' }, - { id: 2, name: '濂�' }, + { id: 0, name: 'table.field.user.sexes.unknown' }, + { id: 1, name: "table.field.user.sexes.male" }, + { id: 2, name: 'table.field.user.sexes.female' }, ]} />, <TextInput source="phone" label="table.field.user.phone" />, diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/AuthController.java b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/AuthController.java index 78b2069..d1744e9 100644 --- a/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/AuthController.java +++ b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/AuthController.java @@ -14,10 +14,8 @@ import com.vincent.rsf.server.system.entity.Menu; import com.vincent.rsf.server.system.entity.User; import com.vincent.rsf.server.system.entity.UserLogin; -import com.vincent.rsf.server.system.service.RoleMenuService; -import com.vincent.rsf.server.system.service.TenantService; -import com.vincent.rsf.server.system.service.UserLoginService; -import com.vincent.rsf.server.system.service.UserService; +import com.vincent.rsf.server.system.service.*; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @@ -45,6 +43,8 @@ private RoleMenuService roleMenuService; @Resource private TenantService tenantService; + @Autowired + private UserRoleService userRoleService; @PostMapping("/login") public R login(@RequestBody LoginParam param, HttpServletRequest request) { @@ -74,7 +74,9 @@ @GetMapping("/auth/user") public R userInfo() { - return R.ok(userService.getByIdRel(getLoginUserId())); + User user = userService.getByIdRel(getLoginUserId()); + user.setRoles(userRoleService.listByUserId(user.getId())); + return R.ok(user); } @GetMapping("/auth/menu") @@ -85,9 +87,8 @@ return R.ok().add(Utils.toTreeData(voList, 0L, MenuVo::getParentId, MenuVo::getId, MenuVo::setChildren)); } - @PreAuthorize("hasAuthority('sys:auth:user')") - @OperationLog - @PutMapping("/auth/user") + @OperationLog("Update UserInfo") + @PostMapping("/auth/user") public R updateInfo(@RequestBody User user) { user.setId(getLoginUserId()); // 涓嶈兘淇敼鐨勫瓧娈� @@ -97,14 +98,14 @@ user.setTenantId(null); user.setStatus(null); if (userService.updateById(user)) { - return R.ok().add(userService.getByIdRel(user.getId())); + return R.ok("Save Success").add(userService.getByIdRel(user.getId())); } return R.error("Save Fail"); } @PreAuthorize("hasAuthority('sys:auth:password')") @OperationLog - @PutMapping("/auth/password") + @PostMapping("/auth/password") public R updatePassword(@RequestBody UpdatePasswordParam param) { if (Cools.isEmpty(param.getOldPassword(), param.getPassword())) { return R.error("Parameters Cannot Be Empty"); -- Gitblit v1.9.1