Procházet zdrojové kódy

Merge branch 'feature_20250331_日报分享' into release

# Conflicts:
#	src/api/index.js
#	src/main.js
#	src/views/week/dailyDetails.vue
#	src/views/week/dailyHistoricalDetails.vue
zhujindu před 4 měsíci
rodič
revize
bd59adebe5

+ 1 - 4
.env.development

@@ -4,11 +4,8 @@ VUE_APP_TITLE = 门店拜访
 # 开发环境配置
 ENV = 'development'
 VUE_APP_Target=https://ssbsfatest.nipponpaint.com.cn
-VUE_APP_SSB_LINK=http://suishenbangtest.nipponpaint.com.cn
+VUE_APP_SSB_LINK=https://suishenbangtest.nipponpaint.com.cn
 VUE_APP_XD_LINK=http://b2btest.nipponpaint.com.cn
-# ali-oss 配置
-VUE_APP_OSS_ACCESS_KEY_ID="LTAI5tG1DTJFA16BHkzHVxjz"
-VUE_APP_OSS_ACCESS_KEY_SECRET="5brWKKEACiUsKPJeUXlB7r2iZGQHNF"
 
 # 门店拜访/开发环境
 #VUE_APP_BASE_API = '/dev-api/'

+ 2 - 2
.env.production

@@ -7,11 +7,11 @@ ENV = 'production'
 
 # 正式环境
 VUE_APP_Target=https://ssbsfa.nipponpaint.com.cn
-VUE_APP_SSB_LINK=http://suishenbang.nipponpaint.com.cn
+VUE_APP_SSB_LINK=https://suishenbang.nipponpaint.com.cn
 VUE_APP_XD_LINK=http://b2b.nipponpaint.com.cn
 # 测试环境
 # VUE_APP_Target=https://ssbsfatest.nipponpaint.com.cn 
-# VUE_APP_SSB_LINK=http://suishenbangtest.nipponpaint.com.cn
+# VUE_APP_SSB_LINK=https://suishenbangtest.nipponpaint.com.cn
 # VUE_APP_XD_LINK=http://b2btest.nipponpaint.com.cn
 VUE_APP_BASE_API='/ssbsfa/'
 devtool=cheap-module-source-map

+ 4 - 7
.env.test

@@ -3,22 +3,19 @@ VUE_APP_TITLE = 门店拜访
 ENV = 'test'
 
 # 本地开发环境配置
-# VUE_APP_Target=http://192.168.100.191:9560/
-# VUE_APP_SSB_LINK=http://suishenbangtest.nipponpaint.com.cn
+# VUE_APP_Target=https://192.168.100.191:9560/
+# VUE_APP_SSB_LINK=https://suishenbangtest.nipponpaint.com.cn
 # VUE_APP_XD_LINK=http://b2btest.nipponpaint.com.cn
 # VUE_APP_BASE_API = '/'
 #测试环境
 VUE_APP_Target=https://ssbsfatest.nipponpaint.com.cn
-VUE_APP_SSB_LINK=http://suishenbangtest.nipponpaint.com.cn
+VUE_APP_SSB_LINK=https://suishenbangtest.nipponpaint.com.cn
 VUE_APP_XD_LINK=http://b2btest.nipponpaint.com.cn
 VUE_APP_BASE_API = '/ssbsfa/'
-# ali-oss 配置
-VUE_APP_OSS_ACCESS_KEY_ID="LTAI5tG1DTJFA16BHkzHVxjz"
-VUE_APP_OSS_ACCESS_KEY_SECRET="5brWKKEACiUsKPJeUXlB7r2iZGQHNF"
 
 # 正式环境
 # VUE_APP_Target=https://ssbsfa.nipponpaint.com.cn
-# VUE_APP_SSB_LINK=http://suishenbang.nipponpaint.com.cn
+# VUE_APP_SSB_LINK=https://suishenbang.nipponpaint.com.cn
 # VUE_APP_XD_LINK=http://b2b.nipponpaint.com.cn
 # VUE_APP_BASE_API='/ssbsfa/'
 # 路由懒加载

+ 3 - 0
package.json

@@ -19,11 +19,14 @@
     "coordtransform": "^2.1.2",
     "core-js": "^3.6.5",
     "element-ui": "^2.15.6",
+    "html2canvas": "^1.0.0-rc.4",
+    "qrcodejs2": "^0.0.2",
     "vant": "^2.12.37",
     "vconsole": "^3.15.1",
     "vue": "^2.6.11",
     "vue-baidu-map": "^0.21.22",
     "vue-jsonp": "^2.0.0",
+    "vue-qr": "^4.0.9",
     "vue-router": "^3.5.3",
     "vuex": "^3.6.0",
     "watermark-dom": "^2.3.0",

+ 40 - 31
public/index.html

@@ -1,38 +1,47 @@
 <!DOCTYPE html>
 <html lang="">
-<head>
-    <meta charset="utf-8">
-    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <head>
+    <meta charset="utf-8" />
+    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
     <meta
-            name="viewport"
-            content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"
-    />
-    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"/>
-    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+      name="viewport"
+      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
+    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
+    <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
     <title><%= webpackConfig.name %></title>
-</head>
-<body class="bgcolor">
-<noscript>
-    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
-</noscript>
-<div id="app"></div>
-<script>
-    if (GetQueryValue("loginName") != null) {
-        localStorage.removeItem('loginType')
-        localStorage.setItem('loginName', GetQueryValue("loginName"));
-        location.href=location.href.split("?")[0]+"?v="+new Date().getTime();
-    }
-    function GetQueryValue(queryName) {
+  </head>
+  <body class="bgcolor">
+    <noscript>
+      <strong
+        >We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without
+        JavaScript enabled. Please enable it to continue.</strong
+      >
+    </noscript>
+    <div id="app"></div>
+    <script>
+      //   if (GetQueryValue('loginName') != null) {
+      //     localStorage.removeItem('loginType');
+      //     localStorage.setItem('loginName', GetQueryValue('loginName'));
+      //     let href = location.href.split('?');
+      //     location.href = href[0] + '?v=' + new Date().getTime() + '&' + href[1];
+      //   }
+      function GetQueryValue(queryName) {
         var query = decodeURI(window.location.search.substring(1));
-        var vars = query.split("&");
-        for (var i = 0; i < vars.length; i++) {var pair = vars[i].split("=");if (pair[0] == queryName) {return pair[1];}}
+        var vars = query.split('&');
+        for (var i = 0; i < vars.length; i++) {
+          var pair = vars[i].split('=');
+          if (pair[0] == queryName) {
+            return pair[1];
+          }
+        }
         return null;
-    }
-</script>
-<script src="//res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
-<script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js"></script>
-<!--生产、uat-->
-<script charset="utf-8" src="https://map.qq.com/api/gljs?v=1.exp&libraries=service,tools&key=Y7SBZ-PI5K5-FOJIT-ILHLY-PN66T-HKB4A"></script>
-</body>
+      }
+    </script>
+    <script src="//res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
+    <script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js"></script>
+    <!--生产、uat-->
+    <script
+      charset="utf-8"
+      src="https://map.qq.com/api/gljs?v=1.exp&libraries=service,tools&key=Y7SBZ-PI5K5-FOJIT-ILHLY-PN66T-HKB4A"></script>
+  </body>
 </html>
-

+ 10 - 0
src/api/digest.js

@@ -0,0 +1,10 @@
+import request from '@/utils/request';
+
+// 获取阿里云oss STS token
+export function wxLogin(query) {
+  return request({
+    url: '/mobile/wx/wxLogin',
+    method: 'get',
+    params: query,
+  });
+}

+ 9 - 0
src/api/index.js

@@ -1030,3 +1030,12 @@ export function deleteSummaryMobile(query) {
     method: 'delete',
   });
 }
+
+// 根据日报id查询汇报当天拜访照片base64格式
+export function imgToBase64(data) {
+  return request({
+    url: '/mobile/reportMobile/imgToBase64',
+    method: 'post',
+    data,
+  });
+}

binární
src/assets/QRcode.png


binární
src/assets/comment.png


binární
src/assets/shareBack.webp


binární
src/assets/shareBack1.png


binární
src/assets/shareLeft.png


binární
src/assets/shareRight.png


binární
src/assets/shareTips.png


binární
src/assets/summaryDay.png


binární
src/assets/testQRcode.png


binární
src/assets/textBack.png


binární
src/assets/titleBack.png


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

@@ -0,0 +1,582 @@
+<template>
+  <div class="share" :style="{ 'z-index': zIndex }">
+    <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>
+      <!-- 点评 -->
+      <!-- <template v-for="item in reportTarget.reportRemarks"> -->
+      <div
+        class="comment summaryDay"
+        v-if="
+          reportRemarksIndex != -1 &&
+          reportTarget.reportRemarks &&
+          reportTarget.reportRemarks.length
+        ">
+        <div class="title-box">
+          <div class="title">
+            <div class="name">
+              {{ reportTarget.reportRemarks[reportRemarksIndex].nickName }}点评
+            </div>
+            <div class="date">
+              {{
+                reportTarget.reportRemarks[reportRemarksIndex].createTime
+                  ? formatChineseDate(
+                      reportTarget.reportRemarks[reportRemarksIndex].createTime.split(' ')[0]
+                    )
+                  : ''
+              }}
+            </div>
+          </div>
+        </div>
+        <div class="commentMessage">
+          {{ reportTarget.reportRemarks[reportRemarksIndex].remarkContent }}
+        </div>
+      </div>
+      <!-- </template> -->
+      <!-- 内容 -->
+      <div class="summaryDay">
+        <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">
+          {{ reportTarget.reportContents.length ? reportTarget.reportContents[0].dayContent : '' }}
+        </div>
+        <div :class="['text']">明日工作计划</div>
+        <div class="content">
+          {{ reportTarget.reportContents.length ? reportTarget.reportContents[1].dayContent : '' }}
+        </div>
+        <div class="text">今日拜访照片</div>
+        <div class="content-photos">
+          <template v-for="item in photosData">
+            <img
+              :src="'data:image/jpg;base64,' + item"
+              crossorigin="anonymous"
+              referrerpolicy="no-referrer"
+              alt=""
+              style="display: block" />
+          </template>
+          <!-- <template v-for="item in photosData">
+            <img
+              :src="'data:image/jpg;base64,' + item"
+              crossorigin="anonymous"
+              referrerpolicy="no-referrer"
+              alt=""
+              style="display: block" />
+          </template> -->
+        </div>
+      </div>
+      <div class="footerShare">
+        <div class="QRcodes" ref="QRcodes">
+          <div class="logo">
+            <img :src="require('@/assets/logo1.png')" />
+          </div>
+        </div>
+        <div class="right-text">
+          <div>长按识别二维码查看详情&点评</div>
+          <div></div>
+        </div>
+      </div>
+    </div>
+    <div
+      class="share-mask"
+      style="background: #fff; position: fixed; top: 0; width: 100%; height: 100%"></div>
+    <div class="html2canvasBox">
+      <div class="shareHeader">
+        <div class="shareTips">
+          长按图片可下载、收藏、转发
+          <!-- <img :src="require('@/assets/shareTips.png')" alt="" /> -->
+        </div>
+        <div class="closeShare" @click="closeShare"><van-icon name="close" /></div>
+      </div>
+      <div id="html2canvas" ref="html2canvas">
+        <div class="scroll-container">
+          <img :src="canvasImageUrl" width="100%" />
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import html2canvas from 'html2canvas';
+import QRCode from 'qrcodejs2';
+import { imgToBase64 } from '@/api/index';
+export default {
+  name: 'share',
+  props: {
+    // 日报数据
+    reportTarget: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    //日报id
+    reportId: {
+      type: [String, Number],
+    },
+    // 点评数据
+    reportRemarksIndex: {
+      type: Number,
+      default: -1,
+    },
+    // 图片转换列表
+    urlList: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+  },
+  data() {
+    return {
+      canvasImageUrl: '',
+      retryCount: 0,
+      photosData: [],
+      zIndex: -1,
+    };
+  },
+  created() {
+    this.zIndex = -1;
+    this.canvasImageUrl = '';
+  },
+  mounted() {
+    this.toastLoading(0, '生成中...', true);
+    // 二维码
+    this.creatQrCode();
+    if (this.urlList.length) {
+      imgToBase64({ urlList: this.urlList }).then((res) => {
+        if (res.data && res.code == 200) {
+          this.photosData = res.data;
+          this.$nextTick(async () => {
+            await this.htmlToCanvas();
+          });
+        } else {
+          this.$toast(res.msg);
+          this.$nextTick(async () => {
+            await this.htmlToCanvas();
+          });
+        }
+      });
+    } else {
+      this.$nextTick(async () => {
+        await this.htmlToCanvas();
+      });
+    }
+  },
+  methods: {
+    //异步执行
+    imageUrlToBase64(imageUrl) {
+      return new Promise((resolve, reject) => {
+        //一定要设置为let,不然图片不显示
+        let image = new Image();
+        //解决跨域问题
+        image.setAttribute('crossOrigin', 'anonymous');
+        image.src = imageUrl;
+        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,
+        allowTaint: false,
+        backgroundColor: null,
+        logging: false, // 关闭日志提升性能
+        onclone: (clonedDoc) => {
+          // 确保克隆的DOM保持原始样式
+          clonedDoc.getElementById('html2canvas').style.overflow = 'auto';
+        },
+      })
+        .then((canvas) => {
+          this.toastLoading().clear();
+          let imageUrl = canvas.toDataURL('image/png');
+          this.canvasImageUrl = imageUrl;
+
+          // 图片加载完成后设置滚动容器高度
+          const img = new Image();
+          img.onload = () => {
+            const scrollContainer = this.$refs.html2canvas.querySelector('.scroll-container');
+            // 根据图片实际高度设置容器高度(增加20px缓冲)
+            // 根据设备像素比调整图片高度
+            // 使用实际渲染高度而非原始图片高度
+            const imgHeight = img.offsetHeight + 20;
+            // 设置容器最小高度保证内容显示,同时允许自动扩展
+            scrollContainer.style.minHeight = `${imgHeight}px`;
+            // 保持父容器为可见滚动
+            scrollContainer.parentElement.style.overflow = 'visible';
+            // 强制浏览器重排
+            scrollContainer.style.display = 'none';
+            scrollContainer.offsetHeight; // 触发重排
+            scrollContainer.style.display = 'block';
+
+            // 添加移动端滚动优化
+            requestAnimationFrame(() => {
+              scrollContainer.style.overflow = 'auto';
+              scrollContainer.style.overflowScrolling = 'touch';
+              scrollContainer.style.webkitOverflowScrolling = 'touch';
+              scrollContainer.style.overscrollBehavior = 'contain';
+              scrollContainer.style.touchAction = 'pan-y';
+            });
+          };
+          img.src = imageUrl;
+          this.zIndex = 9;
+          this.$emit('setShareImg', true);
+        })
+        .catch((error) => {
+          this.toastLoading().clear();
+          console.error('html2canvas error:', error);
+          this.$toast('生成分享图失败,请稍后重试');
+        });
+    },
+    creatQrCode() {
+      // let proText = 'https://suishenbang.nipponpaint.com.cn';
+      let path =
+        process.env.VUE_APP_Target +
+          '/mobile/dailyHistoricalDetails&source=share&reportId=' +
+          this.reportId || '';
+      var qrcode = new QRCode(this.$refs.QRcodes, {
+        text: process.env.VUE_APP_SSB_LINK + '/homeIndex?path=' + path,
+        colorDark: '#000000',
+        colorLight: 'rgba(255,255,255,0)', // 完全透明背景
+        correctLevel: QRCode.CorrectLevel.H,
+        width: 140, // 固定尺寸保证安卓一致性
+        height: 140,
+        margin: 2,
+        render: 'canvas',
+        onRenderingEnd: () => {
+          const canvas = this.$refs.QRcodes.querySelector('canvas');
+          // 显式设置物理像素尺寸
+          const dpr = window.devicePixelRatio || 1;
+          canvas.width = 200 * dpr;
+          canvas.height = 200 * dpr;
+
+          // 设置CSS显示尺寸保持200x200
+          canvas.style.width = '200px';
+          canvas.style.height = '200px';
+
+          // 优化安卓设备显示
+          canvas.style.imageRendering = 'pixelated';
+          canvas.style.transform = 'translateZ(0)'; // 触发硬件加速
+          canvas.style.backgroundColor = '#fff';
+
+          // 调整画布缩放比例
+          const ctx = canvas.getContext('2d');
+          ctx.scale(dpr, dpr);
+        },
+      });
+    },
+    closeShare() {
+      this.canvasImageUrl = '';
+      this.$emit('setShareImg', false);
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.share {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  background: #fff;
+  position: fixed;
+  top: 0;
+
+  .share-content {
+    background: url('../assets/shareBack.png') no-repeat center center;
+    background-size: cover;
+    background-attachment: local;
+    width: 100%;
+    padding: vw(30);
+    position: absolute;
+    padding-bottom: vw(190);
+    top: 0;
+    z-index: -10;
+  }
+
+  .header {
+    display: flex;
+    justify-content: space-between;
+    padding-bottom: vw(40);
+
+    .left-icon {
+      width: vw(114);
+      height: vw(71);
+    }
+
+    .right-icon {
+      width: vw(230);
+      height: vw(78);
+    }
+
+    img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+  .title-box {
+    position: relative;
+    width: 100%;
+    height: auto;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    top: -6px;
+    .title {
+      // width: vw(262);
+      // height: vw(115);
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+      color: #600d0e;
+      font-weight: bold;
+      text-align: center;
+      // background: url('../assets/titleBack.png') no-repeat;
+      // background-size: 100% 100%;
+      padding: vw(20) vw(30);
+      background-color: #ecdd9a;
+      border-radius: 6px 6px 25px 25px;
+      .name {
+        font-size: vw(36);
+      }
+      .date {
+        font-size: vw(28);
+      }
+    }
+  }
+
+  .summaryDay {
+    background: url('../assets/summaryDay.png') no-repeat;
+    background-size: 100%;
+    padding: vw(24);
+    position: relative;
+    margin-top: vw(55);
+    border-radius: 0 0 vw(35) vw(35);
+    padding-top: 0;
+    .text {
+      background: url('../assets/textBack.png') no-repeat;
+      width: 100%;
+      height: vw(94);
+      background-size: cover;
+      color: #7d0207;
+      font-size: vw(36);
+      text-align: center;
+      line-height: vw(94);
+      // margin-top: vw(152);
+      // margin-bottom: vw(45);
+      margin: vw(35) 0;
+      font-weight: bold;
+    }
+
+    .content {
+      font-size: vw(28);
+      font-weight: bold;
+      color: #ffff;
+      line-height: vw(63);
+      white-space: pre-wrap;
+    }
+
+    .content-photos {
+      display: flex;
+      flex-wrap: wrap;
+      //   justify-content: space-between;
+
+      img {
+        width: 30%;
+        height: vw(188);
+        margin-bottom: 15px;
+        margin-right: 5%;
+        background-color: rgba(255, 255, 255, 0.1);
+        &:nth-child(3n) {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+  .comment {
+    .title {
+      // background: url('../assets/comment.png') no-repeat;
+      // background-size: 100% 100%;
+      background-color: #032371;
+      border-radius: 6px 6px 25px 25px;
+      color: #e6cd78;
+    }
+    .commentMessage {
+      padding: vw(60) 0;
+      font-family: PingFang-SC-Medium;
+      font-size: vw(28);
+      font-weight: bold;
+      color: #ffffff;
+    }
+  }
+
+  .footerShare {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    margin-top: vw(100);
+
+    .right-text {
+      // margin-left: vw(12.5);
+      display: flex;
+      // flex-direction: column;
+      // justify-content: space-between;
+      align-items: center;
+      justify-content: center;
+      padding: vw(10) 0;
+      div {
+        color: #ffffff;
+        font-size: vw(30);
+        font-weight: bold;
+      }
+    }
+  }
+  .html2canvasBox {
+    width: 100%;
+    height: 100%;
+    min-height: auto;
+    min-height: 100vh;
+    overflow: hidden !important;
+    display: flex;
+    flex-direction: column;
+    .shareHeader {
+      position: absolute;
+      z-index: 1;
+      top: 10px;
+      width: 100%;
+      display: flex;
+      align-items: center;
+      padding: 0 vw(30);
+      .closeShare {
+        // position: absolute;
+        // z-index: 1;
+        // right: 10px;
+        // top: 10px;
+        color: #fff;
+        .van-icon {
+          font-size: vw(40);
+        }
+      }
+      .shareTips {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        color: #f8f8fa;
+        width: 90%;
+        // flex: 1;
+        margin-right: 10px;
+        background: rgba(157, 157, 188, 0.8);
+        height: vw(60);
+        font-weight: 600;
+        font-size: vw(26);
+        img {
+          width: 100%;
+          // height: vw(60);
+        }
+      }
+    }
+  }
+  #html2canvas {
+    width: 100%;
+    height: 100%;
+    position: static; /* 改为静态定位 */
+
+    .scroll-container {
+      width: 100%;
+      height: 100%;
+      flex: 1;
+      overflow-y: auto !important;
+      -webkit-overflow-scrolling: touch;
+      overscroll-behavior: contain;
+      touch-action: pan-y;
+      // padding: 20px 0;
+      box-sizing: border-box;
+      /* 修复iOS弹性滚动 */
+      overflow-scrolling: touch;
+      max-height: 100vh; /* 添加最大高度限制 */
+      position: relative; /* 修复定位上下文 */
+      img {
+        width: 100%;
+        display: block;
+      }
+    }
+  }
+}
+</style>
+<style lang="scss">
+.share {
+  .QRcodes {
+    width: 140px; /* 固定像素尺寸 */
+    height: 140px;
+    margin-right: 12px;
+    position: relative;
+    background: #ffffff;
+    image-rendering: crisp-edges;
+    image-rendering: -webkit-optimize-contrast; /* 安卓浏览器兼容 */
+    // padding: 2px;
+    .logo {
+      position: absolute;
+      top: 50%;
+      left: 50%;
+      transform: translate(-50%, -50%);
+      width: 40px;
+      height: 40px;
+      img {
+        width: 100% !important;
+        height: 100% !important;
+        object-fit: contain;
+      }
+      z-index: 3;
+    }
+
+    img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+}
+</style>

+ 637 - 0
src/components/share.vue

@@ -0,0 +1,637 @@
+<template>
+  <div class="share" :style="{ 'z-index': zIndex }">
+    <!-- canvasImageUrl canvase 渲染成功后删除原始元素,避免当前页面元素太多出现卡顿 -->
+    <div class="share-content" ref="shareContent">
+      <!-- <div class="share-content" ref="shareContent" v-if="!canvasImageUrl"> -->
+      <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>
+      <!-- 点评 -->
+      <!-- <template v-for="item in reportTarget.reportRemarks"> -->
+      <div
+        class="comment summaryDay"
+        v-if="
+          reportRemarksIndex != -1 &&
+          reportTarget.reportRemarks &&
+          reportTarget.reportRemarks.length
+        ">
+        <div class="title-box">
+          <div class="title">
+            <div class="name">
+              {{ reportTarget.reportRemarks[reportRemarksIndex].nickName }}点评
+            </div>
+            <div class="date">
+              {{
+                reportTarget.reportRemarks[reportRemarksIndex].createTime
+                  ? formatChineseDate(
+                      reportTarget.reportRemarks[reportRemarksIndex].createTime.split(' ')[0]
+                    )
+                  : ''
+              }}
+            </div>
+          </div>
+        </div>
+        <div class="commentMessage">
+          {{ reportTarget.reportRemarks[reportRemarksIndex].remarkContent }}
+        </div>
+      </div>
+      <!-- </template> -->
+      <!-- 内容 -->
+      <div class="summaryDay">
+        <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> -->
+        <template v-if="checkedPlan">
+          <div :class="['text']">今日机会与挑战总结</div>
+          <div class="content">
+            {{
+              reportTarget.reportContents.length ? reportTarget.reportContents[0].dayContent : ''
+            }}
+          </div>
+          <div :class="['text']">明日工作计划</div>
+          <div class="content">
+            {{
+              reportTarget.reportContents.length ? reportTarget.reportContents[1].dayContent : ''
+            }}
+          </div>
+        </template>
+        <template v-if="photosData && photosData.length">
+          <div class="text">今日拜访照片</div>
+          <div class="content-photos">
+            <template v-for="item in photosData">
+              <img
+                :src="'data:image/jpg;base64,' + item"
+                crossorigin="anonymous"
+                referrerpolicy="no-referrer"
+                alt=""
+                style="display: block" />
+            </template>
+            <!-- <template v-for="item in urlList">
+            <img
+              :src="item + '&' + new Date().getTime()"
+              crossOrigin="anonymous"
+              referrerpolicy="no-referrer"
+              alt=""
+              style="display: block" />
+          </template> -->
+          </div>
+        </template>
+      </div>
+      <div class="footerShare">
+        <div class="right-text">
+          <div>长按识别二维码查看详情&点评</div>
+          <div></div>
+        </div>
+        <vue-qr
+          class="QRcodes"
+          :callback="QRCallback"
+          :text="vueQrText"
+          :dotScale="0.8"
+          :margin="8"
+          :logoSrc="require('@/assets/logo1.png')"
+          :logoMargin="2"></vue-qr>
+      </div>
+    </div>
+    <div
+      class="share-mask"
+      style="background: #000; position: fixed; top: 0; width: 100%; height: 100%"></div>
+    <div class="html2canvasBox">
+      <div id="html2canvas" ref="html2canvas">
+        <div class="scroll-container">
+          <div style="position: relative">
+            <div class="shareHeader">
+              <div class="shareTips">
+                长按图片可下载、收藏、转发
+                <!-- <img :src="require('@/assets/shareTips.png')" alt="" /> -->
+              </div>
+              <!-- <div class="closeShare" @click="closeShare"><van-icon name="close" /></div> -->
+              <div class="closeShare" @click="closeShare">返回</div>
+            </div>
+            <img :src="canvasImageUrl" width="100%" class="canvasImage" />
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import html2canvas from 'html2canvas';
+import { imgToBase64 } from '@/api/index';
+import VueQr from 'vue-qr';
+export default {
+  name: 'share',
+  components: { VueQr },
+  props: {
+    // 日报数据
+    reportTarget: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    //日报id
+    reportId: {
+      type: [String, Number],
+    },
+    // 点评数据
+    reportRemarksIndex: {
+      type: Number,
+      default: -1,
+    },
+    // 图片转换列表
+    urlList: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    // 是否显示 今日总结&明日规划
+    checkedPlan: {
+      type: Boolean,
+      default: true,
+    },
+  },
+  data() {
+    return {
+      canvasImageUrl: '',
+      retryCount: 0,
+      photosData: [],
+      zIndex: -1,
+      qrcode: null,
+      vueQrText: '',
+      heightFlag: 'start', //图片高度不足,居中显示
+    };
+  },
+  created() {
+    this.zIndex = -1;
+    this.canvasImageUrl = '';
+    this.vueQrText = 'http://1.npz.cn/2/' + this.reportId;
+    this.toastLoading(0, '生成中...', true);
+  },
+  methods: {
+    // 初始化会先执行二维码生成,成功后回调
+    QRCallback() {
+      // 二维码
+      if (this.urlList.length) {
+        imgToBase64({ urlList: this.urlList }).then((res) => {
+          if (res.data && res.code == 200) {
+            this.photosData = res.data;
+            this.$nextTick(async () => {
+              await this.htmlToCanvas();
+            });
+          } else {
+            this.$toast(res.msg);
+            this.$nextTick(async () => {
+              await this.htmlToCanvas();
+            });
+          }
+        });
+      } else {
+        this.$nextTick(async () => {
+          await this.htmlToCanvas();
+        });
+      }
+    },
+    //异步执行
+    imageUrlToBase64(imageUrl) {
+      return new Promise((resolve, reject) => {
+        //一定要设置为let,不然图片不显示
+        let image = new Image();
+        //解决跨域问题
+        image.setAttribute('crossOrigin', 'anonymous');
+        image.src = imageUrl;
+        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,
+        allowTaint: false,
+        backgroundColor: null,
+        logging: false, // 关闭日志提升性能
+        // onclone: (clonedDoc) => {
+        //   // 确保克隆的DOM保持原始样式
+        //   clonedDoc.getElementById('html2canvas').style.overflow = 'auto';
+        // },
+        // ignoreElements: (e) => {
+        //   if (
+        //     e.contains(element) ||
+        //     element.contains(e) ||
+        //     e.tagName === 'STYLE' ||
+        //     e.tagName === 'LINK' ||
+        //     e.getAttribute('data-html2canvas') != null // header里面的样式不能筛掉
+        //   ) {
+        //     console.log(e);
+        //     return false;
+        //   }
+        //   return true;
+        // },
+      })
+        .then((canvas) => {
+          this.toastLoading().clear();
+          let imageUrl = canvas.toDataURL('image/png');
+          this.canvasImageUrl = imageUrl;
+
+          // 图片加载完成后设置滚动容器高度
+          const img = new Image();
+          img.onload = () => {
+            const canvasImage = this.$refs.html2canvas.querySelector('.canvasImage');
+            const scrollContainer = this.$refs.html2canvas.querySelector('.scroll-container');
+            const shareHeader = this.$refs.html2canvas.querySelector('.shareHeader');
+            console.log(scrollContainer.style);
+            if (canvasImage.height < window.innerHeight) {
+              scrollContainer.style.alignItems = 'center';
+              shareHeader.style.position = 'absolute';
+            } else {
+              scrollContainer.style.alignItems = 'start';
+              shareHeader.style.position = 'fixed';
+            }
+            this.$forceUpdate();
+            // // 根据图片实际高度设置容器高度(增加20px缓冲)
+            // // 根据设备像素比调整图片高度
+            // // 使用实际渲染高度而非原始图片高度
+            // const imgHeight = img.offsetHeight + 20;
+            // // 设置容器最小高度保证内容显示,同时允许自动扩展
+            // scrollContainer.style.minHeight = `${imgHeight}px`;
+            // // 保持父容器为可见滚动
+            // scrollContainer.parentElement.style.overflow = 'visible';
+            // // 强制浏览器重排
+            // scrollContainer.style.display = 'none';
+            // scrollContainer.offsetHeight; // 触发重排
+            // scrollContainer.style.display = 'block';
+
+            // // 添加移动端滚动优化
+            // requestAnimationFrame(() => {
+            //   scrollContainer.style.overflow = 'auto';
+            //   scrollContainer.style.overflowScrolling = 'touch';
+            //   scrollContainer.style.webkitOverflowScrolling = 'touch';
+            //   scrollContainer.style.overscrollBehavior = 'contain';
+            //   scrollContainer.style.touchAction = 'pan-y';
+            // });
+          };
+          img.src = imageUrl;
+          this.zIndex = 9;
+          this.$emit('setShareImg', true);
+          this.$emit('setDailyDetailsBox', false);
+        })
+        .catch((error) => {
+          this.toastLoading().clear();
+          console.error('html2canvas error:', error);
+          this.$toast('生成分享图失败,请稍后重试');
+        });
+    },
+    closeShare() {
+      this.canvasImageUrl = '';
+      this.$emit('setShareImg', false);
+      this.$emit('setDailyDetailsBox', true);
+    },
+  },
+  beforeDestroy() {
+    // 组件销毁时清除实例
+    if (this.qrcode) {
+      this.$refs.qrcode.innerHTML = '';
+    }
+  },
+};
+</script>
+<style lang="scss" scoped>
+.share {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  background: #fff;
+  position: fixed;
+  top: 0;
+
+  .share-content {
+    background: url('../assets/shareBack.webp') no-repeat center;
+    background-size: 100% 100%;
+    // background-attachment: local;
+    width: 100%;
+    // min-height: 100%;
+    padding: vw(30);
+    position: absolute;
+    // padding-bottom: vw(30);
+    top: 0;
+    z-index: -10;
+  }
+
+  .header {
+    display: flex;
+    justify-content: space-between;
+    padding-bottom: vw(40);
+
+    .left-icon {
+      width: vw(114);
+      height: vw(71);
+    }
+
+    .right-icon {
+      width: vw(230);
+      height: vw(78);
+    }
+
+    img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+  .title-box {
+    position: relative;
+    width: 100%;
+    height: auto;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    top: -6px;
+    .title {
+      // width: vw(262);
+      // height: vw(115);
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+      color: #600d0e;
+      font-weight: bold;
+      text-align: center;
+      // background: url('../assets/titleBack.png') no-repeat;
+      // background-size: 100% 100%;
+      padding: vw(20) vw(30);
+      background-color: #ecdd9a;
+      border-radius: 6px 6px 25px 25px;
+      .name {
+        font-size: vw(36);
+      }
+      .date {
+        font-size: vw(28);
+      }
+    }
+  }
+
+  .summaryDay {
+    background: url('../assets/summaryDay.png') no-repeat;
+    background-size: 100%;
+    padding: vw(24);
+    position: relative;
+    margin-top: vw(55);
+    border-radius: 0 0 vw(35) vw(35);
+    padding-top: 0;
+    .text {
+      background: url('../assets/textBack.png') no-repeat;
+      width: 100%;
+      height: vw(94);
+      background-size: cover;
+      color: #7d0207;
+      font-size: vw(36);
+      text-align: center;
+      line-height: vw(94);
+      // margin-top: vw(152);
+      // margin-bottom: vw(45);
+      margin: vw(35) 0;
+      font-weight: bold;
+    }
+
+    .content {
+      font-size: vw(28);
+      font-weight: bold;
+      color: #ffff;
+      line-height: vw(63);
+      white-space: pre-wrap;
+    }
+
+    .content-photos {
+      display: flex;
+      flex-wrap: wrap;
+      //   justify-content: space-between;
+
+      img {
+        // width: 47.5%;
+        // height: 42vw;
+        width: 30%;
+        height: vw(188);
+        margin-bottom: 15px;
+        margin-right: 5%;
+        background-color: rgba(255, 255, 255, 0.1);
+        &:nth-child(3n) {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+  .comment {
+    .title {
+      // background: url('../assets/comment.png') no-repeat;
+      // background-size: 100% 100%;
+      background-color: #032371;
+      border-radius: 6px 6px 25px 25px;
+      color: #e6cd78;
+    }
+    .commentMessage {
+      padding: vw(60) 0;
+      font-family: PingFang-SC-Medium;
+      font-size: vw(28);
+      font-weight: bold;
+      color: #ffffff;
+    }
+  }
+
+  .footerShare {
+    // position: absolute;
+    display: flex;
+    // align-items: center;
+    justify-content: flex-end;
+    margin-top: vw(30);
+    margin-right: 2px;
+
+    .right-text {
+      // margin-left: vw(12.5);
+      display: flex;
+      flex-direction: column;
+      justify-content: space-between;
+      margin-right: vw(24);
+
+      div {
+        color: #ffffff;
+        font-size: vw(26);
+        // font-weight: bold;
+        padding: 6px 0;
+      }
+    }
+    // display: flex;
+    // flex-direction: column;
+    // justify-content: center;
+    // align-items: center;
+    // margin-top: vw(100);
+
+    // .right-text {
+    //   // margin-left: vw(12.5);
+    //   display: flex;
+    //   // flex-direction: column;
+    //   // justify-content: space-between;
+    //   align-items: center;
+    //   justify-content: center;
+    //   padding: vw(10) 0;
+    //   div {
+    //     color: #ffffff;
+    //     font-size: vw(30);
+    //     font-weight: bold;
+    //   }
+    // }
+  }
+  .html2canvasBox {
+    width: 100%;
+    height: 100%;
+    min-height: auto;
+    min-height: 100vh;
+    overflow: hidden !important;
+    display: flex;
+    flex-direction: column;
+  }
+  #html2canvas {
+    width: 100%;
+    height: 100%;
+    position: static; /* 改为静态定位 */
+
+    .scroll-container {
+      width: 100%;
+      height: 100%;
+      flex: 1;
+      overflow-y: auto !important;
+      -webkit-overflow-scrolling: touch;
+      overscroll-behavior: contain;
+      touch-action: pan-y;
+      // padding: 20px 0;
+      box-sizing: border-box;
+      /* 修复iOS弹性滚动 */
+      overflow-scrolling: touch;
+      max-height: 100vh; /* 添加最大高度限制 */
+      position: relative; /* 修复定位上下文 */
+      display: flex;
+      // align-items: start;
+      img {
+        width: 100%;
+        display: block;
+      }
+      .shareHeader {
+        position: absolute;
+        z-index: 1;
+        top: 10px;
+        width: 100%;
+        display: flex;
+        align-items: center;
+        padding: 0 vw(30);
+        .closeShare {
+          // position: absolute;
+          // z-index: 1;
+          // right: 10px;
+          // top: 10px;
+          color: #fff;
+          font-size: vw(30);
+          background: #a2819c;
+          text-align: center;
+          line-height: 28px;
+          border-radius: 6px;
+          padding: 0 7px;
+          border: 2px solid #11224e;
+          .van-icon {
+            font-size: vw(40);
+          }
+        }
+        .shareTips {
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          color: #f8f8fa;
+          width: 82%;
+          // flex: 1;
+          margin-right: 10px;
+          background: rgba(157, 157, 188, 0.8);
+          height: vw(60);
+          font-weight: 600;
+          font-size: vw(26);
+          img {
+            width: 100%;
+            // height: vw(60);
+          }
+        }
+      }
+    }
+  }
+}
+</style>
+<style lang="scss">
+.share {
+  .QRcodes {
+    width: 45px; /* 固定像素尺寸 */
+    height: 45px;
+    position: relative;
+    background: #ffffff;
+    image-rendering: crisp-edges;
+    image-rendering: -webkit-optimize-contrast; /* 安卓浏览器兼容 */
+    // padding: 2px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: 3px;
+    .logo {
+      position: absolute;
+      top: 50%;
+      left: 50%;
+      transform: translate(-50%, -50%);
+      width: 10px;
+      height: 10px;
+      img {
+        object-fit: contain;
+      }
+      z-index: 3;
+    }
+
+    img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+}
+</style>

+ 2 - 0
src/main.js

@@ -17,6 +17,7 @@ import {
   gcj02BD,
   verifyStoreType,
   validatePhone,
+  formatChineseDate,
 } from '@/utils/index';
 import { toastLoading } from '@/utils/commonVant';
 import '@vant/touch-emulator';
@@ -62,6 +63,7 @@ Vue.prototype.parseTimeParagraph = parseTimeParagraph;
 Vue.prototype.Micrometer = Micrometer;
 Vue.prototype.verifyStoreType = verifyStoreType;
 Vue.prototype.validatePhone = validatePhone;
+Vue.prototype.formatChineseDate = formatChineseDate;
 Vue.prototype.Toast = Toast;
 Vue.prototype.notify = Notify;
 var clipboard = new ClipboardJS('.btn');

+ 4 - 0
src/permission.js

@@ -4,6 +4,10 @@ import store from './store';
 const whiteList = ['/login', '/auth-redirect', '/bind', '/register'];
 
 router.beforeEach((to, from, next) => {
+  let queryLoginName = to.query.loginName || null;
+  if (queryLoginName) {
+    localStorage.setItem('loginName', queryLoginName);
+  }
   const username = localStorage.getItem('loginName');
   if (username) {
     /* has token*/

+ 9 - 2
src/utils/TXApiFun.js

@@ -96,8 +96,14 @@ export function getTicketFun(jsApiList = ['getLocation'], configType = 'config')
   return new Promise((resolve, reject) => {
     // 当前页面
     let url = window.location.href;
+    let params = {
+      url: url,
+    };
+    if (configType == 'agentConfig') {
+      params.agent = 1;
+    }
     //  获取签名
-    getTicket({ url: url }).then((response) => {
+    getTicket(params).then((response) => {
       console.log(response);
       toastLoading().clear();
       if (response.code == 200) {
@@ -124,9 +130,10 @@ export function getTicketFun(jsApiList = ['getLocation'], configType = 'config')
             jsApiList: [...jsApiList], //必填,传入需要使用的接口名称
             success: function (res) {
               console.log('获取签名成功');
-              resolve('获取签名成功');
+              resolve(qiyeData);
             },
             fail: function (res) {
+              console.log(res);
               if (res.errMsg.indexOf('function not exist') > -1) {
                 alert('版本过低请升级');
               }

+ 0 - 22
src/utils/ali-oss.js

@@ -1,22 +0,0 @@
-const OSS = require('ali-oss');
-
-// aliyun:
-//   oss:
-//     endpoint: oss-cn-shanghai-internal.aliyuncs.com # oss对外服务的访问域名
-//     cdnpoint: cdn-svs-test.nipponpaint.com.cn
-//     accessKeyId: LTAI5tG1DTJFA16BHkzHVxjz # 访问身份验证中用到用户标识
-//     accessKeySecret: 5brWKKEACiUsKPJeUXlB7r2iZGQHNF # 用户用于加密签名字符串和oss用来验证签名字符串的密钥
-//     bucketName: svs-test
-//     publicRead: false
-const client = new OSS({
-  // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
-  accessKeyId: process.env.VUE_APP_OSS_ACCESS_KEY_ID,
-  accessKeySecret: process.env.VUE_APP_OSS_ACCESS_KEY_SECRET,
-  // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
-  region: 'cdn-svs-test.nipponpaint.com.cn',
-  authorizationV4: true,
-  // yourBucketName填写Bucket名称。
-  bucket: 'svs-test',
-});
-
-export default client;

+ 26 - 0
src/utils/digest.js

@@ -0,0 +1,26 @@
+import Vue from 'vue';
+import { getTicketFun } from '@/utils/TXApiFun';
+// 微信JSSDK实例
+const wx = Vue.prototype.wx;
+import { wxLogin } from '@/api/digest';
+
+export function WXdigest() {
+  getTicketFun(['getCurExternalContact'], 'agentConfig')
+    .then((res) => {
+      // 获取用户code
+      // getWeChatCode();
+    })
+    .catch((err) => {
+      console.log(err);
+    });
+}
+
+function getWeChatCode() {
+  wx.invoke('getCurExternalContact', {}, (res) => {
+    if (res.err_msg === 'getCurExternalContact:ok') {
+      console.log(res);
+    } else {
+      console.log(res);
+    }
+  });
+}

+ 35 - 0
src/utils/index.js

@@ -52,6 +52,41 @@ export function parseTime(time, pattern) {
   }
 }
 // 千分号
+// 中文日期格式(年-月-日)
+export function formatChineseDate(time) {
+  // 统一处理日期格式
+  const formatDate = (dateObj) => {
+    const year = dateObj.getFullYear();
+    const month = (dateObj.getMonth() + 1).toString().padStart(2, '0');
+    const day = dateObj.getDate().toString().padStart(2, '0');
+    return `${year}年${month}月${day}日`;
+  };
+
+  // 处理字符串格式(支持多种分隔符)
+  if (typeof time === 'string') {
+    // 清理日期字符串中的时间部分(如果有)
+    const dateString = time.split(' ')[0];
+    // 匹配 yyyy-mm-dd 或 yyyy/m/d 等格式
+    if (/^\d{4}[-\/]\d{1,2}[-\/]\d{1,2}$/.test(dateString)) {
+      const separator = dateString.includes('-') ? '-' : '/';
+      const [year, month, day] = dateString.split(separator);
+      return formatDate(new Date(year, month - 1, day));
+    }
+  }
+
+  // 处理时间戳和Date对象
+  try {
+    const date = new Date(time);
+    if (!isNaN(date)) {
+      return formatDate(date);
+    }
+  } catch (e) {
+    console.error('Invalid date format:', time);
+  }
+
+  return '无效日期格式';
+}
+
 export function Micrometer(num) {
   if (num != null) {
     let numt = (num || 0).toString().split('.');

+ 0 - 50
src/utils/uploadAliOss copy.js

@@ -1,50 +0,0 @@
-import client from '@/utils/ali-oss';
-
-// 自定义请求头
-const headers = {
-  // 指定Object的存储类型。
-  'x-oss-storage-class': 'Standard',
-  // 指定Object的访问权限。
-  'x-oss-object-acl': 'private',
-  // 通过文件URL访问文件时,指定以附件形式下载文件,下载后的文件名称定义为example.txt。
-  'Content-Disposition': 'attachment; filename="example.txt"',
-  // 设置Object的标签,可同时设置多个标签。
-  'x-oss-tagging': 'Tag1=1&Tag2=2',
-  // 指定PutObject操作时是否覆盖同名目标Object。此处设置为true,表示禁止覆盖同名Object。
-  'x-oss-forbid-overwrite': 'true',
-};
-
-async function uploadAliOss(data) {
-  try {
-    // 填写OSS文件完整路径和本地文件的完整路径。OSS文件完整路径中不能包含Bucket名称。
-    // 如果本地文件的完整路径中未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
-    console.log(blobToFile(base64ToBlob(data), 'h5UploadAliOss'));
-    const result = await client.put(
-      'h5UploadAliOss', //获取一个随机的文件名
-      blobToFile(base64ToBlob(data), 'h5UploadAliOss') //base64转file对象
-      // { 'Content-Type': 'image/jpeg' } //设置Content-Type
-    );
-    console.log(result);
-  } catch (e) {
-    console.log(e);
-  }
-}
-export function base64ToBlob(base64Data) {
-  let arr = base64Data.split(','),
-    fileType = arr[0].match(/:(.*?);/)[1],
-    bstr = atob(arr[1]),
-    l = bstr.length,
-    u8Arr = new Uint8Array(l);
-  while (l--) {
-    u8Arr[l] = bstr.charCodeAt(l);
-  }
-  return new Blob([u8Arr], {
-    type: fileType,
-  });
-}
-export function blobToFile(newBlob, fileName) {
-  newBlob.lastModifiedDate = new Date();
-  newBlob.name = fileName;
-  return newBlob;
-}
-export default uploadAliOss;

+ 1 - 0
src/views/deviceOutside/suishenbangOutstoreVisit.vue

@@ -274,6 +274,7 @@ export default {
         .then(() => {
           stopVisit({ visitsId: this.visitId }).then((res) => {
             if (res.code == 200) {
+              localStorage.removeItem('visitId');
               this.$dialog
                 .alert({
                   title: '系统提示',

+ 2 - 0
src/views/home/index.vue

@@ -48,6 +48,7 @@ import tabBar from '@/components/tabBar';
 import ABtarget from './ABtarget.vue';
 import { mapState } from 'vuex';
 import bottomBtn from './bottomBtn.vue';
+import { WXdigest } from '@/utils/digest';
 export default {
   name: 'home',
   components: { tabBar, hintTabPage, ABtarget, bottomBtn },
@@ -81,6 +82,7 @@ export default {
     },
   },
   activated() {
+    WXdigest();
     if (this.tabVal == '-1') {
       // 从其他页面跳转过来如果;要重新获取对应tab数据
       // if (this.$refs.hintTabPage) this.$refs.hintTabPage.initData();

+ 58 - 16
src/views/week/daily.vue

@@ -140,7 +140,7 @@
             <van-col span="12"><p>&nbsp;</p></van-col>
             <van-col span="12"
               ><p>
-                开户达成率:<span class="colorbalck"
+                目标达成率:<span class="colorbalck"
                   >{{ Micrometer(reportTargetAll.gzKhljSuccessRate) }}%</span
                 >
               </p></van-col
@@ -453,6 +453,7 @@ import {
   getReportInfo,
   getDetailById,
   tsContents,
+  buryingPoint,
 } from '@/api/index';
 import visitedRealTime from '@/views/componentsTarget/visitedRealTime';
 import createStoreBJ from '@/views/componentsTarget/createStoreBJ';
@@ -748,19 +749,50 @@ export default {
             loading1.clear();
             this.isclick = true;
             if (res.code == 200) {
-              this.$dialog
-                .alert({
-                  title: '系统提示',
-                  message: '提交成功',
-                })
-                .then(() => {
-                  if (this.$route.query.reportId != undefined) {
-                    window.location.replace(window.location.origin + '/mobile/myHistoricalDaily');
-                  } else {
-                    this.onClickLeft();
-                    // window.location.replace(window.location.origin + '/mobile/home');
-                  }
-                });
+              if (this.reportTarget.reportPostType == 'fx') {
+                this.$dialog
+                  .alert({
+                    message: '已提交,是否分享',
+                    showCancelButton: true,
+                    confirmButtonText: '分享',
+                    cancelButtonText: '返回首页',
+                    className: 'dailyShareBtn',
+                  })
+                  .then(() => {
+                    buryingPoint({
+                      systemModel: '日报审核',
+                      buryingPointType: 2,
+                      buryingPointValue: this.$route.query.reportId,
+                      buryingPointName: '日报提交分享',
+                      buryingPointPosition: '日报提交',
+                    });
+                    // 跳转历史汇报详情 分享汇报
+                    this.$router.replace({
+                      path: 'dailyDetails',
+                      query: { reportId: res.data, sourceType: 'daily' },
+                    });
+                  })
+                  .catch(() => {
+                    if (this.$route.query.reportId != undefined) {
+                      window.location.replace(window.location.origin + '/mobile/home');
+                    } else {
+                      this.onClickLeft();
+                    }
+                  });
+              } else {
+                this.$dialog
+                  .alert({
+                    title: '系统提示',
+                    message: '提交成功',
+                  })
+                  .then(() => {
+                    if (this.$route.query.reportId != undefined) {
+                      window.location.replace(window.location.origin + '/mobile/myHistoricalDaily');
+                    } else {
+                      this.onClickLeft();
+                    }
+                  });
+              }
             } else {
               this.$toast.fail(res.msg);
             }
@@ -818,7 +850,7 @@ export default {
       });
     },
     onClickLeft() {
-      this.$router.go(-1);
+      this.$router.push('/home');
     },
   },
 };
@@ -877,7 +909,7 @@ export default {
   border-radius: 2px;
 }
 </style>
-<style>
+<style lang="scss">
 .linepAdd .van-cell__title {
   color: #1e5398;
   font-weight: 500;
@@ -912,4 +944,14 @@ export default {
 .linepAdd .contentContainer .contentContainerTitle .colorRed {
   color: red;
 }
+.dailyShareBtn {
+  .van-dialog__confirm {
+    // border: 1px solid #ccc;
+    // border-bottom: none;
+  }
+  .van-hairline--left {
+    background: #0057ba;
+    color: #fff;
+  }
+}
 </style>

+ 2 - 2
src/views/week/dailyApproval.vue

@@ -1,5 +1,5 @@
 <template>
-  <div>
+  <div class="dailyApproval">
     <!--        顶部条-->
     <div class="navBarTOP">
       <van-nav-bar class="navBar" title="日报审批" left-arrow @click-left="onClickLeft" />
@@ -729,7 +729,7 @@ export default {
   },
 };
 </script>
-<style scoped>
+<style scoped lang="scss">
 .container {
   margin: 10px;
 }

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 790 - 442
src/views/week/dailyDetails.vue


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 888 - 515
src/views/week/dailyHistoricalDetails.vue


+ 6 - 0
src/views/week/weekly.vue

@@ -257,6 +257,7 @@ export default {
       type: '-1',
       JZQuota: false,
       YFQuota: false, //应用服务
+      GZdata: false,
     };
   },
   created() {
@@ -296,6 +297,11 @@ export default {
           if (res.data.postType == 'JZ') {
             this.JZQuota = true;
           }
+          if (res.data.postType == 'GZ') {
+            this.GZdata = true;
+          } else {
+            this.GZdata = false;
+          }
           var dayTime = res.data.date;
           this.type = res.data.userType;
           this.timeList = this.parseTimeParagraph(

+ 6 - 0
src/views/week/weeklyApproval.vue

@@ -257,6 +257,7 @@ export default {
       type: '-1',
       JZQuota: false,
       YFQuota: false, //应用服务
+      GZdata: false,
     };
   },
   created() {
@@ -369,6 +370,11 @@ export default {
           if (res.data.postType == 'JZ') {
             this.JZQuota = true;
           }
+          if (res.data.postType == 'GZ') {
+            this.GZdata = true;
+          } else {
+            this.GZdata = false;
+          }
           var dayTime = res.data.date;
           this.type = res.data.userType;
           this.timeList = this.parseTimeParagraph(

+ 6 - 0
src/views/week/weeklyApprovalDetils.vue

@@ -275,6 +275,7 @@ export default {
       ptitle: '',
       JZQuota: false,
       YFQuota: false, //应用服务
+      GZdata: false,
     };
   },
   created() {
@@ -310,6 +311,11 @@ export default {
           if (res.data.postType == 'JZ') {
             this.JZQuota = true;
           }
+          if (res.data.postType == 'GZ') {
+            this.GZdata = true;
+          } else {
+            this.GZdata = false;
+          }
           var dayTime = res.data.date;
           this.type = res.data.userType;
           this.ptitle = res.data.pdeptName + '-' + res.data.ppostName + '-' + res.data.pnickName;

+ 6 - 0
src/views/week/weeklyHistoricalDetils.vue

@@ -289,6 +289,7 @@ export default {
       type: '-1',
       JZQuota: false,
       YFQuota: false, //应用服务
+      GZdata: false,
     };
   },
   created() {
@@ -413,6 +414,11 @@ export default {
           if (res.data.postType == 'JZ') {
             this.JZQuota = true;
           }
+          if (res.data.postType == 'GZ') {
+            this.GZdata = true;
+          } else {
+            this.GZdata = false;
+          }
           var dayTime = res.data.date;
           this.type = res.data.userType;
           this.title =