|
|
@@ -9,32 +9,44 @@
|
|
|
<img :src="require('@/assets/shareRight.png')" />
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="title">
|
|
|
- <div class="name">{{ reportTarget.nickName }}的日报</div>
|
|
|
- <div class="date">
|
|
|
- {{
|
|
|
- reportTarget.commitTime ? formatChineseDate(reportTarget.commitTime.split(' ')[0]) : ''
|
|
|
- }}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
<div class="summaryDay">
|
|
|
- <template v-for="(item, index) in reportTarget.reportContents"
|
|
|
+ <div class="title-box">
|
|
|
+ <div class="title">
|
|
|
+ <div class="name">{{ reportTarget.nickName }}的日报</div>
|
|
|
+ <div class="date">
|
|
|
+ {{
|
|
|
+ reportTarget.commitTime
|
|
|
+ ? formatChineseDate(reportTarget.commitTime.split(' ')[0])
|
|
|
+ : ''
|
|
|
+ }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <template
|
|
|
+ v-for="(item, index) in reportTarget.reportContents"
|
|
|
v-if="reportTarget.reportContents && reportTarget.reportContents.length > 0">
|
|
|
<div class="text">{{ filterText(index) }}</div>
|
|
|
<div class="content">{{ item.dayContent }}</div>
|
|
|
</template>
|
|
|
<div class="text">今日拜访照片</div>
|
|
|
<div class="content-photos">
|
|
|
- <template v-for="item in reportTarget.photos">
|
|
|
- <template v-for="item1 in item.photos">
|
|
|
- <img :src="item1.fileUrl" alt="" crossorigin="anonymous"
|
|
|
- style="display: block; width: 188px; height: 188px; object-fit: cover" @load="handleImageLoad"
|
|
|
- @error="handleImageError" />
|
|
|
- </template>
|
|
|
+ <!-- <template v-for="item in reportTarget.photos">
|
|
|
+ <template v-for="item1 in item.photos">
|
|
|
+ <img :src="item1.baseUrl" crossorigin="anonymous" referrerpolicy="no-referrer" alt=""
|
|
|
+ style="display: block; width: 188px; height: 188px; object-fit: cover" v-if="item1.baseUrl" />
|
|
|
+ </template>photosData
|
|
|
+ </template> -->
|
|
|
+ <template v-for="item in photosData">
|
|
|
+ <img
|
|
|
+ :src="item"
|
|
|
+ crossorigin="anonymous"
|
|
|
+ referrerpolicy="no-referrer"
|
|
|
+ alt=""
|
|
|
+ style="display: block" />
|
|
|
</template>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="footer">
|
|
|
+ <div class="footerShare">
|
|
|
<div class="QRcodes">
|
|
|
<template v-if="processFlag == 'development'">
|
|
|
<img :src="require('@/assets/testQRcode.png')" />
|
|
|
@@ -55,7 +67,7 @@
|
|
|
</div>
|
|
|
</template>
|
|
|
<script>
|
|
|
-import html2canvas from 'html2canvas'
|
|
|
+import html2canvas from 'html2canvas';
|
|
|
export default {
|
|
|
name: 'share',
|
|
|
props: {
|
|
|
@@ -69,37 +81,69 @@ export default {
|
|
|
data() {
|
|
|
return {
|
|
|
processFlag: '',
|
|
|
- canvasImageUrl: "",
|
|
|
+ canvasImageUrl: '',
|
|
|
+ retryCount: 0,
|
|
|
+ photosData: [],
|
|
|
};
|
|
|
},
|
|
|
- mounted() {
|
|
|
+ created() {
|
|
|
+ // this.toastLoading(0, '生成中...', true);
|
|
|
this.processFlag = process.env.NODE_ENV;
|
|
|
- this.$nextTick(() => {
|
|
|
- setTimeout(async () => {
|
|
|
- try {
|
|
|
- await this.htmlToCanvas();
|
|
|
- } catch (error) {
|
|
|
- console.error('初始化生成分享图失败:', error);
|
|
|
- }
|
|
|
- }, 3000);
|
|
|
+ // 使用Promise.all确保所有图片加载完成
|
|
|
+ const photos = this.reportTarget.photos;
|
|
|
+ const photoPromises = [];
|
|
|
+
|
|
|
+ // 收集所有图片转换的Promise
|
|
|
+ photos.forEach((item) => {
|
|
|
+ item.photos.forEach((photo) => {
|
|
|
+ photoPromises.push(this.imageUrlToBase64(photo.fileUrl));
|
|
|
+ });
|
|
|
});
|
|
|
- },
|
|
|
- data() {
|
|
|
- return {
|
|
|
- processFlag: '',
|
|
|
- canvasImageUrl: "",
|
|
|
- loadedImages: new Set(),
|
|
|
- errorImages: new Set(),
|
|
|
- retryCount: 0,
|
|
|
- };
|
|
|
+
|
|
|
+ // 等待所有图片加载完成
|
|
|
+ Promise.all(photoPromises)
|
|
|
+ .then((photosArr) => {
|
|
|
+ this.photosData = photosArr;
|
|
|
+ this.$nextTick(async () => {
|
|
|
+ // await this.htmlToCanvas();
|
|
|
+ });
|
|
|
+ })
|
|
|
+ .catch((error) => {
|
|
|
+ console.error('图片加载失败:', error);
|
|
|
+ this.$toast('图片加载失败,请检查网络');
|
|
|
+ });
|
|
|
+ console.log(photos);
|
|
|
},
|
|
|
methods: {
|
|
|
- handleImageLoad(e) {
|
|
|
- this.loadedImages.add(e.target.src);
|
|
|
- },
|
|
|
- handleImageError(e) {
|
|
|
- console.error('Image load failed:', e.target.src);
|
|
|
- this.errorImages.add(e.target.src);
|
|
|
+ //异步执行
|
|
|
+ imageUrlToBase64(imageUrl) {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ //一定要设置为let,不然图片不显示
|
|
|
+ let image = new Image();
|
|
|
+
|
|
|
+ //解决跨域问题
|
|
|
+ image.setAttribute('crossOrigin', 'anonymous');
|
|
|
+
|
|
|
+ image.src = imageUrl;
|
|
|
+
|
|
|
+ //image.onload为异步加载
|
|
|
+ image.onload = () => {
|
|
|
+ var canvas = document.createElement('canvas');
|
|
|
+ canvas.width = image.width;
|
|
|
+ canvas.height = image.height;
|
|
|
+ var context = canvas.getContext('2d');
|
|
|
+ context.drawImage(image, 0, 0, image.width, image.height);
|
|
|
+
|
|
|
+ var quality = 1;
|
|
|
+ //这里的dataurl就是base64类型
|
|
|
+ let dataURL = canvas.toDataURL('image/png', quality); //使用toDataUrl将图片转换成jpeg的格式,不要把图片压缩成png,因为压缩成png后base64的字符串可能比不转换前的长!
|
|
|
+ resolve(dataURL);
|
|
|
+ };
|
|
|
+
|
|
|
+ image.onerror = () => {
|
|
|
+ reject(new Error('图像加载失败'));
|
|
|
+ };
|
|
|
+ });
|
|
|
},
|
|
|
filterText(index) {
|
|
|
if (index == 0) {
|
|
|
@@ -108,43 +152,26 @@ export default {
|
|
|
return '今日机会与挑战总结';
|
|
|
}
|
|
|
},
|
|
|
- async htmlToCanvas() {
|
|
|
- // 确保所有图片加载完成
|
|
|
- const images = this.$refs.shareContent.querySelectorAll('img');
|
|
|
- await Promise.all(Array.from(images).map(img => {
|
|
|
- debugger
|
|
|
- if (img.complete && img.naturalHeight !== 0) return Promise.resolve();
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- img.addEventListener('load', resolve);
|
|
|
- img.addEventListener('error', () => reject(new Error(`图片加载失败: ${img.src}`)));
|
|
|
- });
|
|
|
- })).catch(error => {
|
|
|
- console.error('图片预加载错误:', error);
|
|
|
- this.$toast('图片加载失败,请检查网络连接');
|
|
|
- throw error;
|
|
|
- });
|
|
|
-
|
|
|
- return html2canvas(this.$refs.shareContent, {
|
|
|
+ htmlToCanvas() {
|
|
|
+ html2canvas(this.$refs.shareContent, {
|
|
|
scale: window.devicePixelRatio || 1,
|
|
|
useCORS: true,
|
|
|
logging: true,
|
|
|
allowTaint: false,
|
|
|
backgroundColor: null,
|
|
|
imageTimeout: 30000,
|
|
|
- ignoreElements: (element) => element.id === 'html2canvas',
|
|
|
- onclone: (clonedDoc) => {
|
|
|
- clonedDoc.getElementById('html2canvas').style.visibility = 'hidden';
|
|
|
- }
|
|
|
})
|
|
|
.then((canvas) => {
|
|
|
+ this.toastLoading().clear();
|
|
|
let imageUrl = canvas.toDataURL('image/png');
|
|
|
this.canvasImageUrl = imageUrl;
|
|
|
})
|
|
|
- .catch(error => {
|
|
|
+ .catch((error) => {
|
|
|
+ this.toastLoading().clear();
|
|
|
console.error('html2canvas error:', error);
|
|
|
this.$toast('生成分享图失败,请稍后重试');
|
|
|
});
|
|
|
- }
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
</script>
|
|
|
@@ -153,6 +180,8 @@ export default {
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
overflow: hidden;
|
|
|
+ // position: fixed;
|
|
|
+ // z-index: -1;
|
|
|
|
|
|
.share-content {
|
|
|
background: url('../assets/shareBack.png') no-repeat center center;
|
|
|
@@ -160,10 +189,12 @@ export default {
|
|
|
background-attachment: local;
|
|
|
width: 100%;
|
|
|
// height: 100%;
|
|
|
- padding: vw(45);
|
|
|
+ padding: vw(30);
|
|
|
position: fixed;
|
|
|
- z-index: -1;
|
|
|
+ // z-index: -1;
|
|
|
padding-bottom: vw(190);
|
|
|
+ top: 0;
|
|
|
+ z-index: 111111;
|
|
|
}
|
|
|
|
|
|
.header {
|
|
|
@@ -185,51 +216,71 @@ export default {
|
|
|
height: 100%;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- .title {
|
|
|
+ .title-box {
|
|
|
display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- color: #ecd98a;
|
|
|
- font-size: vw(36);
|
|
|
- font-weight: bold;
|
|
|
- margin-top: vw(81);
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ position: absolute;
|
|
|
+ top: -6px;
|
|
|
+ left: 50%;
|
|
|
+ margin-left: vw(-169);
|
|
|
+ .title {
|
|
|
+ color: #600d0e;
|
|
|
+ font-size: vw(36);
|
|
|
+ font-weight: bold;
|
|
|
+ // margin-top: vw(81);
|
|
|
+ // width: vw(338);
|
|
|
+ // height: vw(115);
|
|
|
+ text-align: center;
|
|
|
+ background: url('../assets/titleBack.png') no-repeat;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ padding: vw(20) vw(30);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
.summaryDay {
|
|
|
+ background: url('../assets/summaryDay.png') no-repeat;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ padding: vw(24);
|
|
|
+ position: relative;
|
|
|
.text {
|
|
|
background: url('../assets/textBack.png') no-repeat;
|
|
|
- width: vw(595);
|
|
|
+ width: 100%;
|
|
|
height: vw(94);
|
|
|
- background-size: contain;
|
|
|
+ background-size: cover;
|
|
|
color: #7d0207;
|
|
|
font-size: vw(36);
|
|
|
text-align: center;
|
|
|
line-height: vw(94);
|
|
|
- margin: vw(45) 0;
|
|
|
+ margin-top: vw(152);
|
|
|
+ margin-bottom: vw(45);
|
|
|
+ font-weight: bold;
|
|
|
}
|
|
|
|
|
|
.content {
|
|
|
font-size: vw(28);
|
|
|
font-weight: bold;
|
|
|
- color: #e6cd78;
|
|
|
+ color: #ffff;
|
|
|
line-height: vw(63);
|
|
|
+ white-space: pre-wrap;
|
|
|
}
|
|
|
|
|
|
.content-photos {
|
|
|
display: flex;
|
|
|
flex-wrap: wrap;
|
|
|
- justify-content: space-between;
|
|
|
+ // justify-content: space-between;
|
|
|
|
|
|
img {
|
|
|
- width: 188px;
|
|
|
- height: 188px;
|
|
|
+ width: vw(188);
|
|
|
+ height: vw(188);
|
|
|
margin-bottom: 15px;
|
|
|
+ margin-right: 15px;
|
|
|
background-color: rgba(255, 255, 255, 0.1);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- .footer {
|
|
|
+ .footerShare {
|
|
|
display: flex;
|
|
|
// align-items: center;
|
|
|
justify-content: center;
|
|
|
@@ -246,6 +297,21 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ .right-text {
|
|
|
+ margin-left: vw(12.5);
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: space-between;
|
|
|
+
|
|
|
+ div {
|
|
|
+ color: #ffffff;
|
|
|
+ font-size: vw(24);
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #html2canvas {
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
position: fixed;
|