前端页面导出PPT(Vue3)
2023-11-08 15:10 WEB前端小菜鸟 阅读(1383) 评论(0) 收藏 举报问题1:如在首页点击导出把 首页的echarts图作为一个页面导出,然后导出PPT里面还包含其他页面的东西(其他页面的图标 我都获取不到DOM如何截图插入PPT),
解决方案:把其他页面也写在首页,这样不就能获取到DOM了吗 然后把其他页面fixed z-inde:-9999不就ok了吗
问题2:导出PPT的时候太慢太卡 ,客户会误以为死机了,加loading也要等很久才出来loading
核心:就是每一页ppt都单独写成一个页面,然后汇总到一起,每一个页面先获取DOM截图生成base64图片,然后在用ppt插件把每一页图片插进去然后导出搞定
PPT默认比例是16:9我,16除以9==1.77
我的方案是页面写死宽高1920*1080布局1920除以1080 ==1.77 ;
最终方案我用1920*1080布局,导出的图片的w h 都写成100%,这样就能铺满PPT了,每个ppt页面都叫UI出图
然后每一页PPT看做一个DOM,我用的vue3,so绑定的是ref

把每一页PPT当成一个页面,然后获取到每个月页面的DOM,然后把他弄成base64的图片,最后在插入到PPT里面导出
<!-- PPT相关的所有东西 -->
<div ref="ppt" class="ppt-all">
<ppt1 ref="page1Ref"></ppt1>
<ppt2 ref="page2Ref"></ppt2>
<ppt3 :dataAll="dataAll.dataAll" ref="page3Ref"></ppt3>
<ppt4 v-if="dataAll.dataAll" :dataAll="dataAll.dataAll" ref="page4Ref"></ppt4>
<ppt5 :dataAll="dataAll.dataAll" ref="page5Ref"></ppt5>
<ppt6 :dataAll="dataAll.dataAll" ref="page6Ref"></ppt6>
<ppt7 ref="page7Ref"></ppt7>
...
</div>
下面是等所有页面都拿到自己页面的base64图片后再调用 插入PPT的方法,如下第一种注释写法 loadding要很久才回出来,那时PPT也导出,第二种loading实时出来
const exportPPt = async () => {
const loading = ElLoading.service({
lock: true,
text: "导出中",
background: "rgba(0, 0, 0, 0.7)",
});
// await Promise.all([getBase64Result(1, page1Ref.value.page1Ref),
// getBase64Result(2, page2Ref.value.page2Ref),
// getBase64Result(3, page3Ref.value.page3Ref),
// getBase64Result(4, page4Ref.value.page4Ref),
// getBase64Result(5, page5Ref.value.page5Ref),
// getBase64Result(6, page6Ref.value.page6Ref),
// getBase64Result(7, page7Ref.value.page7Ref),
// getBase64Result(8, page8Ref.value.page8Ref),
// getBase64Result(9, page9Ref.value.page9Ref),
// getBase64Result(10, page10Ref.value.page10Ref),
// getBase64Result(11, page11Ref.value.page11Ref),
// getBase64Result(12, page12Ref.value.page12Ref),
// getBase64Result(13, page13Ref.value.page13Ref),
// getBase64Result(14, page14Ref.value.page14Ref),
// getBase64Result(15, page15Ref.value.page15Ref),
// getBase64Result(16, page16Ref.value.page16Ref),
// getBase64Result(17, page17Ref.value.page17Ref),
// getBase64Result(18, page18Ref.value.page18Ref),
// getBase64Result(19, page19Ref.value.page19Ref),
// getBase64Result(20, page20Ref.value.page20Ref),
// getBase64Result(21, page21Ref.value.page21Ref),
// getBase64Result(22, page22Ref.value.page22Ref),
// getBase64Result(23, page23Ref.value.page23Ref),
// getBase64Result(24, page24Ref.value.page24Ref),
// getBase64Result(25, page25Ref.value.page25Ref)])
await getBase64Result(1, page1Ref.value.page1Ref);
await getBase64Result(2, page2Ref.value.page2Ref);
await getBase64Result(3, page3Ref.value.page3Ref);
await getBase64Result(4, page4Ref.value.page4Ref);
await getBase64Result(5, page5Ref.value.page5Ref);
await getBase64Result(6, page6Ref.value.page6Ref);
await getBase64Result(7, page7Ref.value.page7Ref);
await getBase64Result(8, page8Ref.value.page8Ref);
await getBase64Result(9, page9Ref.value.page9Ref);
await getBase64Result(10, page10Ref.value.page10Ref);
await getBase64Result(11, page11Ref.value.page11Ref);
await getBase64Result(12, page12Ref.value.page12Ref);
await getBase64Result(13, page13Ref.value.page13Ref);
await getBase64Result(14, page14Ref.value.page14Ref);
await getBase64Result(15, page15Ref.value.page15Ref);
await getBase64Result(16, page16Ref.value.page16Ref);
await getBase64Result(17, page17Ref.value.page17Ref);
await getBase64Result(18, page18Ref.value.page18Ref);
await getBase64Result(19, page19Ref.value.page19Ref);
await getBase64Result(20, page20Ref.value.page20Ref);
await getBase64Result(21, page21Ref.value.page21Ref);
await getBase64Result(22, page22Ref.value.page22Ref);
await getBase64Result(23, page23Ref.value.page23Ref);
await getBase64Result(24, page24Ref.value.page24Ref);
await getBase64Result(25, page25Ref.value.page25Ref);
lastPPT();
loading.close();
};
这里就导出,先安装插件
npm install pptxgenjs --save // ppt插件
import html2canvas from "html2canvas"; //DOM转转图片
const generateImage = (dom: any) => {
return new Promise((resolve) => {
html2canvas(dom).then((canvas) => {
const base64img = canvas.toDataURL("image/png", 1.0); //转base64图片
resolve(base64img);
});
});
};
import pptxgen from "pptxgenjs";
const lastPPT = () => { // 1. 创建PPT let ppt = new pptxgen(); // ppt.layout = 'LAYOUT_WIDE'; //13.5 x 7.5 // 2. 创建一个PPT页面,每调用一次 ppt.addSlide() 都可以生成一张新的页面 // 建议把每个页面的构造抽成一个个函数,然后通过函数调用生成新页面,代码不会很乱 let slide = ppt.addSlide(); // 图片铺满的配置 const optionsImage = { x: 0, y: 0, h: "100%", w: "100%", sizing: { type: "contain" }, // 图片尺寸 }; slide.addImage({ ...optionsImage, data: page1Image.value, // 我用的是二进制图片 }); //第二个幻灯片 ppt.addSlide().addImage({ ...optionsImage, data: page2Image.value, // 我用的是二进制图片 }); //第3个幻灯片 ppt.addSlide().addImage({ ...optionsImage, data: page3Image.value, // 我用的是二进制图片 }); ... //第25个幻灯片 ppt.addSlide().addImage({ ...optionsImage, data: page25Image.value, // 我用的是二进制图片 }); // 4. 生成PPT, 括号中的fileName,就是生成的 PPT名字,可以使用 .then 或者 .catch处理对应事件。 ppt.writeFile({ fileName: "PPT的名字.pptx" }); };
贴一个项目中的代码吧哈哈
<template>
<!-- <el-button class="export-btn" type="primary" @click="exportPPt">导出</el-button> -->
<!-- PPT相关的所有东西 -->
<div ref="ppt" class="ppt-all">
<ppt1 ref="page1Ref"></ppt1>
<ppt2 ref="page2Ref"></ppt2>
<ppt3 :dataAll="dataAll.dataAll" ref="page3Ref"></ppt3>
<ppt4 v-if="dataAll.dataAll" :dataAll="dataAll.dataAll" ref="page4Ref"></ppt4>
<ppt5 :dataAll="dataAll.dataAll" ref="page5Ref"></ppt5>
<ppt6 :dataAll="dataAll.dataAll" ref="page6Ref"></ppt6>
<ppt7 ref="page7Ref"></ppt7>
<ppt8 :dataAll="dataAll.dataAll" ref="page8Ref"></ppt8>
<ppt9 :dataAll="dataAll.dataAll" ref="page9Ref"></ppt9>
<ppt10 :dataAll="dataAll.dataAll" ref="page10Ref"></ppt10>
<ppt11 :dataAll="dataAll.dataAll" ref="page11Ref"></ppt11>
<ppt12 v-if="dataAll.dataAll" :dataAll="dataAll.dataAll" ref="page12Ref"></ppt12>
<ppt13 :dataAll="dataAll.dataAll" ref="page13Ref"></ppt13>
<ppt14 :dataAll="dataAll.dataAll" ref="page14Ref"></ppt14>
<ppt15 :dataAll="dataAll.dataAll" ref="page15Ref"></ppt15>
<ppt16 :dataAll="dataAll.dataAll" ref="page16Ref"></ppt16>
<ppt17 :dataAll="dataAll.dataAll" ref="page17Ref"></ppt17>
<ppt18 :dataAll="dataAll.dataAll" ref="page18Ref"></ppt18>
<ppt19 :dataAll="dataAll.dataAll" ref="page19Ref"></ppt19>
<ppt20 v-if="dataAll.dataAll" :dataAll="dataAll.dataAll" ref="page20Ref"></ppt20>
<ppt21 :dataAll="dataAll.dataAll" ref="page21Ref"></ppt21>
<ppt22 :dataAll="dataAll.dataAll" ref="page22Ref"></ppt22>
<ppt23 ref="page23Ref"></ppt23>
<ppt24 :dataAll="dataAll.dataAll" ref="page24Ref"></ppt24>
<ppt25 ref="page25Ref"></ppt25>
<ppt26 ref="page26Ref"></ppt26>
</div>
</template>
<script lang="ts" setup>
import { defineExpose, ref, reactive,defineEmits } from "vue";
import { ElLoading } from "element-plus";
import request from "@/API/request";
import serviceModule from "@/API/login";
import { ElMessage } from "element-plus";
import ppt1 from "./ppt1.vue";
import ppt2 from "./ppt2.vue";
import ppt3 from "./ppt3.vue";
import ppt4 from "./ppt4.vue";
import ppt5 from "./ppt5.vue";
import ppt6 from "./ppt6.vue";
import ppt7 from "./ppt7.vue";
import ppt8 from "./ppt8.vue";
import ppt9 from "./ppt9.vue";
import ppt10 from "./ppt10.vue";
import ppt11 from "./ppt11.vue";
import ppt12 from "./ppt12.vue";
import ppt13 from "./ppt13.vue";
import ppt14 from "./ppt14.vue";
import ppt15 from "./ppt15.vue";
import ppt16 from "./ppt16.vue";
import ppt17 from "./ppt17.vue";
import ppt18 from "./ppt18.vue";
import ppt19 from "./ppt19.vue";
import ppt20 from "./ppt20.vue";
import ppt21 from "./ppt21.vue";
import ppt22 from "./ppt22.vue";
import ppt23 from "./ppt23.vue";
import ppt24 from "./ppt24.vue";
import ppt25 from "./ppt25.vue";
import ppt26 from "./ppt26.vue";
import pptxgen from "pptxgenjs";
import html2canvas from "html2canvas";
const ppt = ref(null);
const page1Ref = ref(null);
const page1Image = ref("");
const page2Ref = ref(null);
const page2Image = ref("");
const page3Ref = ref(null);
const page3Image = ref("");
const page4Ref = ref(null);
const page4Image = ref("");
const page5Ref = ref(null);
const page5Image = ref("");
const page6Ref = ref(null);
const page6Image = ref("");
const page7Ref = ref(null);
const page7Image = ref("");
const page8Ref = ref(null);
const page8Image = ref("");
const page9Ref = ref(null);
const page9Image = ref("");
const page10Ref = ref(null);
const page10Image = ref("");
const page11Ref = ref(null);
const page11Image = ref("");
const page12Ref = ref(null);
const page12Image = ref("");
const page13Ref = ref(null);
const page13Image = ref("");
const page14Ref = ref(null);
const page14Image = ref("");
const page15Ref = ref(null);
const page15Image = ref("");
const page16Ref = ref(null);
const page16Image = ref("");
const page17Ref = ref(null);
const page17Image = ref("");
const page18Ref = ref(null);
const page18Image = ref("");
const page19Ref = ref(null);
const page19Image = ref("");
const page20Ref = ref(null);
const page20Image = ref("");
const page21Ref = ref(null);
const page21Image = ref("");
const page22Ref = ref(null);
const page22Image = ref("");
const page23Ref = ref(null);
const page23Image = ref("");
const page24Ref = ref(null);
const page24Image = ref("");
const page25Ref = ref(null);
const page25Image = ref("");
const page26Ref = ref(null);
const page26Image = ref("");
const emit = defineEmits(['handleDataAll']);
const dataAll = reactive({
dataAll: {},
});
// 生成图片
const generateImage = (dom: any) => {
return new Promise((resolve) => {
html2canvas(dom).then((canvas) => {
const base64img = canvas.toDataURL("image/png", 1.0);
resolve(base64img);
});
});
};
// 获取到结果
async function getBase64Result(val: number, dom) {
if (val === 1) {
page1Image.value = await generateImage(dom);
}
if (val === 2) {
page2Image.value = await generateImage(dom);
}
if (val === 3) {
page3Image.value = await generateImage(dom);
}
if (val === 4) {
page4Image.value = await generateImage(dom);
}
if (val === 5) {
page5Image.value = await generateImage(dom);
}
if (val === 6) {
page6Image.value = await generateImage(dom);
}
if (val === 7) {
page7Image.value = await generateImage(dom);
}
if (val === 8) {
page8Image.value = await generateImage(dom);
}
if (val === 9) {
page9Image.value = await generateImage(dom);
}
if (val === 10) {
page10Image.value = await generateImage(dom);
}
if (val === 11) {
page11Image.value = await generateImage(dom);
}
if (val === 12) {
page12Image.value = await generateImage(dom);
}
if (val === 13) {
page13Image.value = await generateImage(dom);
}
if (val === 14) {
page14Image.value = await generateImage(dom);
}
if (val === 15) {
page15Image.value = await generateImage(dom);
}
if (val === 16) {
page16Image.value = await generateImage(dom);
}
if (val === 17) {
page17Image.value = await generateImage(dom);
}
if (val === 18) {
page18Image.value = await generateImage(dom);
}
if (val === 19) {
page19Image.value = await generateImage(dom);
}
if (val === 20) {
page20Image.value = await generateImage(dom);
}
if (val === 21) {
page21Image.value = await generateImage(dom);
}
if (val === 22) {
page22Image.value = await generateImage(dom);
}
if (val === 23) {
page23Image.value = await generateImage(dom);
}
if (val === 24) {
page24Image.value = await generateImage(dom);
}
if (val === 25) {
page25Image.value = await generateImage(dom);
}
if (val === 26) {
page26Image.value = await generateImage(dom);
}
}
const exportPPt = async () => {
const loading = ElLoading.service({
lock: true,
text: "导出中",
background: "rgba(0, 0, 0, 0.7)",
});
// await Promise.all([getBase64Result(1, page1Ref.value.page1Ref),
// getBase64Result(2, page2Ref.value.page2Ref),
// getBase64Result(3, page3Ref.value.page3Ref),
// getBase64Result(4, page4Ref.value.page4Ref),
// getBase64Result(5, page5Ref.value.page5Ref),
// getBase64Result(6, page6Ref.value.page6Ref),
// getBase64Result(7, page7Ref.value.page7Ref),
// getBase64Result(8, page8Ref.value.page8Ref),
// getBase64Result(9, page9Ref.value.page9Ref),
// getBase64Result(10, page10Ref.value.page10Ref),
// getBase64Result(11, page11Ref.value.page11Ref),
// getBase64Result(12, page12Ref.value.page12Ref),
// getBase64Result(13, page13Ref.value.page13Ref),
// getBase64Result(14, page14Ref.value.page14Ref),
// getBase64Result(15, page15Ref.value.page15Ref),
// getBase64Result(16, page16Ref.value.page16Ref),
// getBase64Result(17, page17Ref.value.page17Ref),
// getBase64Result(18, page18Ref.value.page18Ref),
// getBase64Result(19, page19Ref.value.page19Ref),
// getBase64Result(20, page20Ref.value.page20Ref),
// getBase64Result(21, page21Ref.value.page21Ref),
// getBase64Result(22, page22Ref.value.page22Ref),
// getBase64Result(23, page23Ref.value.page23Ref),
// getBase64Result(24, page24Ref.value.page24Ref),
await getBase64Result(1, page1Ref.value.page1Ref);
await getBase64Result(2, page2Ref.value.page2Ref);
await getBase64Result(3, page3Ref.value.page3Ref);
await getBase64Result(4, page4Ref.value.page4Ref);
await getBase64Result(5, page5Ref.value.page5Ref);
await getBase64Result(6, page6Ref.value.page6Ref);
await getBase64Result(7, page7Ref.value.page7Ref);
await getBase64Result(8, page8Ref.value.page8Ref);
await getBase64Result(9, page9Ref.value.page9Ref);
await getBase64Result(10, page10Ref.value.page10Ref);
await getBase64Result(11, page11Ref.value.page11Ref);
await getBase64Result(12, page12Ref.value.page12Ref);
await getBase64Result(13, page13Ref.value.page13Ref);
await getBase64Result(14, page14Ref.value.page14Ref);
await getBase64Result(15, page15Ref.value.page15Ref);
await getBase64Result(16, page16Ref.value.page16Ref);
await getBase64Result(17, page17Ref.value.page17Ref);
await getBase64Result(18, page18Ref.value.page18Ref);
await getBase64Result(19, page19Ref.value.page19Ref);
await getBase64Result(20, page20Ref.value.page20Ref);
await getBase64Result(21, page21Ref.value.page21Ref);
await getBase64Result(22, page22Ref.value.page22Ref);
await getBase64Result(23, page23Ref.value.page23Ref);
await getBase64Result(24, page24Ref.value.page24Ref);
await getBase64Result(25, page25Ref.value.page25Ref);
await getBase64Result(26, page26Ref.value.page26Ref);
lastPPT();
loading.close();
};
const lastPPT = () => {
// 1. 创建PPT
let ppt = new pptxgen();
// ppt.layout = 'LAYOUT_WIDE'; //13.5 x 7.5
// 2. 创建一个PPT页面,每调用一次 ppt.addSlide() 都可以生成一张新的页面
// 建议把每个页面的构造抽成一个个函数,然后通过函数调用生成新页面,代码不会很乱
let slide = ppt.addSlide();
// 图片铺满的配置
const optionsImage = {
x: 0,
y: 0,
h: "100%",
w: "100%",
sizing: { type: "contain" }, // 图片尺寸
};
slide.addImage({
...optionsImage,
data: page1Image.value, // 我用的是二进制图片
});
//第二个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page2Image.value, // 我用的是二进制图片
});
//第3个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page3Image.value, // 我用的是二进制图片
});
//第4个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page4Image.value, // 我用的是二进制图片
});
//第5个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page5Image.value, // 我用的是二进制图片
});
//第6个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page6Image.value, // 我用的是二进制图片
});
//第7个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page7Image.value, // 我用的是二进制图片
});
//第8个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page8Image.value, // 我用的是二进制图片
});
//第9个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page9Image.value, // 我用的是二进制图片
});
//第10个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page10Image.value, // 我用的是二进制图片
});
// 11-20
//第11个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page11Image.value, // 我用的是二进制图片
});
//第12个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page12Image.value, // 我用的是二进制图片
});
//第13个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page13Image.value, // 我用的是二进制图片
});
//第14个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page14Image.value, // 我用的是二进制图片
});
//第15个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page15Image.value, // 我用的是二进制图片
});
//第16个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page16Image.value, // 我用的是二进制图片
});
//第17个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page17Image.value, // 我用的是二进制图片
});
//第18个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page18Image.value, // 我用的是二进制图片
});
//第19个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page19Image.value, // 我用的是二进制图片
});
//第20个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page20Image.value, // 我用的是二进制图片
});
//第21个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page21Image.value, // 我用的是二进制图片
});
//第22个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page22Image.value, // 我用的是二进制图片
});
//第23个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page23Image.value, // 我用的是二进制图片
});
//第24个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page24Image.value, // 我用的是二进制图片
});
//第25个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page25Image.value, // 我用的是二进制图片
});
//第26个幻灯片
ppt.addSlide().addImage({
...optionsImage,
data: page26Image.value, // 我用的是二进制图片
});
// 4. 生成PPT, 括号中的fileName,就是生成的 PPT名字,可以使用 .then 或者 .catch处理对应事件。
ppt.writeFile({ fileName: "分析报告.pptx" });
};
async function getAllPPtData() {
const selectData = JSON.parse(localStorage.getItem("selectTopData"));
let date = "";
date =
selectData.date.split("-")[0] +
selectData.date.split("-")[1] +
selectData.date.split("-")[2];
let params = {
scenesType: "XX社区",
profileName: selectData.business === "全部" ? "" : selectData.business,
flag: selectData.flag,
codeId: selectData.areaCode,
statDate: date,
};
let res = await request(serviceModule.AllPptData, params);
if (res.data.code === 200) {
dataAll.dataAll = res.data.data;
emit('handleDataAll',dataAll.dataAll)
} else {
ElMessage.error(res.data.msg);
}
// request(serviceModule.AllPptData, params).then((res) => {
// if (res.data.code === 200) {
// console.log("获取dead", res);
// dataAll.dataAll = res.data.data;
// } else {
// ElMessage.error(res.data.msg);
// }
// });
}
// onMounted(() => {
// setTimeout(() => {
// getAllPPtData();
// }, 1000);
// });
defineExpose({
ppt,
exportPPt,
getAllPPtData,
});
</script>
<style lang="less">
.ppt-all {
position: fixed;
top: 0;
left: 0;
z-index: -9999;
font-family: Source Han Sans CN;
background-color: #ffffff;
}
.cm-width {
width: 1920px;
height: 1080px;
// border: 1px solid red;
font-family: Source Han Sans CN;
box-sizing: border-box;
background-image: url("@/assets/images/ppt/bg.png");
background-repeat: no-repeat;
background-size: contain;
position: relative;
}
.cm-pageNumber{
position: absolute;
right: 30px;
bottom: 30px;
font-size: 26px;
}
.cm-active {
color: rgba(22, 110, 244, 1) !important;
font-size: 42px !important;
font-weight: bold !important;
}
.ppt-all {
.resultInfo {
padding: 0 75px;
text-align: left !important;
}
.desc {
padding-left: 75px;
padding-right: 75px;
}
}</style>
浙公网安备 33010602011771号