PDF下载

This commit is contained in:
bb_pan 2025-12-15 10:31:45 +08:00
parent de41f8a4cf
commit b478676799
6 changed files with 137 additions and 18 deletions

View File

@ -55,6 +55,7 @@
"js-beautify": "1.13.0",
"js-cookie": "3.0.1",
"jsencrypt": "3.0.0-rc.1",
"jspdf": "^2.5.2",
"jszip": "^3.10.1",
"moment": "^2.30.1",
"nprogress": "0.2.0",

View File

@ -1,3 +1,5 @@
import html2canvas from 'html2canvas'
import jsPDF from 'jspdf'
/**
* 通用js方法封装处理
* Copyright (c) 2019 bonus
@ -13,12 +15,15 @@ export function parseTime(time, pattern) {
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
time = parseInt(time)
} else if (typeof time === 'string') {
time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '')
time = time
.replace(new RegExp(/-/gm), '/')
.replace('T', ' ')
.replace(new RegExp(/\.[\d]{3}/gm), '')
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
if (typeof time === 'number' && time.toString().length === 10) {
time = time * 1000
}
date = new Date(time)
@ -30,7 +35,7 @@ export function parseTime(time, pattern) {
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
a: date.getDay(),
}
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key]
@ -56,9 +61,10 @@ export function resetForm(refName) {
// 添加日期范围
export function addDateRange(params, dateRange, propName) {
let search = params
search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {}
search.params =
typeof search.params === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {}
dateRange = Array.isArray(dateRange) ? dateRange : []
if (typeof (propName) === 'undefined') {
if (typeof propName === 'undefined') {
search.params['beginTime'] = dateRange[0]
search.params['endTime'] = dateRange[1]
} else {
@ -75,7 +81,7 @@ export function selectDictLabel(datas, value) {
}
var actions = []
Object.keys(datas).some((key) => {
if (datas[key].value == ('' + value)) {
if (datas[key].value == '' + value) {
actions.push(datas[key].label)
return true
}
@ -100,7 +106,7 @@ export function selectDictLabels(datas, value, separator) {
Object.keys(value.split(currentSeparator)).some((val) => {
var match = false
Object.keys(datas).some((key) => {
if (datas[key].value == ('' + temp[val])) {
if (datas[key].value == '' + temp[val]) {
actions.push(datas[key].label + currentSeparator)
match = true
}
@ -114,8 +120,10 @@ export function selectDictLabels(datas, value, separator) {
// 字符串格式化(%s )
export function sprintf(str) {
var args = arguments, flag = true, i = 1
str = str.replace(/%s/g, function() {
var args = arguments,
flag = true,
i = 1
str = str.replace(/%s/g, function () {
var arg = args[i++]
if (typeof arg === 'undefined') {
flag = false
@ -161,7 +169,7 @@ export function handleTree(data, id, parentId, children) {
let config = {
id: id || 'id',
parentId: parentId || 'parentId',
childrenList: children || 'children'
childrenList: children || 'children',
}
var childrenListMap = {}
@ -211,10 +219,10 @@ export function tansParams(params) {
for (const propName of Object.keys(params)) {
const value = params[propName]
var part = encodeURIComponent(propName) + '='
if (value !== null && value !== '' && typeof (value) !== 'undefined') {
if (value !== null && value !== '' && typeof value !== 'undefined') {
if (typeof value === 'object') {
for (const key of Object.keys(value)) {
if (value[key] !== null && value[key] !== '' && typeof (value[key]) !== 'undefined') {
if (value[key] !== null && value[key] !== '' && typeof value[key] !== 'undefined') {
let params = propName + '[' + key + ']'
var subPart = encodeURIComponent(params) + '='
result += subPart + encodeURIComponent(value[key]) + '&'
@ -237,3 +245,73 @@ export function blobValidate(data) {
export function indexContinuation(num, size) {
return (num - 1) * size + 1
}
// 下载PDF
export async function downloadPDF(options) {
const {
id, // 要导出的 DOM id
fileName = '未命名', // 文件名
modal, // this.$modal
message, // this.$message
margin = { top: 15, right: 15, bottom: 15, left: 15 },
scale = 2,
} = options
if (!id) {
console.error('downloadPDF: id is required')
return
}
try {
modal?.loading?.('正在生成PDF请稍候...')
const element = document.getElementById(id)
if (!element) {
message?.error?.('未找到要导出的内容')
return
}
const canvas = await html2canvas(element, {
scale,
useCORS: true,
allowTaint: true,
backgroundColor: '#ffffff',
})
const pdf = new jsPDF('p', 'mm', 'a4')
const pageWidth = 210
const pageHeight = 297
const contentWidth = pageWidth - margin.left - margin.right
const contentHeight = pageHeight - margin.top - margin.bottom
const imgWidth = contentWidth
const imgHeight = (canvas.height * imgWidth) / canvas.width
let heightLeft = imgHeight
let position = margin.top
const imgData = canvas.toDataURL('image/jpeg', 1.0)
// 首页
pdf.addImage(imgData, 'JPEG', margin.left, position, imgWidth, imgHeight)
heightLeft -= contentHeight
// 分页
while (heightLeft > 0) {
pdf.addPage()
position = margin.top - (imgHeight - heightLeft)
pdf.addImage(imgData, 'JPEG', margin.left, position, imgWidth, imgHeight)
heightLeft -= contentHeight
}
pdf.save(`${fileName}_${Date.now()}.pdf`)
message?.success?.('PDF下载成功')
} catch (error) {
console.error('生成PDF失败:', error)
message?.error?.('生成PDF失败请稍后重试')
} finally {
modal?.closeLoading?.()
}
}

View File

@ -99,12 +99,13 @@
<!-- 出库记录单 -->
<el-dialog title="维修记录单" :visible.sync="outRecordVisible" width="80%" append-to-body>
<el-row style="display: flex; justify-content: flex-end; gap: 8px;">
<el-button size="mini" type="primary" @click="handleDownloadPDF">下载PDF</el-button>
<el-button size="mini" type="primary" @click="onHandleDownload">下载</el-button>
<el-button size="mini" type="primary" @click="onHandlePrint">打印</el-button>
<el-button size="mini" type="primary" @click="onHandleClose">关闭</el-button>
</el-row>
<vue-easy-print ref="recordPrintRef" tableShow style="width: 100%">
<vue-easy-print ref="recordPrintRef" id="print-content" tableShow style="width: 100%">
<h2 style="text-align: center;font-size: 28px;">维修记录单</h2>
<el-row class="record-row">
<el-col :span="16">
@ -167,6 +168,7 @@
<script>
import { getRoamRecordListAPI, getOutRecordListAPI } from '@/api/EquipmentRoamRecord'
import vueEasyPrint from 'vue-easy-print'
import { downloadPDF } from '@/utils/bonus'
export default {
components: {
@ -266,6 +268,14 @@ export default {
//
onHandleClose() {
this.outRecordVisible = false
},
handleDownloadPDF() {
downloadPDF({
id: 'print-content',
fileName: '维修记录单',
modal: this.$modal,
message: this.$message
})
}
}
}

View File

@ -104,12 +104,13 @@
<!-- 出库记录单 -->
<el-dialog title="出库记录单" :visible.sync="outRecordVisible" width="80%" append-to-body>
<el-row style="display: flex; justify-content: flex-end; gap: 8px;">
<el-button size="mini" type="primary" @click="handleDownloadPDF">下载PDF</el-button>
<el-button size="mini" type="primary" @click="onHandleDownload">下载</el-button>
<el-button size="mini" type="primary" @click="onHandlePrint">打印</el-button>
<el-button size="mini" type="primary" @click="onHandleClose">关闭</el-button>
</el-row>
<vue-easy-print ref="recordPrintRef" tableShow style="width: 100%">
<vue-easy-print ref="recordPrintRef" id="print-content" tableShow style="width: 100%">
<h2 style="text-align: center;font-size: 28px;">出库记录单</h2>
<el-row class="record-row">
<el-col :span="16">
@ -176,6 +177,7 @@
<script>
import { getRoamRecordListAPI, getOutRecordListAPI } from '@/api/EquipmentRoamRecord'
import vueEasyPrint from 'vue-easy-print'
import { downloadPDF } from '@/utils/bonus'
export default {
components: {
@ -275,6 +277,14 @@ export default {
//
onHandleClose() {
this.outRecordVisible = false
},
handleDownloadPDF() {
downloadPDF({
id: 'print-content',
fileName: '出库记录单',
modal: this.$modal,
message: this.$message
})
}
}
}

View File

@ -107,12 +107,13 @@
<!-- 出库记录单 -->
<el-dialog title="退役记录单" :visible.sync="outRecordVisible" width="80%" append-to-body>
<el-row style="display: flex; justify-content: flex-end; gap: 8px;">
<el-button size="mini" type="primary" @click="handleDownloadPDF">下载PDF</el-button>
<el-button size="mini" type="primary" @click="onHandleDownload">下载</el-button>
<el-button size="mini" type="primary" @click="onHandlePrint">打印</el-button>
<el-button size="mini" type="primary" @click="onHandleClose">关闭</el-button>
</el-row>
<vue-easy-print ref="recordPrintRef" tableShow style="width: 100%">
<vue-easy-print ref="recordPrintRef" id="print-content" tableShow style="width: 100%">
<h2 style="text-align: center;font-size: 28px;">退役记录单</h2>
<el-row class="record-row">
<el-col :span="16">
@ -177,6 +178,7 @@
<script>
import { getRoamRecordListAPI, getOutRecordListAPI } from '@/api/EquipmentRoamRecord'
import vueEasyPrint from 'vue-easy-print'
import { downloadPDF } from '@/utils/bonus'
export default {
components: {
@ -276,6 +278,14 @@ export default {
//
onHandleClose() {
this.outRecordVisible = false
},
handleDownloadPDF() {
downloadPDF({
id: 'print-content',
fileName: '退役记录单',
modal: this.$modal,
message: this.$message
})
}
}
}

View File

@ -93,12 +93,13 @@
<!-- 出库记录单 -->
<el-dialog title="退库记录单" :visible.sync="outRecordVisible" width="80%" append-to-body>
<el-row style="display: flex; justify-content: flex-end; gap: 8px;">
<el-button size="mini" type="primary" @click="handleDownloadPDF">下载PDF</el-button>
<el-button size="mini" type="primary" @click="onHandleDownload">下载</el-button>
<el-button size="mini" type="primary" @click="onHandlePrint">打印</el-button>
<el-button size="mini" type="primary" @click="onHandleClose">关闭</el-button>
</el-row>
<vue-easy-print ref="recordPrintRef" tableShow style="width: 100%">
<vue-easy-print ref="recordPrintRef" id="print-content" tableShow style="width: 100%">
<h2 style="text-align: center;font-size: 28px;">退库记录单</h2>
<el-row class="record-row">
<el-col :span="16">
@ -167,6 +168,7 @@
<script>
import { getRoamRecordListAPI, getOutRecordListAPI } from '@/api/EquipmentRoamRecord'
import vueEasyPrint from 'vue-easy-print'
import { downloadPDF } from '@/utils/bonus'
export default {
components: {
@ -266,6 +268,14 @@ export default {
//
onHandleClose() {
this.outRecordVisible = false
},
handleDownloadPDF() {
downloadPDF({
id: 'print-content',
fileName: '退库记录单',
modal: this.$modal,
message: this.$message
})
}
}
}