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