打印

224 阅读1分钟

这次需要批量打印样品标识卡(多个table表格),尺寸要求是100*60,遇到了很多问题。 一个table占满一张纸,不换纸,大小刚刚好,需要:

  1. 配置打印机纸张尺寸正确:100*60
  2. window.open()的新页面的默认margin需要清除掉:body{margin:0}
  3. 设置一个table外面有一个不显示的标签,刚好占满整张纸:.card{width:100vw;height:100vh}

打印机配置

打印机纸张尺寸配置:100*60,配置步骤: (先装打印机驱动) 控制面板\硬件和声音\设备和打印机: 右键-> 打印机属性 -> (现在又出现提示驱动没装,已经能打印了,之后再更新)

代码实现

1. 打印的步骤

  1. 获取字符串: let codeHtml = getCodeHtml()
  2. 打开新页面 :win = window.open('', 'printwindow')
  3. 新页面内容渲染: win.document.write(codeHtml)
  4. 打印 win.print()
  5. 关闭页面 win.close() 代码如下:
import { htmlTemplate } from './htmlTemplate';
const getCodeHtml=()=>{ // 获取打印模板
        return htmlTemplate(list)
}
const handlePrint = () =>{ // 打印
    let codeHtml = getCodeHtml()
    const win = window.open('', 'printwindow')
    win.document.write(codeHtml)
    win.print()
    win.close() // 不调用这个方法会导致后续write页面追加,每次不是重新打印
}

2、根据数据 获取打印字符串

htmlTemplate.js 打印模板

import {htmlTemplateStyle} from './htmlTemplateStyle.js'
export const htmlTemplate = (arr) =>{
    
    // <img class="logo" src='http://srtest.weiputech.com/erpImg/logo.png' alt="" />
    let header = `
        <div class="tr_title">
            <div class="logo_wrapper">
                
                <img class="logo" src='./logo.png' alt="" />
            </div>
            <div class="title">
                样品标识卡
            </div>
        </div>
    `

    let trList = (tData)=>{
        let textStr = (item)=>{
            let strt = ''
            strt +=  `
            <div class="tr">
                <div class="th">${item.th}</div>
                <div class="td">`
            if(item.type==='input'){
                strt +=`<div class="input td_text">${item.value}</div>`
            }else if(item.type === 'text'){
                strt += `<div class="td_text">${item.value}</div>`
            }
                strt += `</div>
            </div>
            `
            return strt
        }
        let listStr = (item)=>{
            let checkItemStr = (item)=>{
                // let checkedImgStr = item.isChecked && `<img class="icon_checked" src="http://srtest.weiputech.com/erpImg/check.png" alt="" />` || ''
                let checkedImgStr = item.isChecked && `<img class="icon_checked" src="./check.png" alt="" />` || ''
                return `
                <div class="group_check">
                    <div class="icon_check_table">
                        ${checkedImgStr}
                    </div>
                    <div>
                        ${item.label}
                    </div>
                </div>
                `
            }
            let inputItemStr = (item)=>{
                return `
                <div class="group_check">
                    ${item.type==='inputCheck' && checkItemStr(item) || ''}
                    ${item.type==='input' && item.label||''}
                    <div class="input ${item.type}">${item.value}</div>
                    <div>${item.unit}</div>
                </div>
                `
                
            }
            let res =  `
            <div class="tr">
                <div class="th">${item.th}</div>
                <div class="group_td">
                    `
    
            item.value.forEach(td=>{
                res += `<div class="td">
                        <div class="td_list">
                `
                td.forEach(tdItem=>{
                    switch(tdItem.type){
                        case 'check':
                            // res += 'test'
                            res += checkItemStr(tdItem)
                            break
                        case 'input':
                        case 'inputCheck':
                            res += inputItemStr(tdItem)
                            break;
                        default:
                            res += tdItem.type
                            break;
                    }
                })
                res += `</div>
                    </div>`
            })        
            res +=      `
                </div>
            </div>
            `
            return res
        }
        // trLists.forEach(tData=>{
            let str = ``
            Object.keys(tData).forEach(key=>{
                let tdObj = tData[key]
                const { type} = tdObj
                switch(type){
                    case 'input':
                    case 'text':
                        str += textStr(tdObj)
                        break;
                    case 'list':
                        str += listStr(tdObj)
                        break;
                    default:
                        break
                }
    
            })
        // })
        return str
    }
    let content=htmlTemplateStyle+'<div>'
    arr.forEach(tData=>{
        content += `
        <div class="card">
            <div class="table">
                ${header}
                ${trList(tData)}
            </div>
        </div>
        `
    })
    content += '</div>'
    // content = getReplacedStr(content)
    return content
}

3、获取打印页样式

样式可以通过style标签内嵌 最终是: <style> //...样式 </style>

下面是htmlTemplateStyle.js

export const htmlTemplateStyle=  `<style>
        body{
            margin:0;
        }
        .card{
            width:100vw;
        height:100vh;
        overflow:hidden;
        box-sizing:border-box;
        padding:8px 0;
        }
        .table{
            margin:0 auto;
        width: 340px;
        height:208px;
        border: 1px solid;
        border-bottom: none;
        font-size: 1px;
        color: rgba(0,0,0,0.85);
        line-height: 19px;
        overflow:hidden;
        }
        .input{
            width: 110px;
        border: none;
        border-bottom: 1px solid;
        height: 16px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        
        }
        .tr_title{
            height: 28px;
        line-height: 28px;
        font-size: 15px;
        color: rgba(0,0,0,0.85);
        display: flex;
        justify-content: flex-start;
        align-items: center;
        border-bottom: 1px solid;
        }
        .logo_wrapper{
            box-sizing: border-box;
            width: 70px;
        }
        .logo{
            width:70px;
        }
        .title{
            flex: 1;
        text-align: center;
        }
        .tr{
            width: 100%;
        border-bottom: 1px solid;
        display: flex;
        justify-content: flex-start;
        align-items: center;
        }
        .th{
            box-sizing: border-box;
            padding-left: 5px;
            width: 70px;
            height: 100%; 
            flex-shrink:0;
        }
        .group_td{
            flex: 1;
        }
        .td{
            width: 100%;
            flex: 1;
            box-sizing: border-box;
            height: 19px;
            display: flex;
            justify-content: flex-start;
            align-items: center; 
        }
        .td_text{
            text-align:center;
            width:100%;
        }
        .input.td_text{
            border: none;
            height: 16px;
            padding: 0;
            width: 100%;
            text-align: center;
        }
        .input.inputCheck{
            width: 40px;
        }
        .td_list{
            width: 100%; 
        display: flex;
        align-items: center;
        justify-content: flex-start;
        }
        .group_check{
            padding-left: 10px;
        display: flex;
        flex: left;
        align-items: center;
        }
        .icon_check_table{
            margin-right: 5px;
            width: 10px;
            height: 10px;
            border: 1px solid;
            position: relative;
        }
        .icon_checked{
            width: 8px;
        height: 8px;
         position: absolute;
         left: 1px;
        }
    </style>`

这次想要打印的页面结构是这样的

// <div>
//     <div class="card">
//     <div class="table">
//         {/* 第一行 */}
//         <div class="tr_title">
//             <div class="logo_wrapper">
//                 <img class="logo" src={require('./c68e43d49351935632ed5cb46c358f5.png')} alt="" />
//             </div>
//             <div class="title">
//                 样品标识卡
//             </div>
//         </div>
//         {/* 行 */}
//         {/* type : text input */}
//         <div class="tr">
//             <div class="th"></div>
//             <div class="td"></div>
//         </div>

//         {/* 行 */}
//         {/* type:;list */}
//         <div class="tr">
//             <div class="th"></div>
//             <div class="group_td">
//                 <div class="td">
//                     <div class="td_list">
//                         {/* type: check */}
//                         {/* 遍历 开始 */}
//                         <div class="group_check">
//                             <div class="icon_check_table">
//                                 {/* 需要判断 isChecked */}
//                                 <img class="icon_checked" src="" alt="" />
//                             </div>
//                             <div>
//                                 {/* tdItem.label */}
//                             </div>
//                         </div>
//                         {/* 遍历 结束 */}
//                         {/* type:input 、inputCheck  */}
//                         <div class="group_check">
//                             {/* type: inputCheck */}
//                             <div class="icon_check_table">
//                                 <img class="icon_checked" src="" alt="" />
//                             </div>
//                             {/* end */}
//                             <div>
//                                 {/* tdItem.label */}
//                             </div>
//                             <div>
//                                 {/* tdItem.value */}
//                             </div>
//                             <div>
//                                 {/* tdItem.unit */}
//                             </div>
//                         </div>
//                     </div>
//                 </div>
//             </div>
//         </div>

//     </div>
//  </div>
// </div>