skyouc
2025-02-21 65953b12f9d667c54049c34050d39bf90556585c
Merge branch 'dev' of http://47.97.1.152:5880/r/wms-master into dev

# Conflicts:
# rsf-admin/src/page/basicInfo/matnr/MatnrListAside.jsx
3个文件已修改
2个文件已添加
1个文件已删除
20 文件已重命名
781 ■■■■ 已修改文件
rsf-admin/src/page/ResourceContent.js 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/matnr/MatnrCreate.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/matnr/MatnrEdit.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/matnr/MatnrList.jsx 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/matnr/MatnrListAside.jsx 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/matnr/MatnrPanel.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/matnr/index.jsx 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupCreate.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupEdit.jsx 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupList copy.jsx 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupList.jsx 339 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupPanel.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/matnrGroup/index.jsx 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/shipper/ShipperCreate.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/shipper/ShipperEdit.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/shipper/ShipperList.jsx 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/shipper/ShipperPanel.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/shipper/index.jsx 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/warehouse/WarehouseCreate.jsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/warehouse/WarehouseEdit.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/warehouse/WarehouseList.jsx 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/warehouse/WarehousePanel.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/basicInfo/warehouse/index.jsx 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/matnrGroup/MatnrGroupEdit.jsx 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatnrGroupController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/MatnrGroup.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/ResourceContent.js
@@ -14,10 +14,10 @@
import user from './system/user';
import operationRecord from './system/operationRecord';
import customer from './customer';
import shipper from './shipper';
import matnr from './matnr';
import matnrGroup from './matnrGroup';
import warehouse from './warehouse';
import shipper from './basicInfo/shipper';
import matnr from './basicInfo/matnr';
import matnrGroup from './basicInfo/matnrGroup';
import warehouse from './basicInfo/warehouse';
import warehouseAreas from './warehouseAreas';
import loc from './loc';
import container from './container';
rsf-admin/src/page/basicInfo/matnr/MatnrCreate.jsx
File was renamed from rsf-admin/src/page/matnr/MatnrCreate.jsx
@@ -27,9 +27,9 @@
    Grid,
    Box,
} from '@mui/material';
import DialogCloseButton from "../components/DialogCloseButton";
import StatusSelectInput from "../components/StatusSelectInput";
import MemoInput from "../components/MemoInput";
import DialogCloseButton from "@/page/components/DialogCloseButton";
import StatusSelectInput from "@/page/components/StatusSelectInput";
import MemoInput from "@/page/components/MemoInput";
const MatnrCreate = (props) => {
    const { open, setOpen } = props;
rsf-admin/src/page/basicInfo/matnr/MatnrEdit.jsx
File was renamed from rsf-admin/src/page/matnr/MatnrEdit.jsx
@@ -24,10 +24,10 @@
import { Stack, Grid, Box, Typography } from '@mui/material';
import * as Common from '@/utils/common';
import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
import EditBaseAside from "../components/EditBaseAside";
import CustomerTopToolBar from "../components/EditTopToolBar";
import MemoInput from "../components/MemoInput";
import StatusSelectInput from "../components/StatusSelectInput";
import EditBaseAside from "@/page/components/EditBaseAside";
import CustomerTopToolBar from "@/page/components/EditTopToolBar";
import MemoInput from "@/page/components/MemoInput";
import StatusSelectInput from "@/page/components/StatusSelectInput";
const FormToolbar = () => {
    const { getValues } = useFormContext();
rsf-admin/src/page/basicInfo/matnr/MatnrList.jsx
File was renamed from rsf-admin/src/page/matnr/MatnrList.jsx
@@ -36,14 +36,14 @@
import { styled } from '@mui/material/styles';
import MatnrCreate from "./MatnrCreate";
import MatnrPanel from "./MatnrPanel";
import EmptyData from "../components/EmptyData";
import MyCreateButton from "../components/MyCreateButton";
import MyExportButton from '../components/MyExportButton';
import PageDrawer from "../components/PageDrawer";
import MyField from "../components/MyField";
import EmptyData from "@/page/components/EmptyData";
import MyCreateButton from "@/page/components/MyCreateButton";
import MyExportButton from '@/page/components/MyExportButton';
import PageDrawer from "@/page/components/PageDrawer";
import MyField from "@/page/components/MyField";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import * as Common from '@/utils/common';
import ImportButton from "../components/ImportButton";
import ImportButton from "@/page/components/ImportButton";
import MatListAside from './MatnrListAside';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
@@ -143,7 +143,10 @@
                rowClick={(id, resource, record) => false}
                expand={() => <MatnrPanel />}
                expandSingle={true}
                omit={['id', 'createTime', 'createBy', 'memo']}
                omit={['id','shipperId','erpCode','spec','model','weight','color','size','describle'
                    ,'nromNum','unit','purchaseUnit','stockUnit','stockLeval','isLabelMange','safeQty'
                    ,'minQty','maxQty','stagn','valid','validWarn','flagCheck','updateTime', 'updateBy'
                    , 'createTime', 'createBy', 'memo']}
            >
                <NumberField source="id" />
                <TextField source="name" label="table.field.matnr.name" />
rsf-admin/src/page/basicInfo/matnr/MatnrListAside.jsx
File was renamed from rsf-admin/src/page/matnr/MatnrListAside.jsx
@@ -3,7 +3,15 @@
import {
    SavedQueriesList,
    FilterLiveSearch,
    useListContext,
    useNotify,
    FilterList,
    FilterListItem,
    useStore,
    FilterFormInput,
    FilterLiveForm,
    TextInput,
    useGetList,
    useListContext
} from 'react-admin';
import BookmarkIcon from '@mui/icons-material/BookmarkBorder';
import { Box, Typography, Card, CardContent, useTheme, TextField } from '@mui/material';
@@ -15,9 +23,32 @@
const MatListAside = () => {
    const theme = useTheme();
    const notify = useNotify();
    const { setFilters } = useListContext(); // 获取列表上下文
    const [selectedOption, setSelectedOption] = useState(null);
    const treeData = [
    const [treeData, setTreeData] = useState([]);
    useEffect(() => {
        request.post('/matnrGroup/tree')
            .then(res => {
                console.log('Tree Data:', res);
                if (res?.data?.code === 200) {
                    setTreeData(res.data.data);
                } else {
                    notify(res.data.msg);
                }
            })
            .catch(error => {
                notify('Error fetching tree data');
            });
    },[]);
    const treeData1 = [
        {
            id: '19',
            label: '半成品 ',
@@ -56,6 +87,9 @@
        setFilters({ groupId: nodeId });
        // 在这里可以根据 nodeId 更新主内容区域
    };
    const handleSearch = () => {
            console.log('Search Input:', selectedOption);
    };
    const CustomCheckbox = React.forwardRef(function CustomCheckbox(props, ref) {
@@ -89,7 +123,7 @@
        >
            <CardContent>
                <SavedQueriesList icon={<BookmarkIcon />} />
                <FilterLiveSearch source='condition' hiddenLabel  />
                <FilterLiveSearch source="condition"  />
                <RichTreeView
                    defaultExpandedItems={['grid', 'pickers']}
                    expansionTrigger="iconContainer"
rsf-admin/src/page/basicInfo/matnr/MatnrPanel.jsx
File was renamed from rsf-admin/src/page/matnr/MatnrPanel.jsx
@@ -4,7 +4,7 @@
    useTranslate,
    useRecordContext,
} from 'react-admin';
import PanelTypography from "../components/PanelTypography";
import PanelTypography from "@/page/components/PanelTypography";
import * as Common from '@/utils/common'
const MatnrPanel = () => {
rsf-admin/src/page/basicInfo/matnr/index.jsx
rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupCreate.jsx
File was renamed from rsf-admin/src/page/matnrGroup/MatnrGroupCreate.jsx
@@ -27,9 +27,9 @@
    Grid,
    Box,
} from '@mui/material';
import DialogCloseButton from "../components/DialogCloseButton";
import StatusSelectInput from "../components/StatusSelectInput";
import MemoInput from "../components/MemoInput";
import DialogCloseButton from "@/page/components/DialogCloseButton";
import StatusSelectInput from "@/page/components/StatusSelectInput";
import MemoInput from "@/page/components/MemoInput";
const MatnrGroupCreate = (props) => {
    const { open, setOpen } = props;
rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupEdit.jsx
New file
@@ -0,0 +1,181 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    CreateBase,
    useTranslate,
    TextInput,
    NumberInput,
    BooleanInput,
    DateInput,
    SaveButton,
    SelectInput,
    ReferenceInput,
    ReferenceArrayInput,
    AutocompleteInput,
    Toolbar,
    required,
    useNotify,
    Form,
    useUpdate,
    useCreate,
    useCreateContext,
    Labeled,
    NumberField,
    useRecordContext,
    DeleteButton,
} from 'react-admin';
import {
    Dialog,
    DialogActions,
    DialogContent,
    DialogTitle,
    Stack,
    Grid,
    Box,
} from '@mui/material';
import DialogCloseButton from "@/page/components/DialogCloseButton";
import TreeSelectInput from "@/page/components/TreeSelectInput";
import { useWatch, useFormContext } from "react-hook-form";
import * as Common from '@/utils/common';
import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
import EditBaseAside from "@/page/components/EditBaseAside";
import CustomerTopToolBar from "@/page/components/EditTopToolBar";
import MemoInput from "@/page/components/MemoInput";
import StatusSelectInput from "@/page/components/StatusSelectInput";
const EditContent = ({ editRecord }) => {
    const { resource } = useCreateContext();
    return (
        <Grid container rowSpacing={2} columnSpacing={2}>
            <Grid item xs={6} display="flex" gap={1}>
                <TreeSelectInput
                    label="table.field.matnrGroup.parentId"
                    value={editRecord?.parentId}
                    isTranslate
                    resource={resource}
                />
            </Grid>
            <Grid item xs={6} display="flex" gap={1}>
                <TextInput
                    label="table.field.matnrGroup.name"
                    source="name"
                    parse={v => v}
                    validate={required()}
                />
            </Grid>
            <Grid item xs={6} display="flex" gap={1}>
                <TextInput
                    label="table.field.matnrGroup.code"
                    source="code"
                    parse={v => v}
                />
            </Grid>
        </Grid>
    )
}
const MatnrGroupEdit = (props) => {
    const { editRecord, open, setOpen, callback, resource } = props;
    const translate = useTranslate();
    const notify = useNotify();
    const [update] = useUpdate();
    const [create] = useCreate();
    const handleClose = (event, reason) => {
        if (reason !== "backdropClick") {
            setOpen(false);
        }
    };
    const handleSuccess = async (data) => {
        setOpen(false);
        callback();
        notify('common.response.success', { type: 'info' });
    };
    const handleError = async (data) => {
        notify('common.response.fail', { type: 'error' });
    };
    const onSubmit = (data) => {
        const _params = { ...data };
        if (editRecord) {
            if (_params.parentId === editRecord.id) {
                notify('common.response.dataError', { type: 'error' });
                return;
            }
            update(
                resource,
                {
                    id: editRecord.id,
                    data: _params,
                },
                {
                    onSuccess: () => {
                        handleSuccess();
                    },
                    onError: (error) => {
                        handleError();
                    },
                }
            );
        } else {
            create(
                resource,
                { data: _params },
                {
                    onSuccess: () => {
                        handleSuccess();
                    },
                    onError: (error) => {
                        handleError();
                    },
                }
            );
        }
    };
    return (
    <>
        <CreateBase>
            <Dialog
                open={open}
                onClose={handleClose}
                aria-labelledby="form-dialog-title"
                fullWidth
                disableRestoreFocus
                maxWidth="md"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
            >
                <Form record={editRecord} onSubmit={onSubmit}>
                    <DialogTitle id="form-dialog-title" sx={{
                        position: 'sticky',
                        top: 0,
                        backgroundColor: 'background.paper',
                        zIndex: 1000
                    }}
                    >
                        {editRecord ? translate('update.title') : translate('create.title')}
                        <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
                            <DialogCloseButton onClose={handleClose} />
                        </Box>
                    </DialogTitle>
                    <DialogContent sx={{ mt: 2 }}>
                        <EditContent
                            editRecord={editRecord}
                        />
                    </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>
    </>
    )
}
export default MatnrGroupEdit;
rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupList copy.jsx
File was renamed from rsf-admin/src/page/matnrGroup/MatnrGroupList.jsx
@@ -36,11 +36,11 @@
import { styled } from '@mui/material/styles';
import MatnrGroupCreate from "./MatnrGroupCreate";
import MatnrGroupPanel from "./MatnrGroupPanel";
import EmptyData from "../components/EmptyData";
import MyCreateButton from "../components/MyCreateButton";
import MyExportButton from '../components/MyExportButton';
import PageDrawer from "../components/PageDrawer";
import MyField from "../components/MyField";
import EmptyData from "@/page/components/EmptyData";
import MyCreateButton from "@/page/components/MyCreateButton";
import MyExportButton from '@/page/components/MyExportButton';
import PageDrawer from "@/page/components/PageDrawer";
import MyField from "@/page/components/MyField";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import * as Common from '@/utils/common';
rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupList.jsx
New file
@@ -0,0 +1,339 @@
import React from 'react';
import {
    Title,
    useTranslate,
    useNotify,
    useRedirect,
    useRefresh,
    useDelete,
} from 'react-admin';
import { styled } from '@mui/material/styles';
import {
    Box,
    Collapse,
    IconButton,
    Table,
    TableBody,
    TableCell,
    TableContainer,
    TableHead,
    TableRow,
    Paper,
    Card,
    Typography,
    TextField,
    Tooltip,
    Button,
    Chip,
    LinearProgress,
} from '@mui/material';
import { Add, Edit, Delete } from '@mui/icons-material';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
import RefreshIcon from '@mui/icons-material/Refresh';
import request from '@/utils/request';
import MatnrGroupEdit from "./MatnrGroupEdit";
import * as Icons from '@mui/icons-material';
const RESOURCE = 'matnrGroup';
const TITLE = 'menu.matnrGroup';
const columns = [
    {
        id: 'name',
        label: 'table.field.matnrGroup.name',
        minWidth: 200,
    },
    {
        id: 'code',
        label: 'table.field.matnrGroup.code',
        minWidth: 80,
    },
    {
        id: 'parentId',
        label: 'table.field.matnrGroup.parentId',
        minWidth: 100,
    }
];
const getIconComponent = (iconStr) => {
    return Icons[iconStr] || null;
};
const StyledTableRow = styled(TableRow)(({ theme }) => ({
    '& .MuiButtonBase-root': {
        padding: '0px 8px'
    }
}));
const StyledTableCell = styled(TableCell)(({ theme }) => ({
    overflow: 'hidden',
    textOverflow: 'ellipsis',
    whiteSpace: 'nowrap',
    maxWidth: 600,
}));
const TreeTableRow = (props) => {
    const { row, depth = 0, openNodes, setOpenNodes, onEdit, onDelete } = props;
    const translate = useTranslate();
    const toggleNode = (id) => {
        setOpenNodes(prevState => ({ ...prevState, [id]: !prevState[id] }));
    };
    const isOpen = openNodes[row.id] || false;
    return (
        <React.Fragment>
            <StyledTableRow hover tabIndex={-1} key={row.id}>
                <StyledTableCell sx={{ padding: 0 }}>
                    {row.children && (
                        <IconButton
                            aria-label="expand row"
                            size="small"
                            onClick={() => toggleNode(row.id)}
                        >
                            {isOpen ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />}
                        </IconButton>
                    )}
                </StyledTableCell>
                {columns.map((column, idx) => {
                    if (column.id !== 'actions') {
                        let value = row[column.id];
                        if (column.id === 'name' && row['type'] === 0) {
                            value = translate(value);
                        }
                        return (
                            <StyledTableCell
                                key={column.id}
                                align={column.align || 'left'}
                                style={{
                                    paddingLeft: idx === 0 && (depth * 16 + 16),
                                    opacity: column.id === 'icon' && .6
                                }}
                                onClick={() => toggleNode(row.id)}
                            >
                                {column.format ? column.format(value) : value}
                            </StyledTableCell>
                        )
                    }
                })}
                <StyledTableCell>
                    <Tooltip title="Edit">
                        <IconButton onClick={() => onEdit(row)}>
                            <Edit />
                        </IconButton>
                    </Tooltip>
                    <Tooltip title="Delete">
                        <IconButton onClick={() => onDelete(row)}>
                            <Delete />
                        </IconButton>
                    </Tooltip>
                </StyledTableCell>
            </StyledTableRow>
            {row.children && isOpen && (
                row.children.map((child) => (
                    <TreeTableRow
                        key={child.id}
                        row={child}
                        depth={depth + 1}
                        onEdit={onEdit}
                        onDelete={onDelete}
                        openNodes={openNodes}
                        setOpenNodes={setOpenNodes}
                    />
                ))
            )}
        </React.Fragment>
    );
};
const MatnrGroupList = () => {
    const translate = useTranslate();
    const notify = useNotify();
    const redirect = useRedirect();
    const refresh = useRefresh();
    const [deleteOne] = useDelete();
    const [treeData, setTreeData] = React.useState(null);
    const [filter, setFilter] = React.useState("");
    const [createDialog, setCreateDialog] = React.useState(false);
    const [editRecord, setEditRecord] = React.useState(null);
    const [openNodes, setOpenNodes] = React.useState({});
    const [expandAll, setExpandAll] = React.useState(false);
    const http = async () => {
        const res = await request.post(RESOURCE + '/tree', {
            condition: filter
        });
        if (res?.data?.code === 200) {
            setTreeData(res.data.data);
        } else {
            notify(res.data.msg);
        }
    }
    React.useEffect(() => {
        http();
    }, [filter]);
    const handleRefresh = () => {
        http();
    };
    const handleAdd = () => {
        setEditRecord(null);
        setCreateDialog(true);
    };
    const handleEdit = (node) => {
        setEditRecord(node);
        setCreateDialog(true);
    };
    const handleDelete = (node) => {
        if (window.confirm(translate('ra.message.delete_content'))) {
            deleteOne(
                RESOURCE,
                { id: node.id },
                {
                    onSuccess: () => {
                        handleRefresh();
                        notify('Department deleted successfully', { type: 'info', messageArgs: { _: 'Department deleted successfully' } });
                    },
                    onError: (error) => {
                        notify(`Error: ${error.message}`, { type: 'warning', messageArgs: { _: `Error: ${error.message}` } });
                    },
                }
            );
        }
    };
    const toggleExpandAll = () => {
        setExpandAll(prevExpandAll => {
            const newExpandAll = !prevExpandAll;
            const newOpenNodes = {};
            const updateOpenNodes = (nodes) => {
                nodes.forEach(node => {
                    newOpenNodes[node.id] = newExpandAll;
                    if (node.children) {
                        updateOpenNodes(node.children);
                    }
                });
            };
            updateOpenNodes(treeData);
            setOpenNodes(newOpenNodes);
            return newExpandAll;
        });
    };
    return (
        <div>
            <MatnrGroupEdit
                editRecord={editRecord}
                open={createDialog}
                setOpen={setCreateDialog}
                callback={() => {
                    handleRefresh();
                }}
                resource={RESOURCE}
            />
            <Title title={TITLE} />
            <Box sx={{ mt: 2, mr: 3, mb: 1, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                <Box width={300} >
                    <Button
                        variant="outlined"
                        color="primary"
                        startIcon={expandAll ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />}
                        onClick={toggleExpandAll}
                        sx={{ ml: 1 }}
                    >
                        {expandAll ? translate('common.action.collapseAll') : translate('common.action.expandAll')}
                    </Button>
                    {/* <TextField
                        label="Search"
                        value={filter}
                        onChange={({ target }) => {
                            setFilter(target.value)
                        }}
                        variant="filled"
                        size="small"
                        margin="dense"
                        fullWidth
                    /> */}
                </Box>
                <Box>
                    <Button
                        variant="outlined"
                        color="primary"
                        startIcon={<RefreshIcon />}
                        onClick={handleRefresh}
                        sx={{ ml: 1 }}
                    >
                        {translate('ra.action.refresh')}
                    </Button>
                    <Button
                        variant="outlined"
                        color="primary"
                        startIcon={<Add />}
                        onClick={handleAdd}
                        sx={{ ml: 1 }}
                    >
                        {translate('ra.action.add')}
                    </Button>
                </Box>
            </Box>
            <Card sx={{
                position: 'relative',
            }}>
                {!treeData && (
                    <LinearProgress
                        sx={{
                            height: "3px",
                            position: 'absolute',
                            top: 0,
                            left: 0,
                            right: 0,
                        }}
                    />
                )}
                <TableContainer component={Paper}>
                    <Table size="small">
                        <TableHead>
                            <TableRow>
                                <StyledTableCell sx={{ padding: 0, width: 60 }} />
                                {columns.map((column, idx) => (
                                    <StyledTableCell
                                        key={idx}
                                        align={column.align || 'left'}
                                        style={{
                                            minWidth: column.minWidth
                                        }}
                                    >
                                        {translate(column.label)}
                                    </StyledTableCell>
                                ))}
                            </TableRow>
                        </TableHead>
                        <TableBody>
                            {treeData && treeData.length > 0 && (
                                treeData.map((row) => (
                                    <TreeTableRow
                                        key={row.id}
                                        row={row}
                                        onEdit={handleEdit}
                                        onDelete={handleDelete}
                                        openNodes={openNodes}
                                        setOpenNodes={setOpenNodes}
                                    />
                                ))
                            )}
                        </TableBody>
                    </Table>
                </TableContainer>
            </Card>
        </div>
    );
}
export default MatnrGroupList;
rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupPanel.jsx
File was renamed from rsf-admin/src/page/matnrGroup/MatnrGroupPanel.jsx
@@ -4,7 +4,7 @@
    useTranslate,
    useRecordContext,
} from 'react-admin';
import PanelTypography from "../components/PanelTypography";
import PanelTypography from "@/page/components/PanelTypography";
import * as Common from '@/utils/common'
const MatnrGroupPanel = () => {
rsf-admin/src/page/basicInfo/matnrGroup/index.jsx
rsf-admin/src/page/basicInfo/shipper/ShipperCreate.jsx
File was renamed from rsf-admin/src/page/shipper/ShipperCreate.jsx
@@ -27,9 +27,9 @@
    Grid,
    Box,
} from '@mui/material';
import DialogCloseButton from "../components/DialogCloseButton";
import StatusSelectInput from "../components/StatusSelectInput";
import MemoInput from "../components/MemoInput";
import DialogCloseButton from "@/page/components/DialogCloseButton";
import StatusSelectInput from "@/page/components/StatusSelectInput";
import MemoInput from "@/page/components/MemoInput";
const ShipperCreate = (props) => {
    const { open, setOpen } = props;
rsf-admin/src/page/basicInfo/shipper/ShipperEdit.jsx
File was renamed from rsf-admin/src/page/shipper/ShipperEdit.jsx
@@ -24,10 +24,10 @@
import { Stack, Grid, Box, Typography } from '@mui/material';
import * as Common from '@/utils/common';
import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
import EditBaseAside from "../components/EditBaseAside";
import CustomerTopToolBar from "../components/EditTopToolBar";
import MemoInput from "../components/MemoInput";
import StatusSelectInput from "../components/StatusSelectInput";
import EditBaseAside from "@/page/components/EditBaseAside";
import CustomerTopToolBar from "@/page/components/EditTopToolBar";
import MemoInput from "@/page/components/MemoInput";
import StatusSelectInput from "@/page/components/StatusSelectInput";
const FormToolbar = () => {
    const { getValues } = useFormContext();
rsf-admin/src/page/basicInfo/shipper/ShipperList.jsx
File was renamed from rsf-admin/src/page/shipper/ShipperList.jsx
@@ -36,11 +36,11 @@
import { styled } from '@mui/material/styles';
import ShipperCreate from "./ShipperCreate";
import ShipperPanel from "./ShipperPanel";
import EmptyData from "../components/EmptyData";
import MyCreateButton from "../components/MyCreateButton";
import MyExportButton from '../components/MyExportButton';
import PageDrawer from "../components/PageDrawer";
import MyField from "../components/MyField";
import EmptyData from "@/page/components/EmptyData";
import MyCreateButton from "@/page/components/MyCreateButton";
import MyExportButton from '@/page/components/MyExportButton';
import PageDrawer from "@/page/components/PageDrawer";
import MyField from "@/page/components/MyField";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import * as Common from '@/utils/common';
rsf-admin/src/page/basicInfo/shipper/ShipperPanel.jsx
File was renamed from rsf-admin/src/page/shipper/ShipperPanel.jsx
@@ -4,7 +4,7 @@
    useTranslate,
    useRecordContext,
} from 'react-admin';
import PanelTypography from "../components/PanelTypography";
import PanelTypography from "@/page/components/PanelTypography";
import * as Common from '@/utils/common'
const ShipperPanel = () => {
rsf-admin/src/page/basicInfo/shipper/index.jsx
rsf-admin/src/page/basicInfo/warehouse/WarehouseCreate.jsx
File was renamed from rsf-admin/src/page/warehouse/WarehouseCreate.jsx
@@ -27,9 +27,9 @@
    Grid,
    Box,
} from '@mui/material';
import DialogCloseButton from "../components/DialogCloseButton";
import StatusSelectInput from "../components/StatusSelectInput";
import MemoInput from "../components/MemoInput";
import DialogCloseButton from "@/page/components/DialogCloseButton";
import StatusSelectInput from "@/page/components/StatusSelectInput";
import MemoInput from "@/page/components/MemoInput";
const WarehouseCreate = (props) => {
    const { open, setOpen } = props;
rsf-admin/src/page/basicInfo/warehouse/WarehouseEdit.jsx
File was renamed from rsf-admin/src/page/warehouse/WarehouseEdit.jsx
@@ -24,10 +24,10 @@
import { Stack, Grid, Box, Typography } from '@mui/material';
import * as Common from '@/utils/common';
import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
import EditBaseAside from "../components/EditBaseAside";
import CustomerTopToolBar from "../components/EditTopToolBar";
import MemoInput from "../components/MemoInput";
import StatusSelectInput from "../components/StatusSelectInput";
import EditBaseAside from "@/page/components/EditBaseAside";
import CustomerTopToolBar from "@/page/components/EditTopToolBar";
import MemoInput from "@/page/components/MemoInput";
import StatusSelectInput from "@/page/components/StatusSelectInput";
const FormToolbar = () => {
    const { getValues } = useFormContext();
rsf-admin/src/page/basicInfo/warehouse/WarehouseList.jsx
File was renamed from rsf-admin/src/page/warehouse/WarehouseList.jsx
@@ -36,11 +36,11 @@
import { styled } from '@mui/material/styles';
import WarehouseCreate from "./WarehouseCreate";
import WarehousePanel from "./WarehousePanel";
import EmptyData from "../components/EmptyData";
import MyCreateButton from "../components/MyCreateButton";
import MyExportButton from '../components/MyExportButton';
import PageDrawer from "../components/PageDrawer";
import MyField from "../components/MyField";
import EmptyData from "@/page/components/EmptyData";
import MyCreateButton from "@/page/components/MyCreateButton";
import MyExportButton from '@/page/components/MyExportButton';
import PageDrawer from "@/page/components/PageDrawer";
import MyField from "@/page/components/MyField";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import * as Common from '@/utils/common';
rsf-admin/src/page/basicInfo/warehouse/WarehousePanel.jsx
File was renamed from rsf-admin/src/page/warehouse/WarehousePanel.jsx
@@ -4,7 +4,7 @@
    useTranslate,
    useRecordContext,
} from 'react-admin';
import PanelTypography from "../components/PanelTypography";
import PanelTypography from "@/page/components/PanelTypography";
import * as Common from '@/utils/common'
const WarehousePanel = () => {
rsf-admin/src/page/basicInfo/warehouse/index.jsx
rsf-admin/src/page/matnrGroup/MatnrGroupEdit.jsx
File was deleted
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MatnrGroupController.java
@@ -106,7 +106,7 @@
    }
    @PreAuthorize("hasAuthority('manager:matnrGroup:list')")
    @GetMapping("/matnrGroup/tree")
    @PostMapping("/matnrGroup/tree")
    public R tree() {
        List<MatnrGroup> matnrs = matnrGroupService.list(new LambdaQueryWrapper<>());
        List<MatnrGroup> treeData = Utils.toTreeData(matnrs, 0L, MatnrGroup::getParentId, MatnrGroup::getId, MatnrGroup::setChildren);
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/MatnrGroup.java
@@ -196,4 +196,8 @@
        }
    }
    public String getLabel(){
        return this.name;
    }
}