From 48ad97c8a8afa2c9333bd00545dbc54bb4f0870a Mon Sep 17 00:00:00 2001 From: zjj <3272660260@qq.com> Date: 星期五, 23 五月 2025 09:28:03 +0800 Subject: [PATCH] #盘点出库 --- rsf-admin/src/page/outWork/checkOutBound/CheckOutBoundList.jsx | 358 +++++++++++++++++++++++++++++++++++++++++++++++++++ rsf-admin/src/page/outWork/components/StaSelect.jsx | 0 rsf-admin/src/page/outWork/outBound/OutBoundList.jsx | 4 rsf-admin/src/i18n/zh.js | 3 rsf-admin/src/page/ResourceContent.js | 3 rsf-admin/src/page/outWork/checkOutBound/index.jsx | 18 ++ rsf-admin/src/page/outWork/components/locItemInfoModal.jsx | 0 7 files changed, 383 insertions(+), 3 deletions(-) diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js index 74875e8..d206f30 100644 --- a/rsf-admin/src/i18n/zh.js +++ b/rsf-admin/src/i18n/zh.js @@ -215,10 +215,11 @@ outBound: { stockWithdrawal: '鎻愬彇搴撳瓨', withdrawal:'鎻愬彇', - outSta: '鍑哄簱绔�', + outSta: '鍑哄簱/鎷f枡绔�', outQty: '鍑哄簱鏁伴噺', anfme: '鏁伴噺', createTask: '鐢熸垚浠诲姟', + checkSta: '鐩樼偣绔�' }, basContainer: { diff --git a/rsf-admin/src/page/ResourceContent.js b/rsf-admin/src/page/ResourceContent.js index 9636298..f324b18 100644 --- a/rsf-admin/src/page/ResourceContent.js +++ b/rsf-admin/src/page/ResourceContent.js @@ -50,6 +50,7 @@ import warehouseStock from './statistics/stockManage'; import basContainer from './basicInfo/basContainer'; import outBound from "./outWork/outBound"; +import checkOutBound from "./outWork/checkOutBound"; const ResourceContent = (node) => { switch (node.component) { @@ -145,6 +146,8 @@ return basContainer; case 'outBound': return outBound; + case 'checkOutBound': + return checkOutBound; default: return { list: ListGuesser, diff --git a/rsf-admin/src/page/outWork/checkOutBound/CheckOutBoundList.jsx b/rsf-admin/src/page/outWork/checkOutBound/CheckOutBoundList.jsx new file mode 100644 index 0000000..a290e9c --- /dev/null +++ b/rsf-admin/src/page/outWork/checkOutBound/CheckOutBoundList.jsx @@ -0,0 +1,358 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { useWatch, useFormContext } from "react-hook-form"; +import { + CreateBase, + useTranslate, + TextInput, + NumberInput, + BooleanInput, + DateInput, + SaveButton, + SelectInput, + ReferenceInput, + ReferenceArrayInput, + AutocompleteInput, + Toolbar, + required, + useDataProvider, + useNotify, + Form, + useCreateController, + useListContext, + useRefresh, + Edit, + useRedirect, +} from 'react-admin'; +import { + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Stack, + Grid, + TextField, + Box, + Button, + Paper, + TableContainer, + Table, + TableHead, + TableBody, + TableRow, + TableCell, + Tooltip, + IconButton, + styled, + Select, + MenuItem, + Typography, + Card, +} from '@mui/material'; +import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting'; +import ConfirmButton from "../../components/ConfirmButton"; +import TreeSelectInput from "@/page/components/TreeSelectInput"; +import { DataGrid, useGridApiRef } from '@mui/x-data-grid'; +import DictSelect from "../../components/DictSelect"; +import AddIcon from '@mui/icons-material/Add'; +import DeleteIcon from '@mui/icons-material/Delete'; +import request from '@/utils/request'; +import LocItemInfoModal from "../components/locItemInfoModal"; +import { Delete } from '@mui/icons-material'; +import _, { set } from 'lodash'; +import StaSelect from "../components/StaSelect"; +import { redirect } from "react-router"; +import { number } from "prop-types"; + +const CheckOutBoundList = () => { + + const [createDialog, setCreateDialog] = useState(false); + const [tabelData, setTableData] = useState([]); + const [selectedRows, setSelectedRows] = useState([]); + const [sta, setSta] = useState(""); + const notify = useNotify(); + const tableRef = useRef(); + tableRef.current = useGridApiRef(); + const translate = useTranslate(); + + const handleDeleteItem = () => { + const newTableData = _.filter(tabelData, (item) => !selectedRows.includes(item.matnrId)); + setTableData(newTableData); + } + + // 娣诲姞涓�涓鐞嗘柊鏁版嵁鐨勫嚱鏁帮紝璁剧疆outQty榛樿鍊� + const handleSetData = (newData) => { + // 涓烘柊娣诲姞鐨勬暟鎹缃畂utQty榛樿鍊间负anfme鐨勫�� + const dataWithDefaultQty = newData.map(item => ({ + ...item, + outQty: item.outQty || item.anfme // 濡傛灉outQty宸插瓨鍦ㄥ垯淇濈暀锛屽惁鍒欎娇鐢╝nfme鐨勫�� + })); + setTableData([...tabelData, ...dataWithDefaultQty]); + }; + + + + return ( + <> + <Card sx={{ p: 2, mb: 2, mt: 2 }}> + <Grid container spacing={2}> + <Grid item xs={12}> + <Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 1 }}> + <Typography variant="h6"> + {translate('table.field.outBound.stockWithdrawal')} + </Typography> + <Stack direction='row' spacing={2}> + <Button + variant="contained" + color="primary" + startIcon={<AddIcon />} + onClick={() => setCreateDialog(true)} + > + {translate('table.field.outBound.withdrawal')} + </Button> + </Stack> + </Box> + </Grid> + </Grid> + </Card> + <Card sx={{ p: 2, mb: 2 }}> + <Form> + <Grid container spacing={2}> + <Grid item xs={12}> + <Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 1 }}> + <Typography variant="h6" > + {translate('table.field.outBound.checkSta')} + </Typography> + <Stack direction='row' spacing={2} minWidth={200}> + <StaSelect + source="sta" + label={translate("table.field.outBound.checkSta")} + onChange={(e) => { + setSta(e.target.value); + console.log("绔欑偣宸查�夋嫨:", e.target.value); + }} + size="small" + type="[107]" + /> + </Stack> + <Stack direction='row' spacing={2} minWidth={200}> + <SubmitButton + sta={sta} + data={tabelData} + setTableData={setTableData} + /> + </Stack> + </Box> + </Grid> + </Grid> + </Form> + </Card> + <Card sx={{ mb: 2 }}> + <Box sx={{}}> + <ModalTable tabelData={tabelData} setTableData={setTableData} selectedRows={selectedRows} setSelectedRows={setSelectedRows} tableRef={tableRef}></ModalTable> + </Box> + </Card> + <LocItemInfoModal + open={createDialog} + setOpen={setCreateDialog} + data={tabelData} + setData={handleSetData} + /> + + </> + ) +} + +export default CheckOutBoundList; + +const SubmitButton = (props) => { + const translate = useTranslate(); + const notify = useNotify(); + const redirect = useRedirect(); + const refresh = useRefresh(); + const { sta, data, setTableData } = props; + const check = () => { + if (sta === "" || sta === undefined || sta === null) { + notify("璇烽�夋嫨绔欑偣"); + return; + } + if (data.length === 0) { + notify("璇烽�夋嫨鐗╂枡"); + return; + } + http(sta, data); + } + const http = async (sta, items) => { + console.log(items); + + const filter = items.filter(item => (item.outQty + item.workQty) > item.anfme); + if (filter.length > 0) { + notify(translate('toolbar.request.error.out_stock_qty')) + return + } + const { data: { code, data, msg } } = await request.post(`/locItem/generate/task`, { siteNo: sta, items: items }); + if (code === 200) { + notify(msg); + refresh() + setTableData([]) + redirect("/task") + } else { + notify(msg); + } + } + return ( + <ConfirmButton + variant="contained" + color="primary" + onConfirm={check} + label={"table.field.outBound.createTask"} + > + </ConfirmButton> + ) + +} + +const ModalTable = ({ tabelData, setTableData, selectedRows, setSelectedRows, tableRef }) => { + const translate = useTranslate(); + const notify = useNotify(); + + const [columns, setColumns] = useState([ + { + field: 'outQty', + headerName: translate('table.field.outBound.outQty') + "*", + width: 100, + type: 'number', + editable: true, + headerClassName: "custom", + }, + { + field: 'anfme', + headerName: translate('table.field.locItem.anfme'), + type: 'number', + width: 100, + editable: false, + }, + { + field: 'workQty', + headerName: translate('table.field.locItem.workQty'), + width: 100, + type: 'number', + editable: false, + }, + { + field: 'matnrCode', + headerName: translate('table.field.locItem.matnrCode'), + width: 130, + editable: false, + }, + { + field: 'maktx', + headerName: translate('table.field.locItem.maktx'), + width: 250, + editable: false, + }, + { + field: 'batch', + headerName: translate('table.field.locItem.batch'), + width: 250, + 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(() => { + 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]) + } else { + notify(msg); + } + } + + + const handleDelete = (row) => { + const newData = _.filter(cdata.current, (item) => item.id !== row.id); + setTableData(newData); + }; + + + const processRowUpdate = (newRow, oldRow) => { + const rows = tabelData.map((r) => + r.id === newRow.id ? { ...newRow } : r + ) + setTableData(rows) + return newRow; + }; + + const handleSelectionChange = (ids) => { + setSelectedRows(ids) + }; + + tableRef.current = useGridApiRef(); + + return ( + <div style={{ height: 500, width: '100%' }}> + <DataGrid + apiRef={tableRef} + rows={tabelData} + columns={columns} + disableRowSelectionOnClick + getRowId={(row) => row.matnrId ? row.matnrId : row.id} + disableColumnFilter + disableColumnSelector + disableColumnSorting + disableMultipleColumnsSorting + processRowUpdate={processRowUpdate} + initialState={{ + pagination: { + paginationModel: { + pageSize: 25, + }, + }, + }} + pageSizeOptions={[10, 25, 50, 100]} + editMode="row" + checkboxSelection + onRowSelectionModelChange={handleSelectionChange} + selectionModel={selectedRows} + sx={{ + '& .MuiDataGrid-cell input': { + border: '1px solid #ccc' + }, + }} + /> + </div> + ); +}; diff --git a/rsf-admin/src/page/outWork/checkOutBound/index.jsx b/rsf-admin/src/page/outWork/checkOutBound/index.jsx new file mode 100644 index 0000000..c99b807 --- /dev/null +++ b/rsf-admin/src/page/outWork/checkOutBound/index.jsx @@ -0,0 +1,18 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { + ListGuesser, + EditGuesser, + ShowGuesser, +} from "react-admin"; + +import CheckOutBoundList from "./CheckOutBoundList"; + + +export default { + list: CheckOutBoundList, + edit: EditGuesser, + show: ShowGuesser, + recordRepresentation: (record) => { + return `${record.id}` + } +}; diff --git a/rsf-admin/src/page/outWork/outBound/StaSelect.jsx b/rsf-admin/src/page/outWork/components/StaSelect.jsx similarity index 100% rename from rsf-admin/src/page/outWork/outBound/StaSelect.jsx rename to rsf-admin/src/page/outWork/components/StaSelect.jsx diff --git a/rsf-admin/src/page/outWork/outBound/locItemInfoModal.jsx b/rsf-admin/src/page/outWork/components/locItemInfoModal.jsx similarity index 100% rename from rsf-admin/src/page/outWork/outBound/locItemInfoModal.jsx rename to rsf-admin/src/page/outWork/components/locItemInfoModal.jsx diff --git a/rsf-admin/src/page/outWork/outBound/OutBoundList.jsx b/rsf-admin/src/page/outWork/outBound/OutBoundList.jsx index e7bf5b2..9b9a2e3 100644 --- a/rsf-admin/src/page/outWork/outBound/OutBoundList.jsx +++ b/rsf-admin/src/page/outWork/outBound/OutBoundList.jsx @@ -56,10 +56,10 @@ import AddIcon from '@mui/icons-material/Add'; import DeleteIcon from '@mui/icons-material/Delete'; import request from '@/utils/request'; -import LocItemInfoModal from "./locItemInfoModal"; +import LocItemInfoModal from "../components/locItemInfoModal"; import { Delete } from '@mui/icons-material'; import _, { set } from 'lodash'; -import StaSelect from "./StaSelect"; +import StaSelect from "../components/StaSelect"; import { redirect } from "react-router"; import { number } from "prop-types"; -- Gitblit v1.9.1