How to achieve the most realistic Web printing
The company organized a physical examination. In the hospital, I found that I could print the physical examination form quickly with my ID card, which was very convenient. However, on closer inspection, the printing effect was very poor.
The status quo
Note: If you call Ctrl + P directly, it will print the current viewport, you can choose the printer and printer paper, which obviously does not meet the business requirements; If window.print() is called, you can only write CSS to the HTML and upload it to the printer, and you cannot preset the printer, paper, and other Settings, nor save the template. Most of the printing is done by calling window.print() and has the following problems:
Printing style, typesetting problems.
The printing style is different from browser writing. The page display has one set of CSS, and the HTML string passed to the printer also has one set of CSS, and is not compatible with all paper.Unable to qualify default printer, printer paper, and save as template.
Using ActiveX (only in IE) does not meet service requirements.
Use Websocket to establish a connection with the local machine to obtain the printed information from the local machine.Custom paper problems.
Unable to customize paper.The browser display is inconsistent with the printed result.
This is the most common problem that needs to be solved.
Happened to need to do the printing function, so decided to refactor to solve the above problem. I adopted the second scheme and integrated PAZU cloud printing, using an exe script developed by c++, connected with the local Websocket at runtime to return printed information. For more information, please go to PAZU official website
Printing effect
The printed results tend to be real after testing, almost identical with the Web display.
Print ideas
The general idea is to visualize the printer device parameters, configure them, and preset them to the printer device when you click print. If customization is not supported, synchronize to printer first and select.
Print template Settings
1. Obtain printed data
A typical ERP detail page contains details on the primary Table Form and sub-table
1. Get the Form
GetSlideInfo () {
let CondiData = []
let SlideInfoVnode = this.$refs.SlideInfo.$children[0]
let FormItems = findComponentsDownward(SlideInfoVnode, 'FormItem')
FormItems.forEach((item, itemIndex) = > {
let field = item.$children
if (field.length) {
const fieldVnode = item.$children[0]
let fieldValue = this.GetExportFieldValue(fieldVnode)
let formItem = {
key: item.prop,
label: item.label.split(':') [0].
value: fieldValue,
index: itemIndex
}
Object.assign(formItem, fieldVnode.print)
CondiData.push(formItem)
}
})
return CondiData
}
Copy the code
Use FindComponentSProgram to get all formItems, then get the VueComponment of the FormItem, and get the print information in the component instance. To support batch printing of list details, a V-print is registered:
import { typeOf } from '@/libs/util'
export default {
inserted: (el, { value, arg }, vnode)= > {
if(! value)return
if(typeOf(value) ! ='object') value = {}
vnode.componentInstance.print = Object.assign(value, { renderType: arg || 'input' })
},
update: (el, { value, arg }, vnode)= > {
if(! value)return
if(typeOf(value) ! ='object') value = {}
vnode.componentInstance.print = Object.assign(value, { renderType: arg || 'input' })
}
}
Copy the code
The page is then written so that it is mounted to the component instance Data while inserted.
v-print:pick="{id:'orderBranchId',code:'orderBranchCode',name:'orderBranchName'}"
Copy the code
2. Construct and print route data
Before constructing data, we need to build dynamic routes and add them to the front-end route whitelist:
{
path: '/print'.
name: 'print'.
component: Main,
children: [{
path: 'print-setting/:sheetType'.
name: 'print-setting'.
meta: {
title: 'Print Settings'
},
component: (a)= > import('@/view/main-components/print-setting.vue')
}]
}
Copy the code
To keep the data persistent, I save the data to store and set it to sessionStorage:
import { setSession } from '@/libs/session.js'
export default {
state: {
printTabs: {}
},
mutations: {
setPrintTab (state, tab) {
state.printTabs[tab.route] = tab.data
setSession(tab.route, tab.data)
}
}
}
Copy the code
After constructing the data, enter the printing page:
this.setPrintTab({ route: this.$route.meta.code, data: params })
this.$router.push({ name: 'print-setting', params: { sheetType: this.$route.meta.code } })
Copy the code
2. Create a print template
1. Drag and drop integration and self-adaptation
The print drag item is composed of four draggable which can be dragged to each other. Vuedraggable is used here.
<Row style="height:100%">
<Form style="height:100%" justify :label-position="labelPositon" ref="formList">
<draggable id="formList" :list="formList" style="height:100%" group="people" :animation="150" :ghostClass="cls+'-left-item-chosen'">
<Col
:span="8*item.span"
:class="[cls+'-form-item',{'item-select':item.selected}]"
v-for="(item, index) in formList"
:key="index"
@click.native="handleFormItemClick(item, index)"
>
<form-item v-if=! "" item.blank" :label="item.label" >{{item.value}}</form-item>
<div :class="cls+'-blank'" v-else></div>
</Col>
</draggable>
</Form>
</Row>
Copy the code
Set 4 drag groups to drag each other if they are the same.
2. Printer information
Read native printer:
PAZU.TPrinter.getPrinters(a)
Copy the code
Read current printer paper:
PAZU.TPrinter.getPaperForms(a)
Copy the code
Print and print verification:
validatePrintExe () {
return new Promise((resolve, reject) = > {
PAZU.TPrinter.getPrinters(res= > {
if (res === 'err') {
resolve(false)
} else {
resolve(true)
}
})
})
},
async handlePrint () {
if (await this.validatePrintExe()) {
this.doPageSetup()
PAZU.print('printContent'.null.null.true)
api.updatePrintCount({ ids: Object.values(this.printData.ids).join('~&z')},this.printData.action)
} else {
this.showPrintDownLoad = true
}
}
Copy the code
Synchronize custom paper to printer:
handleSynchronizeComfirm () {
this.$refs.synchronizeForm.validate(valid => {
if (valid) {
PAZU.TPrinter.createPaper(this.baseSetting.width, this.baseSetting.height, (res) => {
if (res) {
this.$message. warning(' size [${res}] paper already exists. `)
} else {
this.showPrintor = false
this.$Message.info('Synchronization succeeded. ')
}
}, this.synchronize.printName, this.synchronize.pageName)
}
})
}
Copy the code
The problem summary
One set was problematic to print and in great demand, but when writing the document chapter, I found that I didn’t know how to open up the portable ideas and technical difficulties unilaterally. I don’t know how to write the rest of the article.
First, how to achieve the consistent web display and print results?
- Web display and print styles use the same set of CSS and are configured for adaptation.
How to print pictures?
- You must use the IMG tag and transfer the image to base64.
Three, printing blank page problem and treatment?
- I strictly follow the Web display, accurate to 1px, so it does not appear blank pages, and the typesetting is correct, but when the number of printed pages is more than 100 pages, due to the problem of the browser px decimal calculation, there is about 10mm error when it reaches 100 pages. Then add page-break-after: always to each page and there will be blank pages.
4. Keep-alive dynamic route cache problem
I will explain why I need to modify the source code and why dynamic routing keep-alive failed. I will first test 3.0 keep-Alive when Vue3.0 is officially released.