From b2835c4388aa4abdbd41a7ab7592eb1a1804947a Mon Sep 17 00:00:00 2001 From: verou <857149855@qq.com> Date: 星期一, 24 三月 2025 16:12:21 +0800 Subject: [PATCH] feat:逻辑分区 --- rsf-admin/src/page/basicInfo/loc/BindModal.jsx | 2 rsf-admin/src/page/basicInfo/locAreaMat/BindLocModal.jsx | 220 +++++++++++++ rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatList.jsx | 4 rsf-admin/src/page/components/ConfirmModal.jsx | 50 +++ rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatCreate.jsx | 4 rsf-admin/src/page/basicInfo/matnr/MatnrList.jsx | 2 rsf-admin/src/page/basicInfo/locAreaMat/BindMatnrModal.jsx | 216 +++++++++++++ rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatEdit.jsx | 4 rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatPanel.jsx | 434 ++++++++++++++++++++++++-- 9 files changed, 887 insertions(+), 49 deletions(-) diff --git a/rsf-admin/src/page/basicInfo/loc/BindModal.jsx b/rsf-admin/src/page/basicInfo/loc/BindModal.jsx index 0a8145f..04cd607 100644 --- a/rsf-admin/src/page/basicInfo/loc/BindModal.jsx +++ b/rsf-admin/src/page/basicInfo/loc/BindModal.jsx @@ -41,8 +41,6 @@ IconButton, styled, - - } from '@mui/material'; import DialogCloseButton from "../../components/DialogCloseButton"; import DictionarySelect from "../../components/DictionarySelect"; diff --git a/rsf-admin/src/page/basicInfo/locAreaMat/BindLocModal.jsx b/rsf-admin/src/page/basicInfo/locAreaMat/BindLocModal.jsx new file mode 100644 index 0000000..07f22b4 --- /dev/null +++ b/rsf-admin/src/page/basicInfo/locAreaMat/BindLocModal.jsx @@ -0,0 +1,220 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { + CreateBase, + useTranslate, + TextInput, + NumberInput, + BooleanInput, + DateInput, + SaveButton, + SelectInput, + ReferenceInput, + ReferenceArrayInput, + AutocompleteInput, + Toolbar, + required, + useDataProvider, + useNotify, + Form, + useCreateController, + useListContext, + useRefresh, + SelectArrayInput, + useRecordContext, + +} from 'react-admin'; +import { + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Grid, + TextField, + Box, + Button, + Paper, + TableContainer, + Table, + TableHead, + TableBody, + TableRow, + TableCell, + Tooltip, + IconButton, + styled, + +} from '@mui/material'; +import DialogCloseButton from "../../components/DialogCloseButton"; +import DictionarySelect from "../../components/DictionarySelect"; +import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form"; +import SaveIcon from '@mui/icons-material/Save'; +import request from '@/utils/request'; +import { Add, Edit, Delete } from '@mui/icons-material'; +import _ from 'lodash'; +import { DataGrid } from '@mui/x-data-grid'; +import StatusSelectInput from "../../components/StatusSelectInput"; +import TreeSelectInput from "@/page/components/TreeSelectInput"; +const BindMatnrModal = ({ open, setOpen, reload }) => { + const refresh = useRefresh(); + const translate = useTranslate(); + const record = useRecordContext(); + + const notify = useNotify(); + + const [formData, setFormData] = useState({ + areaId: null, + warehouseId: null, + matnrId: null, + typeId: null, + }); + + + const handleClose = (event, reason) => { + if (reason !== "backdropClick") { + setOpen(false); + reset() + } + }; + + const reset = () => { + setFormData({ + areaId: null, + matnrId: null, + warehouseId: null, + typeId: null, + }) + } + + + const handleChange = (value, name) => { + setFormData((prevData) => ({ + ...prevData, + [name]: value + })); + refresh() + }; + + const removeEmptyKeys = (obj) => { + return _.pickBy(obj, (value) => { + if (_.isObject(value)) { + const newObj = removeEmptyKeys(value); + return !_.isEmpty(newObj); + } + return !_.isNil(value) && (_.isNumber(value) ? value !== 0 : !_.isEmpty(value)); + }); + } + + const handleSubmit = async () => { + const parmas = { + areaMatId: record.id, + matnrId: formData.matnrId, + areaId: formData.areaId, + warehouseId: formData.warehouseId, + typeId: formData.typeId, + } + + + const res = await request.post(`/locAreaMatRela/matnr/bind`, parmas); + if (res?.data?.code === 200) { + handleClose() + reload() + + } else { + notify(res.data.msg); + } + } + + const [groupId, setGroupId] = useState(); + + const warehouseChange = (e) => { + setGroupId(e.target.value) + } + + return ( + <Dialog open={open} maxWidth="md" fullWidth> + <Form onSubmit={handleSubmit}> + <DialogCloseButton onClose={handleClose} /> + <DialogTitle>{translate('toolbar.bindmatnr')}</DialogTitle> + <DialogContent sx={{ mt: 2 }}> + <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}> + <Grid container spacing={2}> + <Grid item xs={4}> + <ReferenceInput + source="warehouseId" + reference="warehouse" + > + <AutocompleteInput + label="table.field.loc.warehouseId" + optionText="name" + onChange={(value) => handleChange(value, 'warehouseId')} + value={formData.warehouseId} + validate={required()} + filterToQuery={(val) => ({ name: val })} + /> + </ReferenceInput> + + </Grid> + + <Grid item xs={4}> + <ReferenceInput + source="areaId" + reference="warehouseAreas" + > + <AutocompleteInput + label="table.field.loc.areaId" + optionText="name" + onChange={(value) => handleChange(value, 'areaId')} + value={formData.areaId} + validate={required()} + filterToQuery={(val) => ({ name: val })} + /> + </ReferenceInput> + + </Grid> + + <Grid item xs={4}> + <ReferenceArrayInput source="typeId" reference="locType" > + <SelectArrayInput + label="table.field.locAreaMatRela.locTypeId" + validate={required()} + optionText={'name'} + value={formData.typeId} + onChange={(e) => handleChange(e.target.value, 'typeId')} + /> + </ReferenceArrayInput> + + </Grid> + + + <Grid item xs={4}> + <ReferenceArrayInput source="matnrId" reference="matnr" filter={{ groupId: formData.groupId }}> + <SelectArrayInput + label="table.field.locAreaMatRela.matnrId" + validate={required()} + value={formData.matnrId} + onChange={(e) => handleChange(e.target.value, 'matnrId')} + /> + </ReferenceArrayInput> + </Grid> + + + + + + </Grid> + + </Box> + </DialogContent> + <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> + <Box sx={{ width: '100%', display: 'flex', justifyContent: 'space-between' }}> + <Button type="submit" variant="contained" startIcon={<SaveIcon />}> + {translate('toolbar.confirm')} + </Button> + </Box> + </DialogActions> + </Form> + </Dialog> + ); +} + +export default BindMatnrModal; \ No newline at end of file diff --git a/rsf-admin/src/page/basicInfo/locAreaMat/BindMatnrModal.jsx b/rsf-admin/src/page/basicInfo/locAreaMat/BindMatnrModal.jsx new file mode 100644 index 0000000..9523f61 --- /dev/null +++ b/rsf-admin/src/page/basicInfo/locAreaMat/BindMatnrModal.jsx @@ -0,0 +1,216 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { + CreateBase, + useTranslate, + TextInput, + NumberInput, + BooleanInput, + DateInput, + SaveButton, + SelectInput, + ReferenceInput, + ReferenceArrayInput, + AutocompleteInput, + Toolbar, + required, + useDataProvider, + useNotify, + Form, + useCreateController, + useListContext, + useRefresh, + SelectArrayInput, + useRecordContext, + +} from 'react-admin'; +import { + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Grid, + TextField, + Box, + Button, + Paper, + TableContainer, + Table, + TableHead, + TableBody, + TableRow, + TableCell, + Tooltip, + IconButton, + styled, + +} from '@mui/material'; +import DialogCloseButton from "../../components/DialogCloseButton"; +import DictionarySelect from "../../components/DictionarySelect"; +import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form"; +import SaveIcon from '@mui/icons-material/Save'; +import request from '@/utils/request'; +import { Add, Edit, Delete } from '@mui/icons-material'; +import _ from 'lodash'; +import { DataGrid } from '@mui/x-data-grid'; +import StatusSelectInput from "../../components/StatusSelectInput"; +import TreeSelectInput from "@/page/components/TreeSelectInput"; +const BindMatnrModal = ({ open, setOpen, reload }) => { + const refresh = useRefresh(); + const translate = useTranslate(); + const record = useRecordContext(); + + const notify = useNotify(); + + const [formData, setFormData] = useState({ + areaId: null, + warehouseId: null, + groupId: null, + locId: null, + }); + + + const handleClose = (event, reason) => { + if (reason !== "backdropClick") { + setOpen(false); + reset() + } + }; + + const reset = () => { + setFormData({ + areaId: null, + warehouseId: null, + groupId: null, + locId: null, + }) + } + + + const handleChange = (value, name) => { + setFormData((prevData) => ({ + ...prevData, + [name]: value + })); + refresh() + }; + + const removeEmptyKeys = (obj) => { + return _.pickBy(obj, (value) => { + if (_.isObject(value)) { + const newObj = removeEmptyKeys(value); + return !_.isEmpty(newObj); + } + return !_.isNil(value) && (_.isNumber(value) ? value !== 0 : !_.isEmpty(value)); + }); + } + + const handleSubmit = async () => { + const parmas = { + areaMatId: record.id, + groupId: [formData.groupId], + areaId: formData.areaId, + warehouseId: formData.warehouseId, + locId: formData.locId, + } + + + const res = await request.post(`/locAreaMatRela/matnr/bind`, parmas); + if (res?.data?.code === 200) { + handleClose() + reload() + + } else { + notify(res.data.msg); + } + } + + const [groupId, setGroupId] = useState(); + + const warehouseChange = (e) => { + setGroupId(e.target.value) + } + + return ( + <Dialog open={open} maxWidth="md" fullWidth> + <Form onSubmit={handleSubmit}> + <DialogCloseButton onClose={handleClose} /> + <DialogTitle>{translate('toolbar.bindloc')}</DialogTitle> + <DialogContent sx={{ mt: 2 }}> + <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}> + <Grid container spacing={2}> + <Grid item xs={4}> + <ReferenceInput + source="warehouseId" + reference="warehouse" + > + <AutocompleteInput + label="table.field.loc.warehouseId" + optionText="name" + onChange={(value) => handleChange(value, 'warehouseId')} + value={formData.warehouseId} + validate={required()} + filterToQuery={(val) => ({ name: val })} + /> + </ReferenceInput> + </Grid> + + <Grid item xs={4}> + <ReferenceInput + source="areaId" + reference="warehouseAreas" + > + <AutocompleteInput + label="table.field.loc.areaId" + optionText="name" + onChange={(value) => handleChange(value, 'areaId')} + value={formData.areaId} + validate={required()} + filterToQuery={(val) => ({ name: val })} + /> + </ReferenceInput> + + </Grid> + + <Grid item xs={4}> + <TreeSelectInput + label="table.field.locAreaMatRela.groupId" + resource={'matnrGroup'} + source="groupId" + value={formData.groupId} + onChange={(e) => handleChange(e.target.value, 'groupId')} + /> + </Grid> + + + + + <Grid item xs={4}> + <ReferenceArrayInput source="locId" reference="loc" > + <SelectArrayInput + label="table.field.locAreaMatRela.locId" + validate={required()} + optionText={'code'} + value={formData.locId} + onChange={(e) => handleChange(e.target.value, 'locId')} + /> + </ReferenceArrayInput> + + </Grid> + + </Grid> + + </Box> + </DialogContent> + <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> + <Box sx={{ width: '100%', display: 'flex', justifyContent: 'space-between' }}> + <Button type="submit" variant="contained" startIcon={<SaveIcon />}> + {translate('toolbar.confirm')} + </Button> + </Box> + </DialogActions> + </Form> + </Dialog> + ); +} + +export default BindMatnrModal; \ No newline at end of file diff --git a/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatCreate.jsx b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatCreate.jsx index b0446fe..9f726dc 100644 --- a/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatCreate.jsx +++ b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatCreate.jsx @@ -92,7 +92,7 @@ autoFocus /> </Grid> - <Grid item xs={6} display="flex" gap={1}> + {/* <Grid item xs={6} display="flex" gap={1}> <NumberInput label="table.field.locAreaMat.warehouseId" source="warehouseId" @@ -103,7 +103,7 @@ label="table.field.locAreaMat.areaId" source="areaId" /> - </Grid> + </Grid> */} <Grid item xs={6} display="flex" gap={1}> <TextInput label="table.field.locAreaMat.depict" diff --git a/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatEdit.jsx b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatEdit.jsx index ca29be5..752dbfd 100644 --- a/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatEdit.jsx +++ b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatEdit.jsx @@ -71,7 +71,7 @@ autoFocus /> </Stack> - <Stack direction='row' gap={2}> + {/* <Stack direction='row' gap={2}> <NumberInput label="table.field.locAreaMat.warehouseId" source="warehouseId" @@ -82,7 +82,7 @@ label="table.field.locAreaMat.areaId" source="areaId" /> - </Stack> + </Stack> */} <Stack direction='row' gap={2}> <TextInput label="table.field.locAreaMat.depict" diff --git a/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatList.jsx b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatList.jsx index b5d2ac1..a27e68c 100644 --- a/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatList.jsx +++ b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatList.jsx @@ -119,8 +119,8 @@ > <NumberField source="id" /> <TextField source="code" label="table.field.locAreaMat.code" /> - <NumberField source="warehouseId" label="table.field.locAreaMat.warehouseId" /> - <NumberField source="areaId" label="table.field.locAreaMat.areaId" /> + {/* <NumberField source="warehouseId" label="table.field.locAreaMat.warehouseId" /> + <NumberField source="areaId" label="table.field.locAreaMat.areaId" /> */} <TextField source="depict" label="table.field.locAreaMat.depict" /> <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}> diff --git a/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatPanel.jsx b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatPanel.jsx index 311841d..6ca9111 100644 --- a/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatPanel.jsx +++ b/rsf-admin/src/page/basicInfo/locAreaMat/LocAreaMatPanel.jsx @@ -1,57 +1,411 @@ -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: '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}> - 1 + <MatnrTree matnrTree={matnrTree} setParmas={setParmas} reload={reload} /> </Grid> - <Grid item xs={3}> - 2 + + {/* 搴撲綅绫诲瀷 */} + <Grid item xs={2}> + <LocTree locTree={locTree} 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, 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 diff --git a/rsf-admin/src/page/basicInfo/matnr/MatnrList.jsx b/rsf-admin/src/page/basicInfo/matnr/MatnrList.jsx index 23079ee..5dc0c6c 100644 --- a/rsf-admin/src/page/basicInfo/matnr/MatnrList.jsx +++ b/rsf-admin/src/page/basicInfo/matnr/MatnrList.jsx @@ -86,7 +86,7 @@ overflow: 'hidden', textOverflow: 'ellipsis', display: 'block', - width: '100px', + width: '300px', }, '& .RaDatagrid-table': { width: '100%' diff --git a/rsf-admin/src/page/components/ConfirmModal.jsx b/rsf-admin/src/page/components/ConfirmModal.jsx new file mode 100644 index 0000000..118cab1 --- /dev/null +++ b/rsf-admin/src/page/components/ConfirmModal.jsx @@ -0,0 +1,50 @@ +import React, { useState, useRef, useEffect, useMemo, useCallback } from "react"; +import { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from '@mui/material'; +import { + useTranslate, +} from 'react-admin'; + +const ConfirmModal = (props) => { + const { open, onConfirm, setOpen } = props; + const translate = useTranslate(); + + + + const handleClose = (event) => { + event.stopPropagation(); + setOpen(false); + }; + + const handleConfirm = (event) => { + handleClose(event); + onConfirm(); + }; + + return ( + <> + <Dialog + aria-labelledby="dialog-title" + aria-describedby="dialog-description" + open={open} + onClose={handleClose} + > + <DialogTitle>{translate('common.msg.confirm.tip')}</DialogTitle> + <DialogContent> + <DialogContentText> + {translate('common.msg.confirm.desc')} + </DialogContentText> + </DialogContent> + <DialogActions> + <Button onClick={handleClose} color="primary"> + {translate('ra.action.cancel')} + </Button> + <Button onClick={handleConfirm} color="primary"> + {translate('ra.action.confirm')} + </Button> + </DialogActions> + </Dialog> + </> + ) +} + +export default ConfirmModal; \ No newline at end of file -- Gitblit v1.9.1