From f34089d1d321efe55c98e6f2638d924ae515effd Mon Sep 17 00:00:00 2001 From: skyouc Date: 星期三, 06 八月 2025 14:09:18 +0800 Subject: [PATCH] Merge branch 'devlop' of http://47.97.1.152:5880/r/wms-master into devlop --- rsf-admin/src/page/stockManage/locRevise/ReviseLogList.jsx | 182 +++++++ /dev/null | 93 ---- rsf-admin/src/page/stockManage/locRevise/LocsReviseDetl.jsx | 374 ++++++++++++++++ rsf-admin/src/page/stockManage/locRevise/LocReviseList.jsx | 4 rsf-admin/src/page/stockManage/locRevise/SelectMatnrInfo.jsx | 261 +++++++++++ rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx | 104 +++- rsf-admin/src/page/stockManage/locRevise/LocReviseEdit.jsx | 163 +++--- rsf-admin/src/page/stockManage/locRevise/ReviseLogItemList.jsx | 115 +++++ rsf-admin/src/i18n/zh.js | 6 rsf-admin/src/i18n/en.js | 6 rsf-admin/src/page/stockManage/locRevise/SelectLocsRevise.jsx | 43 11 files changed, 1,128 insertions(+), 223 deletions(-) diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js index f97fa0a..bb04d47 100644 --- a/rsf-admin/src/i18n/en.js +++ b/rsf-admin/src/i18n/en.js @@ -912,6 +912,10 @@ orgAreaName: "Area Name", exceTime: "Exce Time" }, + reviseLog: { + reviseId: 'Revise Id', + reviseCode: 'Revise Code', + }, waitPakinItem: { pakinId: "pakinId", maktx: "maktx", @@ -1129,8 +1133,10 @@ trackCode: "trackCode", unit: "unit", anfme: "anfme", + outQty: 'Revise Qty', qty: 'Qty', workQty: 'Work Qty', + reviseQty: 'Revise Qty', batch: "batch", splrBatch: "splrBatch", spec: "spec", diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js index e36c5af..74d5ae8 100644 --- a/rsf-admin/src/i18n/zh.js +++ b/rsf-admin/src/i18n/zh.js @@ -949,6 +949,10 @@ areaName: "搴撳尯", exceTime: "璋冩暣鏃堕棿", }, + reviseLog: { + reviseId: '璋冩暣鍗旾D', + reviseCode: '璋冩暣鍗�', + }, waitPakinItem: { pakinId: "缁勬墭Id", maktx: "鐗╂枡", @@ -1134,9 +1138,11 @@ maktx: "鐗╂枡鍚嶇О", unit: '鍗曚綅', anfme: '鏁伴噺', + outQty: '璋冩暣鏁伴噺', matnrCode: "鐗╂枡缂栫爜", trackCode: "璺熻釜鐮�", workQty: '鎵ц鏁�', + reviseQty: '瀹為檯鏁伴噺', qty: '瀹屾垚鏁�', batch: "鎵规", splrBatch: "鎵规", diff --git a/rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx b/rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx index daf0441..efc0ff6 100644 --- a/rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx +++ b/rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx @@ -23,9 +23,12 @@ CreateBase, TopToolbar, FilterButton, + ReferenceField, SearchInput, List, Create, + useGetOne, + useRecordContext, } from 'react-admin'; import { Dialog, @@ -59,6 +62,23 @@ import request from '@/utils/request'; import _, { set } from 'lodash'; + + +const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ + '& .css-1vooibu-MuiSvgIcon-root': { + height: '.9em' + }, + '& .RaDatagrid-row': { + cursor: 'auto' + }, + '& .column-name': { + }, + '& .opt': { + width: 200 + }, +})); + + const LocReviseCreate = (props) => { const { open, setOpen, orderId } = props; const tableRef = useRef(); @@ -66,21 +86,14 @@ const refresh = useRefresh(); const translate = useTranslate(); const [tabelData, setTableData] = useState([]); + const [locRevise, setLocRevise] = useState(); const [disabled, setDisabled] = useState(false); - const [isVisible, setIsVisible] = useState("block"); + const [isVisible, setIsVisible] = useState("none"); const [selectedRows, setSelectedRows] = useState([]); const [createDialog, setCreateDialog] = useState(false); const [formData, setFormData] = useState({ type: '0', orgAreaId: null, tarAreaId: null, exceTime: null, code: null }); const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_stock_revise_type')) || []; - const setFinally = () => { - const rows = tableRef.current.state.editRows; - for (const key in rows) { - const find = tabelData.find(item => item.matnrId === +key); - find.anfme = rows[key].anfme.value; - } - setTableData([...tabelData]); - } const FormToolbar = () => { return ( @@ -133,26 +146,22 @@ } const mutationOptions = { - onSuccess: (data) => { + onSuccess: (id) => { setIsVisible("block") setDisabled(true) + setLocRevise(id) refresh() }, - }; - - const handleChange = (value, name) => { - setFormData((prevData) => ({ - ...prevData, - [name]: value - })); }; return ( <> <Box sx={{ padding: 1 }}> - <Create resource="locRevise" + <Create + resource="locRevise" title={false} - mutationOptions={mutationOptions} > + // mutationOptions={mutationOptions} + > <SimpleForm toolbar={<FormToolbar />}> <Grid container spacing={2} sx={{ '& .MuiToolbar-root-RaToolbar-root.RaToolbar-defaultToolbar': { @@ -202,14 +211,54 @@ </Stack> </Box> <Box sx={{ mt: 2 }}> - <TransferTableView - tabelData={tabelData} - setTableData={setTableData} - orderId={orderId} - selectedRows={selectedRows} - setSelectedRows={setSelectedRows} - tableRef={tableRef}> - </TransferTableView> + <List + sx={{ + flexGrow: 1, + transition: (theme) => + theme.transitions.create(['all'], { + duration: theme.transitions.duration.enteringScreen, + }), + }} + resource="reviseLog" + title={"menu.reviseLog"} + empty={false} + filters={false} + sort={{ field: "create_time", order: "desc" }} + actions={false} + perPage={DEFAULT_PAGE_SIZE} + > + <StyledDatagrid + preferenceKey='reviseLog' + bulkActionButtons={false} + rowClick={(id, resource, record) => false} + expand={false} + expandSingle={true} + omit={['id', 'reviseId', 'createTime', 'createBy', 'memo']} + > + <NumberField source="id" /> + <NumberField source="reviseId" label="table.field.reviseLog.reviseId" /> + <TextField source="reviseCode" label="table.field.reviseLog.reviseCode" /> + <NumberField source="warehouseId" label="table.field.loc.warehouseId" /> + <NumberField source="areaId" label="table.field.loc.areaId" /> + <NumberField source="type" label="table.field.loc.type" /> + <TextField source="barcode" label="table.field.loc.barcode" /> + <TextField source="useStatus" label="table.field.loc.useStatus" /> + <NumberField source="channel" label="table.field.loc.channel" /> + <NumberField source="row" label="table.field.loc.row" /> + <NumberField source="col" label="table.field.loc.col" /> + <NumberField source="lev" label="table.field.loc.lev" /> + <TextField source="updateBy$" label="common.field.updateBy" /> + <DateField source="updateTime" label="common.field.updateTime" showTime /> + <TextField source="createBy$" label="common.field.createBy" /> + <DateField source="createTime" label="common.field.createTime" showTime /> + <BooleanField source="statusBool" label="common.field.status" sortable={false} /> + <TextField source="memo" label="common.field.memo" sortable={false} /> + <WrapperField cellClassName="opt" label="common.field.opt"> + <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} /> + <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} /> + </WrapperField> + </StyledDatagrid> + </List> </Box> </Box> </Card> @@ -217,6 +266,7 @@ <SelectLocsRevise data={tabelData} queryForm={formData} + locRevise={locRevise} open={createDialog} setOpen={setCreateDialog} selectedRows={selectedRows} diff --git a/rsf-admin/src/page/stockManage/locRevise/LocReviseEdit.jsx b/rsf-admin/src/page/stockManage/locRevise/LocReviseEdit.jsx index 80db4ee..71ba80d 100644 --- a/rsf-admin/src/page/stockManage/locRevise/LocReviseEdit.jsx +++ b/rsf-admin/src/page/stockManage/locRevise/LocReviseEdit.jsx @@ -28,91 +28,100 @@ import CustomerTopToolBar from "@/page/components/EditTopToolBar"; import MemoInput from "@/page/components/MemoInput"; import StatusSelectInput from "@/page/components/StatusSelectInput"; +import ReviseLogList from "./ReviseLogList"; const LocReviseEdit = () => { const translate = useTranslate(); + const [disabled, setDisabled] = useState(false); + + const FormToolbar = () => { + return ( + <Toolbar sx={{ justifyContent: 'flex-end' }}> + <SaveButton disabled={disabled} /> + <DeleteButton mutationMode="optimistic" /> + </Toolbar> + ) + } return ( - <Edit - redirect="list" - mutationMode={EDIT_MODE} - actions={<CustomerTopToolBar />} - aside={<EditBaseAside />} - > - <SimpleForm - shouldUnregister - warnWhenUnsavedChanges - toolbar={false} - mode="onTouched" - defaultValues={{}} - sx={{ - "& .MuiFormLabel-root.MuiInputLabel-root.Mui-disabled": { - bgcolor: 'white', - WebkitTextFillColor: "rgba(0, 0, 0)" - }, - - "& .MuiInputBase-input.MuiFilledInput-input.Mui-disabled": { - bgcolor: 'white', - WebkitTextFillColor: "rgba(0, 0, 0)" - } - }} - // validate={(values) => { }} + <> + <Edit + redirect="list" + mutationMode={EDIT_MODE} + actions={<CustomerTopToolBar />} + aside={<EditBaseAside />} > - <Grid container width={{ xs: '100%', xl: '80%' }} rowSpacing={3} columnSpacing={3}> - <Grid item xs={24} md={12}> - <Typography variant="h6" gutterBottom> - {translate('common.edit.title.main')} - </Typography> - <Stack direction='row' gap={2}> - <TextInput - label="table.field.locRevise.code" - source="code" - parse={v => v} - readOnly - /> - <SelectInput - label="table.field.locRevise.type" - source="type" - choices={[ - { id: 0, name: ' 搴撳瓨璋冩暣' }, - { id: 2, name: ' 鐩樼偣璋冩暣' }, - ]} - readOnly - /> - <NumberInput - label="table.field.locRevise.anfme" - source="anfme" - readOnly - /> - </Stack> - <Stack direction='row' gap={2}> - <NumberInput - label="table.field.locRevise.reviseQty" - source="reviseQty" - readOnly - /> - <SelectInput - label="table.field.locRevise.exceStatus" - source="exceStatus" - choices={[ - { id: 0, name: '鏈墽琛�' }, - { id: 1, name: '鎵ц涓�' }, - { id: 2, name: '鎵ц瀹屾垚' }, - ]} - readOnly - /> - <TextInput - label="table.field.locRevise.areaName" - source="orgAreaName" - parse={v => v} - readOnly - /> - </Stack> + <SimpleForm + shouldUnregister + warnWhenUnsavedChanges + toolbar={<FormToolbar />} + mode="onTouched" + defaultValues={{}} + // sx={{ + // "& .MuiFormLabel-root.MuiInputLabel-root.Mui-disabled": { + // bgcolor: 'white', + // WebkitTextFillColor: "rgba(0, 0, 0)" + // }, + + // "& .MuiInputBase-input.MuiFilledInput-input.Mui-disabled": { + // bgcolor: 'white', + // WebkitTextFillColor: "rgba(0, 0, 0)" + // } + // }} + validate={(values) => { }} + > + <Grid container width={{ xs: '100%', xl: '80%' }} rowSpacing={3} columnSpacing={3}> + <Grid item xs={24} md={12}> + <Typography variant="h6" gutterBottom> + {translate('common.edit.title.main')} + </Typography> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.locRevise.code" + source="code" + parse={v => v} + readOnly + /> + <SelectInput + label="table.field.locRevise.type" + source="type" + choices={[ + { id: 0, name: ' 搴撳瓨璋冩暣' }, + { id: 2, name: ' 鐩樼偣璋冩暣' }, + ]} + /> + <NumberInput + label="table.field.locRevise.anfme" + source="anfme" + /> + </Stack> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.locRevise.reviseQty" + source="reviseQty" + /> + <SelectInput + label="table.field.locRevise.exceStatus" + source="exceStatus" + choices={[ + { id: 0, name: '鏈墽琛�' }, + { id: 1, name: '鎵ц涓�' }, + { id: 2, name: '鎵ц瀹屾垚' }, + ]} + /> + <TextInput + label="table.field.locRevise.areaName" + source="orgAreaName" + parse={v => v} + /> + </Stack> + </Grid> </Grid> - </Grid> - </SimpleForm> - </Edit > + </SimpleForm> + </Edit > + <ReviseLogList /> + </> ) } diff --git a/rsf-admin/src/page/stockManage/locRevise/LocReviseList.jsx b/rsf-admin/src/page/stockManage/locRevise/LocReviseList.jsx index efdc6fc..a679f64 100644 --- a/rsf-admin/src/page/stockManage/locRevise/LocReviseList.jsx +++ b/rsf-admin/src/page/stockManage/locRevise/LocReviseList.jsx @@ -37,12 +37,8 @@ import MyExportButton from '@/page/components/MyExportButton'; import PageEditDrawer from "@/page/components/PageEditDrawer"; import { Box, Typography, Card, Stack } from '@mui/material'; -import PageDrawer from "@/page/components/PageDrawer"; -import EmptyData from "@/page/components/EmptyData"; import LocReviseCreate from "./LocReviseCreate"; -import MyField from "@/page/components/MyField"; import { styled } from '@mui/material/styles'; -import LocRevisePanel from "./LocRevisePanel"; const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ '& .css-1vooibu-MuiSvgIcon-root': { diff --git a/rsf-admin/src/page/stockManage/locRevise/LocRevisePanel.jsx b/rsf-admin/src/page/stockManage/locRevise/LocRevisePanel.jsx deleted file mode 100644 index 2360324..0000000 --- a/rsf-admin/src/page/stockManage/locRevise/LocRevisePanel.jsx +++ /dev/null @@ -1,93 +0,0 @@ -import React, { useState, useRef, useEffect, useMemo } from "react"; -import { Box, Card, CardContent, Grid, Typography, Tooltip } from '@mui/material'; -import { - useTranslate, - useRecordContext, -} from 'react-admin'; -import PanelTypography from "@/page/components/PanelTypography"; -import * as Common from '@/utils/common' - -const LocRevisePanel = () => { - const record = useRecordContext(); - if (!record) return null; - const translate = useTranslate(); - return ( - <> - <Card sx={{ width: { xs: 300, sm: 500, md: 600, lg: 800 }, margin: 'auto' }}> - <CardContent> - <Grid container spacing={2}> - <Grid item xs={12} sx={{ display: 'flex', justifyContent: 'space-between' }}> - <Typography variant="h6" gutterBottom align="left" sx={{ - maxWidth: { xs: '100px', sm: '180px', md: '260px', lg: '360px' }, - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis', - }}> - {Common.camelToPascalWithSpaces(translate('table.field.locRevise.id'))}: {record.id} - </Typography> - {/* inherit, primary, secondary, textPrimary, textSecondary, error */} - <Typography variant="h6" gutterBottom align="right" > - ID: {record.id} - </Typography> - </Grid> - </Grid> - <Grid container spacing={2}> - <Grid item xs={12} container alignContent="flex-end"> - <Typography variant="caption" color="textSecondary" sx={{ wordWrap: 'break-word', wordBreak: 'break-all' }}> - {Common.camelToPascalWithSpaces(translate('common.field.memo'))}:{record.memo} - </Typography> - </Grid> - </Grid> - <Box height={20}> </Box> - <Grid container spacing={2}> - <Grid item xs={6}> - <PanelTypography - title="table.field.locRevise.code" - property={record.code} - /> - </Grid> - <Grid item xs={6}> - <PanelTypography - title="table.field.locRevise.type" - property={record.type$} - /> - </Grid> - <Grid item xs={6}> - <PanelTypography - title="table.field.locRevise.anfme" - property={record.anfme} - /> - </Grid> - <Grid item xs={6}> - <PanelTypography - title="table.field.locRevise.reviseQty" - property={record.reviseQty} - /> - </Grid> - <Grid item xs={6}> - <PanelTypography - title="table.field.locRevise.exceStatus" - property={record.exceStatus$} - /> - </Grid> - <Grid item xs={6}> - <PanelTypography - title="table.field.locRevise.orgAreaId" - property={record.orgAreaId} - /> - </Grid> - <Grid item xs={6}> - <PanelTypography - title="table.field.locRevise.orgAreaName" - property={record.orgAreaName} - /> - </Grid> - - </Grid> - </CardContent> - </Card > - </> - ); -}; - -export default LocRevisePanel; diff --git a/rsf-admin/src/page/stockManage/locRevise/LocsReviseDetl.jsx b/rsf-admin/src/page/stockManage/locRevise/LocsReviseDetl.jsx new file mode 100644 index 0000000..04602df --- /dev/null +++ b/rsf-admin/src/page/stockManage/locRevise/LocsReviseDetl.jsx @@ -0,0 +1,374 @@ +import React, { useState, useEffect, useRef } from "react"; +import { + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Stack, + Grid, + Box, + Button, + Paper, + styled, + Tooltip, + IconButton, + TextField, +} from '@mui/material'; + +import { EDIT_MODE, DEFAULT_START_PAGE, DEFAULT_ITEM_PAGE_SIZE, DEFAULT_PAGE_SIZE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting'; +import { useTranslate, useNotify, useRefresh, DatagridConfigurable, useGetOne } from 'react-admin'; +import DialogCloseButton from "../../components/DialogCloseButton"; +import { Add, Edit, Delete, Save } from '@mui/icons-material'; +import { DataGrid, useGridApiRef } from '@mui/x-data-grid'; +import SelectMatnrInfo from "./SelectMatnrInfo"; +import SaveIcon from '@mui/icons-material/Save'; +import request from '@/utils/request'; + +const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ + '& .css-1vooibu-MuiSvgIcon-root': { + height: '.9em' + }, + '& .RaDatagrid-row': { + cursor: 'auto' + }, + '& .opt': { + width: 180 + }, +})); + +const LocsReviseDetl = (props) => { + const { open, setOpen, record } = props; + const handleClose = (event, reason) => { + if (reason !== "backdropClick") { + setOpen(false); + } + }; + + const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_stock_revise_type')) || []; + const [page, setPage] = useState({ page: DEFAULT_START_PAGE, pageSize: DEFAULT_PAGE_SIZE }); + const [formData, setFormData] = useState({ locCode: record?.locCode }); + const [selectedRows, setSelectedRows] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const [tableData, setTableData] = useState([]); + const [openMatnr, setOpenMatnr] = useState(); + const [dyFields, setDyFields] = useState([]); + const [rowCount, setRowCount] = useState(0); + const translate = useTranslate(); + const refresh = useRefresh(); + const notify = useNotify(); + const tableRef = useRef() + + + const handleChange = (e) => { + const { name, value } = e.target; + setFormData(() => ({ + ...formData, + [name]: value + })); + }; + + const handleSubmit = () => { + const rows = tableRef.current.getSelectedRows(); + const selectedData = [...rows.entries()].map(([Key, value]) => value) + const value = selectedData.map((el => { + return { + id: el.id, + locCode: el.locCode, + matnrId: el.matnrId, + maktx: el.maktx || '', + matnrCode: el.matnrCode || '', + batch: el.batch, + anfme: el.anfme, + reviseQty: el.reviseQty, + spec: el.spec, + model: el.model, + unit: el.unit, + } + })); + + saveReviseLog(value); + }; + + const saveReviseLog = async (values) => { + const parmas = { + reviseLogId: record?.id, + items: values, + } + console.log(values); + + const res = await request.post(`/reviseLogItem/items/save`, parmas); + if (res?.data?.code === 200) { + setOpen(false); + refresh() + } else { + notify(res.data.msg); + } + } + + const getData = async () => { + setIsLoading(true) + console.log(formData); + + const res = await request.post(`/locItem/page`, { + locCode: record?.locCode, + current: page?.page, + pageSize: page?.pageSize, + orderBy: "create_time desc" + }); + if (res?.data?.code === 200) { + setTableData(res.data.data.records); + setRowCount(res.data?.data?.total); + } else { + notify(res.data.msg); + } + setIsLoading(false) + }; + + useEffect(() => { + getData(); + }, [open, page]); + + const handleSearch = () => { + // getData() + setOpenMatnr(true) + }; + + return ( + <> + <Dialog + open={open} + onClose={handleClose} + aria-labelledby="form-dialog-title" + fullWidth + disableRestoreFocus + maxWidth="xl" + > + <DialogTitle id="form-dialog-title" sx={{ + position: 'sticky', + top: 0, + backgroundColor: 'background.paper', + zIndex: 1000 + }}> + {translate("common.action.newAddMats")} + <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}> + <DialogCloseButton onClose={handleClose} /> + </Box> + </DialogTitle> + <DialogContent sx={{ mt: 2 }}> + {/* <Box> + <List + sx={{ + flexGrow: 1, + marginRight: 1, + transition: (theme) => + theme.transitions.create(['all'], { + duration: theme.transitions.duration.enteringScreen, + }), + }} + resource="loc" + title={"menu.loc"} + empty={false} + filter={{ useStatus: 'F' }} + filters={filters} + sort={{ field: "'row'" }} + actions={false} + perPage={DEFAULT_PAGE_SIZE} + aside={false} + > + <StyledDatagrid + preferenceKey='loc' + align="left" + bulkActionButtons={false} + rowClick={() => false} + omit={['id', 'areaId', 'type', 'barcode']} + > + <NumberField source="id" /> + <TextField source="code" label="table.field.locItem.locCode" /> + </StyledDatagrid> + </List> + </Box> */} + <Box> + <Box component="form" onSubmit={handleSubmit} sx={{ display: 'flex', flexDirection: 'column', gap: 3, justifyContent: 'flex-end' }}> + <Grid item md={12} sx={{ justifyContent: 'flex-end', display: 'flex' }}> + <Button variant="text" onClick={handleSearch}>{translate("page.whMat.title.add")}</Button> + </Grid> + </Box> + <Box sx={{ mt: 2, height: 600, width: '100%' }}> + <SelectReviseMatnr + page={page} + setPage={setPage} + tableRef={tableRef} + rowCount={rowCount} + dyFields={dyFields} + isLoading={isLoading} + tableData={tableData} + selectedRows={selectedRows} + setDyFields={setDyFields} + setTableData={setTableData} + setSelectedRows={setSelectedRows} + /> + </Box> + </Box> + </DialogContent> + <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> + <Box sx={{ width: '100%', display: 'flex', justifyContent: 'flex-end' }}> + <Button onClick={handleSubmit} variant="contained" startIcon={<SaveIcon />}> + {translate('toolbar.confirm')} + </Button> + </Box> + </DialogActions> + </Dialog> + <SelectMatnrInfo open={openMatnr} setOpen={setOpenMatnr} setData={setTableData} data={tableData} /> + </> + ); +}; + +export default LocsReviseDetl; + +const SelectReviseMatnr = ({ tableData, setTableData, page, isLoading, setPage, rowCount, selectedRows, setSelectedRows, tableRef, setDyFields, dyFields }) => { + const translate = useTranslate(); + const notify = useNotify(); + const [dynamicFields, setDynamicFields] = useState([]); + const [columns, setColumns] = useState([ + { + field: 'matnrCode', + headerName: translate('table.field.locItem.matnrCode'), + width: 130, + editable: false, + }, + { + field: 'maktx', + headerName: translate('table.field.locItem.maktx'), + minWidth: 100, + flex: 1, + editable: false, + }, + { + field: 'batch', + headerName: translate('table.field.locItem.batch'), + minWidth: 100, + flex: 1, + editable: true, + }, + { + field: 'anfme', + headerName: translate('table.field.locItem.anfme') + "*", + minWidth: 100, + flex: 1, + editable: false, + }, + { + field: 'reviseQty', + headerName: translate('table.field.locItem.outQty') + "*", + minWidth: 100, + type: 'number', + flex: 1, + editable: true, + }, + { + field: 'spec', + headerName: translate('table.field.locItem.spec'), + minWidth: 100, + flex: 1, + editable: false, + }, + { + field: 'model', + headerName: translate('table.field.locItem.model'), + minWidth: 100, + flex: 1, + editable: false, + }, + { + field: 'unit', + headerName: translate('table.field.locItem.unit'), + minWidth: 100, + flex: 1, + editable: false, + }, + ]) + + const operate = { + field: 'action', + headerName: '鎿嶄綔', + width: 140, + lockPosition: 'left', + renderCell: (params) => ( + <Tooltip title="Delete"> + <IconButton onClick={() => handleDelete(params.row)}> + <Delete /> + </IconButton> + </Tooltip> + ), + } + + const handleDelete = (rows) => { + const tableRows = tableData.filter(item => item.matnrCode != rows.matnrCode); + setTableData(tableRows); + } + + const handleSelectionChange = (ids) => { + setSelectedRows(ids) + }; + + useEffect(() => { + if (dynamicFields.length < 1) { + getDynamicFields(); + } + }, [dyFields]); + + const getDynamicFields = async () => { + const { + data: { code, data, msg }, + } = await request.get("/fields/enable/list"); + if (code === 200) { + const cols = data.map(el => ({ + field: el.fields, + headerName: el.fieldsAlise, + minWidth: 100, + flex: 1, + editable: el.unique, + valueGetter: (value, row) => { + return row.extendFields?.[el.fields] || ''; + }, + })) + setDyFields(data) + setDynamicFields(cols); + setColumns([...columns, ...cols, operate]) + } else { + notify(msg); + } + } + + tableRef.current = useGridApiRef(); + + return ( + <div style={{ width: '100%' }}> + <DataGrid + sx={{ height: 600 }} + size="small" + apiRef={tableRef} + rows={tableData} + columns={columns} + checkboxSelection + onRowSelectionModelChange={handleSelectionChange} + selectionModel={selectedRows} + disableColumnMenu={true} + disableRowSelectionOnClick + disableColumnSorting + disableMultipleColumnsSorting + rowCount={rowCount} + paginationMode="server" + paginationModel={page} + onPaginationModelChange={setPage} + loading={isLoading} + slotProps={{ + loadingOverlay: { + variant: 'linear-progress', + noRowsVariant: 'linear-progress', + }, + }} + /> + </div> + ); +}; \ No newline at end of file diff --git a/rsf-admin/src/page/stockManage/locRevise/ReviseLogItemList.jsx b/rsf-admin/src/page/stockManage/locRevise/ReviseLogItemList.jsx new file mode 100644 index 0000000..d0a6fec --- /dev/null +++ b/rsf-admin/src/page/stockManage/locRevise/ReviseLogItemList.jsx @@ -0,0 +1,115 @@ +import React, { useState, useRef, useEffect, useMemo, useCallback } from "react"; +import { useNavigate } from 'react-router-dom'; +import { + List, + DatagridConfigurable, + SearchInput, + TopToolbar, + SelectColumnsButton, + EditButton, + FilterButton, + CreateButton, + ExportButton, + BulkDeleteButton, + WrapperField, + useRecordContext, + useTranslate, + useNotify, + useListContext, + FunctionField, + TextField, + NumberField, + DateField, + BooleanField, + ReferenceField, + TextInput, + DateTimeInput, + DateInput, + SelectInput, + NumberInput, + ReferenceInput, + ReferenceArrayInput, + AutocompleteInput, + DeleteButton, +} from 'react-admin'; + +import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting'; +import { Box, Typography, Card, Stack } from '@mui/material'; +import { styled } from '@mui/material/styles'; +import * as Common from '@/utils/common'; + +const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ + '& .css-1vooibu-MuiSvgIcon-root': { + height: '.9em' + }, + '& .RaDatagrid-row': { + cursor: 'auto' + }, + '& .column-name': { + }, + '& .opt': { + width: 200 + }, +})); + + +const ReviseLogItemList = () => { + const [createDialog, setCreateDialog] = useState(false); + const [drawerVal, setDrawerVal] = useState(false); + const translate = useTranslate(); + const record = useRecordContext(); + + return ( + <Box display="flex"> + <List + resource="reviseLogItem" + sx={{ + flexGrow: 1, + transition: (theme) => + theme.transitions.create(['all'], { + duration: theme.transitions.duration.enteringScreen, + }), + }} + title={"menu.reviseLogItem"} + empty={false} + filters={false} + pagination={false} + filter={{ reviseLogId: record?.id }} + sort={{ field: "create_time", order: "desc" }} + actions={false} + perPage={DEFAULT_PAGE_SIZE} + > + <StyledDatagrid + preferenceKey='reviseLogItem' + bulkActionButtons={false} + rowClick={(id, resource, record) => false} + expand={false} + expandSingle={true} + omit={['id', 'locId', 'locCode', 'matnrId', 'fieldsIndex', 'memo', 'statusBool']} + > + <NumberField source="id" /> + <NumberField source="locId" label="table.field.locItem.locId" /> + <TextField source="locCode" label="table.field.locItem.locCode" /> + <NumberField source="matnrId" label="table.field.locItem.matnrId" /> + <TextField source="matnrCode" label="table.field.locItem.matnrCode" /> + <TextField source="maktx" label="table.field.locItem.maktx" /> + <TextField source="unit" label="table.field.locItem.unit" /> + <NumberField source="anfme" label="table.field.locItem.anfme" /> + <NumberField source="reviseQty" label="table.field.locItem.reviseQty" /> + <TextField source="batch" label="table.field.locItem.batch" /> + <TextField source="spec" label="table.field.locItem.spec" /> + <TextField source="model" label="table.field.locItem.model" /> + <TextField source="fieldsIndex" label="table.field.locItem.fieldsIndex" /> + <TextField source="updateBy$" label="common.field.updateBy" /> + <DateField source="updateTime" label="common.field.updateTime" showTime /> + <TextField source="createBy" label="common.field.createBy" /> + <DateField source="createTime" label="common.field.createTime" showTime /> + <BooleanField source="statusBool" label="common.field.status" sortable={false} /> + <TextField source="memo" label="common.field.memo" sortable={false} /> + </StyledDatagrid> + </List> + </Box> + ) +} + +export default ReviseLogItemList; diff --git a/rsf-admin/src/page/stockManage/locRevise/ReviseLogList.jsx b/rsf-admin/src/page/stockManage/locRevise/ReviseLogList.jsx new file mode 100644 index 0000000..e5408cf --- /dev/null +++ b/rsf-admin/src/page/stockManage/locRevise/ReviseLogList.jsx @@ -0,0 +1,182 @@ +import React, { useState, useRef, useEffect, useMemo, useCallback } from "react"; +import { useNavigate } from 'react-router-dom'; +import { + List, + DatagridConfigurable, + SearchInput, + TopToolbar, + SelectColumnsButton, + EditButton, + FilterButton, + CreateButton, + ExportButton, + BulkDeleteButton, + WrapperField, + useRecordContext, + useTranslate, + useNotify, + useListContext, + FunctionField, + TextField, + NumberField, + DateField, + BooleanField, + ReferenceField, + TextInput, + DateTimeInput, + DateInput, + SelectInput, + NumberInput, + ReferenceInput, + ReferenceArrayInput, + AutocompleteInput, + DeleteButton, + useGetRecordId, + Button, +} from 'react-admin'; +import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting'; +import MyCreateButton from "@/page/components/MyCreateButton"; +import { Box, Typography, Card, Stack } from '@mui/material'; +import ReviseLogItemList from "./ReviseLogItemList"; +import SelectLocsRevise from "./SelectLocsRevise"; +import EditIcon from '@mui/icons-material/Edit'; +import LocsReviseDetl from "./LocsReviseDetl"; +import { styled } from '@mui/material/styles'; +import * as Common from '@/utils/common'; + +const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ + '& .css-1vooibu-MuiSvgIcon-root': { + height: '.9em' + }, + '& .RaDatagrid-row': { + cursor: 'auto' + }, + '& .column-name': { + }, + '& .opt': { + width: 200 + }, +})); + +const filters = [ + <SearchInput source="condition" alwaysOn />, + <DateInput label='common.time.after' source="timeStart" alwaysOn />, + <DateInput label='common.time.before' source="timeEnd" alwaysOn />, + <NumberInput source="reviseId" label="table.field.reviseLog.reviseId" />, + <TextInput source="reviseCode" label="table.field.reviseLog.reviseCode" />, + <NumberInput source="warehouseId" label="table.field.loc.warehouseId" />, + <NumberInput source="areaId" label="table.field.loc.areaId" />, + <NumberInput source="type" label="table.field.loc.type" />, + <TextInput source="barcode" label="table.field.loc.barcode" />, + <TextInput source="useStatus" label="table.field.loc.useStatus" />, + <NumberInput source="channel" label="table.field.loc.channel" />, + <NumberInput source="row" label="table.field.loc.row" />, + <NumberInput source="col" label="table.field.loc.col" />, + <NumberInput source="lev" label="table.field.loc.lev" />, + <TextInput label="common.field.memo" source="memo" />, + <SelectInput + label="common.field.status" + source="status" + choices={[ + { id: '1', name: 'common.enums.statusTrue' }, + { id: '0', name: 'common.enums.statusFalse' }, + ]} + resettable + />, +] + +const ReviseLogList = () => { + const [createDialog, setCreateDialog] = useState(false); + const [drawerVal, setDrawerVal] = useState(false); + const [item, setItem] = useState(); + const translate = useTranslate(); + const orderId = useGetRecordId(); + + return ( + <Box display="flex"> + <List + resource="reviseLog" + sx={{ + flexGrow: 1, + transition: (theme) => + theme.transitions.create(['all'], { + duration: theme.transitions.duration.enteringScreen, + }), + }} + title={"menu.reviseLog"} + empty={false} + filters={filters} + filter={{ reviseId: orderId }} + sort={{ field: "create_time", order: "desc" }} + actions={( + <TopToolbar> + <FilterButton /> + <MyCreateButton onClick={() => { setCreateDialog(true); }} /> + <SelectColumnsButton preferenceKey='check' /> + </TopToolbar> + )} + perPage={DEFAULT_PAGE_SIZE} + > + <StyledDatagrid + preferenceKey='reviseLog' + bulkActionButtons={false} + rowClick={(id, resource, record) => false} + expand={<ReviseLogItemList />} + expandSingle={true} + omit={['id', 'reviseId', 'createTime', 'createBy', 'memo']} + > + <NumberField source="id" /> + <NumberField source="reviseId" label="table.field.reviseLog.reviseId" /> + <TextField source="reviseCode" label="table.field.reviseLog.reviseCode" /> + <TextField source="locCode" label="table.field.locItem.locCode" /> + <NumberField source="warehouseId" label="table.field.loc.warehouseId" /> + <NumberField source="areaId" label="table.field.loc.areaId" /> + <NumberField source="type" label="table.field.loc.type" /> + <TextField source="barcode" label="table.field.loc.barcode" /> + <TextField source="useStatus" label="table.field.loc.useStatus" /> + <NumberField source="channel" label="table.field.loc.channel" /> + <NumberField source="row" label="table.field.loc.row" /> + <NumberField source="col" label="table.field.loc.col" /> + <NumberField source="lev" label="table.field.loc.lev" /> + <TextField source="updateBy$" label="common.field.updateBy" /> + <DateField source="updateTime" label="common.field.updateTime" showTime /> + <TextField source="createBy$" label="common.field.createBy" /> + <DateField source="createTime" label="common.field.createTime" showTime /> + <BooleanField source="statusBool" label="common.field.status" sortable={false} /> + <TextField source="memo" label="common.field.memo" sortable={false} /> + <WrapperField cellClassName="opt" label="common.field.opt"> + <EditLocRevise setDrawerVal={setDrawerVal} setItem={setItem} /> + <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} redirect={false} /> + </WrapperField> + </StyledDatagrid> + </List> + <SelectLocsRevise + locRevise={orderId} + open={createDialog} + setOpen={setCreateDialog} + /> + <LocsReviseDetl + open={drawerVal} + record={item} + setOpen={setDrawerVal} + /> + </Box> + ) +} + +export default ReviseLogList; + +const EditLocRevise = ({ setDrawerVal, setItem }) => { + const record = useRecordContext(); + console.log("=======>"); + console.log(record); + const editRevise = () => { + setDrawerVal(true) + setItem(record) + } + + return ( + <Button label="common.button.edit" startIcon={<EditIcon />} onClick={editRevise}></Button> + ) +} + diff --git a/rsf-admin/src/page/stockManage/locRevise/SelectLocsRevise.jsx b/rsf-admin/src/page/stockManage/locRevise/SelectLocsRevise.jsx index d9b25a2..4052be8 100644 --- a/rsf-admin/src/page/stockManage/locRevise/SelectLocsRevise.jsx +++ b/rsf-admin/src/page/stockManage/locRevise/SelectLocsRevise.jsx @@ -16,9 +16,8 @@ } from '@mui/material'; import { EDIT_MODE, DEFAULT_START_PAGE, DEFAULT_ITEM_PAGE_SIZE, DEFAULT_PAGE_SIZE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting'; -import { useTranslate, useNotify, useRefresh, DatagridConfigurable} from 'react-admin'; +import { useTranslate, useNotify, useRefresh, DatagridConfigurable, useGetOne } from 'react-admin'; import DialogCloseButton from "../../components/DialogCloseButton"; -import TreeSelectInput from "@/page/components/TreeSelectInput"; import { Add, Edit, Delete, Save } from '@mui/icons-material'; import SaveIcon from '@mui/icons-material/Save'; import { DataGrid } from '@mui/x-data-grid'; @@ -31,21 +30,18 @@ '& .RaDatagrid-row': { cursor: 'auto' }, - '& .column-name': { - }, '& .opt': { width: 180 }, })); const SelectLocsRevise = (props) => { - const { open, setOpen, data, setData } = props; + const { open, setOpen, locRevise } = props; const handleClose = (event, reason) => { if (reason !== "backdropClick") { setOpen(false); } }; - const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_stock_revise_type')) || []; const [page, setPage] = useState({ page: DEFAULT_START_PAGE, pageSize: DEFAULT_PAGE_SIZE }); const [formData, setFormData] = useState({ useStatus: 'F', code: null }); @@ -65,20 +61,12 @@ })); }; - const reset = () => { - setFormData({ - code: '', - useStatus: 'F', - }) - } - const handleSubmit = () => { - const hasarr = data.map(el => +el.matnrId) - const selectedData = selectedRows.filter(item => !hasarr.includes(item)).map(id => (tableData.find(row => row.id === id))); + const selectedData = tableData.filter(item => selectedRows.includes(item.id)); const value = selectedData.map((el => { return { id: el.id, - code: el.code, + locCode: el.code, areaId: el.areaId, barcode: el.barcode || '', channel: el.channel || '', @@ -89,11 +77,24 @@ useStatus: el.useStatus, warehouseId: el.warehouseId, } - })) - setData([...data, ...value]); - setOpen(false); - reset(); + })); + + saveReviseLog(value); }; + + const saveReviseLog = async (values) => { + const parmas = { + reviseId: locRevise, + items: values, + } + const res = await request.post(`/reviseLog/items/save`, parmas); + if (res?.data?.code === 200) { + setOpen(false); + refresh() + } else { + notify(res.data.msg); + } + } const getData = async () => { setIsLoading(true) @@ -106,12 +107,10 @@ if (res?.data?.code === 200) { setTableData(res.data.data.records); setRowCount(res.data?.data?.total); - } else { notify(res.data.msg); } setIsLoading(false) - }; useEffect(() => { diff --git a/rsf-admin/src/page/stockManage/locRevise/SelectMatnrInfo.jsx b/rsf-admin/src/page/stockManage/locRevise/SelectMatnrInfo.jsx new file mode 100644 index 0000000..3ee7df3 --- /dev/null +++ b/rsf-admin/src/page/stockManage/locRevise/SelectMatnrInfo.jsx @@ -0,0 +1,261 @@ +import React, { useState, useEffect } from "react"; +import { + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Stack, + Grid, + TextField, + Box, + Button, + Paper, + styled +} from '@mui/material'; + +import { EDIT_MODE, DEFAULT_START_PAGE, DEFAULT_PAGE_SIZE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting'; +import DialogCloseButton from "../../components/DialogCloseButton"; +import { useTranslate, useNotify, useRefresh } from 'react-admin'; +import TreeSelectInput from "@/page/components/TreeSelectInput"; +import QueryStatsIcon from '@mui/icons-material/QueryStats'; +import SaveIcon from '@mui/icons-material/Save'; +import { DataGrid } from '@mui/x-data-grid'; +import request from '@/utils/request'; + +const SelectMatnrInfo = (props) => { + const { open, setOpen, data, setData } = props; + const translate = useTranslate(); + const refresh = useRefresh(); + const notify = useNotify(); + + const handleClose = (event, reason) => { + if (reason !== "backdropClick") { + setOpen(false); + } + }; + + const [page, setPage] = useState({ page: DEFAULT_START_PAGE, pageSize: DEFAULT_PAGE_SIZE }); + const [selectedRows, setSelectedRows] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const [tableData, setTableData] = useState([]); + const [formData, setFormData] = useState({}); + const [dyFields, setDyFields] = useState([]); + const [rowCount, setRowCount] = useState(0); + const handleChange = (e) => { + const { name, value } = e.target; + setFormData(() => ({ + [name]: value + })); + }; + + const reset = () => { + setFormData({ + name: null, + code: null, + }) + } + + const handleSubmit = () => { + const hasarr = data.map(el => +el.id) + const selectedData = selectedRows.filter(item => !hasarr.includes(item)).map(id => (tableData.find(row => row.id === id))); + const value = selectedData.map((el => { + const dynamicFields = dyFields.reduce((acc, item) => { + acc[item.fields] = el['extendFields']?.[item.fields] || ''; + return acc; + }, {}); + return { + id: el.id, + matnrId: el.id, + maktx: el.name, + matnrCode: el.code, + batch: el.splrBatch, + unit: el.stockUnit || '', + spec: el.spec, + model: el.model, + fieldsIndex: el.fieldsIndex, + purUnit: el.purchaseUnit || '', + ...dynamicFields + } + })) + setData([...data, ...value]); + setOpen(false); + reset(); + }; + + const getData = async () => { + setIsLoading(true) + const res = await request.post(`/matnr/page`, { + ...formData, + current: page?.page, + pageSize: page?.pageSize, + orderBy: "create_time desc" + }); + if (res?.data?.code === 200) { + setTableData(res.data.data.records); + setRowCount(res.data?.data?.total); + } else { + notify(res.data.msg); + } + setIsLoading(false) + }; + + useEffect(() => { + getData(); + }, [open, page]); + + const handleSearch = () => { + getData() + }; + + return ( + <Dialog + open={open} + onClose={handleClose} + aria-labelledby="form-dialog-title" + fullWidth + disableRestoreFocus + maxWidth="lg" + > + <DialogTitle id="form-dialog-title" sx={{ + position: 'sticky', + top: 0, + backgroundColor: 'background.paper', + zIndex: 1000 + }}> + {translate("common.action.newAddMats")} + <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}> + <DialogCloseButton onClose={handleClose} /> + </Box> + </DialogTitle> + <DialogContent sx={{ mt: 2, }}> + <Box component="form" onSubmit={handleSubmit} sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}> + <Grid container spacing={2}> + <Grid item md={3}> + <TextField + label={translate('table.field.matnr.name')} + name="name" + value={formData.name} + onChange={handleChange} + size="small" + /> + </Grid> + <Grid item md={3}> + <TextField + label={translate('table.field.matnr.code')} + name="code" + value={formData.code} + onChange={handleChange} + size="small" + /> + </Grid> + <Grid item md={3} sx={{display: "flex", margin: 2}}> + <Button variant="contained" onClick={handleSearch} startIcon={<QueryStatsIcon />}>{translate("toolbar.query")}</Button> + </Grid> + </Grid> + </Box> + <Box sx={{ mt: 2, height: 400, width: '100%' }}> + <AsnWareModalTable + tableData={tableData} + setTableData={setTableData} + dyFields={dyFields} + page={page} + rowCount={rowCount} + setPage={setPage} + isLoading={isLoading} + setDyFields={setDyFields} + selectedRows={selectedRows} + setSelectedRows={setSelectedRows} + /> + </Box> + </DialogContent> + <DialogActions sx={{ position: 'sticky', bottom: 1, backgroundColor: 'background.paper', zIndex: 1000 }}> + <Box sx={{ width: '100%', display: 'flex', justifyContent: 'flex-end' }}> + <Button onClick={handleSubmit} variant="contained" startIcon={<SaveIcon />}> + {translate('toolbar.confirm')} + </Button> + </Box> + </DialogActions> + </Dialog> + ); +}; + +export default SelectMatnrInfo; + +const AsnWareModalTable = ({ tableData, setTableData, page, isLoading, pageSize, setPage, rowCount, selectedRows, setSelectedRows, dyFields, setDyFields }) => { + const translate = useTranslate(); + const notify = useNotify(); + + const [columns, setColumns] = useState([ + // { field: 'id', headerName: 'ID', width: 100 }, + { field: 'name', headerName: translate('table.field.matnr.name'), width: 300 }, + { field: 'code', headerName: translate('table.field.matnr.code'), width: 200 }, + { field: 'groupId$', headerName: translate('table.field.matnr.groupId'), width: 100 }, + { field: 'spec', headerName: translate('table.field.matnr.spec'), width: 100 }, + { field: 'model', headerName: translate('table.field.matnr.model'), width: 100 }, + { field: 'weight', headerName: translate('table.field.matnr.weight'), width: 100 }, + { field: 'describle', headerName: translate('table.field.matnr.describle'), width: 100 }, + { field: 'nromNum', headerName: translate('table.field.matnr.nromNum'), width: 100 }, + { field: 'unit', headerName: translate('table.field.matnr.unit'), width: 100 }, + { field: 'purchaseUnit', headerName: translate('table.field.matnr.purUnit'), width: 100 }, + { field: 'stockUnit', headerName: translate('table.field.matnr.stockUnit'), width: 100 }, + { field: 'stockLeval$', headerName: translate('table.field.matnr.stockLevel'), width: 100, sortable: false }, + ]) + + + const handleSelectionChange = (ids) => { + setSelectedRows(ids) + }; + + useEffect(() => { + getDynamicFields(); + }, []); + + const getDynamicFields = async () => { + const { + data: { code, data, msg }, + } = await request.get("/fields/enable/list"); + if (code === 200) { + const cols = data.map(el => ({ + field: el.fields, + headerName: el.fieldsAlise, + minWidth: 100, + flex: 1, + editable: el.unique, + valueGetter: (value, row) => { + return row.extendFields?.[el.fields] || ''; + }, + })) + setDyFields(data) + setColumns([...columns, ...cols]) + } else { + notify(msg); + } + } + + return ( + <div style={{ height: 400, width: '100%' }}> + <DataGrid + size="small" + rows={tableData} + columns={columns} + checkboxSelection + onRowSelectionModelChange={handleSelectionChange} + selectionModel={selectedRows} + disableColumnMenu={true} + disableColumnSorting + disableMultipleColumnsSorting + rowCount={rowCount} + paginationMode="server" + paginationModel={page} + onPaginationModelChange={setPage} + loading={isLoading} + slotProps={{ + loadingOverlay: { + variant: 'linear-progress', + noRowsVariant: 'linear-progress', + }, + }} + /> + </div> + ); +}; \ No newline at end of file -- Gitblit v1.9.1