import React, { useState } from "react";
|
import {
|
Table,
|
TableBody,
|
TableCell,
|
TableHead,
|
TableRow,
|
IconButton,
|
Checkbox,
|
} from "@mui/material";
|
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
|
import KeyboardArrowRightIcon from "@mui/icons-material/KeyboardArrowRight";
|
|
// 递归收集所有节点的 ID
|
const collectAllNodeIds = (nodes) => {
|
let allIds = [];
|
nodes.forEach((node) => {
|
allIds.push(node.id);
|
if (node.children) {
|
allIds = allIds.concat(collectAllNodeIds(node.children));
|
}
|
});
|
return allIds;
|
};
|
|
// 递归收集某个节点及其所有子节点的 ID
|
const collectNodeAndChildrenIds = (node) => {
|
let ids = [node.id];
|
if (node.children) {
|
node.children.forEach((child) => {
|
ids = ids.concat(collectNodeAndChildrenIds(child));
|
});
|
}
|
return ids;
|
};
|
|
// 检查某个节点的所有子节点是否都被选中
|
const areAllChildrenSelected = (node, selectedNodeIds) => {
|
const childrenIds = collectAllNodeIds(node.children || []);
|
return childrenIds.every((id) => selectedNodeIds.includes(id));
|
};
|
|
// 递归渲染树状表格行
|
const renderTreeRows = (
|
nodes,
|
level = 0,
|
openNodes,
|
setOpenNodes,
|
selectedNodeIds,
|
setSelectedNodeIds,
|
) => {
|
return nodes.map((node) => {
|
const isOpen = openNodes.includes(node.id);
|
const toggleOpen = () => {
|
if (isOpen) {
|
setOpenNodes(openNodes.filter((id) => id !== node.id));
|
} else {
|
setOpenNodes([...openNodes, node.id]);
|
}
|
};
|
|
const allChildrenIds = collectNodeAndChildrenIds(node);
|
const allChildrenSelected = allChildrenIds.every((id) =>
|
selectedNodeIds.includes(id),
|
);
|
const someChildrenSelected =
|
allChildrenIds.some((id) => selectedNodeIds.includes(id)) &&
|
!allChildrenSelected;
|
|
const handleCheckboxChange = () => {
|
let newSelectedNodeIds = [...selectedNodeIds];
|
if (allChildrenSelected) {
|
allChildrenIds.forEach((id) => {
|
newSelectedNodeIds = newSelectedNodeIds.filter(
|
(selectedId) => selectedId !== id,
|
);
|
});
|
} else {
|
allChildrenIds.forEach((id) => {
|
if (!newSelectedNodeIds.includes(id)) {
|
newSelectedNodeIds.push(id);
|
}
|
});
|
}
|
setSelectedNodeIds(newSelectedNodeIds);
|
};
|
|
return (
|
<React.Fragment key={node.id}>
|
<TableRow size="small">
|
<TableCell padding="none" width={20}>
|
{node.children && (
|
<IconButton size="small" onClick={toggleOpen}>
|
{isOpen ? (
|
<KeyboardArrowDownIcon fontSize="small" />
|
) : (
|
<KeyboardArrowRightIcon fontSize="small" />
|
)}
|
</IconButton>
|
)}
|
</TableCell>
|
<TableCell width={20} style={{ paddingLeft: 20 * level }}>
|
<Checkbox
|
size="small"
|
checked={allChildrenSelected}
|
indeterminate={someChildrenSelected}
|
onChange={handleCheckboxChange}
|
/>
|
</TableCell>
|
<TableCell>{node.matnrCode}</TableCell>
|
<TableCell>{node.fullName || node.matnrName}</TableCell>
|
<TableCell>{node.matnrGroupId}</TableCell>
|
<TableCell>{node.specification || "-"}</TableCell>
|
<TableCell>{node.color || "-"}</TableCell>
|
<TableCell>{node.size || "-"}</TableCell>
|
<TableCell>{node.minWeight || "-"}</TableCell>
|
<TableCell>{node.maxWeight || "-"}</TableCell>
|
</TableRow>
|
{isOpen &&
|
node.children &&
|
renderTreeRows(
|
node.children,
|
level + 1,
|
openNodes,
|
setOpenNodes,
|
selectedNodeIds,
|
setSelectedNodeIds,
|
)}
|
</React.Fragment>
|
);
|
});
|
};
|
|
const TreeTable = ({ data }) => {
|
const [openNodes, setOpenNodes] = useState([]);
|
const [selectedNodeIds, setSelectedNodeIds] = useState([]);
|
const allNodeIds = collectAllNodeIds(data);
|
|
const handleSelectAll = (event) => {
|
if (event.target.checked) {
|
setSelectedNodeIds(allNodeIds);
|
} else {
|
setSelectedNodeIds([]);
|
}
|
};
|
|
const isAllSelected = selectedNodeIds.length === allNodeIds.length;
|
|
return (
|
<Table size="small" style={{ backgroundColor: "#121317" }}>
|
<TableHead>
|
<TableRow size="small">
|
<TableCell width={20}></TableCell>
|
<TableCell width={20}>
|
<Checkbox
|
size="small"
|
checked={isAllSelected}
|
indeterminate={
|
selectedNodeIds.length > 0 &&
|
selectedNodeIds.length < allNodeIds.length
|
}
|
onChange={handleSelectAll}
|
/>
|
</TableCell>
|
<TableCell>物料编码</TableCell>
|
<TableCell>物料名称</TableCell>
|
<TableCell>物料分组</TableCell>
|
<TableCell>规格</TableCell>
|
<TableCell>颜色</TableCell>
|
<TableCell>尺寸</TableCell>
|
<TableCell>最小重量</TableCell>
|
<TableCell>最大重量</TableCell>
|
</TableRow>
|
</TableHead>
|
<TableBody>
|
{renderTreeRows(
|
data,
|
0,
|
openNodes,
|
setOpenNodes,
|
selectedNodeIds,
|
setSelectedNodeIds,
|
)}
|
</TableBody>
|
</Table>
|
);
|
};
|
|
export default TreeTable;
|