在基於ABP框架的前端項目Vue&Element項目中採用電子簽章處理文件和列印處理

在一些內部OA或者流轉的文件,或者給一些客戶的報價文件、合約,或者一些醫院出示的給保險機構的病歷資料等,有時候可能都希望快速的使用電子簽章的處理方式來給文件蓋上特定的印章,本篇隨筆介紹基於Vue&Element的前端項目採用第三方組件

vue-drag-resize和圖片轉換Base64的方式實現圖片印章的蓋章處理。

1、圖片轉換為Base64處理

圖片轉換為Base64編碼可以通過在線工具的轉換方式實現圖片轉Base64編碼,網上很多在線的處理,百度一下即可。
如://c.runoob.com/front-end/59/ 或者 //tool.chinaz.com/tools/imgtobase 試過都可以,非常方便。
如果我們喜歡通過C#程式碼進行圖片的轉換也可以使用自己封裝的函數實現處理,如下所示。

Base64 在CSS中的使用

.demoImg{ background-image: url("data:image/jpg;base64,/9j/4QMZRXhpZgAASUkqAAgAAAAL...."); }

Base64 在HTML中的使用

<img width="40" height="30" src="data:image/jpg;base64,/9j/4QMZRXhpZgAASUkqAAgAAAAL...." />

 

我們使用C#程式碼轉換的處理程式碼如下所示。

        private void btnBase64_Click(object sender, EventArgs e)
        {
            var base64 = ImageHelper.ImageToBase64Str(this.pictureBox1.Image);
            if(chkData.Checked)
            {
                base64 = "data:image/jpeg;base64," + base64;
            }
            this.txtBase64.Text = base64;
        }

而其中調用是通過我們公用類庫中的圖片輔助類進行,詳細轉換程式碼如下所示。

        /// <summary>
        /// 從文件中轉換圖片對象到Base64編碼
        /// </summary>
        /// <param name="imageFilePath">圖片文件路徑</param>
        /// <returns></returns>
        public static string ImageToBase64Str(string imageFilePath)
        {
            Image image = Image.FromFile(imageFilePath);
            using (MemoryStream ms = new MemoryStream())
            {
                image.Save(ms, image.RawFormat);//ImageFormat.Jpeg
                byte[] imageBytes = ms.GetBuffer();
                string imgBase64Str = Convert.ToBase64String(imageBytes);

                //釋放資源,讓別的使用
                image.Dispose();
                return imgBase64Str;
            }
        }

        /// <summary>
        /// 轉換圖片對象到Base64編碼
        /// </summary>
        /// <param name="image">Image圖片對象</param>
        /// <returns></returns>
        public static string ImageToBase64Str(Image image)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                image.Save(ms, image.RawFormat);//ImageFormat.Jpeg
                byte[] imageBytes = ms.GetBuffer();
                string imgBase64Str = Convert.ToBase64String(imageBytes);
                return imgBase64Str;
            }
        } 

這樣,我們在前端Vue的項目中,就可以賦值這段圖片Base64程式碼到HTML文件中就可以了,如下是前端Vue項目程式碼所示(縮減了部分Base64編碼)。

這樣我們就可以在頁面中放置一個Base64編碼的圖片在頁面中了。

 

2、使用vue-drag-resize組件實現印章圖片的拖動

常規的圖片,放置在頁面中,位置是固定的,如果我們需要拖動印章,那麼就需要引入可拖動面板的Vue組件vue-drag-resize來處理它了。

vue-drag-resize是Github上的一個開源組件,地址是://github.com/kirillmurashov/vue-drag-resize

這個組件的使用和其他組件的使用方式一樣,非常方便。

import Vue from 'vue'
import VueDragResize from 'vue-drag-resize'

Vue.component('vue-drag-resize', VueDragResize)

在組件或者頁面中使用的程式碼如下所示。

import VueDragResize from 'vue-drag-resize'
export default {
  components: { VueDragResize },

它的HTML程式碼如下所示。

<template>
    <div id="app">
        <VueDragResize :isActive="true" :w="200" :h="200" v-on:resizing="resize" v-on:dragging="resize">
            <h3>Hello World!</h3>
            <p>{{ top }} х {{ left }} </p>
            <p>{{ width }} х {{ height }}</p>
        </VueDragResize>
    </div>
</template>

為了把印章圖片可以拖動,我們在HTML中放置印章圖片包含在這個組件面板中。

如下面程式碼所示。

把圖片放置在這個組件容器中後,圖片就可以隨意拖動,確認位置後,就可以確定它的位置,我們可以通過記錄圖片的位置X, Y的值並存儲起來,下次直接確定位置也可以。

定義組件的初始X位置。

<vue-drag-resize :x="0">

定義組件的初始Y位置。

<vue-drag-resize :y="0">

例如我們定義了一個報價單,並通過設置,把圖片放置在頁面中,讓使用者可以通過拖動印章的方式,放到合適的位置上去,然後進行列印報價單即可帶有印章的報價單出來了。

 這樣就可以實現電子印章的拖動和放置處理了,記住其位置和狀態,下次就可以直接定位到指定的位置上了。

另外,一般文檔都需要列印,關於列印的處理,有很多方式,可以使用print.js(//github.com/crabbly/Print.js),也可以使用 vue-print-nb (//github.com/Power-kxLee/vue-print-nb),甚至複雜的定義可以考慮使用CLODOP組件來處理,不過我們這裡可以簡單的內置Windows 對象的列印操作方式來處理普通的頁面列印即可。

    print () {
      const print = this.$refs.print.innerHTML
      const printPart = print + csstyle;
      const newTab = window.open('_blank');
      newTab.document.body.innerHTML = printPart;
      newTab.print();
      newTab.close();
    },

列印效果如下所示,採用了對應的CSS樣式處理後,和實際的頁面效果相當。

 

在項目中,涉及到了html內容列印的需求,調用了瀏覽器的window.print用於列印
顯示不全問題

由於window.print是1:1列印,列印內容過寬時,瀏覽器會自動從左截取掉超寬部分,因此在列印前需將頁面進行調整
列印頁邊距設定為 0mm 時,網頁內最大元素的解析度:794×1123
因此可以將內容div設置為700px,剩餘空間設置為頁邊距

去除瀏覽器默認頁眉頁腳

頁眉列印默認有頁眉頁腳資訊,展現到頁面外邊距範圍,我們可以通過去除頁面模型page的外邊距,使得內容不會延伸到頁面的邊緣,再通過設置 body 元素的 margin 來保證 A4 紙列印出來的頁面帶有外邊距

由於window.print列印自帶頁眉頁腳,用於存放列印url,日期時間,頁面名稱等內容,為屏蔽這些內容可使用css進行屏蔽

@media print {
  @page {
    margin: 0;
  }
  body {
    margin: 1cm;
  }
}

只屏蔽頁腳

@page { margin-bottom: 0; }
事件監聽

有兩個事件可以監聽到到列印事件,一個是beforeprint,一個是afterprint,分別表示列印事件觸發前後。
這個事件在 IE6 就已經支援了,兼容大概是 Firefox、IE全支援, Chrome63+支援, Safari暫不支援

我們可在處理事件onbeforeprint() 將一些不需要列印的元素隱藏,和列印後的處理事件 onafterprint()放開隱藏的元素

window.addEventListener('beforeprint', ()=> {
  document.body.innerHTML = '列印前觸發';
});

window.addEventListener('afterprint', ()=> {
  document.body.innerHTML = '列印後觸發';
});
設置列印布局(橫向、縱向、邊距)
 @media print {
    @page {
      // 縱向
      size: portrait; 
 
     // 橫向
      size: landscape;
 
      // 邊距
      margin: 0cm 0cm 0cm 0cm;
    }
  }

 

 如果需要了解更多Vue&Element的開發知識,可以查看我的隨筆分類,裡面總結了很多我在實際開發過程中遇到的問題,和經驗分享。

循序漸進VUE+Element