import React, { useState, useRef, useEffect } from "react"; 
 | 
import { 
 | 
    Grid, Card, Typography, Button, Checkbox, Tooltip, 
 | 
    IconButton, 
 | 
} from '@mui/material'; 
 | 
import { useTranslate, useRecordContext, useNotify } from 'react-admin'; 
 | 
import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; 
 | 
import { TreeItem2 } from "@mui/x-tree-view/TreeItem2"; 
 | 
import { useTreeViewApiRef } from '@mui/x-tree-view/hooks'; 
 | 
import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord'; 
 | 
import AddIcon from '@mui/icons-material/Add'; 
 | 
import DeleteIcon from '@mui/icons-material/Delete'; 
 | 
import BindMatnrModal from './BindMatnrModal'; 
 | 
import BindLocModal from './BindLocModal'; 
 | 
import ConfirmModal from "@/page/components/ConfirmModal"; 
 | 
import { DataGrid } from '@mui/x-data-grid'; 
 | 
import request from '@/utils/request'; 
 | 
import { haveChildren } from '@/utils/common'; 
 | 
  
 | 
  
 | 
const LocAreaMatPanel = () => { 
 | 
    const record = useRecordContext(); 
 | 
    if (!record) return null; 
 | 
    const translate = useTranslate(); 
 | 
    const notify = useNotify(); 
 | 
  
 | 
    const columns = [ 
 | 
        { field: 'id', headerName: 'ID', width: 100 }, 
 | 
        { field: 'areaId$', headerName: translate('table.field.locAreaMatRela.areaId'), width: 100 }, 
 | 
        { field: 'locId$', headerName: translate('table.field.locAreaMatRela.locId'), width: 100 }, 
 | 
        { field: 'locTypeId$', headerName: translate('table.field.locAreaMatRela.locTypeId'), width: 100 }, 
 | 
        { field: 'matnrId$', headerName: translate('table.field.locAreaMatRela.matnrId'), width: 100 }, 
 | 
        { field: 'groupId$', headerName: translate('table.field.locAreaMatRela.groupId'), width: 100 }, 
 | 
        { 
 | 
            field: 'action', 
 | 
            headerName: '操作', 
 | 
            minWidth: 100, 
 | 
            sticky: 'left', 
 | 
            flex: 1, 
 | 
            renderCell: (params) => ( 
 | 
                <Tooltip title="Delete"> 
 | 
                    <IconButton onClick={(e) => handleDelete(params.row, e)}> 
 | 
                        <DeleteIcon /> 
 | 
                    </IconButton> 
 | 
                </Tooltip> 
 | 
            ), 
 | 
        }, 
 | 
    ]; 
 | 
  
 | 
    const handleDelete = async (row, e) => { 
 | 
        e.stopPropagation() 
 | 
        const { data: { code, data, msg } } = await request.post(`/locAreaMatRela/remove/${row.id}`); 
 | 
  
 | 
        if (code === 200) { 
 | 
            reload() 
 | 
            notify(msg); 
 | 
        } else { 
 | 
            notify(msg); 
 | 
        } 
 | 
  
 | 
    } 
 | 
  
 | 
    const [parmas, setParmas] = useState({ 
 | 
        current: 1, 
 | 
        pageSize: 99, 
 | 
        areaMatId: record.id, 
 | 
        locTypeId: '', 
 | 
        groupId: '', 
 | 
    }); 
 | 
  
 | 
    const [tableData, setTableData] = useState([]); 
 | 
    const [matnrTree, setMatnrTree] = useState([]); 
 | 
    const [locTree, setLocTree] = useState([]); 
 | 
  
 | 
    useEffect(() => { 
 | 
        reload() 
 | 
    }, [parmas]) 
 | 
  
 | 
    const reload = () => { 
 | 
        requestTable() 
 | 
        requestMatnr() 
 | 
        requestLocType() 
 | 
    } 
 | 
  
 | 
    const requestTable = async () => { 
 | 
        const { data: { code, data, msg } } = await request.post(`/locAreaMatRela/page`, parmas); 
 | 
  
 | 
        if (code === 200) { 
 | 
            setTableData(data.records || []) 
 | 
        } else { 
 | 
            notify(msg); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    const requestMatnr = async () => { 
 | 
        const { data: { code, data, msg } } = await request.get(`/locAreaMatRela/groups/${record.id}`); 
 | 
  
 | 
        if (code === 200) { 
 | 
            setMatnrTree(haveChildren(data) || []) 
 | 
        } else { 
 | 
            notify(msg); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    const requestLocType = async () => { 
 | 
        const { data: { code, data, msg } } = await request.get(`/locAreaMatRela/locType/${record.id}`); 
 | 
  
 | 
        if (code === 200) { 
 | 
            setLocTree(haveChildren(data) || []) 
 | 
        } else { 
 | 
            notify(msg); 
 | 
        } 
 | 
    } 
 | 
  
 | 
  
 | 
    return ( 
 | 
        <Grid container spacing={2}> 
 | 
            {/* 物料分组 */} 
 | 
            <Grid item xs={2}> 
 | 
                <MatnrTree matnrTree={matnrTree} parmas={parmas} setParmas={setParmas} reload={reload} /> 
 | 
            </Grid> 
 | 
  
 | 
            {/* 库位类型 */} 
 | 
            <Grid item xs={2}> 
 | 
                <LocTree locTree={locTree} parmas={parmas} setParmas={setParmas} reload={reload} /> 
 | 
            </Grid> 
 | 
  
 | 
            {/* 其他内容 */} 
 | 
            <Grid item xs={8}> 
 | 
                <DataGrid 
 | 
                    size="small" 
 | 
                    rows={tableData} 
 | 
                    columns={columns} 
 | 
                    checkboxSelection 
 | 
                    disableColumnMenu={true} 
 | 
                    disableColumnSorting 
 | 
                    disableMultipleColumnsSorting 
 | 
                    initialState={{ 
 | 
                        pagination: { 
 | 
                            paginationModel: { 
 | 
                                pageSize: 10, 
 | 
                            }, 
 | 
                        }, 
 | 
                    }} 
 | 
                    pageSizeOptions={[10]} 
 | 
                /> 
 | 
            </Grid> 
 | 
        </Grid> 
 | 
    ); 
 | 
}; 
 | 
  
 | 
export default LocAreaMatPanel; 
 | 
  
 | 
  
 | 
const MatnrTree = ({ matnrTree, parmas, setParmas, reload }) => { 
 | 
  
 | 
    const record = useRecordContext(); 
 | 
    const notify = useNotify(); 
 | 
  
 | 
    function getItemDescendantsIds(item) { 
 | 
        const ids = []; 
 | 
        item.children?.forEach((child) => { 
 | 
            ids.push(child.id); 
 | 
            ids.push(...getItemDescendantsIds(child)); 
 | 
        }); 
 | 
  
 | 
        return ids; 
 | 
    } 
 | 
  
 | 
    const [selectedItems, setSelectedItems] = useState([]); 
 | 
    const toggledItemRef = useRef({}); 
 | 
    const apiRef = useTreeViewApiRef(); 
 | 
  
 | 
    const handleItemSelectionToggle = (event, itemId, isSelected) => { 
 | 
        event.stopPropagation() 
 | 
        event.preventDefault(); 
 | 
        toggledItemRef.current[itemId] = isSelected; 
 | 
    }; 
 | 
  
 | 
    const handleSelectedItemsChange = (event, newSelectedItems) => { 
 | 
        event.stopPropagation() 
 | 
        event.preventDefault(); 
 | 
        setSelectedItems(newSelectedItems); 
 | 
  
 | 
        const itemsToSelect = []; 
 | 
        const itemsToUnSelect = {}; 
 | 
        Object.entries(toggledItemRef.current).forEach(([itemId, isSelected]) => { 
 | 
            const item = apiRef.current.getItem(itemId); 
 | 
            if (isSelected) { 
 | 
                itemsToSelect.push(...getItemDescendantsIds(item)); 
 | 
            } else { 
 | 
                getItemDescendantsIds(item).forEach((descendantId) => { 
 | 
                    itemsToUnSelect[descendantId] = true; 
 | 
                }); 
 | 
            } 
 | 
        }); 
 | 
  
 | 
        const newSelectedItemsWithChildren = Array.from( 
 | 
            new Set( 
 | 
                [...newSelectedItems, ...itemsToSelect].filter( 
 | 
                    (itemId) => !itemsToUnSelect[itemId], 
 | 
                ), 
 | 
            ), 
 | 
        ); 
 | 
  
 | 
        setSelectedItems(newSelectedItemsWithChildren); 
 | 
  
 | 
        toggledItemRef.current = {}; 
 | 
    }; 
 | 
  
 | 
    const [addDialog, setAddDialog] = useState(false); 
 | 
    const [delectDialog, setDelectDialog] = useState(false); 
 | 
  
 | 
  
 | 
    const handleDelete = () => { 
 | 
        if (selectedItems.length > 0) { 
 | 
            setDelectDialog(true) 
 | 
        } else { 
 | 
            notify('请选择物料分组'); 
 | 
        } 
 | 
  
 | 
    }; 
 | 
  
 | 
    const contirmDelete = async () => { 
 | 
        const parmas = { 
 | 
            aeaMatId: record.id, 
 | 
            groupId: selectedItems 
 | 
        } 
 | 
  
 | 
        const res = await request.post(`/locAreaMatRela/group/remove`, parmas); 
 | 
        if (res?.data?.code === 200) { 
 | 
            reload() 
 | 
            notify(res.data.msg); 
 | 
  
 | 
        } else { 
 | 
            notify(res.data.msg); 
 | 
        } 
 | 
  
 | 
    }; 
 | 
  
 | 
    const handleAdd = () => { 
 | 
        setAddDialog(true) 
 | 
  
 | 
    }; 
 | 
  
 | 
    const handleNodeSelect = (event, nodeId) => { 
 | 
        event.stopPropagation(); 
 | 
        parmas.groupId = nodeId; 
 | 
        parmas.locTypeId = ''; 
 | 
        setParmas(parmas) 
 | 
        reload() 
 | 
    }; 
 | 
  
 | 
    return ( 
 | 
        <Card sx={{ p: 1 }}> 
 | 
            <div style={{ display: 'flex', justifyContent: 'space-between', paddingBottom: '3px', marginBottom: '3px', borderBottom: '1px dashed #d4d4d4' }}> 
 | 
                <div style={{ fontSize: '17px' }}>物料分组</div> 
 | 
                {/* <div style={{ display: 'flex', alignItems: 'center', gap: '3px' }}> 
 | 
                    <AddIcon color={'info'} sx={{ cursor: 'pointer' }} onClick={() => handleAdd()} /> 
 | 
  
 | 
                    <DeleteIcon color={'warning'} sx={{ cursor: 'pointer' }} onClick={() => handleDelete()} /> 
 | 
                </div> */} 
 | 
            </div> 
 | 
  
 | 
            <RichTreeView 
 | 
                expansionTrigger="iconContainer" 
 | 
                // checkboxSelection 
 | 
                // multiSelect 
 | 
                items={matnrTree} 
 | 
                apiRef={apiRef} 
 | 
                getItemId={(item) => item.id} 
 | 
                getItemLabel={(item) => item.name} 
 | 
                defaultExpandedItems={['grid']} 
 | 
                selectedItems={selectedItems} 
 | 
                onSelectedItemsChange={handleSelectedItemsChange} 
 | 
                onItemSelectionToggle={handleItemSelectionToggle} 
 | 
                onItemClick={handleNodeSelect} 
 | 
            /> 
 | 
  
 | 
            <BindMatnrModal 
 | 
                open={addDialog} 
 | 
                setOpen={setAddDialog} 
 | 
                selectedItems={selectedItems} 
 | 
                reload={reload} 
 | 
            /> 
 | 
  
 | 
            <ConfirmModal 
 | 
                open={delectDialog} 
 | 
                setOpen={setDelectDialog} 
 | 
                onConfirm={contirmDelete} 
 | 
            /> 
 | 
        </Card> 
 | 
    ) 
 | 
} 
 | 
  
 | 
const LocTree = ({ locTree, setParmas, parmas, reload }) => { 
 | 
  
 | 
    const record = useRecordContext(); 
 | 
    const notify = useNotify(); 
 | 
  
 | 
    function getItemDescendantsIds(item) { 
 | 
        const ids = []; 
 | 
        item.children?.forEach((child) => { 
 | 
            ids.push(child.id); 
 | 
            ids.push(...getItemDescendantsIds(child)); 
 | 
        }); 
 | 
  
 | 
        return ids; 
 | 
    } 
 | 
  
 | 
    const [selectedItems, setSelectedItems] = useState([]); 
 | 
    const toggledItemRef = useRef({}); 
 | 
    const apiRef = useTreeViewApiRef(); 
 | 
  
 | 
    const handleItemSelectionToggle = (event, itemId, isSelected) => { 
 | 
        toggledItemRef.current[itemId] = isSelected; 
 | 
    }; 
 | 
  
 | 
    const handleSelectedItemsChange = (event, newSelectedItems) => { 
 | 
        setSelectedItems(newSelectedItems); 
 | 
  
 | 
        const itemsToSelect = []; 
 | 
        const itemsToUnSelect = {}; 
 | 
        Object.entries(toggledItemRef.current).forEach(([itemId, isSelected]) => { 
 | 
            const item = apiRef.current.getItem(itemId); 
 | 
            if (isSelected) { 
 | 
                itemsToSelect.push(...getItemDescendantsIds(item)); 
 | 
            } else { 
 | 
                getItemDescendantsIds(item).forEach((descendantId) => { 
 | 
                    itemsToUnSelect[descendantId] = true; 
 | 
                }); 
 | 
            } 
 | 
        }); 
 | 
  
 | 
        const newSelectedItemsWithChildren = Array.from( 
 | 
            new Set( 
 | 
                [...newSelectedItems, ...itemsToSelect].filter( 
 | 
                    (itemId) => !itemsToUnSelect[itemId], 
 | 
                ), 
 | 
            ), 
 | 
        ); 
 | 
  
 | 
        setSelectedItems(newSelectedItemsWithChildren); 
 | 
  
 | 
        toggledItemRef.current = {}; 
 | 
    }; 
 | 
  
 | 
    const [addDialog, setAddDialog] = useState(false); 
 | 
    const [delectDialog, setDelectDialog] = useState(false); 
 | 
  
 | 
  
 | 
    const handleDelete = () => { 
 | 
        if (selectedItems.length > 0) { 
 | 
            setDelectDialog(true) 
 | 
        } else { 
 | 
            notify('请选择库位类型'); 
 | 
        } 
 | 
  
 | 
    }; 
 | 
  
 | 
    const contirmDelete = async () => { 
 | 
        const parmas = { 
 | 
            areaMatId: record.id, 
 | 
            typeId: selectedItems 
 | 
        } 
 | 
  
 | 
        const res = await request.post(`/locAreaMatRela/locType/remove`, parmas); 
 | 
        if (res?.data?.code === 200) { 
 | 
            reload() 
 | 
            notify(res.data.msg); 
 | 
  
 | 
        } else { 
 | 
            notify(res.data.msg); 
 | 
        } 
 | 
  
 | 
    }; 
 | 
  
 | 
    const handleAdd = () => { 
 | 
        setAddDialog(true) 
 | 
  
 | 
    }; 
 | 
  
 | 
    const handleNodeSelect = (event, nodeId) => { 
 | 
        event.stopPropagation(); 
 | 
        parmas.locTypeId = nodeId; 
 | 
        parmas.groupId = ''; 
 | 
        setParmas(parmas) 
 | 
        reload() 
 | 
    }; 
 | 
  
 | 
    return ( 
 | 
        <Card sx={{ p: 1 }}> 
 | 
            <div style={{ display: 'flex', justifyContent: 'space-between', paddingBottom: '3px', marginBottom: '3px', borderBottom: '1px dashed #d4d4d4' }}> 
 | 
                <div style={{ fontSize: '17px' }}>库位类型</div> 
 | 
                {/* <div style={{ display: 'flex', alignItems: 'center', gap: '3px' }}> 
 | 
                    <AddIcon color={'info'} sx={{ cursor: 'pointer' }} onClick={() => handleAdd()} /> 
 | 
  
 | 
                    <DeleteIcon color={'warning'} sx={{ cursor: 'pointer' }} onClick={() => handleDelete()} /> 
 | 
                </div> */} 
 | 
            </div> 
 | 
  
 | 
            <RichTreeView 
 | 
                expansionTrigger="iconContainer" 
 | 
                items={locTree} 
 | 
                apiRef={apiRef} 
 | 
                getItemId={(item) => item.id} 
 | 
                getItemLabel={(item) => item.name} 
 | 
                defaultExpandedItems={['grid']} 
 | 
                onItemClick={handleNodeSelect} 
 | 
                onItemSelectionToggle={handleItemSelectionToggle} 
 | 
                // checkboxSelection 
 | 
                // multiSelect 
 | 
                selectedItems={selectedItems} 
 | 
                onSelectedItemsChange={handleSelectedItemsChange} 
 | 
            /> 
 | 
  
 | 
            <BindLocModal 
 | 
                open={addDialog} 
 | 
                setOpen={setAddDialog} 
 | 
                selectedItems={selectedItems} 
 | 
                reload={reload} 
 | 
            /> 
 | 
  
 | 
            <ConfirmModal 
 | 
                open={delectDialog} 
 | 
                setOpen={setDelectDialog} 
 | 
                onConfirm={contirmDelete} 
 | 
            /> 
 | 
        </Card> 
 | 
    ) 
 | 
} 
 |