zhujindu 8 ماه پیش
والد
کامیت
1035450d2f
4فایلهای تغییر یافته به همراه423 افزوده شده و 82 حذف شده
  1. BIN
      src/assets/summaryDay.png
  2. BIN
      src/assets/titleBack.png
  3. 275 0
      src/components/share copy.vue
  4. 148 82
      src/components/share.vue

BIN
src/assets/summaryDay.png


BIN
src/assets/titleBack.png


+ 275 - 0
src/components/share copy.vue

@@ -0,0 +1,275 @@
+<template>
+  <div class="share">
+    <div class="share-content" ref="shareContent">
+      <div class="header">
+        <div class="left-icon">
+          <img :src="require('@/assets/shareLeft.png')" />
+        </div>
+        <div class="right-icon">
+          <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"
+          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.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; width: 188px; height: 188px; object-fit: cover" />
+          </template>
+        </div>
+      </div>
+      <div class="footerShare">
+        <div class="QRcodes">
+          <template v-if="processFlag == 'development'">
+            <img :src="require('@/assets/testQRcode.png')" />
+          </template>
+          <template v-else>
+            <img :src="require('@/assets/QRcode.png')" />
+          </template>
+        </div>
+        <div class="right-text">
+          <div>长按识别二维码</div>
+          <div>查看详情&点评</div>
+        </div>
+      </div>
+    </div>
+    <div id="html2canvas" ref="html2canvas">
+      <img :src="canvasImageUrl" />
+    </div>
+  </div>
+</template>
+<script>
+import html2canvas from 'html2canvas'
+export default {
+  name: 'share',
+  props: {
+    reportTarget: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      processFlag: '',
+      canvasImageUrl: "",
+      retryCount: 0,
+      photosData: [],
+    };
+  },
+  created() {
+    this.processFlag = process.env.NODE_ENV;
+    let photos = this.reportTarget.photos;
+    let photosArr = [];
+    let num = 0
+    for (let i = 0; i < photos.length; i++) {
+      for (let j = 0; j < photos[i].photos.length; j++) {
+        this.imageUrlToBase64(photos[i].photos[j].fileUrl).then(base64 => {
+          // photos[i].photos[j].baseUrl = base64;
+          photosArr.push(base64)
+          num++
+        });
+      }
+      if (num == photosArr.length) {
+        this.photosData = photosArr
+        this.$nextTick(() => {
+          setTimeout(async () => {
+            await this.htmlToCanvas();
+          }, 2000)
+        })
+      }
+    }
+    console.log(photos)
+  },
+  methods: {
+    //异步执行
+    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) {
+        return '明日工作计划';
+      } else {
+        return '今日机会与挑战总结';
+      }
+    },
+    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) => {
+          let imageUrl = canvas.toDataURL('image/png');
+          this.canvasImageUrl = imageUrl;
+        })
+        .catch(error => {
+          console.error('html2canvas error:', error);
+          this.$toast('生成分享图失败,请稍后重试');
+        });
+    }
+  },
+};
+</script>
+<style lang="scss" scoped>
+.share {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  // position: fixed;
+  // z-index: -1;
+
+  .share-content {
+    background: url('../assets/shareBack.png') no-repeat center center;
+    background-size: cover;
+    background-attachment: local;
+    width: 100%;
+    // height: 100%;
+    padding: vw(45);
+    // position: fixed;
+    // z-index: -1;
+    padding-bottom: vw(190);
+  }
+
+  .header {
+    display: flex;
+    justify-content: space-between;
+
+    .left-icon {
+      width: vw(114);
+      height: vw(71);
+    }
+
+    .right-icon {
+      width: vw(230);
+      height: vw(78);
+    }
+
+    img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+
+  .title {
+    display: flex;
+    justify-content: space-between;
+    color: #ecd98a;
+    font-size: vw(36);
+    font-weight: bold;
+    margin-top: vw(81);
+  }
+
+  .summaryDay {
+    .text {
+      background: url('../assets/textBack.png') no-repeat;
+      width: vw(595);
+      height: vw(94);
+      background-size: contain;
+      color: #7d0207;
+      font-size: vw(36);
+      text-align: center;
+      line-height: vw(94);
+      margin: vw(45) 0;
+    }
+
+    .content {
+      font-size: vw(28);
+      font-weight: bold;
+      color: #e6cd78;
+      line-height: vw(63);
+    }
+
+    .content-photos {
+      display: flex;
+      flex-wrap: wrap;
+      justify-content: space-between;
+      overflow: hidden;
+      width: 100%;
+      height: 300px;
+
+      img {
+        width: 188px;
+        height: 188px;
+        margin-bottom: 15px;
+        background-color: rgba(255, 255, 255, 0.1);
+      }
+    }
+  }
+
+  .footerShare {
+    display: flex;
+    // align-items: center;
+    justify-content: center;
+    margin-top: vw(100);
+
+    .QRcodes {
+      width: vw(87);
+      height: vw(87);
+      margin-right: vw(12.5);
+
+      img {
+        width: 100%;
+        height: 100%;
+      }
+    }
+
+    img {
+      width: 100%;
+    }
+  }
+}
+</style>

+ 148 - 82
src/components/share.vue

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