打印导出
This commit is contained in:
parent
859407c81d
commit
c2898550f3
@ -101,34 +101,38 @@ function base64ToBlob(base64: string, mimeType: string) {
|
|||||||
* @param type 可选,'pdf' | 'excel',不传默认 pdf
|
* @param type 可选,'pdf' | 'excel',不传默认 pdf
|
||||||
* @param fileName 可选,excel下载文件名
|
* @param fileName 可选,excel下载文件名
|
||||||
*/
|
*/
|
||||||
function printBase64PDF(base64: string, type: 'pdf' | 'excel' = 'pdf', fileName: string = '文件') {
|
function printBase64PDF(base64: string) {
|
||||||
if (type === 'pdf') {
|
// PDF打印逻辑
|
||||||
// PDF打印逻辑
|
const blob = base64ToBlob(base64, 'application/pdf');
|
||||||
const blob = base64ToBlob(base64, 'application/pdf');
|
const pdfUrl = URL.createObjectURL(blob);
|
||||||
const pdfUrl = URL.createObjectURL(blob);
|
const iframe = document.createElement('iframe');
|
||||||
const iframe = document.createElement('iframe');
|
iframe.style.display = 'none';
|
||||||
iframe.style.display = 'none';
|
iframe.src = pdfUrl;
|
||||||
iframe.src = pdfUrl;
|
document.body.appendChild(iframe);
|
||||||
document.body.appendChild(iframe);
|
iframe.onload = () => {
|
||||||
iframe.onload = () => {
|
iframe.contentWindow?.print();
|
||||||
iframe.contentWindow?.print();
|
setTimeout(() => {
|
||||||
setTimeout(() => {
|
URL.revokeObjectURL(pdfUrl);
|
||||||
URL.revokeObjectURL(pdfUrl);
|
iframe.remove(); // 修复原代码iframe残留dom
|
||||||
iframe.remove(); // 修复原代码iframe残留dom
|
}, 1000);
|
||||||
}, 1000);
|
};
|
||||||
};
|
}
|
||||||
} else if (type === 'excel') {
|
|
||||||
// excel导出下载逻辑
|
/**
|
||||||
const blob = base64ToBlob(base64, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
* 后端返回Blob文件流
|
||||||
const downloadUrl = URL.createObjectURL(blob);
|
* @param pdfBlob 后端接口返回的文件流blob,responseType:blob
|
||||||
const a = document.createElement('a');
|
*/
|
||||||
a.href = downloadUrl;
|
function printBlobPDF(pdfBlob: Blob, fileName: string) {
|
||||||
a.download = encodeURIComponent(fileName + '.xlsx');
|
|
||||||
document.body.appendChild(a);
|
const pdfUrl = URL.createObjectURL(pdfBlob);
|
||||||
a.click();
|
const iframe = document.createElement('iframe');
|
||||||
a.remove();
|
iframe.style.display = 'none';
|
||||||
URL.revokeObjectURL(downloadUrl);
|
iframe.src = pdfUrl;
|
||||||
}
|
document.body.appendChild(iframe);
|
||||||
|
iframe.onload = () => {
|
||||||
|
iframe.contentWindow?.print();
|
||||||
|
setTimeout(() => URL.revokeObjectURL(pdfUrl), 1000); // 释放内存
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -209,5 +213,35 @@ function calcMeanWithSymbols(arr) {
|
|||||||
// 保留2位小数返回
|
// 保留2位小数返回
|
||||||
return Math.round(avg * 100) / 100
|
return Math.round(avg * 100) / 100
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 导出文件(Excel下载)
|
||||||
|
* @param blob 文件二进制blob
|
||||||
|
* @param fileName 文件名
|
||||||
|
*/
|
||||||
|
function exportFile(blob: Blob, fileName: string) {
|
||||||
|
const a = document.createElement('a')
|
||||||
|
const url = URL.createObjectURL(blob)
|
||||||
|
a.href = url
|
||||||
|
a.download = fileName
|
||||||
|
document.body.appendChild(a)
|
||||||
|
a.click()
|
||||||
|
// 释放内存
|
||||||
|
URL.revokeObjectURL(url)
|
||||||
|
a.remove()
|
||||||
|
}
|
||||||
|
|
||||||
export const classCom = { decimalToHexColor, convertHexToNumber, getContrastTextColor, printBase64PDF, printPDF, useAutoSize, getDayDiff, calcMeanWithSymbols }
|
|
||||||
|
|
||||||
|
|
||||||
|
export const classCom = {
|
||||||
|
decimalToHexColor,
|
||||||
|
convertHexToNumber,
|
||||||
|
getContrastTextColor,
|
||||||
|
printBase64PDF,
|
||||||
|
printPDF,
|
||||||
|
useAutoSize,
|
||||||
|
getDayDiff,
|
||||||
|
calcMeanWithSymbols,
|
||||||
|
exportFile,
|
||||||
|
printBlobPDF
|
||||||
|
}
|
||||||
|
|||||||
@ -130,7 +130,8 @@
|
|||||||
<el-input v-model="form.paramName" :placeholder="`请输入${menuname}名称`" />
|
<el-input v-model="form.paramName" :placeholder="`请输入${menuname}名称`" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="`${menuname}默认值`" prop="paramDefvalue">
|
<el-form-item :label="`${menuname}默认值`" prop="paramDefvalue">
|
||||||
<el-select v-model="form.paramDefvalue" :placeholder="`请选择${menuname}默认值`" style="width: 100%" clearable>
|
<el-select v-model="form.paramDefvalue" :placeholder="`请选择${menuname}默认值`" style="width: 100%" clearable
|
||||||
|
filterable allow-create default-first-option>
|
||||||
<el-option v-for="item in defaultOptions" :key="item.value" :label="item.label + ' ' + item.value"
|
<el-option v-for="item in defaultOptions" :key="item.value" :label="item.label + ' ' + item.value"
|
||||||
:value="item.value" />
|
:value="item.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
|
|||||||
@ -7,8 +7,8 @@
|
|||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<div class="mb8">
|
<div class="mb8">
|
||||||
<el-button type="primary" icon="Search" @click="search">查询</el-button>
|
<el-button type="primary" icon="Search" @click="search">查询</el-button>
|
||||||
<el-button type="warning" icon="Printer" plain @click="print">打印</el-button>
|
<el-button type="warning" icon="Printer" plain :loading="printLoading" @click="print">打印</el-button>
|
||||||
<el-button type="primary" icon="Download" plain @click="exportHandle">导出Excel</el-button>
|
<el-button type="primary" icon="Download" plain :loading="exportLoading" @click="exportHandle">导出Excel</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-form ref="form" :model="queryParams" inline size="small" class="stats-form" label-width="auto">
|
<el-form ref="form" :model="queryParams" inline size="small" class="stats-form" label-width="auto">
|
||||||
@ -139,7 +139,6 @@ const userStore = useUserStore()
|
|||||||
const mbStore = useCommonStore();
|
const mbStore = useCommonStore();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
|
|
||||||
const openDetail = ref(false)
|
const openDetail = ref(false)
|
||||||
const mxtableData = ref([])
|
const mxtableData = ref([])
|
||||||
const queryParams = ref({
|
const queryParams = ref({
|
||||||
@ -155,7 +154,8 @@ const checkBoxs = ref([])
|
|||||||
const originalColumn = ref([]) //原始列
|
const originalColumn = ref([]) //原始列
|
||||||
const tableColumns = ref([]);
|
const tableColumns = ref([]);
|
||||||
const Template = ref({})
|
const Template = ref({})
|
||||||
|
const exportLoading = ref(false)
|
||||||
|
const printLoading = ref(false)
|
||||||
|
|
||||||
const instrGroupOptions = ref([])
|
const instrGroupOptions = ref([])
|
||||||
const instrGroupFields = ref([
|
const instrGroupFields = ref([
|
||||||
@ -301,7 +301,6 @@ const getPrintFooterText = (col, idx) => {
|
|||||||
|
|
||||||
// 打印
|
// 打印
|
||||||
const print = () => {
|
const print = () => {
|
||||||
// 不直接改 originalColumn,拷贝一份,避免影响导出等其他功能
|
|
||||||
const printColumns = originalColumn.value.map(item => {
|
const printColumns = originalColumn.value.map(item => {
|
||||||
const matchTabCol = tableColumns.value.find(col => col.prop === item.paramCode)
|
const matchTabCol = tableColumns.value.find(col => col.prop === item.paramCode)
|
||||||
return { ...item, paramSequence: matchTabCol ? matchTabCol.paramSequence : 0 }
|
return { ...item, paramSequence: matchTabCol ? matchTabCol.paramSequence : 0 }
|
||||||
@ -312,50 +311,11 @@ const print = () => {
|
|||||||
Column: printColumns,
|
Column: printColumns,
|
||||||
Template: Template.value
|
Template: Template.value
|
||||||
}
|
}
|
||||||
|
printLoading.value = true
|
||||||
printTemplate(data).then(res => {
|
printTemplate(data).then(res => {
|
||||||
// 后端错误 JSON 判断,避免静默失败
|
classCom.printBlobPDF(res)
|
||||||
if (res instanceof Blob && res.type.includes('application/json')) {
|
}).finally(() => {
|
||||||
const reader = new FileReader()
|
printLoading.value = false
|
||||||
reader.onload = e => {
|
|
||||||
const err = JSON.parse(e.target.result)
|
|
||||||
ElMessage.error(err.msg || '打印失败')
|
|
||||||
}
|
|
||||||
reader.readAsText(res)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const blob = new Blob([res], { type: 'application/pdf' })
|
|
||||||
const pdfUrl = URL.createObjectURL(blob)
|
|
||||||
|
|
||||||
// 不要 display:none,Chrome 对隐藏 iframe 的 PDF 打印有兼容问题;移出屏幕即可
|
|
||||||
const iframe = document.createElement('iframe')
|
|
||||||
iframe.style.position = 'fixed'
|
|
||||||
iframe.style.right = '0'
|
|
||||||
iframe.style.bottom = '0'
|
|
||||||
iframe.style.width = '0'
|
|
||||||
iframe.style.height = '0'
|
|
||||||
iframe.style.border = '0'
|
|
||||||
iframe.src = pdfUrl
|
|
||||||
document.body.appendChild(iframe)
|
|
||||||
|
|
||||||
iframe.onload = () => {
|
|
||||||
// 等 PDF 渲染完再打印,避免空白页
|
|
||||||
setTimeout(() => {
|
|
||||||
const win = iframe.contentWindow
|
|
||||||
if (win) {
|
|
||||||
win.focus()
|
|
||||||
win.print() // Chrome/Firefox 阻塞到打印对话框关闭
|
|
||||||
}
|
|
||||||
// print() 阻塞时,这里在对话框关闭后才执行;留 2s 缓冲再清理
|
|
||||||
setTimeout(() => {
|
|
||||||
URL.revokeObjectURL(pdfUrl)
|
|
||||||
iframe.remove()
|
|
||||||
}, 2000)
|
|
||||||
}, 300)
|
|
||||||
}
|
|
||||||
}).catch(() => {
|
|
||||||
ElMessage.error('打印失败')
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -374,18 +334,13 @@ const exportHandle = () => {
|
|||||||
Column: originalColumn.value,
|
Column: originalColumn.value,
|
||||||
Template: Template.value
|
Template: Template.value
|
||||||
};
|
};
|
||||||
|
exportLoading.value = true;
|
||||||
exportTemplate(data).then(res => {
|
exportTemplate(data).then(res => {
|
||||||
//classCom.printBase64PDF(res.data, 'excel', '统计报表')
|
classCom.exportFile(res, statsTitle.value)
|
||||||
// 若依拦截器对 blob 直接透传,res 就是 Blob
|
}).finally(() => {
|
||||||
const blob = new Blob([res], {
|
exportLoading.value = false;
|
||||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
|
||||||
})
|
|
||||||
const link = document.createElement('a')
|
|
||||||
link.href = URL.createObjectURL(blob)
|
|
||||||
link.download = '导出_' + new Date().getTime() + '.xlsx'
|
|
||||||
link.click()
|
|
||||||
URL.revokeObjectURL(link.href) // 释放内存
|
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const xmList = ref([])
|
const xmList = ref([])
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user