From 3b8bd7dbba101f4207a08bf0254a9e58bc708348 Mon Sep 17 00:00:00 2001
From: vincentlu <t1341870251@gmail.com>
Date: 星期一, 19 一月 2026 13:34:12 +0800
Subject: [PATCH] #

---
 zy-acs-manager/src/main/java/com/zy/acs/manager/system/service/impl/UserServiceImpl.java        |    9 
 /dev/null                                                                                       |  139 ---------
 zy-acs-flow/src/i18n/en.js                                                                      |   14 
 zy-acs-flow/src/page/settings/BaseSettings.jsx                                                  |  274 ++++++++++++++++++
 zy-acs-flow/src/page/settings/SecuritySettings.jsx                                              |  208 +++++++++++++
 zy-acs-flow/src/page/settings/index.jsx                                                         |  106 +++++++
 zy-acs-flow/src/App.jsx                                                                         |    2 
 zy-acs-flow/src/i18n/zh.js                                                                      |   14 
 zy-acs-manager/src/main/java/com/zy/acs/manager/system/service/UserService.java                 |    2 
 zy-acs-flow/src/api/auth/index.js                                                               |   18 +
 zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/conveyor/ConveyorController.java |    4 
 zy-acs-manager/src/main/java/com/zy/acs/manager/system/controller/AuthController.java           |   66 ++-
 12 files changed, 686 insertions(+), 170 deletions(-)

diff --git a/zy-acs-flow/src/App.jsx b/zy-acs-flow/src/App.jsx
index 00924d9..4b17446 100644
--- a/zy-acs-flow/src/App.jsx
+++ b/zy-acs-flow/src/App.jsx
@@ -15,7 +15,7 @@
 import AuthProvider from "./config/authProvider";
 import DataProvider from "./config/dataProvider";
 import Dashboard from "./page/dashboard/Dashboard";
-import Settings from "./page/settings/Settings";
+import Settings from "./page/settings";
 import Login from "./page/login";
 import * as Common from './utils/common'
 import { themes } from './themes/themes';
diff --git a/zy-acs-flow/src/api/auth/index.js b/zy-acs-flow/src/api/auth/index.js
index 68bd7ea..9a25a8b 100644
--- a/zy-acs-flow/src/api/auth/index.js
+++ b/zy-acs-flow/src/api/auth/index.js
@@ -34,6 +34,24 @@
     return Promise.reject(new Error(res.data.msg));
 }
 
+export async function queryUserInfo(_params) {
+    const res = await request.get('/auth/user', { params: _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);
+    return res.data;
+}
+
+export async function requestResetPassword(_params) {
+    const res = await request.post('/auth/reset/password', _params);
+    return res.data;
+}
+
 export async function sendEmailCode(_params) {
     const res = await request.get('/email/code', { params: _params });
     return res.data;
diff --git a/zy-acs-flow/src/i18n/en.js b/zy-acs-flow/src/i18n/en.js
index 5e2ec9b..082291b 100644
--- a/zy-acs-flow/src/i18n/en.js
+++ b/zy-acs-flow/src/i18n/en.js
@@ -618,6 +618,20 @@
                 code: 'Send Code',
             },
         },
+        settings: {
+            resetPwd: {
+                currPwd: 'Current Password',
+                newPwd: 'New Password',
+                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.",
+                }
+            }
+        },
         code: {
             dirRule: {
                 helper: 'Select one direction to disable; other directions remain available.',
diff --git a/zy-acs-flow/src/i18n/zh.js b/zy-acs-flow/src/i18n/zh.js
index b9db6c8..32006ac 100644
--- a/zy-acs-flow/src/i18n/zh.js
+++ b/zy-acs-flow/src/i18n/zh.js
@@ -618,6 +618,20 @@
                 code: '鑾峰彇楠岃瘉鐮�',
             },
         },
+        settings: {
+            resetPwd: {
+                currPwd: '褰撳墠瀵嗙爜',
+                newPwd: '鏂板瘑鐮�',
+                confirmNewPwd: '纭鏂板瘑鐮�',
+                resetBtn: '閲嶇疆瀵嗙爜',
+                tip: {
+                    usernameLimit: '浠呭厑璁歌緭鍏� 3-20 涓嫳鏂囧瓧姣嶆垨鏁板瓧锛屼笉鑳藉寘鍚壒娈婂瓧绗�',
+                    pwdInputLimit: "瀵嗙爜蹇呴』涓�6-13浣�,涓斿繀椤诲寘鍚瓧姣嶅拰鏁板瓧",
+                    pwdNotSameAsOld: "鏂板瘑鐮佷笉鑳戒笌褰撳墠瀵嗙爜鐩稿悓",
+                    pwdNotMatch: "纭瀵嗙爜涓嶄竴鑷�",
+                }
+            }
+        },
         code: {
             dirRule: {
                 helper: '閫夋嫨涓�涓柟鍚戠鐢紝鍏朵綑鏂瑰悜淇濇寔鍙敤',
diff --git a/zy-acs-flow/src/page/settings/BaseSettings.jsx b/zy-acs-flow/src/page/settings/BaseSettings.jsx
new file mode 100644
index 0000000..3a7ff59
--- /dev/null
+++ b/zy-acs-flow/src/page/settings/BaseSettings.jsx
@@ -0,0 +1,274 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    useTranslate,
+    useNotify,
+} from 'react-admin';
+import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form";
+import {
+    Stack,
+    Grid,
+    Box,
+    Typography,
+    TextField,
+    Button,
+    FormControl,
+    InputLabel,
+    Select,
+    MenuItem,
+    FormHelperText,
+    CircularProgress,
+    LinearProgress,
+} from '@mui/material';
+import { updateUserInfo } from '@/api/auth';
+import avatar from '/avatar.jpg'
+
+const BaseSettings = (props) => {
+    const translate = useTranslate();
+    const notify = useNotify();
+    const { children, userInfo } = props;
+
+    const {
+        control,
+        handleSubmit,
+        watch,
+        setValue,
+        getValues,
+        reset,
+        formState: {
+            errors,
+            isDirty,
+        },
+        setError,
+        clearErrors,
+    } = 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 } });
+                const userToPersist = {
+                    avatar: avatar,
+                    fullName: data.nickname,
+                    id: data.id,
+                    username: data.username
+                }
+                localStorage.setItem("user", JSON.stringify(userToPersist));
+            } else if (code === 10005 || code === 10006) {
+                setError('email', {
+                    message: 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 sx={{
+            position: 'relative',
+            p: 3,
+            flex: 1,
+            overflow: 'auto',
+        }}>
+            {!userInfo && (
+                <LinearProgress
+                    sx={{
+                        height: "2px",
+                        position: 'absolute',
+                        top: 0,
+                        left: 0,
+                        right: 0,
+                    }}
+                />
+            )}
+            <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>
+
+        </Box>
+    )
+}
+
+export default BaseSettings;
\ No newline at end of file
diff --git a/zy-acs-flow/src/page/settings/SecuritySettings.jsx b/zy-acs-flow/src/page/settings/SecuritySettings.jsx
new file mode 100644
index 0000000..42aeaad
--- /dev/null
+++ b/zy-acs-flow/src/page/settings/SecuritySettings.jsx
@@ -0,0 +1,208 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    useTranslate,
+    useNotify,
+} from 'react-admin';
+import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form";
+import {
+    Stack,
+    Box,
+    Typography,
+    TextField,
+    Button,
+    CircularProgress,
+    InputAdornment,
+    IconButton,
+} from '@mui/material';
+import { requestResetPassword } from '@/api/auth';
+import Visibility from '@mui/icons-material/Visibility';
+import VisibilityOff from '@mui/icons-material/VisibilityOff';
+
+const SecuritySettings = (props) => {
+    const translate = useTranslate();
+    const notify = useNotify();
+    const { userInfo } = props;
+
+    const { control, handleSubmit, watch, setValue, getValues, reset, formState: { errors }, setError } = useForm();
+
+    const oldPasswordVal = watch('oldPassword');
+    const newPasswordVal = watch('newPassword');
+    const confirmPasswordVal = watch('confirmPassword');
+
+    const [loading, setLoading] = useState(false);
+    const [showOldPassword, setShowOldPassword] = useState(false);
+    const [showNewPassword, setShowNewPassword] = useState(false);
+
+    useEffect(() => {
+        if (userInfo) {
+        }
+    }, [userInfo, setValue])
+
+    const onSubmit = (params) => {
+        setLoading(true);
+        requestResetPassword(params).then(res => {
+            setLoading(false);
+            const { code, msg, data } = res;
+            if (code === 200) {
+                notify(msg, { type: 'success', messageArgs: { _: msg } });
+                reset();
+            } else if (code === 10001) {
+                setError('oldPassword', {
+                    message: 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
+            sx={{
+                p: 3,
+                flex: 1,
+                overflow: 'auto',
+            }}
+        >
+            <form onSubmit={handleSubmit(onSubmit)} noValidate>
+                <Stack
+                    direction='column'
+                    spacing={3}
+                    sx={{
+                        width: '30%',
+                        pt: 1
+                    }}
+                >
+                    <Controller
+                        name="oldPassword"
+                        control={control}
+                        defaultValue=""
+                        rules={{ required: translate('ra.validation.required') }}
+                        render={({ field, fieldState: { error } }) => (
+                            <TextField
+                                {...field}
+                                label={translate('page.settings.resetPwd.currPwd')}
+                                type={showOldPassword ? 'text' : 'password'}
+                                variant="outlined"
+                                autoComplete="off"
+                                error={Boolean(errors.oldPassword)}
+                                helperText={errors.oldPassword?.message || ""}
+                                InputProps={{
+                                    endAdornment: (
+                                        <InputAdornment position="end">
+                                            <IconButton
+                                                aria-label="toggle password visibility"
+                                                onClick={() => setShowOldPassword((show) => !show)}
+                                                onMouseDown={(event) => { event.preventDefault() }}
+                                                edge="end"
+                                            >
+                                                {showOldPassword ? <VisibilityOff /> : <Visibility />}
+                                            </IconButton>
+                                        </InputAdornment>
+                                    ),
+                                }}
+                            />
+                        )}
+                    />
+                    <Controller
+                        name="newPassword"
+                        control={control}
+                        defaultValue=""
+                        rules={{
+                            required: translate('ra.validation.required'),
+                            pattern: {
+                                value: /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d\.]{6,13}$/,
+                                message: translate('page.settings.resetPwd.tip.pwdInputLimit'),
+                            },
+                            validate: (value) => {
+                                if (value === oldPasswordVal) {
+                                    return translate('page.settings.resetPwd.tip.pwdNotSameAsOld');
+                                }
+                                return true;
+                            }
+                        }}
+                        render={({ field, fieldState: { error } }) => (
+                            <TextField
+                                {...field}
+                                label={translate('page.settings.resetPwd.newPwd')}
+                                type={showNewPassword ? 'text' : 'password'}
+                                variant="outlined"
+                                autoComplete="off"
+                                error={Boolean(errors.newPassword)}
+                                helperText={errors.newPassword?.message || ""}
+                                InputProps={{
+                                    endAdornment: (
+                                        <InputAdornment position="end">
+                                            <IconButton
+                                                aria-label="toggle password visibility"
+                                                onClick={() => setShowNewPassword((show) => !show)}
+                                                onMouseDown={(event) => { event.preventDefault() }}
+                                                edge="end"
+                                            >
+                                                {showNewPassword ? <VisibilityOff /> : <Visibility />}
+                                            </IconButton>
+                                        </InputAdornment>
+                                    ),
+                                }}
+                            />
+                        )}
+                    />
+                    <Controller
+                        name="confirmPassword"
+                        control={control}
+                        defaultValue=""
+                        rules={{
+                            required: translate('ra.validation.required'),
+                            validate: value =>
+                                value === newPasswordVal || translate('page.settings.resetPwd.tip.pwdNotMatch'),
+                        }}
+                        render={({ field, fieldState: { error } }) => (
+                            <TextField
+                                {...field}
+                                label={translate('page.settings.resetPwd.confirmNewPwd')}
+                                type={showNewPassword ? 'text' : 'password'}
+                                variant="outlined"
+                                autoComplete="off"
+                                error={Boolean(errors.confirmPassword)}
+                                helperText={errors.confirmPassword?.message || ""}
+                                InputProps={{
+                                    endAdornment: (
+                                        <InputAdornment position="end">
+                                            <IconButton
+                                                aria-label="toggle password visibility"
+                                                onClick={() => setShowNewPassword((show) => !show)}
+                                                onMouseDown={(event) => { event.preventDefault() }}
+                                                edge="end"
+                                            >
+                                                {showNewPassword ? <VisibilityOff /> : <Visibility />}
+                                            </IconButton>
+                                        </InputAdornment>
+                                    ),
+                                }}
+                            />
+                        )}
+                    />
+                    <Button
+                        type="submit"
+                        variant="contained"
+                        disabled={loading || !(oldPasswordVal && newPasswordVal && confirmPasswordVal)}
+                        sx={{
+                            alignSelf: 'flex-start',
+                            width: '120px'
+                        }}
+                    >
+                        {loading && <CircularProgress size={25} thickness={2} />}
+                        {translate('page.settings.resetPwd.resetBtn')}
+                    </Button>
+                </Stack>
+            </form>
+
+        </Box>
+    )
+}
+
+export default SecuritySettings;
\ No newline at end of file
diff --git a/zy-acs-flow/src/page/settings/Settings.jsx b/zy-acs-flow/src/page/settings/Settings.jsx
deleted file mode 100644
index 7833c47..0000000
--- a/zy-acs-flow/src/page/settings/Settings.jsx
+++ /dev/null
@@ -1,139 +0,0 @@
-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,
-} from 'react-admin';
-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';
-
-const Settings = () => {
-    const authProvider = useAuthProvider();
-    const navigate = useNavigate();
-    const translate = useTranslate();
-    const theme = useTheme();
-    const [value, setValue] = React.useState(0);
-
-    useEffect(() => {
-        authProvider.checkAuth().catch(() => {
-            navigate('/login');
-        });
-    }, [authProvider, navigate]);
-
-    useEffect(() => {
-    }, [value]);
-
-    return (
-        <>
-            <Card sx={{ backgroundColor: 'initial' }}>
-                <CardContent >
-                    <Box
-                        mt={2}
-                        sx={{
-                            flexGrow: 1,
-                            bgcolor: 'background.paper',
-                            display: 'flex',
-                            height: 224,
-                            border: `1px solid #${theme[0] === 'light' ? 'ddd' : '333'}`,
-                            borderRadius: 2
-                        }}
-                    >
-                        <Tabs
-                            orientation="vertical"
-                            variant="scrollable"
-                            value={value}
-                            onChange={(event, newValue) => {
-                                setValue(newValue);
-                            }}
-                            indicatorColor="secondary"
-                            textColor="inherit"
-                            sx={{
-                                borderRight: 1,
-                                borderColor: 'divider',
-                                width: 150,
-                            }}
-                        >
-                            <Tab
-                                label={translate('settings.base')}
-                                id='vertical-tab-0'
-                                aria-controls='vertical-tabpanel-0'
-                            />
-                            <Tab label={translate('settings.security')}
-                                id='vertical-tab-1'
-                                aria-controls='vertical-tabpanel-1'
-                            />
-                        </Tabs>
-                        <BaseSettings
-                            value={value}
-                        />
-                        <SecuritySettings
-                            value={value}
-                        />
-                    </Box>
-                </CardContent>
-            </Card>
-        </>
-    )
-}
-
-const BaseSettings = (props) => {
-    const { children, value, ...other } = props;
-
-    return (
-        <Box
-            hidden={value !== 0}
-            sx={{ p: 3 }}
-            {...other}
-        >
-            <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>
-
-                </Grid>
-            </Grid>
-        </Box>
-
-    )
-}
-
-const SecuritySettings = (props) => {
-    const { children, value, ...other } = props;
-
-    return (
-        <Box
-            hidden={value !== 1}
-            sx={{ p: 3 }}
-            {...other}
-        >
-            <Typography>
-                Security Settings
-            </Typography>
-        </Box>
-
-    )
-}
-
-export default Settings;
\ No newline at end of file
diff --git a/zy-acs-flow/src/page/settings/index.jsx b/zy-acs-flow/src/page/settings/index.jsx
new file mode 100644
index 0000000..ff3f665
--- /dev/null
+++ b/zy-acs-flow/src/page/settings/index.jsx
@@ -0,0 +1,106 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import { useNavigate } from 'react-router-dom';
+import {
+    useTranslate,
+    useAuthProvider,
+} from 'react-admin';
+import { useWatch, useFormContext } from "react-hook-form";
+import { Stack, Grid, Box, Typography, Card, CardContent, Tabs, Tab, useTheme } from '@mui/material';
+import * as Common from '@/utils/common';
+import BaseSettings from "./BaseSettings";
+import SecuritySettings from "./SecuritySettings"
+import { queryUserInfo } from '@/api/auth';
+
+const Index = () => {
+    const authProvider = useAuthProvider();
+    const navigate = useNavigate();
+    const translate = useTranslate();
+    const theme = useTheme();
+
+    const [value, setValue] = useState(0);
+    const [userInfo, setUserInfo] = useState(null);
+
+    useEffect(() => {
+        authProvider.checkAuth().catch(() => {
+            navigate('/login');
+        });
+    }, [authProvider, navigate]);
+
+    useEffect(() => {
+        queryUserInfo().then(res => {
+            setUserInfo(res);
+        })
+    }, []);
+
+    return (
+        <>
+            <Card sx={{ backgroundColor: 'initial' }}>
+                <CardContent >
+                    <Box
+                        mt={2}
+                        sx={{
+                            flexGrow: 1,
+                            bgcolor: 'background.paper',
+                            display: 'flex',
+                            border: `1px solid #${theme.palette.mode === 'light' ? 'ddd' : '333'}`,
+                            borderRadius: 2,
+                            pt: 1,
+                            pb: 1,
+                        }}
+                    >
+                        <Tabs
+                            orientation="vertical"
+                            variant="scrollable"
+                            value={value}
+                            onChange={(event, newValue) => {
+                                setValue(newValue);
+                            }}
+                            indicatorColor="primary"
+                            textColor="inherit"
+                            TabIndicatorProps={{
+                                style: {
+                                    left: 0,
+                                    right: 'auto',
+                                    width: '5px',
+                                    borderRadius: '2px',
+                                    opacity: .8,
+                                }
+                            }}
+                            sx={{
+                                borderRight: 1,
+                                borderColor: 'divider',
+                                width: 150,
+                            }}
+                        >
+                            <Tab
+                                label={translate('settings.base')}
+                                id='vertical-tab-0'
+                                aria-controls='vertical-tabpanel-0'
+                            />
+                            <Tab label={translate('settings.security')}
+                                id='vertical-tab-1'
+                                aria-controls='vertical-tabpanel-1'
+                            />
+                        </Tabs>
+
+                        {value === 0 && (
+                            <BaseSettings
+                                value={value}
+                                userInfo={userInfo}
+                            />
+                        )}
+                        {value === 1 && (
+                            <SecuritySettings
+                                value={value}
+                                userInfo={userInfo}
+                            />
+                        )}
+
+                    </Box>
+                </CardContent>
+            </Card>
+        </>
+    )
+}
+
+export default Index;
\ No newline at end of file
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/conveyor/ConveyorController.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/conveyor/ConveyorController.java
index 5aae91c..835bdad 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/conveyor/ConveyorController.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/conveyor/ConveyorController.java
@@ -39,7 +39,7 @@
             );
             for (Sta sta : list) {
                 resultList.add(new ConveyorQueryResult(sta.getStaNo()
-                        , staService.hasWorkingAgv(sta.getId())));
+                        , !staService.hasWorkingAgv(sta.getId())));
             }
         } else {
             for (String staNo : staNos) {
@@ -49,7 +49,7 @@
                     continue;
                 }
                 resultList.add(new ConveyorQueryResult(staNo
-                        , staService.hasWorkingAgv(sta.getId())));
+                        , !staService.hasWorkingAgv(sta.getId())));
             }
         }
 
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/system/controller/AuthController.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/system/controller/AuthController.java
index 6b79bab..c2a021c 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/system/controller/AuthController.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/system/controller/AuthController.java
@@ -49,6 +49,15 @@
     @Resource
     private TenantService tenantService;
 
+    @GetMapping("/system/info")
+    public R systemInfo() {
+        SystemInfoVo infoVo = new SystemInfoVo();
+        infoVo.setName(configProperties.getSystemName());
+        infoVo.setVersion(configProperties.getSystemVersion());
+        infoVo.setMode(configProperties.getSystemMode().toString());
+        return R.ok(infoVo);
+    }
+
     @PostMapping("/login")
     public R login(@RequestBody LoginParam param, HttpServletRequest request) {
 //        System.out.println(userService.encodePassword("123456"));
@@ -70,11 +79,6 @@
         return R.ok("Sign In Success").add(new LoginResult(accessToken, user));
     }
 
-    @GetMapping("/auth/user")
-    public R userInfo() {
-        return R.ok(userService.getByIdRel(getLoginUserId()));
-    }
-
     @GetMapping("/auth/menu")
     public R userMenu() {
         List<Menu> menus = roleMenuService.listMenuByUserId(getLoginUserId(), Menu.TYPE_MENU);
@@ -83,54 +87,60 @@
         return R.ok().add(Utils.toTreeData(voList, 0L, MenuVo::getParentId, MenuVo::getId, MenuVo::setChildren));
     }
 
-    @PreAuthorize("hasAuthority('sys:auth:user')")
-    @OperationLog
-    @PutMapping("/auth/user")
+    @GetMapping("/auth/user")
+    public R userInfo() {
+        User user = userService.getById(getLoginUserId());
+        return R.ok(userService.setUserAuthInfo(user));
+    }
+
+    @OperationLog("Update UserInfo")
+    @PostMapping("/auth/user")
     public R updateInfo(@RequestBody User user) {
         user.setId(getLoginUserId());
-        // 涓嶈兘淇敼鐨勫瓧娈�
         user.setUsername(null);
         user.setPassword(null);
         user.setEmailVerified(null);
         user.setTenantId(null);
         user.setStatus(null);
+        if (!Cools.isEmpty(user.getEmail())) {
+            if (!emailService.isValid(user.getEmail())) {
+                return R.parse(BusinessRes.INVALID_EMAIL);
+            }
+            User one = userService.getByEmail(user.getEmail(), null);
+            if (null != one  && !one.getId().equals(user.getId())) {
+                return R.parse(BusinessRes.EMAIL_EXIT);
+            }
+        }
         if (userService.updateById(user)) {
-            return R.ok().add(userService.getByIdRel(user.getId()));
+            return R.ok("Save Success").add(userService.getById(user.getId()));
         }
         return R.error("Save Fail");
     }
 
-    @PreAuthorize("hasAuthority('sys:auth:password')")
-    @OperationLog
-    @PutMapping("/auth/password")
-    public R updatePassword(@RequestBody UpdatePasswordParam param) {
-        if (Cools.isEmpty(param.getOldPassword(), param.getPassword())) {
-            return R.error("Parameters Cannot Be Empty");
+    @OperationLog("Reset Password")
+    @PostMapping("/auth/reset/password")
+    public R resetPassword(@RequestBody UpdatePasswordParam param) {
+        if (Cools.isEmpty(param.getOldPassword(), param.getNewPassword())) {
+            return R.parse(BaseRes.PARAM);
         }
         Long userId = getLoginUserId();
         if (userId == null) {
             return R.error("Please Login First");
         }
         if (!userService.comparePassword(userService.getById(userId).getPassword(), param.getOldPassword())) {
-            return R.error("The Origin Password Was Incorrect");
+            return R.parse(BusinessRes.INVALID_PASSWORD);
         }
         User user = new User();
         user.setId(userId);
-        user.setPassword(userService.encodePassword(param.getPassword()));
+        user.setPassword(userService.encodePassword(param.getNewPassword()));
         if (userService.updateById(user)) {
-            return R.ok("Update Success");
+            return R.ok("Reset Password Success");
         }
-        return R.error("Update Fail");
+        return R.error("Reset Password Fail");
     }
 
-    @GetMapping("/system/info")
-    public R systemInfo() {
-        SystemInfoVo infoVo = new SystemInfoVo();
-        infoVo.setName(configProperties.getSystemName());
-        infoVo.setVersion(configProperties.getSystemVersion());
-        infoVo.setMode(configProperties.getSystemMode().toString());
-        return R.ok(infoVo);
-    }
+
+
 
     // ----------------------------------------------------
 
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/system/service/UserService.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/system/service/UserService.java
index 10ef2ed..44d56a0 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/system/service/UserService.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/system/service/UserService.java
@@ -19,4 +19,6 @@
 
     String encodePassword(String password);
 
+    User setUserAuthInfo(User user);
+
 }
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/system/service/impl/UserServiceImpl.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/system/service/impl/UserServiceImpl.java
index 544d67b..a8842d5 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/system/service/impl/UserServiceImpl.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/system/service/impl/UserServiceImpl.java
@@ -63,4 +63,13 @@
         return password == null ? null : bCryptPasswordEncoder.encode(password);
     }
 
+    @Override
+    public User setUserAuthInfo(User user) {
+        if (user != null) {
+            user.setRoles(userRoleService.listByUserId(user.getId()));
+            user.setAuthorities(roleMenuService.listMenuByUserId(user.getId(), null));
+        }
+        return user;
+    }
+
 }

--
Gitblit v1.9.1