Pdf.vue 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. <template>
  2. <el-dialog
  3. class="my-dialog"
  4. fullscreen
  5. append-to-body
  6. :model-value="showDialog"
  7. @close="closeDialog()"
  8. >
  9. <div class="pdf-main">
  10. <div class="title" >
  11. <div class="name" ></div>
  12. <div class="pdf-close cursor-pointer" @click="closeDialog"></div>
  13. </div>
  14. <div id="printTest" class="pdf-dialog-box">
  15. <div class="pdf-my-body" >
  16. <div class="pdfBox" >
  17. <div class="a4" id="pdfDom">
  18. <div class="a4_title">确权单</div>
  19. <table class="a4_table" border=1 style="border-collapse: collapse;">
  20. <tr>
  21. <td class="name">农场地址</td>
  22. <td class="text">{{rowData.address}}</td>
  23. <td class="name">农场名称</td>
  24. <td class="text">{{rowData.farmName}}</td>
  25. </tr>
  26. <tr>
  27. <td class="name">创建时间</td>
  28. <td class="text">{{rowData.createDate}}</td>
  29. <td class="name">农场面积</td>
  30. <td class="text">{{rowData.area}}亩</td>
  31. </tr>
  32. <tr>
  33. <td class="name">作物物种</td>
  34. <td class="text">{{rowData.speciesTypeName}}</td>
  35. <td class="name">客户姓名</td>
  36. <td class="text">{{rowData.masterName}}</td>
  37. </tr>
  38. <tr>
  39. <td class="name">联系电话</td>
  40. <td class="text">{{rowData.masterTel}}</td>
  41. </tr>
  42. <tr>
  43. <td class="name">经纬度</td>
  44. <td colspan="3" class="text2">{{rowData.points}}</td>
  45. </tr>
  46. </table>
  47. <div class="a4_sub_title">地块四至图</div>
  48. <img :key="imgUrl" v-show="imgUrl" class="img-content img" style="z-index: 999" width="595" height="500" :src="imgUrl" />
  49. <div :key="imgUrl" v-show="!imgUrl" class="img-content" ref="mapRef" id="mapRefId"></div>
  50. <div class="signature">签名:______________</div>
  51. </div>
  52. </div>
  53. </div>
  54. </div>
  55. <div style="text-align: left">
  56. <el-button size="large" color="#626aef" @click="html2Canvas1('test')">打印</el-button>
  57. <!-- <el-button size="large" color="#626aef" v-print="printObj">打印</el-button> -->
  58. <!-- <el-button size="large" color="#626aef" @click="closeDialog">关闭</el-button>-->
  59. </div>
  60. </div>
  61. </el-dialog>
  62. </template>
  63. <script setup>
  64. import html2Canvas from 'html2canvas'
  65. import JsPDF from 'jspdf'
  66. import {reactive, ref, toRefs, computed, nextTick, onMounted} from "vue";
  67. import {useStore} from "vuex";
  68. import {WKT} from "ol/format";
  69. import PdfMap from "./pdfMap";
  70. import { dateFormat } from "@/utils/date_util";
  71. import {getAreaByWkt} from "../../utils/map";
  72. const emit = defineEmits(["closeDialog","success"])
  73. const state = useStore().state;
  74. const sendConfirmShow = ref(false)
  75. const mapRef = ref(null)
  76. let pdfMap = new PdfMap()
  77. let rowData = ref({})
  78. async function send(){
  79. closeDialog();
  80. }
  81. const props = defineProps({
  82. title:{
  83. type:String,
  84. required:true
  85. },
  86. showDialog: {
  87. type: Boolean,
  88. default: true,
  89. },
  90. rowId:{
  91. type: Number,
  92. required:true,
  93. }
  94. });
  95. let printObj = {
  96. id:"printTest",
  97. popTitle: 'good print',
  98. beforeOpenCallback (vue) {
  99. toImg(true)
  100. console.log('打开之前')
  101. },
  102. openCallback (vue) {
  103. let {masterName, farmName, masterTel} = rowData.value
  104. document.title =`${farmName}-${masterTel}-${masterName}`
  105. console.log('执行了打印')
  106. },
  107. closeCallback (vue) {
  108. document.title =`飞鸟确权平台`
  109. console.log('关闭了打印工具')
  110. }
  111. }
  112. let imgUrl = ref(null)
  113. const executor = ref([])
  114. const executorList = ref([])
  115. const formRef = ref(null);
  116. const {title, rowId} = toRefs(props);
  117. const closeDialog = (key) => {
  118. switch (key){
  119. case "sendConfirm":
  120. sendConfirmShow.value = false;
  121. return
  122. }
  123. emit("closeDialog", "pdf");
  124. };
  125. function toImg() {
  126. // let canvas = pdfMap.kmap.map.getViewport().querySelector('canvas')
  127. // let dataURL = canvas.toDataURL('image/webp');
  128. // imgUrl.value = dataURL;
  129. }
  130. function html2Canvas1(){
  131. html2Canvas(document.querySelector('#pdfDom'), {//获取文档中 id="pdfDom" 的元素,返回匹配指定选择器的第一个元素
  132. allowTaint: true //允许跨源图像污染画布
  133. }).then(function (canvas) {
  134. let contentWidth = canvas.width // 获得容器的宽
  135. let contentHeight = canvas.height // 获得容器的高
  136. //一页pdf显示html页面生成的canvas高度;
  137. let pageHeight = contentWidth / 592.28 * 841.89
  138. let leftHeight = contentHeight //未生成pdf的html页面高度
  139. let position = 0 //页面偏移
  140. //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
  141. let imgWidth = 595.28
  142. let imgHeight = 592.28 / contentWidth * contentHeight
  143. //图片格式,(0-1,数字越大,代表导出的图片越清晰,默认值:0.92)
  144. let pageData = canvas.toDataURL('image/jpeg', 1.0)
  145. //第一个参数: l:横向 p:纵向
  146. //第二个参数:测量单位("pt","mm", "cm", "m", "in" or "px")
  147. //格式,默认为“a4”,如果想用自己的格式例如[595.28, 841.89]
  148. let PDF = new JsPDF('', 'pt', 'a4')
  149. //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
  150. //当内容未超过pdf一页显示的范围,无需分页
  151. if (leftHeight < pageHeight) {
  152. PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
  153. } else {
  154. while (leftHeight > 0) {
  155. PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
  156. leftHeight -= pageHeight
  157. position -= 841.89
  158. //避免添加空白页
  159. if (leftHeight > 0) {
  160. PDF.addPage()
  161. }
  162. }
  163. }
  164. // 导出pdf文件命名
  165. // PDF.save(title + '.pdf')
  166. PDF.save('test.pdf')
  167. })
  168. }
  169. onMounted(()=>{
  170. VE_API.authentic.getDetails({id:rowId.value}).then(({data})=>{
  171. data.createDate = dateFormat(new Date(), "YYYY-mm-dd HH:MM:SS");
  172. data.area = getAreaByWkt(data.geom)
  173. rowData.value = data
  174. pdfMap.initMap(data,mapRef.value)
  175. setTimeout(function(){
  176. toImg(false)
  177. },1500)
  178. })
  179. })
  180. </script>
  181. <style lang="scss" scoped>
  182. $title-height:0px;
  183. $body-height:calc(100% - $title-height);
  184. .pdf-main{
  185. left: 25%;
  186. right: 25%;
  187. top:10%;
  188. bottom:10%;
  189. background: rgba(1,17,22,0.8);
  190. box-shadow: 0px 0px 20px 0px #00FFF0;
  191. border-radius: 4px;
  192. border: 2px solid rgba(81,233,240,0.6);
  193. position: absolute;
  194. .title{
  195. width: 100%;
  196. height: $title-height;
  197. box-sizing: border-box;
  198. background: rgba(0,77,101,0.8);
  199. border-radius: 4px 4px 0px 0px;
  200. border-bottom: 2px solid rgba(81,233,240,0.3);
  201. display: flex;
  202. align-items: center;
  203. justify-content: space-between;
  204. .name{
  205. margin-left: 20px;
  206. font-size: 16px;
  207. font-weight: 600;
  208. color: #00FFF0;
  209. height: 22px;
  210. }
  211. .pdf-close{
  212. width: 16px;
  213. height: 16px;
  214. background-image: url("@/assets/img/close.png");
  215. background-size: 100% 100%;
  216. }
  217. }
  218. }
  219. .pdf-dialog-box{
  220. font-family: PingFangSC-Regular, PingFang SC;
  221. width: 100%;
  222. height: 100%;
  223. .pdf-my-body{
  224. width: 100%;
  225. height: $body-height;
  226. box-sizing: border-box;
  227. padding: 20px;
  228. ::-webkit-scrollbar-thumb {
  229. /* 滚动条里面小方块 */
  230. background: rgb(70, 71, 71);;
  231. border-radius: 6px;
  232. }
  233. ::-webkit-scrollbar-track {
  234. /* 滚动条里面轨道 */
  235. background: #ededed;
  236. }
  237. }
  238. .pdfBox{
  239. height: calc(100%);
  240. width: 100%;
  241. overflow-y: scroll;
  242. background-color: rgba(141, 142, 142);
  243. padding: 10px;
  244. box-sizing: border-box;
  245. display: flex;
  246. justify-content: center;
  247. }
  248. .a4{
  249. font-family: PingFangSC-Medium, PingFang SC;
  250. background-color: #FFFFFF;
  251. width:595px;
  252. height:1000px;
  253. margin: 5px 0px 5px 0px;
  254. padding: 19px 63px 19px 63px;
  255. font-weight: 600;
  256. color: #000000;
  257. .a4_title{
  258. width:595px;
  259. height: 33px;
  260. font-size: 24px;
  261. text-align: center;
  262. margin: 10px 0px 10px 0px;
  263. }
  264. .a4_sub_title{
  265. font-size: 16px;
  266. margin: 10px 0px 10px 0px;
  267. }
  268. .a4_table{
  269. height: calc(842px - 33px - 26px - 600px);
  270. max-height: calc(842px - 33px - 26px - 600px);
  271. width:595px;
  272. font-size: 12px;
  273. .name{
  274. width: 50px;
  275. height: 20px;
  276. line-height: 20px;
  277. padding-right: 9px;
  278. box-sizing: border-box;
  279. text-align: right;
  280. }
  281. .text{
  282. width: 122px;
  283. height: 20px;
  284. line-height: 20px;
  285. text-align: left;
  286. padding-left: 9px;
  287. box-sizing: border-box;
  288. }
  289. .text2{
  290. text-align: left;
  291. font-size: 10px;
  292. font-weight: normal;
  293. }
  294. }
  295. .img-content{
  296. width:595px;
  297. height: 500px;
  298. z-index: 1000;
  299. .ol-viewport{
  300. width:595px !important;
  301. height: 500px !important;
  302. .ol-layers{
  303. width:595px !important;
  304. height: 500px !important;
  305. .ol-layer{
  306. width:595px !important;
  307. height: 500px !important;
  308. }
  309. }
  310. }
  311. }
  312. .img{
  313. z-index: 999;
  314. }
  315. .signature{
  316. width:595px;
  317. height: 20px;
  318. z-index: 1000;
  319. margin-top: 40px;
  320. text-align: right;
  321. }
  322. }
  323. }
  324. canvas{
  325. width:595px;
  326. height: 500px;
  327. }
  328. </style>