zjj
9 天以前 eab76cd34bff799686f68e6b70f86c9001e4913f
rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupList.jsx
@@ -1,156 +1,357 @@
import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
import { useNavigate } from 'react-router-dom';
import React from 'react';
import {
    List,
    DatagridConfigurable,
    SearchInput,
    TopToolbar,
    SelectColumnsButton,
    EditButton,
    FilterButton,
    CreateButton,
    ExportButton,
    BulkDeleteButton,
    WrapperField,
    useRecordContext,
    Title,
    useTranslate,
    useNotify,
    useListContext,
    FunctionField,
    TextField,
    NumberField,
    DateField,
    BooleanField,
    ReferenceField,
    TextInput,
    DateTimeInput,
    DateInput,
    SelectInput,
    NumberInput,
    ReferenceInput,
    ReferenceArrayInput,
    AutocompleteInput,
    DeleteButton,
    useRedirect,
    useRefresh,
    useDelete,
} from 'react-admin';
import { Box, Typography, Card, Stack } from '@mui/material';
import { styled } from '@mui/material/styles';
import MatnrGroupCreate from "./MatnrGroupCreate";
import MatnrGroupPanel from "./MatnrGroupPanel";
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 {
    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 StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
        height: '.9em'
const RESOURCE = 'matnrGroup';
const TITLE = 'menu.matnrGroup';
const columns = [
    {
        id: 'code',
        label: 'table.field.matnrGroup.code',
        minWidth: 80,
    },
    '& .RaDatagrid-row': {
        cursor: 'auto'
    {
        id: 'name',
        label: 'table.field.matnrGroup.name',
        Width: 100,
    },
    '& .column-name': {
    },
    '& .opt': {
        width: 200
    },
    {
        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 filters = [
    <SearchInput source="condition" alwaysOn />,
    <DateInput label='common.time.after' source="timeStart" alwaysOn />,
    <DateInput label='common.time.before' source="timeEnd" alwaysOn />,
const StyledTableCell = styled(TableCell)(({ theme }) => ({
    overflow: 'hidden',
    textOverflow: 'ellipsis',
    whiteSpace: 'nowrap',
    maxWidth: 600,
}));
    <TextInput source="name" label="table.field.matnrGroup.name" />,
    <TextInput source="code" label="table.field.matnrGroup.code" />,
    <NumberInput source="parentId" label="table.field.matnrGroup.parentId" />,
const TreeTableRow = (props) => {
    const { row, depth = 0, openNodes, setOpenNodes, onEdit, onDelete } = props;
    const translate = useTranslate();
    <TextInput label="common.field.memo" source="memo" />,
    <SelectInput
        label="common.field.status"
        source="status"
        choices={[
            { id: '1', name: 'common.enums.statusTrue' },
            { id: '0', name: 'common.enums.statusFalse' },
        ]}
        resettable
    />,
]
    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 [createDialog, setCreateDialog] = useState(false);
    const [drawerVal, setDrawerVal] = useState(false);
    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(true);
    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;
        });
    };
    // 初始化 openNodes 以展开所有节点
    React.useEffect(() => {
        if (treeData) {
            const newOpenNodes = {};
            const updateOpenNodes = (nodes) => {
                nodes.forEach(node => {
                    newOpenNodes[node.id] = true;
                    if (node.children) {
                        updateOpenNodes(node.children);
                    }
                });
            };
            updateOpenNodes(treeData);
            setOpenNodes(newOpenNodes);
        }
    }, [treeData]);
    return (
        <Box display="flex">
            <List
                sx={{
                    flexGrow: 1,
                    transition: (theme) =>
                        theme.transitions.create(['all'], {
                            duration: theme.transitions.duration.enteringScreen,
                        }),
                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                }}
                title={"menu.matnrGroup"}
                empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
                filters={filters}
                sort={{ field: "create_time", order: "desc" }}
                actions={(
                    <TopToolbar>
                        <FilterButton />
                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
                        <SelectColumnsButton preferenceKey='matnrGroup' />
                        <MyExportButton />
                    </TopToolbar>
                )}
                perPage={DEFAULT_PAGE_SIZE}
            >
                <StyledDatagrid
                    preferenceKey='matnrGroup'
                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                    rowClick={(id, resource, record) => false}
                    expand={() => <MatnrGroupPanel />}
                    expandSingle={true}
                    omit={['id', 'createTime', 'createBy', 'memo']}
                >
                    <NumberField source="id" />
                    <TextField source="name" label="table.field.matnrGroup.name" />
                    <TextField source="code" label="table.field.matnrGroup.code" />
                    <NumberField source="parentId" label="table.field.matnrGroup.parentId" />
                    <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}>
                        <TextField source="nickname" />
                    </ReferenceField>
                    <DateField source="updateTime" label="common.field.updateTime" showTime />
                    <ReferenceField source="createBy" label="common.field.createBy" reference="user" link={false} sortable={false}>
                        <TextField source="nickname" />
                    </ReferenceField>
                    <DateField source="createTime" label="common.field.createTime" showTime />
                    <BooleanField source="statusBool" label="common.field.status" sortable={false} />
                    <TextField source="memo" label="common.field.memo" sortable={false} />
                    <WrapperField cellClassName="opt" label="common.field.opt">
                        <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} />
                        <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} />
                    </WrapperField>
                </StyledDatagrid>
            </List>
            <MatnrGroupCreate
        <div>
            <MatnrGroupEdit
                editRecord={editRecord}
                open={createDialog}
                setOpen={setCreateDialog}
                callback={() => {
                    handleRefresh();
                }}
                resource={RESOURCE}
            />
            <PageDrawer
                title='MatnrGroup Detail'
                drawerVal={drawerVal}
                setDrawerVal={setDrawerVal}
            >
            </PageDrawer>
        </Box>
    )
            <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="搜索名称"
                        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;
export default MatnrGroupList;