You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

183 lines
4.0 KiB

<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>