skyouc
9 天以前 0345d3175861c5612e937487770a5ba4e8468b14
收货单打印功能优化
5个文件已修改
238 ■■■■■ 已修改文件
rsf-admin/package-lock.json 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/package.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/orders/asnOrder/OrderPrintPreview.jsx 189 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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": {
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"
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();
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>}
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("参数不能为空!!");
        }