From 8708598a8e75c36dcdd446c634e11bbeaf48ddab Mon Sep 17 00:00:00 2001
From: skyouc
Date: 星期四, 07 八月 2025 10:38:50 +0800
Subject: [PATCH] 库存调整功能优化
---
rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx | 646 +++++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 518 insertions(+), 128 deletions(-)
diff --git a/rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx b/rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx
index d47e380..efc0ff6 100644
--- a/rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx
+++ b/rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx
@@ -1,164 +1,554 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
- CreateBase,
useTranslate,
TextInput,
- NumberInput,
- BooleanInput,
DateInput,
- SaveButton,
- SelectInput,
ReferenceInput,
- ReferenceArrayInput,
AutocompleteInput,
+ SelectColumnsButton,
+ DatagridConfigurable,
Toolbar,
required,
- useDataProvider,
useNotify,
- Form,
- useCreateController,
+ DeleteButton,
+ BooleanField,
+ EditButton,
+ WrapperField,
+ SaveButton,
+ SimpleForm,
+ NumberField,
+ useRefresh,
+ TextField,
+ DateField,
+ CreateBase,
+ TopToolbar,
+ FilterButton,
+ ReferenceField,
+ SearchInput,
+ List,
+ Create,
+ useGetOne,
+ useRecordContext,
} from 'react-admin';
import {
Dialog,
DialogActions,
DialogContent,
DialogTitle,
+ IconButton,
+ MenuItem,
+ Tooltip,
+ Select,
+ Button,
Stack,
Grid,
+ Card,
Box,
+ CardContent,
} from '@mui/material';
-import DialogCloseButton from "@/page/components/DialogCloseButton";
-import StatusSelectInput from "@/page/components/StatusSelectInput";
-import MemoInput from "@/page/components/MemoInput";
+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 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 } = props;
-
- const translate = useTranslate();
+ const { open, setOpen, orderId } = props;
+ const tableRef = useRef();
const notify = useNotify();
+ const refresh = useRefresh();
+ const translate = useTranslate();
+ const [tabelData, setTableData] = useState([]);
+ const [locRevise, setLocRevise] = useState();
+ const [disabled, setDisabled] = useState(false);
+ 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 handleClose = (event, reason) => {
- if (reason !== "backdropClick") {
- setOpen(false);
- }
- };
- const handleSuccess = async (data) => {
- setOpen(false);
- notify('common.response.success');
- };
+ const FormToolbar = () => {
+ return (
+ <Toolbar sx={{ justifyContent: 'flex-end' }}>
+ <SaveButton disabled={disabled} />
+ <DeleteButton mutationMode="optimistic" />
+ </Toolbar>
+ )
+ }
+ // const handleSubmit = async () => {
+ // setFinally()
+ // setDisabled(true)
- const handleError = async (error) => {
- notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
+ // 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: (id) => {
+ setIsVisible("block")
+ setDisabled(true)
+ setLocRevise(id)
+ refresh()
+ },
};
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>
+ <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>
- </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>
+ <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 }}>
+ <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>
+ </Box>
+ <SelectLocsRevise
+ data={tabelData}
+ queryForm={formData}
+ locRevise={locRevise}
+ 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: 'code',
+ headerName: translate('table.field.locItem.locCode'),
+ width: 100,
+ editable: false,
+ },
+ {
+ field: 'areaId',
+ headerName: translate('table.field.loc.areaId'),
+ width: 130,
+ editable: false,
+ },
+ {
+ field: 'type',
+ headerName: translate('table.field.loc.type'),
+ type: 'number',
+ minWidth: 100,
+ flex: 1,
+ editable: true,
+ valueFormatter: (val) => val < 0 ? 0 : val,
+ },
+ {
+ field: 'warehouseId',
+ headerName: translate('table.field.loc.warehouseId'),
+ minWidth: 100,
+ flex: 1,
+ editable: true,
+ renderEditCell: (params) => (
+ <SelectInputSplrCodeEditCell {...params} />
+ ),
+ },
+ {
+ field: 'useStatus',
+ headerName: translate('table.field.loc.useStatus') + "*",
+ minWidth: 100,
+ flex: 1,
+ editable: true,
+ renderEditCell: (params) => (
+ <SelectInputSplrNameEditCell {...params} />
+ ),
+ },
+ {
+ field: 'channel',
+ headerName: translate('table.field.loc.channel'),
+ minWidth: 100,
+ flex: 1,
+ editable: true,
+ },
+ {
+ field: 'row',
+ headerName: translate('table.field.loc.row'),
+ minWidth: 100,
+ flex: 1,
+ editable: false,
+ },
+ {
+ field: 'col',
+ headerName: translate('table.field.loc.col'),
+ minWidth: 100,
+ flex: 1,
+ editable: false,
+ },
+ {
+ field: 'lev',
+ headerName: translate('table.field.loc.lev'),
+ minWidth: 100,
+ flex: 1,
+ editable: false,
+ },
+ ])
+
+ 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 handleSelectionChange = (ids) => {
+ setSelectedRows(ids)
+ };
+
+ tableRef.current = useGridApiRef();
+ const tableIds = tabelData.map(map => map.id);
+
+ 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;
--
Gitblit v1.9.1