美文网首页
前端打印

前端打印

作者: Johnson杰 | 来源:发表于2018-04-17 16:15 被阅读735次

    简单介绍一下前端打印的做法和一些问题

    一、简介

    前端打印即浏览器打印,是通过浏览器的打印功能来实现打印效果的做法。

    通过前端打印,可以实现的功能。


    image.png

    二、基本打印

    首先用最普通的方式实现一些前端打印。

    print.vue:

    <template>
        <div class="print-box" style="margin-left: 20px; margin-right: 20px">
            <h2 class="print-header" style="margin-top: 0px">预分拣单</h2>
    
            <div class="top-info-box">
                <div class="flex-box">
                    <div class="flex-2">预分拣单:{{printData.crossDockingNo}}</div>
                    <div class="flex-1">总SKU数:{{printData.skuQty}}</div>
                    <div class="flex-1">总PCS数:{{printData.pcsQty}}</div>
                </div>
                <div class="flex-box">
                    <div class="flex-1">生单时间:{{printData.createTime}}</div>
                    <div class="flex-1">打印时间:{{printData.printTime}}</div>
                </div>
            </div>
    
            <hr class="top-line" style="margin-top: 2px;margin-bottom: 2px;"/>
    
            <ul class="printTable">
                <li v-for="item in printData.commodityList" :key="item.commodityCode">
                    <div class="table-top-box">
                        <div class="flex-box">
                            <div class="flex-1">商品编码:{{item.commodityCode}}</div>
                            <div class="flex-1">越库数量:{{item.crossQty}}</div>
                        </div>
                        <div class="flex-box">
                            <div class="flex-2">品名:{{item.commodityName}}</div>
                            <div class="flex-1">规格:{{item.spec}}</div>
                            <div class="flex-1">单位:{{item.unit}}</div>
                        </div>
                    </div>
                    <table>
                        <thead>
                            <tr>
                                <th>门店编码</th>
                                <th>门店名称</th>
                                <th>门店库位</th>
                                <th>播种数量</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr v-for="subItem in item.distributionDetail" :key="subItem.storeCode">
                                <td>{{ subItem.storeCode }}</td>
                                <td>{{ subItem.storeName }}</td>
                                <td>{{ subItem.collectionLocation}}</td>
                                <td>{{ subItem.matchQty }}</td>
                            </tr>
                        </tbody>
                    </table>
                </li>
            </ul>
    
            <hr class="bottom-line" style="margin-top: 2px;margin-bottom: 2px;"/>
    
            <div class="footer-center">
                <el-button @click="startPrint" type="primary">打印</el-button>
            </div>
        </div>
    </template>
    
    <script>
        export default {
            data() {
                return {
                    printData: {}
                }
            },
            mounted() {
                this.init();
            },
            methods: {
                init() {
                    const data = {
                        'crossDockingNo': 'PSTSHW000218314-9999',
                        'skuCount': 3,
                        'pcsCount': 2452,
                        'createTime': '2018-03-14 17:40:01',
                        'printTime': '2018-03-14 17:40:01',
                        'commodityList': [
                            {
                                'commodityCode': 200004960001,
                                'commodityName': '薯片',
                                'spec': '32.4g',
                                'unit': '袋',
                                'crossQty': 150,
                                'distributionDetail': [
                                    {
                                        'storeCode': 0,
                                        'storeName': '人广店',
                                        'collectionLocation': 'MENDIAN1',
                                        'matchQty': 21,
                                    }
                                ]
                            }
                        ],
                    };
                    for (let i = 0; i < 10; i++) {
                        const item = Object.assign({}, data.commodityList[0].distributionDetail[0]);
                        item.storeCode = i + 1;
                        data.commodityList[0].distributionDetail.push(item);
                    }
                    for (let i = 0; i < 10; i++) {
                        const item = Object.assign({}, data.commodityList[0]);
                        item.commodityCode = i + 1;
                        data.commodityList.push(data.commodityList[0]);
                    }
                    this.printData = data || {};
                },
                startPrint() {
                    // 打开一个新窗口
                    const myWindow = window.open('', '标题');
    
                    // 获取id为app内的html
                    const bodyHtml = window.document.getElementById('app').innerHTML;
    
                    // 获取head标签内的html
                    let headHtml = document.head.innerHTML;
    
                    // 头中的screen换成打印样式print
                    headHtml = headHtml.replace('screen', 'screen, print');
    
                    //重新写入文档流
                    myWindow.document.write('<html>');
                    myWindow.document.write(headHtml);
                    myWindow.document.write('<body >');
                    myWindow.document.write(bodyHtml);
                    myWindow.document.write('<script>setTimeout(function() {window.print(); window.close();}, 500)</');
                    myWindow.document.write('script>');
                    myWindow.document.write('</body></html>');
                }
            }
        };
    </script>
    
    <style lang="less" scoped>
        @import url("./print.less");
    </style>
    

    print.less:

    .print-box {
        font-size: 12px;
        padding: 2px;
        @media print {
            font-family: "PingFang SC", "Hiragino Sans GB", "Helvetica Neue", Roboto, Noto, sans-serif;
        }
    
        .print-header {
            text-align: center;
            margin-top: 15px;
            font-weight: bold;
        }
    
        .top-line {
            height: 10px;
            border: none;
            border-top: 10px groove;
            margin-top: 12px;
            margin-bottom: 12px;
        }
    
        .table-top-box {
            font-size: 18px;
        }
    
        .flex-box {
            display: flex;
    
            .flex-2 {
                flex: 2;
            }
            .flex-1 {
                flex: 1;
            }
        }
    
        .printTable li {
            margin-top: 20px;
    
            .table-top-box {
                margin-bottom: 10px;
            }
        }
    
        .bottom-line {
            height: 1px;
            border: none;
            border-top: 3px groove; /* solid */
            margin-top: 12px;
            margin-bottom: 12px;
        }
    
        @border-color: #e1e1e1;
    
        .printTable {
            table {
                text-align: center;
                font-size: 12px;
                border: 1px solid @border-color;
                width: 100%;
    
                th, td {
                    padding: 1px;
                    border-bottom: 1px solid @border-color;
                    border-right: 1px solid @border-color;
                }
    
                th {
                    text-align: center;
    
                    &:last-child {
                        border-right: none;
                    }
                }
    
                tr {
                  td:last-child {
                    border-right: none;
                  }
    
                  &:last-child {
                    td {
                      border-bottom: none;
                    }
                  }
                }
            }
        }
    
        .footer-center {
            @media print {
                display: none;
            }
            margin-top: 12px;
            text-align: center;
        }
    }
    

    打印预览:

    image.png

    三、功能设置

    3.1 页面设置

    @page 规则用于指定打印页面的一些属性,包括纸张尺寸、方向、页边距、分页等特性。

    @page :pseudo-class {
      size: A4 landscape;
      margin:2cm;
    }
    

    3.2 分页

    page-break-before用于设置元素前面的分页行为,可取值:

    • auto默认值。如果必要则在元素前插入分页符。
    • always在元素前插入分页符。
    • avoid避免在元素前插入分页符。
    • left在元素之前足够的分页符,一直到一张空白的左页为止。
    • right在元素之前足够的分页符,一直到一张空白的右页为止。
    • inherit规定应该从父元素继承 page-break-before 属性的设置。

    page-break-after设置元素后的分页行为。取值与page-break-before一样。

    page-break-inside设置元素内部的分页行为。取值如下:

    • auto默认。如果必要则在元素内部插入分页符。
    • avoid避免在元素内部插入分页符。
    • inherit规定应该从父元素继承 page-break-inside 属性的设置。
    @media print {
      section {page-break-before: always;}
      h1 {page-break-after: always;}
      p {page-break-inside: avoid;}
    }
    

    3.3 分页保留行数

    orphans设置当元素内部发生分页时必须在页面底部保留的最少行数。
    widows设置当元素内部发生分页时必须在页面顶部保留的最少行数。

    @media print {
      p {orphans:3; widows:2;}
    }
    

    3.4 显示背景色

    打印默认不显示背景色,在 screen 下的设置是不起效果的。
    可以通过设置改变。

    @media print {
      * {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
      }
    }
    

    四、其他

    1. 对于页面上有显示而不想打印的内容,可以将其display设置为none来避免打印。
    2. 需要打印的内容尽量避免float,有些浏览器不会正确的打印浮动的内容。
    3. 可以调用window.print()函数来打印当前页面。
    4. 分页打印或换页打印:page- break-beforepage-break-after CSS属性并不会修改网页在屏幕上的显示,这两个属性是用来控制文件的打印方式。

    相关文章

      网友评论

          本文标题:前端打印

          本文链接:https://www.haomeiwen.com/subject/mgpskftx.html