From 44ae31d5ea49bf686b17b670e56e5984808553a4 Mon Sep 17 00:00:00 2001 From: skyouc Date: 星期六, 02 八月 2025 17:10:42 +0800 Subject: [PATCH] 库存调整修改 --- rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx | 584 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 457 insertions(+), 127 deletions(-) diff --git a/rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx b/rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx index d47e380..36f977a 100644 --- a/rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx +++ b/rsf-admin/src/page/stockManage/locRevise/LocReviseCreate.jsx @@ -1,164 +1,494 @@ 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, + DeleteButton, + SaveButton, + SimpleForm, + useRefresh, + CreateBase, } from 'react-admin'; import { Dialog, DialogActions, DialogContent, DialogTitle, + TextField, + IconButton, + MenuItem, + Tooltip, + Select, + Button, Stack, Grid, Box, } from '@mui/material'; -import DialogCloseButton from "@/page/components/DialogCloseButton"; -import StatusSelectInput from "@/page/components/StatusSelectInput"; -import MemoInput from "@/page/components/MemoInput"; +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 DictSelect from "../../components/DictSelect"; +import SaveIcon from '@mui/icons-material/Save'; +import { styled } from '@mui/material/styles'; +import request from '@/utils/request'; +import _, { set } from 'lodash'; + +const StyledSimpleForm = styled(SimpleForm)(({ theme }) => ({ + '& .MuiToolbar-root-RaToolbar-root': { + '& .RaToolbar-defaultToolbar': { + justifyContent: 'flex-end', + } + } + +})); + 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 [disabled, setDisabled] = useState(false); + 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 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 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 = () => { + if (formData.areaId == null || formData.areaId == undefined) { + notify("搴撳尯涓嶈兘涓虹┖锛侊紒", { type: 'error' }) + return + } + setCreateDialog(true) + } + + const mutationOptions = { + onSuccess: (data) => { + notify(`鏂囩珷 "${data.title}" 鍒涘缓鎴愬姛`, { type: 'success' }); + }, + onError: (error) => { + notify(`鍒涘缓澶辫触: ${error.message}`, { type: 'error' }); } }; - 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 } }); + const handleChange = (value, name) => { + setFormData((prevData) => ({ + ...prevData, + [name]: value + })); }; 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 }}> + <CreateBase resource="locRevise" mutationOptions={mutationOptions} > + <SimpleForm > + <Grid container spacing={2} sx={{ + '& .MuiToolbar-root-RaToolbar-root.RaToolbar-defaultToolbar': { + justifyContent: 'flex-end', + } + }}> + <Grid item md={2}> + <TextInput + source="code" + label={translate("table.field.locRevise.code")} + readOnly + /> </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}> + <AutocompleteInput + choices={dicts} + optionText='label' + optionValue="value" + defaultValue="1" + source="type" + label={translate("table.field.transfer.type")} + /> + </Grid> + <Grid item md={2}> + <ReferenceInput source="areaId" reference="warehouseAreas"> + <AutocompleteInput + optionText='name' + optionValue="id" + label={translate("table.field.locRevise.areaName")} + /> + </ReferenceInput> + </Grid> + <Grid item md={2}> + <DateInput + source="exceTime" + label="table.field.locRevise.exceTime" + /> + </Grid> + </Grid> + </SimpleForm> + </CreateBase> + <Box sx={{ mt: 2 }}> + <Stack direction="row" spacing={2} sx={{ justifyContent: "flex-end" }}> + <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> + <Toolbar sx={{ width: '100%', justifyContent: 'flex-start', bgcolor: 'white' }} > + <Button disabled={disabled} onClick={handleSubmit} variant="contained" startIcon={<SaveIcon />}> + {translate('toolbar.confirm')} + </Button> + </Toolbar> + {/* <CreateBySelectMats + 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: 580, + '& .MuiDataGrid-cell input': { + border: '1px solid #ccc' + }, + }} + /> + </Box> + ); +}; + + export default LocReviseCreate; -- Gitblit v1.9.1