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