From 6c19e2c3af7e24700c65d47830687a9a1750fb59 Mon Sep 17 00:00:00 2001 From: verou <857149855@qq.com> Date: 星期五, 14 三月 2025 14:58:31 +0800 Subject: [PATCH] feat:选择物料 --- rsf-admin/src/page/asnOrder/AsnOrderList.jsx | 17 + rsf-admin/src/page/asnOrder/AsnOrderPanel.jsx | 5 rsf-admin/vite.config.js | 4 rsf-admin/src/page/asnOrder/AsnWareModal.jsx | 340 ++++++++++++++++++++++++++++ rsf-admin/.env | 2 rsf-admin/src/page/asnOrder/AsnOrderModal.jsx | 300 +++++++++++++++++++++++++ 6 files changed, 658 insertions(+), 10 deletions(-) diff --git a/rsf-admin/.env b/rsf-admin/.env index 0413b02..cfc1d5d 100644 --- a/rsf-admin/.env +++ b/rsf-admin/.env @@ -1,2 +1,2 @@ -VITE_BASE_IP=192.168.4.24 +VITE_BASE_IP=47.76.147.249 VITE_BASE_PORT=8080 diff --git a/rsf-admin/src/page/asnOrder/AsnOrderList.jsx b/rsf-admin/src/page/asnOrder/AsnOrderList.jsx index df6f6b0..8c1c2d1 100644 --- a/rsf-admin/src/page/asnOrder/AsnOrderList.jsx +++ b/rsf-admin/src/page/asnOrder/AsnOrderList.jsx @@ -35,7 +35,7 @@ } from 'react-admin'; import { Box, Typography, Card, Stack } from '@mui/material'; import { styled } from '@mui/material/styles'; -import AsnOrderCreate from "./AsnOrderCreate"; +import AsnOrderModal from "./AsnOrderModal"; import AsnOrderPanel from "./AsnOrderPanel"; import EmptyData from "../components/EmptyData"; import MyCreateButton from "../components/MyCreateButton"; @@ -46,6 +46,7 @@ import * as Common from '@/utils/common'; import ConstructionIcon from "@mui/icons-material/Construction"; import FileDownloadIcon from '@mui/icons-material/FileDownload'; +import EditIcon from '@mui/icons-material/Edit'; const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ @@ -179,12 +180,20 @@ <Button label="toolbar.print" onClick={print}> <FileDownloadIcon /> </Button> - <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} /> + {/* <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} /> */} + <Button + color="primary" + startIcon={<EditIcon />} + onClick={() => { setCreateDialog(true) }} + sx={{ ml: 1 }} + label={'ra.action.edit'} + > + </Button> <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} /> </WrapperField> </StyledDatagrid> </List> - <AsnOrderCreate + <AsnOrderModal open={createDialog} setOpen={setCreateDialog} /> @@ -194,7 +203,7 @@ setDrawerVal={setDrawerVal} > </PageDrawer> - </Box> + </Box > ) } export default AsnOrderList; diff --git a/rsf-admin/src/page/asnOrder/AsnOrderModal.jsx b/rsf-admin/src/page/asnOrder/AsnOrderModal.jsx new file mode 100644 index 0000000..87d0b1f --- /dev/null +++ b/rsf-admin/src/page/asnOrder/AsnOrderModal.jsx @@ -0,0 +1,300 @@ +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, + useRefresh, +} from 'react-admin'; +import { + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Stack, + Grid, + TextField, + Box, + Button, + Paper, + TableContainer, + Table, + TableHead, + TableBody, + TableRow, + TableCell, + styled + + +} from '@mui/material'; +import DialogCloseButton from "../components/DialogCloseButton"; +import StatusSelectInput from "../components/StatusSelectInput"; +import ConfirmButton from "../components/ConfirmButton"; +import AsnWareModal from "./AsnWareModal"; +import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form"; +import SaveIcon from '@mui/icons-material/Save'; +import request from '@/utils/request'; +const AsnOrderModal = (props) => { + const { open, setOpen } = props; + + const translate = useTranslate(); + const notify = useNotify(); + const refresh = useRefresh(); + const [createDialog, setCreateDialog] = useState(false); + + const asnId = '' + + const handleClose = (event, reason) => { + if (reason !== "backdropClick") { + setOpen(false); + } + }; + + const [formData, setFormData] = useState({ + type: '', + wkType: '' + }); + + const [tabelData, setTableData] = useState([]); + + const handleChange = (e) => { + const { name, value } = e.target; + setFormData((prevData) => ({ + ...prevData, + [name]: value + })); + }; + + const handleSubmit = () => { + console.log(formData); + }; + + const handleDelete = async () => { + const res = await request.post(`/asnOrder/remove/${asnId}`, {}); + if (res?.data?.code === 200) { + setOpen(false); + refresh(); + } else { + notify(res.data.msg); + } + + }; + + + return ( + <> + <Dialog + open={open} + onClose={handleClose} + aria-labelledby="form-dialog-title" + fullWidth + disableRestoreFocus + maxWidth="md" // 'xs' | 'sm' | 'md' | 'lg' | 'xl' + > + <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 }}> + <Box component="form" onSubmit={handleSubmit} sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}> + <Grid container spacing={2}> + <Grid item xs={4}> + <TextField + label={translate('table.field.asnOrder.type')} + name="type" + value={formData.type} + onChange={handleChange} + variant="outlined" + size="small" + /> + </Grid> + + <Grid item xs={4}> + <TextField + label={translate('table.field.asnOrder.wkType')} + name="wkType" + value={formData.wkType} + onChange={handleChange} + variant="outlined" + size="small" + /> + </Grid> + </Grid> + </Box> + + <Box sx={{ mt: 2 }}> + <Stack direction="row" spacing={2}> + <Button variant="contained" onClick={() => setCreateDialog(true)}>鏂板鐗╂枡</Button> + {asnId !== '' && <ConfirmButton label={'鍒犻櫎'} variant="outlined" color="error" onConfirm={handleDelete} />} + </Stack> + + </Box> + + <Box sx={{ mt: 2 }}> + <AsnOrderModalTable tabelData={tabelData} setTableData={setTableData} ></AsnOrderModalTable> + </Box> + </DialogContent> + <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> + <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }} > + <Button onClick={handleSubmit} variant="contained" startIcon={<SaveIcon />}> + 纭 + </Button> + </Toolbar> + </DialogActions> + + </Dialog> + + <AsnWareModal + open={createDialog} + setOpen={setCreateDialog} + /> + </> + ) +} + +export default AsnOrderModal; + +const AsnOrderModalTable = ({ tabelData, setTableData }) => { + const translate = useTranslate(); + const notify = useNotify(); + const refresh = useRefresh(); + + const columns = [ + { + id: 'matnrId', + label: 'table.field.asnOrderItem.matnrId', + minWidth: 100, + }, + { + id: 'matnk', + label: 'table.field.asnOrderItem.matnk', + minWidth: 100, + }, + { + id: 'poDetlId', + label: 'table.field.asnOrderItem.poDetlId', + minWidth: 100, + }, + { + id: 'poDetlCode', + label: 'table.field.asnOrderItem.poDetlCode', + minWidth: 100, + }, + { + id: 'anfme', + label: 'table.field.asnOrderItem.anfme', + minWidth: 100, + }, + { + id: 'stockUnit', + label: 'table.field.asnOrderItem.stockUnit', + minWidth: 100, + }, + { + id: 'purQty', + label: 'table.field.asnOrderItem.purQty', + minWidth: 100, + }, + { + id: 'purUnit', + label: 'table.field.asnOrderItem.purUnit', + minWidth: 100, + }, + { + id: 'splrCode', + label: 'table.field.asnOrderItem.splrCode', + minWidth: 100, + }, + { + id: 'splrName', + label: 'table.field.asnOrderItem.splrName', + minWidth: 100, + }, + { + id: 'qrcode', + label: 'table.field.asnOrderItem.qrcode', + minWidth: 100, + }, + { + id: 'barcode', + label: 'table.field.asnOrderItem.barcode', + minWidth: 100, + }, + { + id: 'packName', + label: 'table.field.asnOrderItem.packName', + minWidth: 100, + }] + + const StyledTableRow = styled(TableRow)(({ theme }) => ({ + "& .MuiButtonBase-root.": { + padding: "0px 0px", + }, + })); + + const StyledTableCell = styled(TableCell)(({ theme }) => ({ + "& .MuiButtonBase-root": { + padding: "0px 0px", + }, + overflow: "hidden", + textOverflow: "ellipsis", + whiteSpace: "nowrap", + maxWidth: 600, + })); + + return ( + <TableContainer component={Paper} > + <Table size="small" > + <TableHead> + <StyledTableRow key={'head'}> + {columns.map((column) => { + const value = column.label; + return ( + <StyledTableCell + key={column.id} + align={column.align || "left"} + > + {column.format ? column.format(value) : translate(value)} + </StyledTableCell> + ); + + })} + </StyledTableRow> + </TableHead> + + <TableBody> + {tabelData.map((row) => ( + <StyledTableRow key={row.id || Math.random()}> + {columns.map((column) => ( + <StyledTableCell key={column.id} > + {row[column.id]} + </StyledTableCell> + ))} + </StyledTableRow> + ))} + + </TableBody> + </Table> + </TableContainer> + ) +} diff --git a/rsf-admin/src/page/asnOrder/AsnOrderPanel.jsx b/rsf-admin/src/page/asnOrder/AsnOrderPanel.jsx index b327ecd..6577af7 100644 --- a/rsf-admin/src/page/asnOrder/AsnOrderPanel.jsx +++ b/rsf-admin/src/page/asnOrder/AsnOrderPanel.jsx @@ -30,11 +30,6 @@ } } - const StyledTable = styled(TableRow)(({ theme }) => ({ - "& .MuiButtonBase-root.": { - padding: "0px 0px", - }, - })); const StyledTableRow = styled(TableRow)(({ theme }) => ({ "& .MuiButtonBase-root.": { diff --git a/rsf-admin/src/page/asnOrder/AsnWareModal.jsx b/rsf-admin/src/page/asnOrder/AsnWareModal.jsx new file mode 100644 index 0000000..8bd3975 --- /dev/null +++ b/rsf-admin/src/page/asnOrder/AsnWareModal.jsx @@ -0,0 +1,340 @@ +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, + useRefresh, +} from 'react-admin'; +import { + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Stack, + Grid, + TextField, + Box, + Button, + Paper, + TableContainer, + Table, + TableHead, + TableBody, + TableRow, + TableCell, + Checkbox, + styled + + +} from '@mui/material'; +import DialogCloseButton from "../components/DialogCloseButton"; +import StatusSelectInput from "../components/StatusSelectInput"; +import ConfirmButton from "../components/ConfirmButton"; +import MemoInput from "../components/MemoInput"; +import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form"; +import SaveIcon from '@mui/icons-material/Save'; +import request from '@/utils/request'; +const AsnWareModal = (props) => { + const { open, setOpen } = props; + + const translate = useTranslate(); + const notify = useNotify(); + const refresh = useRefresh(); + + const asnId = '' + + const handleClose = (event, reason) => { + if (reason !== "backdropClick") { + setOpen(false); + } + }; + + const [formData, setFormData] = useState({ + type: '', + wkType: '' + }); + + const [tabelData, setTableData] = useState([{ id: 1 }, { id: 2 }]); + const [selectedRows, setSelectedRows] = useState([]); + + const handleChange = (e) => { + const { name, value } = e.target; + setFormData((prevData) => ({ + ...prevData, + [name]: value + })); + }; + + const handleSubmit = () => { + console.log(formData); + }; + + + + const handleSearch = () => { + }; + + return ( + <Dialog + open={open} + onClose={handleClose} + aria-labelledby="form-dialog-title" + fullWidth + disableRestoreFocus + maxWidth="lg" // 'xs' | 'sm' | 'md' | 'lg' | 'xl' + > + <DialogTitle id="form-dialog-title" sx={{ + position: 'sticky', + top: 0, + backgroundColor: 'background.paper', + zIndex: 1000 + }}> + 閫夋嫨鐗╂枡 + <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}> + <DialogCloseButton onClose={handleClose} /> + </Box> + </DialogTitle> + <DialogContent sx={{ mt: 2 }}> + <Box component="form" onSubmit={handleSubmit} sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}> + <Grid container spacing={2}> + <Grid item xs={4}> + <TextField + label={translate('table.field.asnOrder.type')} + name="type" + value={formData.type} + onChange={handleChange} + variant="outlined" + size="small" + /> + </Grid> + + <Grid item xs={4}> + <TextField + label={translate('table.field.asnOrder.wkType')} + name="wkType" + value={formData.wkType} + onChange={handleChange} + variant="outlined" + size="small" + /> + </Grid> + </Grid> + </Box> + + <Box sx={{ mt: 2 }}> + <Stack direction="row" spacing={2}> + <Button variant="contained" onClick={handleSearch}>鎼滅储</Button> + </Stack> + + </Box> + + <Box sx={{ mt: 2 }}> + <AsnWareModalTable tabelData={tabelData} setTableData={setTableData} selectedRows={selectedRows} + setSelectedRows={setSelectedRows}></AsnWareModalTable> + </Box> + </DialogContent> + <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> + <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }} > + <Button onClick={handleSubmit} variant="contained" startIcon={<SaveIcon />}> + 纭 + </Button> + </Toolbar> + </DialogActions> + + + </Dialog> + ) +} + +export default AsnWareModal; + +const AsnWareModalTable = ({ tabelData, setTableData }) => { + const translate = useTranslate(); + const notify = useNotify(); + const refresh = useRefresh(); + + const [selected, setSelected] = React.useState([]); + + const columns = [ + { + id: 'id', + label: 'ID', + minWidth: 100 + }, + { + id: 'name', + label: 'table.field.matnr.name', + minWidth: 100 + }, + { + id: 'code', + label: 'table.field.matnr.code', + minWidth: 100 + }, + { + id: 'spec', + label: 'table.field.matnr.spec', + minWidth: 100 + }, + { + id: 'model', + label: 'table.field.matnr.model', + minWidth: 100 + }, + { + id: 'weight', + label: 'table.field.matnr.weight', + minWidth: 100 + }, + { + id: 'color', + label: 'table.field.matnr.color', + minWidth: 100 + }, + { + id: 'size', + label: 'table.field.matnr.size', + minWidth: 100 + }, + { + id: 'describle', + label: 'table.field.matnr.describle', + minWidth: 100 + }, + { + id: 'nromNum', + label: 'table.field.matnr.nromNum', + minWidth: 100 + }, + { + id: 'unit', + label: 'table.field.matnr.unit', + minWidth: 100 + }, + { + id: 'purchaseUnit', + label: 'table.field.matnr.purUnit', + minWidth: 100 + }, + { + id: 'stockUnit', + label: 'table.field.matnr.stockUnit', + minWidth: 100 + }, + { + id: 'stockLeval$', + label: 'table.field.matnr.stockLevel', + minWidth: 100, + sortable: false + }, + + + ]; + + const StyledTableRow = styled(TableRow)(({ theme }) => ({ + "& .MuiButtonBase-root.": { + padding: "0px 0px", + }, + })); + + const StyledTableCell = styled(TableCell)(({ theme }) => ({ + "& .MuiButtonBase-root": { + padding: "0px 0px", + }, + overflow: "hidden", + textOverflow: "ellipsis", + whiteSpace: "nowrap", + maxWidth: 600, + })); + + const handleClick = (event, id) => { + const selectedIndex = selected.indexOf(id); + let newSelected = []; + + if (selectedIndex === -1) { + newSelected = newSelected.concat(selected, id); + } else if (selectedIndex === 0) { + newSelected = newSelected.concat(selected.slice(1)); + } else if (selectedIndex === selected.length - 1) { + newSelected = newSelected.concat(selected.slice(0, -1)); + } else if (selectedIndex > 0) { + newSelected = newSelected.concat( + selected.slice(0, selectedIndex), + selected.slice(selectedIndex + 1), + ); + } + setSelected(newSelected); + }; + + // const handleSelectAllClick = (event) => { + // if (event.target.checked) { + // const newSelected = tabelData.map((n) => n.id); + // setSelected(newSelected); + // return; + // } + // setSelected([]); + // }; + + return ( + <TableContainer component={Paper} > + <Table size="small" > + <TableHead> + <StyledTableRow key={'head'}> + <TableCell padding="checkbox"> + <Checkbox + color="primary" + /> + </TableCell> + {columns.map((column) => { + const value = column.label; + return ( + <StyledTableCell + key={column.id} + align={column.align || "left"} + > + {column.format ? column.format(value) : translate(value)} + </StyledTableCell> + ); + + })} + </StyledTableRow> + </TableHead> + + <TableBody> + + {tabelData.map((row) => { + const isItemSelected = selected.includes(row.id); + return (<StyledTableRow key={row.id || Math.random()} aria-checked={isItemSelected} selected={isItemSelected} onClick={(event) => handleClick(event, row.id)}> + <TableCell padding="checkbox"> + <Checkbox + color="primary" + checked={isItemSelected} + /> + </TableCell> + {columns.map((column) => ( + <StyledTableCell key={column.id} > + {row[column.id]} + </StyledTableCell> + ))} + </StyledTableRow>) + })} + + </TableBody> + </Table> + </TableContainer> + ) +} diff --git a/rsf-admin/vite.config.js b/rsf-admin/vite.config.js index cf12736..abba897 100644 --- a/rsf-admin/vite.config.js +++ b/rsf-admin/vite.config.js @@ -20,6 +20,10 @@ '/rsf-server': { target: `http://${env.VITE_BASE_IP}:${env.VITE_BASE_PORT}`, changeOrigin: true, + bypass: (req, res, options) => { + const proxyUrl = `${options.target}${req.url}`; + res.setHeader('x-rel-url', proxyUrl); + } // rewrite: (path) => path.replace(/^\/api/, ''), }, '/ws': { -- Gitblit v1.9.1