From 0345d3175861c5612e937487770a5ba4e8468b14 Mon Sep 17 00:00:00 2001 From: skyouc Date: 星期六, 10 五月 2025 09:49:52 +0800 Subject: [PATCH] 收货单打印功能优化 --- rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx | 1 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java | 32 ++++---- rsf-admin/package.json | 2 rsf-admin/package-lock.json | 14 ++- rsf-admin/src/page/orders/asnOrder/OrderPrintPreview.jsx | 189 ++++++++++++++++++++++++++-------------------- 5 files changed, 134 insertions(+), 104 deletions(-) diff --git a/rsf-admin/package-lock.json b/rsf-admin/package-lock.json index 4988039..2ccac71 100644 --- a/rsf-admin/package-lock.json +++ b/rsf-admin/package-lock.json @@ -38,7 +38,7 @@ "react-router": "^6.22.0", "react-router-dom": "^6.26.1", "react-syntax-highlighter": "^15.5.0", - "react-to-print": "^3.0.5", + "react-to-print": "^2.14.11", "svgpath": "^2.6.0", "three": "^0.155.0", "tweedle.js": "^2.1.0" @@ -6625,12 +6625,16 @@ } }, "node_modules/react-to-print": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/react-to-print/-/react-to-print-3.1.0.tgz", - "integrity": "sha512-hiJZVmJtaRm9EHoUTG2bordyeRxVSGy9oFVV7fSvzOWwctPp6jbz2R6NFkaokaTYBxC7wTM/fMV5eCXsNpEwsA==", + "version": "2.14.11", + "resolved": "https://registry.npmmirror.com/react-to-print/-/react-to-print-2.14.11.tgz", + "integrity": "sha512-sePHBaCtZLp8/g4d/gRyI9XQZkveZq6xoukanAHfkzlXOa7sTuXCEQOYq37lIa5MkUoxySdJxYuyClaXPa9Zpg==", "license": "MIT", + "dependencies": { + "prop-types": "^15.8.1" + }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ~19" + "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" } }, "node_modules/react-transition-group": { diff --git a/rsf-admin/package.json b/rsf-admin/package.json index f62c51a..4e1d8b2 100644 --- a/rsf-admin/package.json +++ b/rsf-admin/package.json @@ -42,7 +42,7 @@ "react-router": "^6.22.0", "react-router-dom": "^6.26.1", "react-syntax-highlighter": "^15.5.0", - "react-to-print": "^3.0.5", + "react-to-print": "^2.14.11", "svgpath": "^2.6.0", "three": "^0.155.0", "tweedle.js": "^2.1.0" diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx index 0125c45..063790b 100644 --- a/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx +++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx @@ -116,6 +116,7 @@ const [modalType, setmodalType] = useState(0); const [printOrder, setPrintOrder] = useState(false); const [select, setSelect] = useState({}); + const invoiceRef = useRef(); const billReload = useRef(); const notify = useNotify(); const refresh = useRefresh(); diff --git a/rsf-admin/src/page/orders/asnOrder/OrderPrintPreview.jsx b/rsf-admin/src/page/orders/asnOrder/OrderPrintPreview.jsx index 8f6db2f..872afee 100644 --- a/rsf-admin/src/page/orders/asnOrder/OrderPrintPreview.jsx +++ b/rsf-admin/src/page/orders/asnOrder/OrderPrintPreview.jsx @@ -36,6 +36,7 @@ import { styled } from '@mui/material/styles'; import { QRCodeSVG, QRCodeCanvas } from 'qrcode.react'; // 鐜板湪蹇呴』杩欐牱鐢� import PrintOutlinedIcon from '@mui/icons-material/PrintOutlined'; +import { useReactToPrint } from "react-to-print"; const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ '& .css-1vooibu-MuiSvgIcon-root': { @@ -60,8 +61,8 @@ const OrderPrintPreview = (props) => { const { open, setOpen, record } = props; const notify = useNotify(); + const invoiceRef = useRef(); const translate = useTranslate(); - const [drawerVal, setDrawerVal] = useState(false); const [disabled, setDisabled] = useState(false) const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_order_type')) || []; const business = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_business_type')) || []; @@ -70,88 +71,112 @@ setOpen(false); }; + const printOrders = useReactToPrint({ + content: () => { + return invoiceRef.current + }, + documentTitle: `璁㈠崟`, + pageStyle: ` + @page { + size: A4; + margin: 10mm; + } + @media print { + body { + -webkit-print-color-adjust: exact; + } + }`, + onAfterPrint: () => alert('宸插彂閫佽嚦鎵撳嵃鏈�!') + }) + + return ( - <> - <Dialog - open={open} - onClose={handleClose} - aria-labelledby="form-dialog-title" - aria-hidden - fullWidth - disableRestoreFocus - maxWidth="xl" // 'xs' | 'sm' | 'md' | 'lg' | 'xl' - > - <DialogTitle id="form-dialog-title" sx={{ - position: 'sticky', - top: 0, - textAlign: 'center', - backgroundColor: 'background.paper', - zIndex: 1000 - }}> - {translate('menu.asnOrder')} - <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}> - <DialogCloseButton onClose={handleClose} /> - </Box> - </DialogTitle> - <DialogContent sx={{ mt: 2 }}> - <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}> - <Form defaultValues={record}> - <Grid container spacing={2} sx={{ justifyContent: 'space-between', }}> - <Grid item md={2}> - <Box sx={{ display: 'flex', justifyContent: 'center' }}> - <Typography>鍗曟嵁绫诲瀷锛�</Typography> - <Typography>{record?.type$}</Typography> - </Box> - <Box sx={{ display: 'flex', justifyContent: 'center', padding: 1 }}></Box> - <Box sx={{ display: 'flex', justifyContent: 'center' }}> - <Typography>涓氬姟绫诲瀷锛�</Typography> - <Typography>{record?.wkType$}</Typography> - </Box> - </Grid> - <Grid item md={2}> - <QRCodeSVG value={record?.code} /> - <Typography>{record.code}</Typography> - </Grid> - {/* <Grid item md={2}> - <TextInput source="code" label={"table.field.asnOrder.code"} /> - </Grid> */} - </Grid> - </Form> - <List - resource="asnOrderItem" - sx={{ - flexGrow: 1, - transition: (theme) => - theme.transitions.create(['all'], { - duration: theme.transitions.duration.enteringScreen, - }), - marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0, - }} - title={"menu.asnOrderItem"} - empty={false} - filter={{ asnId: record?.id }} - sort={{ field: "create_time", order: "desc" }} - actions={( - <></> - )} - perPage={DEFAULT_ITEM_PAGE_SIZE} - > - <DynamicFields /> - </List> - </Box> - </DialogContent> - <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> - <Toolbar sx={{ width: '100%', justifyContent: 'end' }} > - <Button disabled={disabled} variant="contained" startIcon={<PrintOutlinedIcon />} label={'toolbar.print'}> - </Button> - </Toolbar> - </DialogActions> - </Dialog> - </> + <Dialog + className="orderPrintPerview" + // ref={invoiceRef} + open={open} + onClose={handleClose} + aria-labelledby="form-dialog-title" + aria-hidden + fullWidth + disableRestoreFocus + maxWidth="xl" // 'xs' | 'sm' | 'md' | 'lg' | 'xl' + > + <DialogTitle id="form-dialog-title" sx={{ + position: 'sticky', + top: 0, + textAlign: 'center', + backgroundColor: 'background.paper', + zIndex: 1000 + }}> + {translate('menu.asnOrder')} + <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}> + <DialogCloseButton onClose={handleClose} /> + </Box> + </DialogTitle> + <DialogContent sx={{ mt: 2 }}> + <OrderPreview ref={invoiceRef} record={record} /> + </DialogContent> + <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> + <Toolbar sx={{ width: '100%', justifyContent: 'end' }} > + <Button disabled={disabled} variant="contained" startIcon={<PrintOutlinedIcon />} label={'toolbar.print'} onClick={printOrders}></Button> + </Toolbar> + </DialogActions> + </Dialog> ) } export default OrderPrintPreview; + + + +const OrderPreview = React.forwardRef(({ record }, ref) => ( + <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }} ref={ref}> + <Form defaultValues={record}> + <Grid container spacing={2} sx={{ justifyContent: 'space-between', }}> + <Grid item md={2}> + <Box sx={{ display: 'flex', justifyContent: 'start' }}> + <Typography>ASN鍗曪細</Typography> + <Typography>{record?.code}</Typography> + </Box> + <Box sx={{ display: 'flex', justifyContent: 'start' }}> + <Typography>PO鍗曪細</Typography> + <Typography>{record?.poCode}</Typography> + </Box> + <Box sx={{ display: 'flex', justifyContent: 'start' }}> + <Typography>鍗曟嵁绫诲瀷锛�</Typography> + <Typography>{record?.type$}</Typography> + </Box> + <Box sx={{ display: 'flex', justifyContent: 'center', padding: 1 }}></Box> + <Box sx={{ display: 'flex', justifyContent: 'start' }}> + <Typography>涓氬姟绫诲瀷锛�</Typography> + <Typography>{record?.wkType$}</Typography> + </Box> + <Box sx={{ display: 'flex', justifyContent: 'center', padding: 1 }}></Box> + </Grid> + <Grid item md={2}> + <QRCodeSVG value={record?.code} /> + <Typography>{record.code}</Typography> + </Grid> + </Grid> + </Form> + <List + resource="asnOrderItem" + title={"menu.asnOrderItem"} + empty={false} + filter={{ asnId: record?.id }} + sort={{ field: "create_time", order: "desc" }} + actions={( + <></> + )} + perPage={DEFAULT_ITEM_PAGE_SIZE} + > + <DynamicFields /> + </List> + </Box> +)); + + const DynamicFields = (props) => { const translate = useTranslate(); @@ -167,7 +192,6 @@ const { data: { code, data, msg }, } = await request.get("/fields/enable/list"); if (code == 200) { const arr = [ - <NumberField source="id" />, <NumberField source="asnId" label="table.field.asnOrderItem.asnId" />, <TextField source="asnCode" label="table.field.asnOrderItem.asnCode" />, <TextField source="poDetlId" label="table.field.asnOrderItem.poDetlId" />, @@ -179,9 +203,10 @@ <TextField source="splrBatch" label="table.field.asnOrderItem.splrBatch" />, <NumberField source="anfme" label="table.field.asnOrderItem.anfme" />, <NumberField source="qty" label="table.field.asnOrderItem.qty" />, - <TextField source="splrName" label="table.field.asnOrderItem.splrName" />, + <NumberField source="purQty" label="table.field.asnOrderItem.purQty" />, + // <TextField source="splrName" label="table.field.asnOrderItem.splrName" />, <TextField source="isptResult$" label="table.field.asnOrderItem.isptResult" />, - <TextField source="trackCode" label="table.field.asnOrderItem.barcode" />, + // <TextField source="trackCode" label="table.field.asnOrderItem.barcode" />, <TextField source="packName" label="table.field.asnOrderItem.packName" />, ] const fields = data.map(el => <TextField key={el.fields} source={`extendFields.[${el.fields}]`} label={el.fieldsAlise} />) @@ -214,7 +239,7 @@ preferenceKey='asnOrderItem' bulkActionButtons={false} rowClick={(id, resource, record) => false} - omit={['id', 'asnId', 'poDetlId', 'poDetlCode', 'matnrId', 'purQty', 'purUnit', 'qrcode', 'trackCode']} + omit={['id', 'asnId', 'poDetlId', 'platItemId','poDetlCode', 'matnrId', 'purQty','splrName', 'purUnit', 'qrcode', 'packName' ,'trackCode']} > {columns.map((column) => column)} </StyledDatagrid>} diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java index 2335a25..7ab439d 100644 --- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java +++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java @@ -121,7 +121,7 @@ } params.setOrders(orders); - svaeOrUpdateOrderItem(params,loginUserId); + svaeOrUpdateOrderItem(params, loginUserId); return R.ok("淇濆瓨鎴愬姛!!"); } @@ -150,20 +150,20 @@ return R.ok("鏄庣粏鍙傛暟涓嶈兘涓虹┖锛侊紒"); } - svaeOrUpdateOrderItem(params,loginUserId); + svaeOrUpdateOrderItem(params, loginUserId); return R.ok("淇敼瀹屾垚锛侊紒"); } /** - * @author Ryan - * @description 鏇存柊鎴栦繚瀛樻槑缁� * @param * @return + * @author Ryan + * @description 鏇存柊鎴栦繚瀛樻槑缁� * @time 2025/4/7 13:28 */ @Transactional(rollbackFor = Exception.class) - public void svaeOrUpdateOrderItem(AsnOrderAndItemsParams params, Long loginUserId) throws Exception{ + public void svaeOrUpdateOrderItem(AsnOrderAndItemsParams params, Long loginUserId) throws Exception { AsnOrder orders = params.getOrders(); params.getItems().forEach(item -> { item.put("asnId", orders.getId()); @@ -185,10 +185,10 @@ } /** - * @author Ryan - * @description 鎵归噺淇敼 * @param * @return + * @author Ryan + * @description 鎵归噺淇敼 * @time 2025/4/1 07:58 */ @Override @@ -199,11 +199,11 @@ } return this.update(new LambdaUpdateWrapper<AsnOrder>() .in(AsnOrder::getId, params.getIds()) - .set(!Objects.isNull(order.getRleStatus()), AsnOrder::getRleStatus, order.getRleStatus()) - .set(!Objects.isNull(order.getNtyStatus()), AsnOrder::getNtyStatus, order.getNtyStatus()) - .set(!Objects.isNull(order.getStatus()), AsnOrder::getStatus, order.getStatus()) - .set(!Objects.isNull(order.getWkType()), AsnOrder::getWkType, order.getWkType()) - .set(!Objects.isNull(order.getExceStatus()), AsnOrder::getExceStatus, order.getExceStatus()) + .set(!Objects.isNull(order.getRleStatus()), AsnOrder::getRleStatus, order.getRleStatus()) + .set(!Objects.isNull(order.getNtyStatus()), AsnOrder::getNtyStatus, order.getNtyStatus()) + .set(!Objects.isNull(order.getStatus()), AsnOrder::getStatus, order.getStatus()) + .set(!Objects.isNull(order.getWkType()), AsnOrder::getWkType, order.getWkType()) + .set(!Objects.isNull(order.getExceStatus()), AsnOrder::getExceStatus, order.getExceStatus()) .set(AsnOrder::getUpdateBy, userId)); } @@ -217,7 +217,7 @@ */ @Override @Transactional(rollbackFor = Exception.class) - public R completeOrder(Long id, Long loginUserId) { + public R completeOrder(Long id, Long loginUserId) { AsnOrder asnOrder = this.getById(id); if (Objects.isNull(asnOrder)) { throw new CoolException("鍗曟嵁涓嶅瓨鍦�!!"); @@ -247,14 +247,14 @@ } /** - * @author Ryan - * @description 鍒犻櫎鍘熶富鍗曞強鏄庣粏锛屽姞鍏ュ巻鍙叉。 * @param * @return + * @author Ryan + * @description 鍒犻櫎鍘熶富鍗曞強鏄庣粏锛屽姞鍏ュ巻鍙叉。 * @time 2025/3/19 19:53 */ @Transactional(rollbackFor = Exception.class) - public synchronized void operateOrderLogs(AsnOrder asrder) throws Exception{ + public synchronized void operateOrderLogs(AsnOrder asrder) throws Exception { if (Objects.isNull(asrder) || Objects.isNull(asrder.getId())) { throw new CoolException("鍙傛暟涓嶈兘涓虹┖锛侊紒"); } -- Gitblit v1.9.1