Explorar o código

pdf导出功能

Your Name hai 2 meses
pai
achega
c77ab5a696
Modificáronse 4 ficheiros con 117 adicións e 18 borrados
  1. 38 0
      package-lock.json
  2. 13 14
      package.json
  3. 48 0
      src/utils/htmlToPdf.js
  4. 18 4
      src/views/anscard/Index.vue

+ 38 - 0
package-lock.json

@@ -5846,6 +5846,11 @@
         "regenerator-runtime": "^0.11.0"
       }
     },
+    "base64-arraybuffer": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
+      "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ=="
+    },
     "base64-js": {
       "version": "1.5.1",
       "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz",
@@ -7548,6 +7553,14 @@
       "resolved": "https://registry.npmmirror.com/cropperjs/-/cropperjs-1.5.12.tgz",
       "integrity": "sha512-re7UdjE5UnwdrovyhNzZ6gathI4Rs3KGCBSc8HCIjUo5hO42CtzyblmWLj6QWVw7huHyDMfpKxhiO2II77nhDw=="
     },
+    "css-line-break": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
+      "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
+      "requires": {
+        "utrie": "^1.0.2"
+      }
+    },
     "css-loader": {
       "version": "1.0.1",
       "resolved": "https://registry.npmmirror.com/css-loader/download/css-loader-1.0.1.tgz?cache=0&sync_timestamp=1635967924209&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fcss-loader%2Fdownload%2Fcss-loader-1.0.1.tgz",
@@ -14735,6 +14748,15 @@
         }
       }
     },
+    "html2canvas": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
+      "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
+      "requires": {
+        "css-line-break": "^2.1.0",
+        "text-segmentation": "^1.0.3"
+      }
+    },
     "http-proxy-middleware": {
       "version": "0.19.1",
       "resolved": "https://registry.nlark.com/http-proxy-middleware/download/http-proxy-middleware-0.19.1.tgz",
@@ -24289,6 +24311,14 @@
         }
       }
     },
+    "text-segmentation": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
+      "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
+      "requires": {
+        "utrie": "^1.0.2"
+      }
+    },
     "thread-loader": {
       "version": "2.1.3",
       "resolved": "https://registry.nlark.com/thread-loader/download/thread-loader-2.1.3.tgz",
@@ -24871,6 +24901,14 @@
         }
       }
     },
+    "utrie": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
+      "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
+      "requires": {
+        "base64-arraybuffer": "^1.0.2"
+      }
+    },
     "uuid": {
       "version": "3.4.0",
       "resolved": "https://registry.npmmirror.com/uuid/-/uuid-3.4.0.tgz",

+ 13 - 14
package.json

@@ -15,32 +15,32 @@
     "cropperjs": "^1.5.12",
     "echarts": "^4.9.0",
     "element-ui": "^2.7.2",
+    "fabric": "^4.6.0",
+    "file-saver": "^2.0.5",
     "font-awesome": "^4.7.0",
+    "html2canvas": "^1.4.1",
     "js-base64": "^2.5.2",
+    "jspdf": "^2.5.1",
+    "moment": "^2.29.1",
     "qrcode.vue": "^1.7.0",
+    "qs": "^6.9.4",
     "url-search-params-polyfill": "^8.0.0",
     "v-contextmenu": "^3.1.1",
-    "vue": "^2.6.6",
+    "v-viewer": "^1.5.1",
+    "vue": "^2.5.2",
     "vue-baidu-map": "^0.21.22",
+    "vue-beauty": "^2.0.0-beta.19",
     "vue-contextmenujs": "^1.4.11",
     "vue-full-calendar": "^2.8.1-0",
     "vue-fullcalendar": "^1.0.9",
+    "vue-quill-editor": "^3.0.6",
     "vue-router": "^3.0.1",
     "vue-ueditor-wrap": "^2.5.6",
     "vue-wordcloud": "^1.1.1",
     "vuedraggable": "^2.24.3",
     "vuex": "^3.0.1",
     "wangeditor": "^3.1.1",
-	"fabric": "^4.4.0",
-	"echarts": "^4.9.0",
-	"file-saver": "^2.0.5",
-	"moment": "^2.29.1",
-	"qs": "^6.9.4",
-	"v-viewer": "^1.5.1",
-	"vue": "^2.5.2",
-	"vue-beauty": "^2.0.0-beta.19",
-	"vue-quill-editor": "^3.0.6",
-	"xlsx": "^0.16.9"
+    "xlsx": "^0.16.9"
   },
   "devDependencies": {
     "@babel/core": "^7.1.0",
@@ -61,7 +61,6 @@
     "sass-loader": "^7.1.0",
     "vue-cropper": "^0.4.9",
     "vue-template-compiler": "^2.5.21"
-	
   },
   "eslintConfig": {
     "root": true,
@@ -73,8 +72,8 @@
       "eslint:recommended"
     ],
     "rules": {
-		"no-mixed-spaces-and-tabs":0
-	},
+      "no-mixed-spaces-and-tabs": 0
+    },
     "parserOptions": {
       "parser": "babel-eslint"
     }

+ 48 - 0
src/utils/htmlToPdf.js

@@ -0,0 +1,48 @@
+import html2canvas from "html2canvas";
+import jsPDF from "jspdf";
+
+export const downloadPDF = page => {
+    html2canvas(page, {
+        useCORS: true, //允许canvas画布内 可以跨域请求外部链接图片, 允许跨域请求。
+        allowTaint: true, //允许跨域
+        scale: 2, //设置放大倍数
+        backgroundColor: '#ffffff'//背景色
+    }).then((canvas)=> {
+        canvas2PDF(canvas);
+    })
+};
+
+const canvas2PDF = canvas => {
+    // 新建JsPDF对象
+    const PDF = new jsPDF({
+        orientation: 'p', //参数: l:横向  p:纵向
+        unit: 'mm', //参数:测量单位("pt","mm", "cm", "m", "in" or "px")
+        format: 'a4', //A4纸
+    })
+    const ctx = canvas.getContext('2d')
+    const a4w = 190
+    const a4h = 277 //A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277
+    const imgHeight = Math.floor(a4h * canvas.width / a4w) //按A4显示比例换算一页图像的像素高度
+    let renderedHeight = 0
+
+    while (renderedHeight < canvas.height) {
+        let page = document.createElement("canvas");
+        page.width = canvas.width;
+        page.height = Math.min(imgHeight, canvas.height - renderedHeight); //可能内容不足一页
+
+        //用getImageData剪裁指定区域,并画到前面创建的canvas对象中
+        page.getContext('2d').putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight)), 0, 0);
+
+        // canvas转图片数据保留10mm边距
+        PDF.addImage(page.toDataURL('image/jpeg', 0.2), 'JPEG', 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width));
+
+        renderedHeight += imgHeight;
+
+        //判断是否分页,如果后面还有内容,添加一个空页
+        if (renderedHeight < canvas.height) {
+            PDF.addPage()
+        }
+    }
+
+    PDF.save("导出.pdf");
+};

+ 18 - 4
src/views/anscard/Index.vue

@@ -243,6 +243,14 @@
 		margin-left: 9mm;
 		margin-top: 9mm;
 	}
+	.breadcrumb{
+		position:relative;
+	}
+	.exportPdf{
+		position:absolute;
+		right:20px;
+		top:10px;
+	}
 </style>
 <template>
   <section class="content">
@@ -251,9 +259,10 @@
             <el-breadcrumb-item><a href="/">试卷管理</a></el-breadcrumb-item>
             <el-breadcrumb-item>答题卡制作</el-breadcrumb-item>
         </el-breadcrumb>
+				<el-button class="exportPdf" type="primary" size="mini" @click="handleExportPdf">导出pdf</el-button>
     </div>
-	<div class="content_div">
-		<div class="left_div">
+	<div class="content_div" v-loading="loading">
+		<div class="left_div" ref="contenterPdf">
 			<div class="page_div">
 				<div class="page_cell" v-for='(page,idx) in paper_page' :style="{
 					top: 300*idx+'mm'
@@ -596,6 +605,7 @@
 <script>
 import Page from "../../components/Page";
 import Editor from "../../components/fuEditor/index1";
+import { downloadPDF } from "@/utils/htmlToPdf.js"
 export default {
   components: {
     Page,Editor
@@ -1250,8 +1260,12 @@ export default {
 		this.list=[]
 		
 	},
-	
-  
+
+		handleExportPdf(){
+			this.loading = true
+			downloadPDF(this.$refs.contenterPdf)
+			this.loading = false
+		}
   },
   created() {