From eb8ded2565e746a360985f702c556b26f750d35a Mon Sep 17 00:00:00 2001
From: skyouc
Date: 星期二, 25 三月 2025 09:07:51 +0800
Subject: [PATCH] Merge branch 'devlop' of http://47.97.1.152:5880/r/wms-master into devlop

---
 rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatPanel.jsx |  411 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 411 insertions(+), 0 deletions(-)

diff --git a/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatPanel.jsx b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatPanel.jsx
new file mode 100644
index 0000000..6ca9111
--- /dev/null
+++ b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatPanel.jsx
@@ -0,0 +1,411 @@
+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';
+
+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: 'matnrId$', headerName: translate('table.field.locAreaMatRela.matnrId'), width: 100 },
+        { field: 'groupId$', headerName: translate('table.field.locAreaMatRela.groupId'), width: 100 },
+        { field: 'locTypeId$', headerName: translate('table.field.locAreaMatRela.locTypeId'), width: 100 },
+        { field: 'locId$', headerName: translate('table.field.locAreaMatRela.locId'), 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({
+        areaMatId: record.id,
+    });
+
+    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(data || [])
+        } else {
+            notify(msg);
+        }
+    }
+
+    const requestLocType = async () => {
+        const { data: { code, data, msg } } = await request.get(`/locAreaMatRela/locType/${record.id}`);
+
+        if (code === 200) {
+            setLocTree(data || [])
+        } else {
+            notify(msg);
+        }
+    }
+
+
+    return (
+        <Grid container spacing={2}>
+            {/* 鐗╂枡鍒嗙粍 */}
+            <Grid item xs={2}>
+                <MatnrTree matnrTree={matnrTree} setParmas={setParmas} reload={reload} />
+            </Grid>
+
+            {/* 搴撲綅绫诲瀷 */}
+            <Grid item xs={2}>
+                <LocTree locTree={locTree} setParmas={setParmas} reload={reload} />
+            </Grid>
+
+            {/* 鍏朵粬鍐呭 */}
+            <Grid item xs={8}>
+                <DataGrid
+                    size="small"
+                    rows={tableData}
+                    columns={columns}
+                    checkboxSelection
+                    disableColumnMenu={true}
+                    disableColumnSorting
+                    disableMultipleColumnsSorting
+                    columnBufferPx={100}
+                />
+            </Grid>
+        </Grid>
+    );
+};
+
+export default LocAreaMatPanel;
+
+
+const MatnrTree = ({ matnrTree, 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()
+    };
+
+    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}
+                selectedItems={selectedItems}
+                getItemId={(item) => item.id}
+                getItemLabel={(item) => item.name}
+                defaultExpandedItems={['grid']}
+                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, 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.preventDefault();
+        console.log(nodeId)
+    };
+
+    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={locTree}
+                apiRef={apiRef}
+                selectedItems={selectedItems}
+                getItemId={(item) => item.id}
+                getItemLabel={(item) => item.name}
+                defaultExpandedItems={['grid']}
+                onSelectedItemsChange={handleSelectedItemsChange}
+                onItemSelectionToggle={handleItemSelectionToggle}
+                onItemClick={handleNodeSelect}
+            />
+
+            <BindLocModal
+                open={addDialog}
+                setOpen={setAddDialog}
+                selectedItems={selectedItems}
+                reload={reload}
+            />
+
+            <ConfirmModal
+                open={delectDialog}
+                setOpen={setDelectDialog}
+                onConfirm={contirmDelete}
+            />
+        </Card>
+    )
+}
\ No newline at end of file

--
Gitblit v1.9.1