From 6867bd50c316d0d628adf35023f01c82523c66a8 Mon Sep 17 00:00:00 2001
From: verou <857149855@qq.com>
Date: 星期三, 26 三月 2025 08:03:20 +0800
Subject: [PATCH] fix:库位分区

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

diff --git a/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatPanel.jsx b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatPanel.jsx
index 311841d..330640d 100644
--- a/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatPanel.jsx
+++ b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatPanel.jsx
@@ -1,57 +1,418 @@
-import React, { useState, useRef, useEffect, useMemo } from "react";
-import { Box, Card, CardContent, Grid, Typography, Tooltip } from '@mui/material';
+import React, { useState, useRef, useEffect } from "react";
 import {
-    useTranslate,
-    useRecordContext,
-    List,
-    DatagridConfigurable,
-    SearchInput,
-    TopToolbar,
-    SelectColumnsButton,
-    EditButton,
-    FilterButton,
-    CreateButton,
-    ExportButton,
-    BulkDeleteButton,
-    WrapperField,
-    useNotify,
-    useListContext,
-    FunctionField,
-    TextField,
-    NumberField,
-    DateField,
-    BooleanField,
-    ReferenceField,
-    TextInput,
-    DateTimeInput,
-    DateInput,
-    SelectInput,
-    NumberInput,
-    ReferenceInput,
-    ReferenceArrayInput,
-    AutocompleteInput,
-    DeleteButton,
-} from 'react-admin';
-import PanelTypography from "../../components/PanelTypography";
-import * as Common from '@/utils/common'
+    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: '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({
+        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(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}>
-                1
+                <MatnrTree matnrTree={matnrTree} parmas={parmas} setParmas={setParmas} reload={reload} />
             </Grid>
-            <Grid item xs={3}>
-                2
+
+            {/* 搴撲綅绫诲瀷 */}
+            <Grid item xs={2}>
+                <LocTree locTree={locTree} parmas={parmas} setParmas={setParmas} reload={reload} />
             </Grid>
-            <Grid item xs={12}>
-                3
+
+            {/* 鍏朵粬鍐呭 */}
+            <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, 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;
+        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;
+        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={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