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({ idsObject.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.