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