| | |
| | | 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, |
| | | 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 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 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 [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 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 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 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 }}> |
| | | <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 }}> |
| | | <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); |
| | | |
| | | // 如果找到对应的供应商记录,同时更新splrCode字段 |
| | | 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); |
| | | |
| | | // 如果找到对应的供应商记录,同时更新splrCode字段 |
| | | 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; |