From 81fa2ee00313e7f786be6f5c109b92ed612f61c1 Mon Sep 17 00:00:00 2001
From: skyouc
Date: 星期二, 05 八月 2025 13:00:05 +0800
Subject: [PATCH] Merge branch 'devlop' of http://47.97.1.152:5880/r/wms-master into devlop

---
 rsf-admin/src/page/stockManage/locRevise/LocReviseList.jsx    |   70 +-
 rsf-admin/src/page/stockManage/locRevise/LocReviseEdit.jsx    |   71 +--
 rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx       |   16 
 rsf-admin/src/page/stockManage/locRevise/SelectLocsRevise.jsx |  327 ++++++++++++++++
 /dev/null                                                     |  164 --------
 rsf-admin/src/page/stockManage/locRevise/index.jsx            |    0 
 rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx  |  504 +++++++++++++++++++++++++
 rsf-admin/src/page/orders/transfer/ManualCreate.jsx           |    2 
 rsf-admin/src/i18n/zh.js                                      |    2 
 rsf-admin/src/i18n/en.js                                      |    2 
 rsf-admin/src/page/ResourceContent.js                         |    2 
 rsf-admin/src/page/stockManage/locRevise/LocRevisePanel.jsx   |    2 
 rsf-admin/.env                                                |    2 
 13 files changed, 905 insertions(+), 259 deletions(-)

diff --git a/rsf-admin/.env b/rsf-admin/.env
index a3c69b2..f793907 100644
--- a/rsf-admin/.env
+++ b/rsf-admin/.env
@@ -1,3 +1,3 @@
-VITE_BASE_IP=127.0.0.1
+VITE_BASE_IP=192.168.4.151
 # VITE_BASE_IP=47.76.147.249
 VITE_BASE_PORT=8080
diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js
index cb9ec00..f97fa0a 100644
--- a/rsf-admin/src/i18n/en.js
+++ b/rsf-admin/src/i18n/en.js
@@ -910,6 +910,7 @@
                 exceStatus: "Exce Status",
                 orgAreaId: "Area Id",
                 orgAreaName: "Area Name",
+                exceTime: "Exce Time"
             },
             waitPakinItem: {
                 pakinId: "pakinId",
@@ -1290,6 +1291,7 @@
         complete: "complete",
         allComfirm: 'All Comfirm',
         createTransfer: 'Create Transfer Order',
+        createLocRevise: 'Create Stock Revise Order',
         verifyComfirm: 'Verify Comfirm',
         close: "close",
         asnCreate: "Create By Order",
diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js
index aee47ba..e36c5af 100644
--- a/rsf-admin/src/i18n/zh.js
+++ b/rsf-admin/src/i18n/zh.js
@@ -947,6 +947,7 @@
                 exceStatus: "鎵ц鐘舵��",
                 areaId: "搴撳尯ID",
                 areaName: "搴撳尯",
+                exceTime: "璋冩暣鏃堕棿",
             },
             waitPakinItem: {
                 pakinId: "缁勬墭Id",
@@ -1303,6 +1304,7 @@
         complete: "瀹岀粨",
         close: "鍏抽棴",
         createTransfer: '鍒涘缓璋冩嫈鍗�',
+        createLocRevise: '鍒涘缓搴撳瓨璋冩暣鍗�',
         asnCreate: "閫氳繃鍗曟嵁鍒涘缓",
         poCreate: "閫氳繃PO鍗曞垱寤�",
         orderPrint: '鎵撳嵃鍗曟嵁',
diff --git a/rsf-admin/src/page/ResourceContent.js b/rsf-admin/src/page/ResourceContent.js
index 516597e..eb79b43 100644
--- a/rsf-admin/src/page/ResourceContent.js
+++ b/rsf-admin/src/page/ResourceContent.js
@@ -56,7 +56,7 @@
 import check from "./orders/check";
 import checkDiff from "./orders/check/checkDiff";
 import transfer from "./orders/transfer";
-import locRevise from './locRevise';
+import locRevise from './stockManage/locRevise';
 
 
 const ResourceContent = (node) => {
diff --git a/rsf-admin/src/page/locRevise/LocReviseCreate.jsx b/rsf-admin/src/page/locRevise/LocReviseCreate.jsx
deleted file mode 100644
index c8f36e1..0000000
--- a/rsf-admin/src/page/locRevise/LocReviseCreate.jsx
+++ /dev/null
@@ -1,164 +0,0 @@
-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,
-} from 'react-admin';
-import {
-    Dialog,
-    DialogActions,
-    DialogContent,
-    DialogTitle,
-    Stack,
-    Grid,
-    Box,
-} from '@mui/material';
-import DialogCloseButton from "../components/DialogCloseButton";
-import StatusSelectInput from "../components/StatusSelectInput";
-import MemoInput from "../components/MemoInput";
-
-const LocReviseCreate = (props) => {
-    const { open, setOpen } = props;
-
-    const translate = useTranslate();
-    const notify = useNotify();
-
-    const handleClose = (event, reason) => {
-        if (reason !== "backdropClick") {
-            setOpen(false);
-        }
-    };
-
-    const handleSuccess = async (data) => {
-        setOpen(false);
-        notify('common.response.success');
-    };
-
-    const handleError = async (error) => {
-        notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
-    };
-
-    return (
-        <>
-            <CreateBase
-                record={{}}
-                transform={(data) => {
-                    return data;
-                }}
-                mutationOptions={{ onSuccess: handleSuccess, onError: handleError }}
-            >
-                <Dialog
-                    open={open}
-                    onClose={handleClose}
-                    aria-labelledby="form-dialog-title"
-                    fullWidth
-                    disableRestoreFocus
-                    maxWidth="md"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
-                >
-                    <Form>
-                        <DialogTitle id="form-dialog-title" sx={{
-                            position: 'sticky',
-                            top: 0,
-                            backgroundColor: 'background.paper',
-                            zIndex: 1000
-                        }}
-                        >
-                            {translate('create.title')}
-                            <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
-                                <DialogCloseButton onClose={handleClose} />
-                            </Box>
-                        </DialogTitle>
-                        <DialogContent sx={{ mt: 2 }}>
-                            <Grid container rowSpacing={2} columnSpacing={2}>
-                                <Grid item xs={6} display="flex" gap={1}>
-                                    <TextInput
-                                        label="table.field.locRevise.code"
-                                        source="code"
-                                        parse={v => v}
-                                        autoFocus
-                                    />
-                                </Grid>
-                                <Grid item xs={6} display="flex" gap={1}>
-                                    <SelectInput
-                                        label="table.field.locRevise.type"
-                                        source="type"
-                                        choices={[
-                                            { id: 0, name: ' 搴撳瓨璋冩暣' },
-                                            { id:  2, name: ' 鐩樼偣璋冩暣' },
-                                        ]}
-                                    />
-                                </Grid>
-                                <Grid item xs={6} display="flex" gap={1}>
-                                    <NumberInput
-                                        label="table.field.locRevise.anfme"
-                                        source="anfme"
-                                    />
-                                </Grid>
-                                <Grid item xs={6} display="flex" gap={1}>
-                                    <NumberInput
-                                        label="table.field.locRevise.reviseQty"
-                                        source="reviseQty"
-                                    />
-                                </Grid>
-                                <Grid item xs={6} display="flex" gap={1}>
-                                    <SelectInput
-                                        label="table.field.locRevise.exceStatus"
-                                        source="exceStatus"
-                                        choices={[
-                                            { id: 0, name: '鏈墽琛�' },
-                                            { id:  1, name: '鎵ц涓�' },
-                                            { id:  2, name: '鎵ц瀹屾垚' },
-                                        ]}
-                                    />
-                                </Grid>
-                                <Grid item xs={6} display="flex" gap={1}>
-                                    <NumberInput
-                                        label="table.field.locRevise.orgAreaId"
-                                        source="orgAreaId"
-                                    />
-                                </Grid>
-                                <Grid item xs={6} display="flex" gap={1}>
-                                    <TextInput
-                                        label="table.field.locRevise.orgAreaName"
-                                        source="orgAreaName"
-                                        parse={v => v}
-                                    />
-                                </Grid>
-
-                                <Grid item xs={6} display="flex" gap={1}>
-                                    <StatusSelectInput />
-                                </Grid>
-                                <Grid item xs={12} display="flex" gap={1}>
-                                    <Stack direction="column" spacing={1} width={'100%'}>
-                                        <MemoInput />
-                                    </Stack>
-                                </Grid>
-                            </Grid>
-                        </DialogContent>
-                        <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
-                            <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }}  >
-                                <SaveButton />
-                            </Toolbar>
-                        </DialogActions>
-                    </Form>
-                </Dialog>
-            </CreateBase>
-        </>
-    )
-}
-
-export default LocReviseCreate;
diff --git a/rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx b/rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx
index bc1906e..9e5071d 100644
--- a/rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx
+++ b/rsf-admin/src/page/orders/outStock/SelectMatnrModal.jsx
@@ -43,18 +43,18 @@
     Select,
     MenuItem
 } from '@mui/material';
+import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form";
 import DialogCloseButton from "../../components/DialogCloseButton";
 import StatusSelectInput from "../../components/StatusSelectInput";
-import ConfirmButton from "../../components/ConfirmButton";
-import MatnrInfoModal from "./MatnrInfoModal";
-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 _, { set } from 'lodash';
-import { DataGrid, useGridApiRef } from '@mui/x-data-grid';
 import DictionarySelect from "../../components/DictionarySelect";
+import { DataGrid, useGridApiRef } from '@mui/x-data-grid';
+import ConfirmButton from "../../components/ConfirmButton";
+import { Add, Edit, Delete } from '@mui/icons-material';
 import DictSelect from "../../components/DictSelect";
+import SaveIcon from '@mui/icons-material/Save';
+import MatnrInfoModal from "./MatnrInfoModal";
+import request from '@/utils/request';
+import _, { set } from 'lodash';
 import "./asnOrder.css";
 
 const SelectMatnrModal = (props) => {
diff --git a/rsf-admin/src/page/orders/transfer/ManualCreate.jsx b/rsf-admin/src/page/orders/transfer/ManualCreate.jsx
index 00ac693..2990e16 100644
--- a/rsf-admin/src/page/orders/transfer/ManualCreate.jsx
+++ b/rsf-admin/src/page/orders/transfer/ManualCreate.jsx
@@ -38,9 +38,9 @@
 import ConfirmationNumberIcon from '@mui/icons-material/ConfirmationNumber';
 import DialogCloseButton from "../../components/DialogCloseButton.jsx";
 import WarehouseSelect from "../../components/WarehouseSelect.jsx";
-import { useFormContext, useWatch } from "react-hook-form";
 import { DataGrid, useGridApiRef } from '@mui/x-data-grid';
 import ConfirmButton from "../../components/ConfirmButton";
+import { useFormContext, useWatch } from "react-hook-form";
 import CreateBySelectMats from "./CreateBySelectMats.jsx";
 import { Add, Edit, Delete } from '@mui/icons-material';
 import DictSelect from "../../components/DictSelect";
diff --git a/rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx b/rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx
new file mode 100644
index 0000000..d8b8919
--- /dev/null
+++ b/rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx
@@ -0,0 +1,504 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+    useTranslate,
+    TextInput,
+    DateInput,
+    ReferenceInput,
+    AutocompleteInput,
+    SelectColumnsButton,
+    DatagridConfigurable,
+    Toolbar,
+    required,
+    useNotify,
+    DeleteButton,
+    BooleanField,
+    EditButton,
+    WrapperField,
+    SaveButton,
+    SimpleForm,
+    NumberField,
+    useRefresh,
+    TextField,
+    DateField,
+    CreateBase,
+    TopToolbar,
+    FilterButton,
+    SearchInput,
+    List,
+    Create,
+} from 'react-admin';
+import {
+    Dialog,
+    DialogActions,
+    DialogContent,
+    DialogTitle,
+    IconButton,
+    MenuItem,
+    Tooltip,
+    Select,
+    Button,
+    Stack,
+    Grid,
+    Card,
+    Box,
+    CardContent,
+} from '@mui/material';
+import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
+import ConfirmationNumberIcon from '@mui/icons-material/ConfirmationNumber';
+import DialogCloseButton from "../../components/DialogCloseButton.jsx";
+import WarehouseSelect from "../../components/WarehouseSelect.jsx";
+import { useWatch, useFormContext } from "react-hook-form";
+import { DataGrid, useGridApiRef } from '@mui/x-data-grid';
+import ConfirmButton from "../../components/ConfirmButton";
+import { Add, Edit, Delete } from '@mui/icons-material';
+import SelectLocsRevise from "./SelectLocsRevise.jsx";
+import DictSelect from "../../components/DictSelect";
+import SaveIcon from '@mui/icons-material/Save';
+import { styled } from '@mui/material/styles';
+import { redirect } from "react-router";
+import request from '@/utils/request';
+import _, { set } from 'lodash';
+
+const LocReviseCreate = (props) => {
+    const { open, setOpen, orderId } = props;
+    const tableRef = useRef();
+    const notify = useNotify();
+    const refresh = useRefresh();
+    const translate = useTranslate();
+    const [tabelData, setTableData] = useState([]);
+    const [disabled, setDisabled] = useState(false);
+    const [isVisible, setIsVisible] = useState("block");
+    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 (
+            <Toolbar sx={{ justifyContent: 'flex-end' }}>
+                <SaveButton disabled={disabled} />
+                <DeleteButton mutationMode="optimistic" />
+            </Toolbar>
+        )
+    }
+    // const handleSubmit = async () => {
+    //     setFinally()
+    //     setDisabled(true)
+
+    //     if (orderId == null || orderId == undefined) {
+    //         const parmas = {
+    //             "revise": formData,
+    //             "items": tabelData,
+    //         }
+
+    //         const res = await request.post(`/transfer/items/save`, parmas);
+    //         if (res?.data?.code === 200) {
+    //             setOpen(false);
+    //         } else {
+    //             notify(res.data.msg);
+    //         }
+    //     } else {
+    //         const parmas = {
+    //             "transfer": formData,
+    //             "items": tabelData,
+    //         }
+    //         const res = await request.post(`/transfer/items/update`, parmas);
+    //         if (res?.data?.code === 200) {
+    //             setOpen(false);
+    //         } else {
+    //             notify(res.data.msg);
+    //         }
+    //     }
+    //     setDisabled(false)
+    //     refresh();
+
+    // };
+
+    const handleDeleteItem = () => {
+        const newTableData = _.filter(tabelData, (item) => !selectedRows.includes(item.matnrId));
+        setTableData(newTableData);
+    }
+
+    const newAddClick = () => {
+        setCreateDialog(true)
+    }
+
+    const mutationOptions = {
+        onSuccess: (data) => {
+            setIsVisible("block")
+            setDisabled(true)
+            refresh()
+        },
+    };
+
+    const handleChange = (value, name) => {
+        setFormData((prevData) => ({
+            ...prevData,
+            [name]: value
+        }));
+    };
+
+    return (
+        <>
+            <Box sx={{ padding: 1 }}>
+                <Create resource="locRevise"
+                    title={false}
+                    mutationOptions={mutationOptions} >
+                    <SimpleForm toolbar={<FormToolbar />}>
+                        <Grid container spacing={2} sx={{
+                            '& .MuiToolbar-root-RaToolbar-root.RaToolbar-defaultToolbar': {
+                                justifyContent: 'flex-end',
+                            }
+                        }}>
+                            <Grid item md={2}>
+                                <AutocompleteInput
+                                    choices={dicts}
+                                    optionText='label'
+                                    optionValue="value"
+                                    defaultValue="1"
+                                    source="type"
+                                    parse={v => v}
+                                    label={translate("table.field.transfer.type")}
+                                />
+                            </Grid>
+                            <Grid item md={2}>
+                                <ReferenceInput source="areaId" reference="warehouseAreas">
+                                    <AutocompleteInput
+                                        optionText='name'
+                                        optionValue="id"
+                                        parse={v => v}
+                                        label={translate("table.field.locRevise.areaName")}
+                                    />
+                                </ReferenceInput>
+                            </Grid>
+                            <Grid item md={2}>
+                                <DateInput
+                                    source="exceTime"
+                                    parse={v => v}
+                                    label="table.field.locRevise.exceTime"
+                                />
+                            </Grid>
+                        </Grid>
+                    </SimpleForm>
+                </Create>
+                <Box sx={{ display: isVisible }}>
+                    <Card sx={{ height: 630 }}>
+                        <Box>
+                            <Box sx={{ mt: 2 }}>
+                                <Stack direction="row" spacing={2} sx={{ justifyContent: "flex-start" }}>
+                                    <Button variant="contained" onClick={newAddClick} >
+                                        {translate('common.action.newAddMats')}
+                                    </Button>
+                                    <ConfirmButton label={"toolbar.delete"} variant="outlined" color="error" onConfirm={handleDeleteItem} />
+                                </Stack>
+                            </Box>
+                            <Box sx={{ mt: 2 }}>
+                                <TransferTableView
+                                    tabelData={tabelData}
+                                    setTableData={setTableData}
+                                    orderId={orderId}
+                                    selectedRows={selectedRows}
+                                    setSelectedRows={setSelectedRows}
+                                    tableRef={tableRef}>
+                                </TransferTableView>
+                            </Box>
+                        </Box>
+                    </Card>
+                </Box>
+                <SelectLocsRevise
+                    data={tabelData}
+                    queryForm={formData}
+                    open={createDialog}
+                    setOpen={setCreateDialog}
+                    selectedRows={selectedRows}
+                    setSelectedRows={setSelectedRows}
+                    setData={setTableData}
+                />
+            </Box>
+        </>
+    )
+}
+
+const SelectInputSplrNameEditCell = (params) => {
+    const [formData, setFormData] = useState([{}])
+    useEffect(() => {
+        getOptions();
+    }, []);
+    const getOptions = async () => {
+        const parmas = {
+            "type": "supplier"
+        }
+        const {
+            data: { code, data, msg },
+        } = await request.post("companys/page", parmas);
+        if (code === 200) {
+            setFormData(data.records)
+        } else {
+            notify(msg);
+        }
+    }
+
+    return (
+        <Select
+            value={params.value}
+            onChange={(e) => {
+                params.api.setEditCellValue({
+                    id: params.id,
+                    field: params.field,
+                    value: e.target.value,
+                })
+                // 鎵惧埌閫変腑鐨勪緵搴斿晢璁板綍
+                const selectedSupplier = formData.find(supplier => supplier.name === e.target.value);
+
+                // 濡傛灉鎵惧埌瀵瑰簲鐨勪緵搴斿晢璁板綍锛屽悓鏃舵洿鏂皊plrCode瀛楁
+                if (selectedSupplier) {
+                    params.api.setEditCellValue({
+                        id: params.id,
+                        field: 'splrCode',
+                        value: selectedSupplier.id,
+                    });
+                }
+            }}
+            fullWidth
+        >
+            {formData.map(e => {
+                return (
+                    <MenuItem value={e.name} children={e.name} key={e.id} />
+                );
+
+            })}
+
+        </Select>
+    );
+};
+
+const SelectInputSplrCodeEditCell = (params) => {
+    const [formData, setFormData] = useState([{}])
+    useEffect(() => {
+        getOptions();
+    }, []);
+    const getOptions = async () => {
+        const parmas = {
+            "type": "supplier"
+        }
+        const {
+            data: { code, data, msg },
+        } = await request.post("companys/page", parmas);
+        if (code === 200) {
+            setFormData(data.records)
+        } else {
+            notify(msg);
+        }
+    }
+
+    return (
+        <Select
+            value={params.value}
+            onChange={(e) => {
+                params.api.setEditCellValue({
+                    id: params.id,
+                    field: params.field,
+                    value: e.target.value,
+                })
+                const selectedSupplier = formData.find(supplier => supplier.id === e.target.value);
+
+                // 濡傛灉鎵惧埌瀵瑰簲鐨勪緵搴斿晢璁板綍锛屽悓鏃舵洿鏂皊plrCode瀛楁
+                if (selectedSupplier) {
+                    params.api.setEditCellValue({
+                        id: params.id,
+                        field: 'splrName',
+                        value: selectedSupplier.name,
+                    });
+                }
+            }}
+            fullWidth
+
+        >
+            {formData.map(e => {
+                return (
+                    <MenuItem value={e.id} children={e.name} key={e.id} />
+                );
+
+            })}
+
+        </Select>
+    );
+};
+
+
+
+const TransferTableView = ({ tabelData, setTableData, orderId, selectedRows, setSelectedRows, tableRef }) => {
+    const [extendColumns, setExtendColumns] = useState([]);
+    const translate = useTranslate();
+    const notify = useNotify();
+    const [columns, setColumns] = useState([
+        {
+            field: 'maktx',
+            headerName: translate('table.field.outStockItem.maktx'),
+            width: 250,
+            editable: false,
+        },
+        {
+            field: 'matnrCode',
+            headerName: translate('table.field.outStockItem.matnrCode'),
+            width: 130,
+            editable: false,
+        },
+        {
+            field: 'anfme',
+            headerName: translate('table.field.outStockItem.anfme'),
+            type: 'number',
+            minWidth: 100,
+            flex: 1,
+            editable: true,
+            valueFormatter: (val) => val < 0 ? 0 : val,
+        },
+        {
+            field: 'splrCode',
+            headerName: translate('table.field.outStockItem.splrCode'),
+            minWidth: 100,
+            flex: 1,
+            editable: true,
+            renderEditCell: (params) => (
+                <SelectInputSplrCodeEditCell {...params} />
+            ),
+        },
+        {
+            field: 'splrName',
+            headerName: translate('table.field.outStockItem.splrName') + "*",
+            minWidth: 100,
+            flex: 1,
+            editable: true,
+            renderEditCell: (params) => (
+                <SelectInputSplrNameEditCell {...params} />
+            ),
+        },
+        {
+            field: 'batch',
+            headerName: translate('table.field.outStockItem.splrBatch'),
+            minWidth: 100,
+            flex: 1,
+            editable: true,
+        },
+        {
+            field: 'stockUnit',
+            headerName: translate('table.field.outStockItem.stockUnit'),
+            minWidth: 100,
+            flex: 1,
+            editable: true,
+        },
+    ])
+
+    const action = {
+        field: 'action',
+        headerName: '鎿嶄綔',
+        width: 70,
+        lockPosition: 'left',
+        renderCell: (params) => (
+            <Tooltip title="Delete">
+                <IconButton onClick={() => handleDelete(params.row)}>
+                    <Delete />
+                </IconButton>
+            </Tooltip>
+        ),
+    }
+
+    let cdata = useRef([]);
+
+    useEffect(() => {
+        if (extendColumns == undefined || extendColumns.length < 1) {
+            getDynamicFields();
+        }
+    }, []);
+
+    useEffect(() => {
+        cdata.current = tabelData
+    }, [tabelData]);
+
+
+    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: false
+            }))
+            setColumns([...columns, ...cols, action])
+            setExtendColumns(cols);
+        } else {
+            notify(msg);
+        }
+    }
+
+
+    const handleDelete = (row) => {
+        const newData = _.filter(cdata.current, (item) => item.matnrId !== row.matnrId);
+        setTableData(newData);
+    };
+
+
+    const processRowUpdate = (newRow, oldRow) => {
+        const rows = tabelData.map((r) =>
+            r.matnrId === newRow.matnrId ? { ...newRow } : r
+        )
+        setTableData(rows)
+        return newRow;
+    };
+
+    const handleSelectionChange = (ids) => {
+        setSelectedRows(ids)
+    };
+
+    tableRef.current = useGridApiRef();
+
+    const tableIds = tabelData.map(map => map.id);
+    // setSelectedRows(tableIds);
+    // // console.log(selectedRows);
+
+
+    return (
+        <Box>
+            <DataGrid
+                apiRef={tableRef}
+                rows={tabelData}
+                columns={columns}
+                disableRowSelectionOnClick
+                initialState={{
+                    pagination: {
+                        paginationModel: {
+                            pageSize: 25,
+                        },
+                    },
+                }}
+                pageSizeOptions={[15, 25, 50, 100]}
+                editMode="row"
+                checkboxSelection
+                rowSelectionModel={tableIds}
+                onRowSelectionModelChange={handleSelectionChange}
+                sx={{
+                    height: 500,
+                    '& .MuiDataGrid-cell input': {
+                        border: '1px solid #ccc'
+                    },
+                }}
+            />
+        </Box>
+    );
+};
+
+
+export default LocReviseCreate;
diff --git a/rsf-admin/src/page/locRevise/LocReviseEdit.jsx b/rsf-admin/src/page/stockManage/locRevise/LocReviseEdit.jsx
similarity index 62%
rename from rsf-admin/src/page/locRevise/LocReviseEdit.jsx
rename to rsf-admin/src/page/stockManage/locRevise/LocReviseEdit.jsx
index d1e9fda..80db4ee 100644
--- a/rsf-admin/src/page/locRevise/LocReviseEdit.jsx
+++ b/rsf-admin/src/page/stockManage/locRevise/LocReviseEdit.jsx
@@ -24,21 +24,11 @@
 import { Stack, Grid, Box, Typography } from '@mui/material';
 import * as Common from '@/utils/common';
 import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
-import EditBaseAside from "../components/EditBaseAside";
-import CustomerTopToolBar from "../components/EditTopToolBar";
-import MemoInput from "../components/MemoInput";
-import StatusSelectInput from "../components/StatusSelectInput";
+import EditBaseAside from "@/page/components/EditBaseAside";
+import CustomerTopToolBar from "@/page/components/EditTopToolBar";
+import MemoInput from "@/page/components/MemoInput";
+import StatusSelectInput from "@/page/components/StatusSelectInput";
 
-const FormToolbar = () => {
-    const { getValues } = useFormContext();
-
-    return (
-        <Toolbar sx={{ justifyContent: 'space-between' }}>
-            <SaveButton />
-            <DeleteButton mutationMode="optimistic" />
-        </Toolbar>
-    )
-}
 
 const LocReviseEdit = () => {
     const translate = useTranslate();
@@ -53,13 +43,24 @@
             <SimpleForm
                 shouldUnregister
                 warnWhenUnsavedChanges
-                toolbar={<FormToolbar />}
+                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) => { }}
             >
                 <Grid container width={{ xs: '100%', xl: '80%' }} rowSpacing={3} columnSpacing={3}>
-                    <Grid item xs={12} md={8}>
+                    <Grid item xs={24} md={12}>
                         <Typography variant="h6" gutterBottom>
                             {translate('common.edit.title.main')}
                         </Typography>
@@ -68,64 +69,46 @@
                                 label="table.field.locRevise.code"
                                 source="code"
                                 parse={v => v}
-                                autoFocus
+                                readOnly
                             />
-                        </Stack>
-                        <Stack direction='row' gap={2}>
                             <SelectInput
                                 label="table.field.locRevise.type"
                                 source="type"
                                 choices={[
                                     { id: 0, name: ' 搴撳瓨璋冩暣' },
-                                    { id:  2, name: ' 鐩樼偣璋冩暣' },
+                                    { id: 2, name: ' 鐩樼偣璋冩暣' },
                                 ]}
+                                readOnly
                             />
-                        </Stack>
-                        <Stack direction='row' gap={2}>
                             <NumberInput
                                 label="table.field.locRevise.anfme"
                                 source="anfme"
+                                readOnly
                             />
                         </Stack>
                         <Stack direction='row' gap={2}>
                             <NumberInput
                                 label="table.field.locRevise.reviseQty"
                                 source="reviseQty"
+                                readOnly
                             />
-                        </Stack>
-                        <Stack direction='row' gap={2}>
                             <SelectInput
                                 label="table.field.locRevise.exceStatus"
                                 source="exceStatus"
                                 choices={[
                                     { id: 0, name: '鏈墽琛�' },
-                                    { id:  1, name: '鎵ц涓�' },
-                                    { id:  2, name: '鎵ц瀹屾垚' },
+                                    { id: 1, name: '鎵ц涓�' },
+                                    { id: 2, name: '鎵ц瀹屾垚' },
                                 ]}
+                                readOnly
                             />
-                        </Stack>
-                        <Stack direction='row' gap={2}>
-                            <NumberInput
-                                label="table.field.locRevise.orgAreaId"
-                                source="orgAreaId"
-                            />
-                        </Stack>
-                        <Stack direction='row' gap={2}>
                             <TextInput
-                                label="table.field.locRevise.orgAreaName"
+                                label="table.field.locRevise.areaName"
                                 source="orgAreaName"
                                 parse={v => v}
+                                readOnly
                             />
                         </Stack>
-
-                    </Grid>
-                    <Grid item xs={12} md={4}>
-                        <Typography variant="h6" gutterBottom>
-                            {translate('common.edit.title.common')}
-                        </Typography>
-                        <StatusSelectInput />
-                        <Box mt="2em" />
-                        <MemoInput />
                     </Grid>
                 </Grid>
             </SimpleForm>
diff --git a/rsf-admin/src/page/locRevise/LocReviseList.jsx b/rsf-admin/src/page/stockManage/locRevise/LocReviseList.jsx
similarity index 77%
rename from rsf-admin/src/page/locRevise/LocReviseList.jsx
rename to rsf-admin/src/page/stockManage/locRevise/LocReviseList.jsx
index 26e4732..efdc6fc 100644
--- a/rsf-admin/src/page/locRevise/LocReviseList.jsx
+++ b/rsf-admin/src/page/stockManage/locRevise/LocReviseList.jsx
@@ -32,17 +32,17 @@
     AutocompleteInput,
     DeleteButton,
 } from 'react-admin';
-import { Box, Typography, Card, Stack } from '@mui/material';
-import { styled } from '@mui/material/styles';
-import LocReviseCreate from "./LocReviseCreate";
-import LocRevisePanel from "./LocRevisePanel";
-import EmptyData from "../components/EmptyData";
-import MyCreateButton from "../components/MyCreateButton";
-import MyExportButton from '../components/MyExportButton';
-import PageDrawer from "../components/PageDrawer";
-import MyField from "../components/MyField";
 import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
-import * as Common from '@/utils/common';
+import MyCreateButton from "@/page/components/MyCreateButton";
+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': {
@@ -62,12 +62,11 @@
     <SearchInput source="condition" alwaysOn />,
     <DateInput label='common.time.after' source="timeStart" alwaysOn />,
     <DateInput label='common.time.before' source="timeEnd" alwaysOn />,
-
     <TextInput source="code" label="table.field.locRevise.code" />,
     <SelectInput source="type" label="table.field.locRevise.type"
         choices={[
             { id: 0, name: ' 搴撳瓨璋冩暣' },
-            { id:  2, name: ' 鐩樼偣璋冩暣' },
+            { id: 2, name: ' 鐩樼偣璋冩暣' },
         ]}
     />,
     <NumberInput source="anfme" label="table.field.locRevise.anfme" />,
@@ -75,13 +74,12 @@
     <SelectInput source="exceStatus" label="table.field.locRevise.exceStatus"
         choices={[
             { id: 0, name: '鏈墽琛�' },
-            { id:  1, name: '鎵ц涓�' },
-            { id:  2, name: '鎵ц瀹屾垚' },
+            { id: 1, name: '鎵ц涓�' },
+            { id: 2, name: '鎵ц瀹屾垚' },
         ]}
     />,
     <NumberInput source="orgAreaId" label="table.field.locRevise.orgAreaId" />,
     <TextInput source="orgAreaName" label="table.field.locRevise.orgAreaName" />,
-
     <TextInput label="common.field.memo" source="memo" />,
     <SelectInput
         label="common.field.status"
@@ -95,10 +93,9 @@
 ]
 
 const LocReviseList = () => {
-    const translate = useTranslate();
-
     const [createDialog, setCreateDialog] = useState(false);
     const [drawerVal, setDrawerVal] = useState(false);
+    const translate = useTranslate();
 
     return (
         <Box display="flex">
@@ -112,7 +109,7 @@
                     marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                 }}
                 title={"menu.locRevise"}
-                empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
+                empty={false}
                 filters={filters}
                 sort={{ field: "create_time", order: "desc" }}
                 actions={(
@@ -127,11 +124,11 @@
             >
                 <StyledDatagrid
                     preferenceKey='locRevise'
-                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
+                    bulkActionButtons={false}
                     rowClick={(id, resource, record) => false}
-                    expand={() => <LocRevisePanel />}
+                    expand={false}
                     expandSingle={true}
-                    omit={['id', 'createTime', 'createBy', 'memo']}
+                    omit={['id', 'createTime', 'createBy', 'orgAreaId', 'memo']}
                 >
                     <NumberField source="id" />
                     <TextField source="code" label="table.field.locRevise.code" />
@@ -139,16 +136,11 @@
                     <NumberField source="anfme" label="table.field.locRevise.anfme" />
                     <NumberField source="reviseQty" label="table.field.locRevise.reviseQty" />
                     <TextField source="exceStatus$" label="table.field.locRevise.exceStatus" sortable={false} />
-                    <NumberField source="orgAreaId" label="table.field.locRevise.orgAreaId" />
-                    <TextField source="orgAreaName" label="table.field.locRevise.orgAreaName" />
-
-                    <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}>
-                        <TextField source="nickname" />
-                    </ReferenceField>
+                    <NumberField source="orgAreaId" label="table.field.locRevise.areaId" />
+                    <TextField source="orgAreaName" label="table.field.locRevise.areaName" />
+                    <TextField source="updateBy$" label="common.field.updateBy" />
                     <DateField source="updateTime" label="common.field.updateTime" showTime />
-                    <ReferenceField source="createBy" label="common.field.createBy" reference="user" link={false} sortable={false}>
-                        <TextField source="nickname" />
-                    </ReferenceField>
+                    <DateField 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} />
@@ -158,16 +150,16 @@
                     </WrapperField>
                 </StyledDatagrid>
             </List>
-            <LocReviseCreate
-                open={createDialog}
-                setOpen={setCreateDialog}
-            />
-            <PageDrawer
-                title='LocRevise Detail'
-                drawerVal={drawerVal}
-                setDrawerVal={setDrawerVal}
+            <PageEditDrawer
+                title={"toolbar.createLocRevise"}
+                drawerVal={createDialog}
+                setDrawerVal={setCreateDialog}
             >
-            </PageDrawer>
+                <LocReviseCreate
+                    open={createDialog}
+                    setOpen={setCreateDialog}
+                />
+            </PageEditDrawer>
         </Box>
     )
 }
diff --git a/rsf-admin/src/page/locRevise/LocRevisePanel.jsx b/rsf-admin/src/page/stockManage/locRevise/LocRevisePanel.jsx
similarity index 98%
rename from rsf-admin/src/page/locRevise/LocRevisePanel.jsx
rename to rsf-admin/src/page/stockManage/locRevise/LocRevisePanel.jsx
index 8ad740f..2360324 100644
--- a/rsf-admin/src/page/locRevise/LocRevisePanel.jsx
+++ b/rsf-admin/src/page/stockManage/locRevise/LocRevisePanel.jsx
@@ -4,7 +4,7 @@
     useTranslate,
     useRecordContext,
 } from 'react-admin';
-import PanelTypography from "../components/PanelTypography";
+import PanelTypography from "@/page/components/PanelTypography";
 import * as Common from '@/utils/common'
 
 const LocRevisePanel = () => {
diff --git a/rsf-admin/src/page/stockManage/locRevise/SelectLocsRevise.jsx b/rsf-admin/src/page/stockManage/locRevise/SelectLocsRevise.jsx
new file mode 100644
index 0000000..1d66d19
--- /dev/null
+++ b/rsf-admin/src/page/stockManage/locRevise/SelectLocsRevise.jsx
@@ -0,0 +1,327 @@
+import React, { useState, useEffect } 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 DialogCloseButton from "../../components/DialogCloseButton";
+import {
+    useTranslate, useNotify, useRefresh, List, FilterButton, NumberField,
+    DateField, ReferenceInput, AutocompleteInput, TextInput, DatagridConfigurable,
+    BooleanField, SearchInput,
+} from 'react-admin';
+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';
+import request from '@/utils/request';
+
+
+
+const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
+    '& .css-1vooibu-MuiSvgIcon-root': {
+        height: '.9em'
+    },
+    '& .RaDatagrid-row': {
+        cursor: 'auto'
+    },
+    '& .column-name': {
+    },
+    '& .opt': {
+        width: 180
+    },
+}));
+
+
+
+const SelectLocsRevise = (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 dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_stock_revise_type')) || [];
+    const [formData, setFormData] = useState({});
+    const [tableData, setTableData] = useState([]);
+    const [dyFields, setDyFields] = useState([]);
+    const [selectedRows, setSelectedRows] = useState([]);
+    const [page, setPage] = useState({ page: DEFAULT_START_PAGE, pageSize: DEFAULT_PAGE_SIZE });
+    const [rowCount, setRowCount] = useState(0);
+    const [isLoading, setIsLoading] = useState(false);
+    const handleChange = (e) => {
+        const { name, value } = e.target;
+        setFormData(() => ({
+            [name]: value
+        }));
+    };
+
+    const reset = () => {
+        setFormData({
+            name: '',
+            code: '',
+            groupId: 0
+        })
+    }
+
+    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 value = selectedData.map((el => {
+            const dynamicFields = dyFields.reduce((acc, item) => {
+                acc[item.fields] = el['extendFields']?.[item.fields] || '';
+                return acc;
+            }, {});
+            return {
+                matnrId: el.id,
+                maktx: el.name,
+                matnrCode: el.code,
+                stockUnit: el.stockUnit || '',
+                purUnit: el.purchaseUnit || '',
+                ...dynamicFields
+            }
+        }))
+        setData([...data, ...value]);
+        setOpen(false);
+        reset();
+    };
+
+    const filters = [
+        <SearchInput source="condition" alwaysOn />,
+    ]
+
+    const getData = async () => {
+        setIsLoading(true)
+        const res = await request.post(`/locItem/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="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 }}>
+                        <Grid container spacing={2} md={6}>
+                            <Grid item md={4}>
+                                <TextField
+                                    label={translate('table.field.locItem.locCode')}
+                                    name="locCode"
+                                    value={formData.name}
+                                    onChange={handleChange}
+                                    size="small"
+                                />
+                            </Grid>
+                            <Grid item md={2} sx={{ margin: 'auto' }}>
+                                <Button variant="contained" onClick={handleSearch}>鎼滅储</Button>
+                            </Grid>
+                        </Grid>
+                    </Box>
+                    <Box sx={{ mt: 2, height: 600, width: '100%' }}>
+                        <AsnWareModalTable
+                            tableData={tableData}
+                            setTableData={setTableData}
+                            dyFields={dyFields}
+                            page={page}
+                            rowCount={rowCount}
+                            setPage={setPage}
+                            isLoading={isLoading}
+                            setDyFields={setDyFields}
+                            selectedRows={selectedRows}
+                            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>
+    );
+};
+
+export default SelectLocsRevise;
+
+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: 'locCode', headerName: translate('table.field.locItem.locCode'), width: 150 },
+        { field: 'matnrCode', headerName: translate('table.field.locItem.matnrCode'), width: 200 },
+        { field: 'maktx', headerName: translate('table.field.locItem.maktx'), width: 300 },
+        { field: 'batch', headerName: translate('table.field.locItem.batch'), width: 100 },
+        { field: 'anfme', headerName: translate('table.field.locItem.anfme'), width: 100 },
+        { field: 'unit', headerName: translate('table.field.matnr.unit'), width: 100 },
+    ])
+
+    const action = {
+        field: 'action',
+        headerName: '鎿嶄綔',
+        width: 140,
+        lockPosition: 'left',
+        renderCell: (params) => (
+            <Tooltip title="Delete">
+                <IconButton onClick={() => handleDelete(params.row)}>
+                    <Delete />
+                </IconButton>
+                <IconButton onClick={() => handleDelete(params.row)}>
+                    <Save />
+                </IconButton>
+            </Tooltip>
+        ),
+    }
+
+
+    const handleSelectionChange = (ids) => {
+        setSelectedRows(ids)
+    };
+
+    useEffect(() => {
+        if (dyFields.length < 1) {
+            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, action])
+        } else {
+            notify(msg);
+        }
+    }
+
+    return (
+        <div style={{ width: '100%' }}>
+            <DataGrid
+                sx={{ height: 600 }}
+                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
diff --git a/rsf-admin/src/page/locRevise/index.jsx b/rsf-admin/src/page/stockManage/locRevise/index.jsx
similarity index 100%
rename from rsf-admin/src/page/locRevise/index.jsx
rename to rsf-admin/src/page/stockManage/locRevise/index.jsx

--
Gitblit v1.9.1