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