|
|
|
<template>
|
|
|
|
<div>
|
|
|
|
<el-dialog v-model="visible" :title="props.title" :width="props.width">
|
|
|
|
<template v-if="visible">
|
|
|
|
<div class="printCode" ref="printNodeRef">
|
|
|
|
<div v-html="props.html"></div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<div class="flex-c-c mt10">
|
|
|
|
<el-button @click="handleClose" icon="CircleClose"> 关 闭 </el-button>
|
|
|
|
<el-button type="primary" v-if="props.isShowExport" @click="handleExport" icon="Download">
|
|
|
|
导 出
|
|
|
|
</el-button>
|
|
|
|
<el-button type="primary" @click="() => printTemplate('notHaveTem')" icon="Printer">
|
|
|
|
打 印
|
|
|
|
</el-button>
|
|
|
|
<el-button type="primary" @click="() => printTemplate('haveTem')" icon="Printer">
|
|
|
|
打 印(自定义模板)
|
|
|
|
</el-button>
|
|
|
|
</div>
|
|
|
|
</el-dialog>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
import { defineProps, computed, ref } from 'vue';
|
|
|
|
import print from '@/utils/print';
|
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
|
|
import { getObjType } from '@/utils/util';
|
|
|
|
import * as XLSX from 'xlsx';
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
html: {
|
|
|
|
type: String,
|
|
|
|
default: '',
|
|
|
|
},
|
|
|
|
modelValue: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false,
|
|
|
|
},
|
|
|
|
width: {
|
|
|
|
type: String,
|
|
|
|
default: '780px',
|
|
|
|
},
|
|
|
|
title: {
|
|
|
|
type: String,
|
|
|
|
default: '二维码',
|
|
|
|
},
|
|
|
|
isShowExport: {
|
|
|
|
type: Boolean,
|
|
|
|
default: true,
|
|
|
|
},
|
|
|
|
printFn: {
|
|
|
|
type: Function,
|
|
|
|
default: null,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const $emit = defineEmits(['update:modelValue']);
|
|
|
|
|
|
|
|
const visible = computed({
|
|
|
|
get: () => props.modelValue,
|
|
|
|
set: val => {
|
|
|
|
$emit('update:modelValue', val);
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const handleClose = () => {
|
|
|
|
visible.value = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
const printNodeRef = ref();
|
|
|
|
|
|
|
|
/** 生成Excel */
|
|
|
|
const createExcel = () => {
|
|
|
|
// const table = this.$refs.tableRef;
|
|
|
|
|
|
|
|
/* 将表格转换为 Workbook 对象 */
|
|
|
|
const wb = XLSX.utils.table_to_book(printNodeRef.value);
|
|
|
|
|
|
|
|
console.log('wb :>> ', wb);
|
|
|
|
|
|
|
|
wb.Sheets.Sheet1;
|
|
|
|
|
|
|
|
//单元格外侧框线
|
|
|
|
const borderAll = {
|
|
|
|
top: {
|
|
|
|
style: 'thin',
|
|
|
|
},
|
|
|
|
bottom: {
|
|
|
|
style: 'thin',
|
|
|
|
},
|
|
|
|
left: {
|
|
|
|
style: 'thin',
|
|
|
|
},
|
|
|
|
right: {
|
|
|
|
style: 'thin',
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
for (const key in wb.Sheets.Sheet1) {
|
|
|
|
const item = wb.Sheets.Sheet1[key];
|
|
|
|
|
|
|
|
const type = getObjType(item);
|
|
|
|
|
|
|
|
console.log('type :>> ', type);
|
|
|
|
|
|
|
|
if (type !== 'object') continue;
|
|
|
|
|
|
|
|
item.s = {
|
|
|
|
border: borderAll,
|
|
|
|
font: {
|
|
|
|
// name: "微软雅黑",
|
|
|
|
// sz: 16,
|
|
|
|
color: { rgb: '000000' },
|
|
|
|
bold: true,
|
|
|
|
italic: false,
|
|
|
|
underline: false,
|
|
|
|
},
|
|
|
|
fill: {
|
|
|
|
fgColor: { rgb: 'C5D9F1' },
|
|
|
|
},
|
|
|
|
alignment: {
|
|
|
|
horizontal: 'center',
|
|
|
|
vertical: 'center',
|
|
|
|
wrapText: false, // 自动换行
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
item.t = 's';
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 导出 Workbook 到 Excel 文件 */
|
|
|
|
XLSX.writeFile(wb, 'data.xlsx');
|
|
|
|
};
|
|
|
|
|
|
|
|
/** 导出 */
|
|
|
|
const handleExport = () => {
|
|
|
|
if (!printNodeRef.value) return ElMessage.warning('数据暂未请求完成, 请稍等');
|
|
|
|
|
|
|
|
ElMessageBox.confirm('确认导出?', '', {
|
|
|
|
confirmButtonText: '确认',
|
|
|
|
cancelButtonText: '关闭',
|
|
|
|
type: 'warning',
|
|
|
|
}).then(() => {
|
|
|
|
// 确认导出
|
|
|
|
createExcel();
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
/** 模板打印 */
|
|
|
|
const printTemplate = (type: 'haveTem' | 'notHaveTem') => {
|
|
|
|
const printNode = document.querySelectorAll('.printCode > div > div');
|
|
|
|
|
|
|
|
const cloneNodeList = [];
|
|
|
|
|
|
|
|
for (let i = 0; i < printNode.length; i++) {
|
|
|
|
cloneNodeList.push(printNode[i].cloneNode(true));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let i = 0; i < cloneNodeList.length; i++) {
|
|
|
|
const element = cloneNodeList[i];
|
|
|
|
|
|
|
|
for (let j = 0; j < element.childNodes.length; j++) {
|
|
|
|
const child = element.childNodes[j];
|
|
|
|
if (child.className !== 'image-container') continue;
|
|
|
|
child.style.setProperty('--isShow', type === 'haveTem' ? 'flex' : 'none');
|
|
|
|
child.style.setProperty('--aa', type === 'haveTem' ? '#000' : '#fff');
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
print(cloneNodeList);
|
|
|
|
};
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
.printCode {
|
|
|
|
max-height: 80vh;
|
|
|
|
overflow-y: scroll;
|
|
|
|
}
|
|
|
|
</style>
|