Quellcode durchsuchen

经销商拜访

zhujindu vor 9 Monaten
Ursprung
Commit
fb994756a0

+ 7 - 0
src/api/index.js

@@ -94,6 +94,13 @@ export function queryMyChainsGroupList(query) {
     params: query,
     params: query,
   });
   });
 }
 }
+export function getUserOutPlaList(query) {
+  return request({
+    url: 'mobile/route/userOutPlan',
+    method: 'get',
+    params: query,
+  });
+}
 
 
 export function getPhotoTypeList(query) {
 export function getPhotoTypeList(query) {
   return request({
   return request({

BIN
src/assets/icon/history.png


BIN
src/assets/icon/imageEmpty.png


BIN
src/assets/icon/jianjie.jpg


BIN
src/assets/icon/sp.png


+ 104 - 0
src/components/deleteUploadImg1.vue

@@ -0,0 +1,104 @@
+<template>
+  <div>
+    <van-row gutter="10">
+      <van-col span="6" v-for="(urls, index) in imgs" :key="index">
+        <div class="imgview">
+          <van-icon name="close" size="16" v-on:click="deleteImg(index, urls.id)" />
+          <img
+            v-if="urls.type == '2'"
+            :src="urls.fileUrl"
+            width="100px"
+            height="100px"
+            @click="previewsImg(index)" />
+          <img
+            v-else
+            :src="urls.fileUrl"
+            width="100px"
+            height="100px"
+            @click="previewsImg(index)" />
+        </div>
+      </van-col>
+    </van-row>
+    <!--  <div style="padding: 10px 16px 0;">-->
+    <!--    <div class="img-box" v-for="(urls, index) in imgs" :key="index">-->
+    <!--      <van-icon name="clear" v-on:click="deleteImg(index,urls.id)"/>-->
+    <!--      <img v-if="urls.type=='2'" :src="urls.fileUrl" width="100px" height="100px" @click="previewsImg(index)"/>-->
+    <!--      <img v-else :src="urls.fileUrl" width="100px" height="100px" @click="previewsImg(index)"/>-->
+    <!--    </div>-->
+    <!--  </div>-->
+  </div>
+</template>
+
+<script>
+import { ImagePreview } from 'vant';
+import { removePhoto } from '@/api/index';
+
+export default {
+  name: 'deleteUploadImg',
+  props: {
+    imgs: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    photoIdentifyType: {
+      // 图匠识别目的(1:店招内容识别,2:门店代码识别,3:调色机识别,4:更换店招)
+      type: String,
+      default: '',
+    },
+  },
+  data() {
+    return {
+      url: process.env.VUE_APP_Target1 + process.env.VUE_APP_BASE_API,
+    };
+  },
+  methods: {
+    deleteImg(index, collectionItemId) {
+      removePhoto({ fileId: collectionItemId }).then((res) => {
+        if (res.code == 200) {
+          this.$toast('删除成功!');
+          this.imgs.splice(index, 1);
+        } else {
+          this.$toast('删除失败!');
+        }
+      });
+    },
+    previewsImg(index) {
+      var arrimg = [];
+      for (var imgi = 0; imgi < this.imgs.length; imgi++) {
+        arrimg.push(this.imgs[imgi].fileUrl);
+      }
+      ImagePreview({
+        images: arrimg,
+        startPosition: index,
+        onClose() {
+          // do something
+        },
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.imgview {
+  width: 100%;
+  height: 72px;
+  position: relative;
+  display: inline-block;
+  i {
+    position: absolute;
+    right: -2px;
+    top: -3px;
+    color: white;
+    background: red;
+    overflow: hidden;
+    border-radius: 50%;
+  }
+  img {
+    width: 100%;
+    height: 100%;
+  }
+}
+</style>

+ 471 - 0
src/components/imageAIVerifyErr.vue

@@ -0,0 +1,471 @@
+<template>
+  <div class="imageAIVerifyErr">
+    <el-dialog
+      title="图像识别结果"
+      :visible.sync="vanPopup"
+      :append-to-body="true"
+      :close-on-click-modal="false"
+      @close="close"
+      custom-class="AIVerifyErrdialog">
+      <div class="AIVerifyErrMask" v-if="npkpiData">
+        <!-- shopSignChange 与历史照片是否一致(是否要更换照片) 0一致(要更换),1不一致(不要更换) -->
+        <template v-if="shopSignChange == 0">
+          <div class="errorImg">
+            <img v-if="url" :src="url" @click="previewsImg(url)" />
+            <img
+              v-else
+              :src="require('@/assets/icon/imageEmpty.png')"
+              width="100%"
+              height="300px" />
+          </div>
+          <div class="AIVerify">
+            <span>{{ contentMessage }}</span>
+          </div>
+          <template v-if="shotsNum >= maxNum">
+            <div class="feedbackMessage">
+              <div class="label">若图像识别不正确,可在此反馈:</div>
+              <div class="value">
+                <van-field
+                  v-model="feedbackMessage"
+                  rows="3"
+                  type="textarea"
+                  placeholder="请输原因" />
+              </div>
+            </div>
+          </template>
+          <div
+            class="uploadBtnAIVerify"
+            :style="{ 'justify-content': shotsNum >= maxNum ? 'space-between' : 'center' }">
+            <div class="confirmUploadAIVerify" @click="uploadImg(false)">重新拍照</div>
+            <div v-if="shotsNum >= maxNum" class="stillUploadAIVerify" @click="confirmUpload">
+              仍要上传
+            </div>
+          </div>
+          <template v-if="shotsNum >= maxNum">
+            <div class="tipsAIVerify" v-if="npkpiData.recognizeType == 1">
+              <van-icon name="warning-o" />上传后作为本店标准店招,未来每次拜访时校验。
+            </div>
+          </template>
+          <template v-else>
+            <!-- 补位 -->
+            <div class="coveringPosition"></div>
+          </template>
+        </template>
+        <template v-if="shopSignChange == 1">
+          <div class="historyImageAIVerify">
+            <!-- 有门店身份证时 只显示门店身份证和本地拜访照 -->
+            <template v-if="storeIDCardUrl">
+              <div class="storeIDCardUrl imageItemAIVerify">
+                <img :src="storeIDCardUrl" @click="previewsImg(storeIDCardUrl)" />
+                <span>门店标准店招</span>
+              </div>
+            </template>
+            <template v-else>
+              <div class="initImage imageItemAIVerify">
+                <img
+                  v-if="createStoreUrl"
+                  :src="createStoreUrl"
+                  @click="previewsImg(createStoreUrl)" />
+                <img v-else :src="require('@/assets/icon/imageEmpty.png')" />
+                <span>建店时门店照</span>
+              </div>
+              <div class="newestImage imageItemAIVerify">
+                <img v-if="lastVisitUrl" :src="lastVisitUrl" @click="previewsImg(lastVisitUrl)" />
+                <img v-else :src="require('@/assets/icon/imageEmpty.png')" />
+                <span>上次拜访店招</span>
+              </div>
+            </template>
+            <div class="presentImage imageItemAIVerify">
+              <img v-if="url" :src="url" @click="previewsImg(url)" />
+              <img v-else :src="require('@/assets/icon/imageEmpty.png')" />
+              <span>本次拜访店招</span>
+            </div>
+          </div>
+          <div class="AIVerify">
+            <span>{{ contentMessage }}</span>
+          </div>
+          <div class="feedbackMessage">
+            <div class="label">若图像识别不正确,可在此反馈:</div>
+            <div class="value">
+              <van-field
+                v-model="feedbackMessage"
+                rows="2"
+                autosize
+                type="textarea"
+                placeholder="请输入反馈意见" />
+            </div>
+          </div>
+          <div class="uploadBtnAIVerify" style="justify-content: center">
+            <div class="confirmUploadAIVerify" @click="uploadImg(true)">重新拍照</div>
+            <div class="changeImageAIVerify" @click="confirmUpDataImage()">更新门店照</div>
+          </div>
+          <div class="tipsRemarkAIVerify">
+            <!-- <div>若历史照片拍摄不规范,请选择<span style="color: #81b337">更新门店照</span></div> -->
+            <div><van-icon name="warning-o" />若历史照片拍摄不规范,请选择更新门店照</div>
+            <div>本次拜访店招会作为本店标准店招,未来每次拜访时校验</div>
+          </div>
+        </template>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import { ImagePreview } from 'vant';
+import store from '@/store';
+import { mapState } from 'vuex';
+export default {
+  props: {
+    imageAIVerifyFlag: {
+      type: Boolean,
+      default: false,
+    },
+    imageAIVerifyData: {
+      type: [Array, Object],
+    },
+    source: {
+      // 新建店还是门店拜访 visit/newCreated
+      type: String,
+    },
+  },
+  computed: {
+    ...mapState({
+      shotsNum: (state) => state.otheStore.shotsNum,
+    }),
+  },
+  watch: {
+    imageAIVerifyFlag: {
+      handler(val) {
+        console.log('imageAIVerifyFlag=' + val);
+        if (val) this.initData();
+      },
+      immediate: true,
+    },
+  },
+  data() {
+    return {
+      contentMessage: '', //提示内容
+      vanPopup: true,
+      shopSignChange: 0,
+      npkpiData: null,
+      feedbackMessage: '', //反馈图像识别不正确原因
+      url: '', //	本次图片路径
+      createStoreUrl: '', //	建店时店招
+      lastVisitUrl: '', //	上次拜访时店招
+      storeIDCardUrl: '', //	门店身份证
+      maxNum: 2,
+    };
+  },
+  methods: {
+    initData() {
+      // 图匠识别目的(1:店招内容识别,2:门店代码识别,3:调色机识别,4:更换店招)
+      // shopSignChange  是否更换店招(0:未更换,1:更换) 1不一致,0一致
+      // checkInfo 图片检查结果
+      // cheatState 是否作弊(0:未作弊,1:作弊)
+      // cheatType	作弊类型
+      // qualifiedState 是否合格(0:不合格,1:合格)
+      // unqualifiedReason	不合格原因
+      this.feedbackMessage = '';
+      this.shopSignChange = 0;
+      this.npkpiData =
+        this.source == 'visit'
+          ? this.imageAIVerifyData.npkpiData
+          : this.imageAIVerifyData[0].npkpiData;
+      let imageAIVerifyData =
+        this.source == 'visit' ? this.imageAIVerifyData : this.imageAIVerifyData[0];
+      this.shopSignMatchList = this.npkpiData.shopSignMatchList;
+      this.url = imageAIVerifyData.url || ''; //	图片路径
+      this.createStoreUrl = imageAIVerifyData.createStoreUrl || ''; //	建店时店招
+      this.lastVisitUrl = imageAIVerifyData.lastVisitUrl || ''; //	上次拜访时店招
+      this.storeIDCardUrl = imageAIVerifyData.storeIDCardUrl || ''; //	门店身份证
+      // 先判断照片作弊情况,然后是否合格,然后是否和历史照片一致
+      // 作弊和不合格记录识别次数,超过两次弹框提醒
+      if (this.npkpiData.checkInfo) {
+        // 作弊
+        if (this.npkpiData.checkInfo.cheatState == 1) {
+          // 增加识别次数
+          store.dispatch('setShotsNum', this.shotsNum + 1);
+          // 作弊原因
+          this.contentMessage = this.contentMessage + this.npkpiData.checkInfo.cheatType;
+          return;
+        }
+        // 不合格
+        if (this.npkpiData.checkInfo.qualifiedState == 0) {
+          // 增加识别次数
+          store.dispatch('setShotsNum', this.shotsNum + 1);
+          // 不合格原因
+          this.contentMessage = this.contentMessage + this.npkpiData.checkInfo.unqualifiedReason;
+          return;
+        }
+        // recognizeType 识别目的(1:店招内容识别,2:门店代码识别,3:调色机识别)
+        if (this.npkpiData.recognizeType == 1) {
+          this.comparisonImage();
+        } else {
+          this.confirmUpload();
+        }
+      }
+    },
+    // 照片和历史照片是否一致
+    comparisonImage() {
+      this.shopSignChange = this.npkpiData.shopSignChange;
+      if (this.npkpiData.shopSignChange == 1) {
+        this.contentMessage = '与历史照片不一致,请确认店招是否更换?';
+        return false;
+      } else {
+        this.confirmUpDataImage();
+      }
+    },
+    // 重新拍照
+    uploadImg(flag) {
+      // flag: true,识别与历史照片不一致状态下,点击重新拍照,照片识别次数需要加1
+      if (flag) {
+        // 增加识别次数
+        store.dispatch('setShotsNum', this.shotsNum + 1);
+      }
+      this.$emit('close');
+      this.$emit('uploadImgFun');
+    },
+    // 照片是否入库,1.照片识别三次不通过仍要上传,2.照片识别通过
+    // isUpdate:是否更新店招照片,只有门店店招需要更新
+    confirmUpload() {
+      // 拜访店招 不合格或作弊三次先提示是否仍要上传,确认后在判断是否与历史照片一致
+      if (this.npkpiData.recognizeType == 1 && this.shotsNum >= this.maxNum) {
+        this.comparisonImage();
+      } else {
+        this.$emit('close');
+        this.$emit('confirmUpload', {
+          data: this.imageAIVerifyData,
+          feedbackMessage: this.feedbackMessage,
+        });
+      }
+    },
+    confirmUpDataImage() {
+      this.$emit('close');
+      this.$emit('confirmUpload', {
+        data: this.imageAIVerifyData,
+        isUpdate: 'true',
+        feedbackMessage: this.feedbackMessage,
+      });
+    },
+    close() {
+      this.$emit('close');
+    },
+    openTips() {
+      this.$dialog
+        .confirm({
+          title: '提示',
+          message: '不规范的照片上传后会更换本店标准店招,未来每次拜访时校验。',
+          showCancelButton: false,
+          className: 'openTips',
+          overlayClass: 'openTipsMask',
+        })
+        .then(() => {});
+    },
+    previewsImg(url) {
+      ImagePreview({
+        images: [url],
+        className: 'AIImageItem',
+        getContainer: 'el-dialog__wrapper',
+      });
+    },
+  },
+};
+</script>
+<style lang="scss">
+.el-dialog__wrapper {
+  z-index: 3333 !important;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background: rgba(0, 0, 0, 0.5) !important;
+  .el-dialog__body {
+    padding: 0px !important;
+  }
+  .el-dialog__header {
+    text-align: center;
+  }
+  .AIVerifyErrdialog {
+    width: vw(690) !important;
+    margin-top: 1vh !important;
+    border-radius: 8px !important;
+    font-size: vw(32) !important;
+    .el-dialog__headerbtn {
+      width: vw(44);
+      height: vw(44);
+      background-color: #e1e1e1;
+      border-radius: 50%;
+      margin-top: -3px;
+    }
+  }
+  .AIVerifyErrMask {
+    width: 100%;
+    padding: vw(30) vw(30) 0 vw(30);
+    overflow: hidden;
+    /* min-height: 180px; */
+    .errorImg {
+      width: 100%;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      min-height: vw(303);
+      img {
+        width: vw(235);
+        height: vw(303);
+        border-radius: vw(10);
+      }
+    }
+    .AIVerify {
+      font-size: vw(32);
+      margin-top: vw(45);
+      display: flex;
+      justify-content: center;
+      span {
+        color: #9e0202;
+        display: block;
+        max-width: 70%;
+      }
+    }
+  }
+  .van-popup {
+    width: 90%;
+    padding: 8px;
+    border-radius: 8px;
+    overflow: hidden;
+  }
+  .van-f-red-AIVerify {
+    color: red;
+    width: 8px;
+    display: inline-block;
+    line-height: 26px;
+  }
+  .photoAIVerify {
+    /*margin-top: 9px;*/
+    float: right;
+  }
+  .title {
+    font-size: 16px;
+    font-weight: 600;
+    text-align: center;
+    padding: 5px;
+  }
+  .contentAIVerify {
+    .uploadImgAIVerify {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      padding: 8px 0;
+      border-top: 1px solid #cfcfcf;
+      .labelAIVerify {
+        font-size: 14px;
+      }
+    }
+  }
+  .tipsAIVerify {
+    padding: vw(30) 0 vw(40) 0;
+    font-size: vw(22);
+    color: #999999;
+  }
+  .coveringPosition {
+    height: vw(60);
+  }
+  .uploadBtnAIVerify {
+    display: flex;
+    align-items: center;
+    margin-top: vw(30);
+    div {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      font-size: vw(28);
+      color: #fff;
+      border-radius: 10px;
+      /* margin: 0 6px; */
+      width: vw(298);
+      height: vw(68);
+      background-blend-mode: normal, normal;
+    }
+    .confirmUploadAIVerify {
+      background-image: linear-gradient(180deg, #ffa1a1 0%, #f6695f 35%, #ed301d 100%),
+        linear-gradient(#aed0f9, #aed0f9);
+      box-shadow: 0px 3px 6px 0px rgba(183, 30, 14, 0.35);
+      margin-right: 6px;
+    }
+    .changeImageAIVerify {
+      background-image: linear-gradient(180deg, #3b89e6 0%, #1e6acb 35%, #014baf 100%),
+        linear-gradient(#0356b9, #0356b9);
+      box-shadow: 0px 3px 6px 0px rgba(6, 60, 131, 0.35);
+      margin-left: 6px;
+    }
+    .stillUploadAIVerify {
+      background-image: linear-gradient(180deg, #3b89e6 0%, #1e6acb 35%, #014baf 100%),
+        linear-gradient(#0356b9, #0356b9);
+      box-shadow: 0px 3px 6px 0px rgba(6, 60, 131, 0.35);
+      margin-left: 6px;
+    }
+  }
+  .historyImageAIVerify {
+    display: flex;
+    justify-content: space-around;
+    padding: 5px 0;
+    .imageItemAIVerify {
+      width: 30%;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      justify-content: center;
+      span {
+        font-size: 12px;
+        padding-top: 3px;
+      }
+      img {
+        width: vw(196);
+        height: vw(228);
+        border-radius: vw(10);
+      }
+    }
+  }
+  .tipsRemarkAIVerify {
+    padding: vw(28) 0;
+    div {
+      font-size: vw(22);
+      color: #999999;
+      position: relative;
+      padding-left: 17px;
+    }
+    .van-icon {
+      position: absolute;
+      left: 0;
+    }
+  }
+  .feedbackMessage {
+    margin-top: vw(45);
+    .label {
+      font-size: vw(26);
+      line-height: vw(50);
+    }
+    .value {
+      .van-cell {
+        padding: 0;
+      }
+    }
+    .van-field__body {
+      border-radius: vw(10);
+      border: solid 1px #aaaaaa;
+      padding-left: vw(10);
+      background-color: #e7e7e7;
+      .van-field__control {
+      }
+    }
+  }
+}
+.openTipsMask,
+.openTips {
+  z-index: 3334 !important;
+}
+.van-overlay {
+  /* z-index: 3334 !important; */
+}
+.van-image-preview {
+  z-index: 3335 !important;
+  background: rgba(0, 0, 0, 0.8) !important;
+}
+</style>

+ 229 - 0
src/components/storeCode.vue

@@ -0,0 +1,229 @@
+<template>
+  <div>
+    <div class="" v-if="insert">
+      <p style="margin: 0" @click="uploadImg">
+        <van-icon name="scan" size="24px" color="#1989fa" />
+      </p>
+    </div>
+  </div>
+</template>
+
+<script>
+import axios from 'axios';
+import { getOptionByResult } from '@/api/index';
+
+export default {
+  name: 'storeCode',
+  props: {
+    index: {
+      type: Number,
+      default: -1,
+    },
+    tid: {
+      type: String,
+      default: '',
+    },
+    cid: {
+      type: Number,
+      default: -1,
+    },
+    code: {
+      type: String,
+      default: '',
+    },
+    index1: {
+      type: [String, Number],
+      default: '',
+    },
+    index2: {
+      type: [String, Number],
+      default: '',
+    },
+    index3: {
+      type: [String, Number],
+      default: '',
+    },
+    index4: {
+      type: [String, Number],
+      default: '',
+    },
+    index5: {
+      type: [String, Number],
+      default: '',
+    },
+    index6: {
+      type: [String, Number],
+      default: '',
+    },
+    index7: {
+      type: [String, Number],
+      default: '',
+    },
+    index8: {
+      type: [String, Number],
+      default: '',
+    },
+    taskId: {
+      type: String,
+      default: '',
+    },
+    collectionId: {
+      type: String,
+      default: '',
+    },
+    type: {
+      type: String,
+      default: '',
+    },
+    insert: {
+      type: Boolean,
+      default: true,
+    },
+  },
+  data() {
+    return {
+      shows: false,
+      url: '',
+    };
+  },
+  methods: {
+    uploadImg() {
+      let url = window.location.href;
+      let that = this;
+      let wx = this.wx;
+      let qiyeData;
+      console.log(that.code);
+      debugger;
+
+      const instance = axios.create();
+      instance.defaults.headers.common['userId'] = localStorage.getItem('loginName');
+      instance
+        .get(process.env.VUE_APP_BASE_API + 'mobile/wx/ticket', {
+          params: {
+            url: url,
+          },
+        })
+        .then((response) => {
+          if (response.status == 200) {
+            qiyeData = response.data.data;
+            wx.config({
+              beta: true, // 必须这么写,否则wx.invoke调用形式的jsapi会有问题
+              debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
+              appId: qiyeData.appId, // 必填,企业微信的corpID
+              timestamp: qiyeData.timestamp, // 必填,生成签名的时间戳
+              nonceStr: qiyeData.nonceStr, // 必填,生成签名的随机串
+              signature: qiyeData.signature, // 必填,签名,见 附录-JS-SDK使用权限签名算法
+              jsApiList: ['ready', 'scanQRCode'],
+            });
+            wx.ready(function () {
+              wx.scanQRCode({
+                desc: 'scanQRCode desc',
+                needResult: 1,
+                scanType: ['barCode'],
+                success: function (res) {
+                  console.log(res);
+                  var result = res.resultStr;
+                  console.log(result);
+                  var success = false;
+                  if (that.code == result && that.code != '' && that.code != null) {
+                    success = true;
+                  }
+                  let loading1 = that.$toast.loading({
+                    duration: 0,
+                    message: '数据加载中...',
+                    forbidClick: true,
+                  });
+                  getOptionByResult({
+                    taskId: that.tid,
+                    collectionId: that.cid,
+                    smResult: success,
+                  }).then((response) => {
+                    loading1.clear();
+                    if (response.code == 200) {
+                      that.$emit('newcode', {
+                        cid: response.data.collectionId,
+                        cpid: response.data.collectionOptionId,
+                        nocpid: response.data.diffCollectionOptionId,
+                        type: that.type,
+                        index: that.index,
+                        code: that.code + ',' + result,
+                        success: success,
+                        index1: that.index1,
+                        index2: that.index2,
+                        index3: that.index3,
+                        index4: that.index4,
+                        index5: that.index5,
+                        index6: that.index6,
+                        index7: that.index7,
+                        index8: that.index8,
+                      });
+                    }
+                  });
+                },
+                error: function (res) {
+                  if (res.errMsg.indexOf('function_not_exist') > 0) {
+                    alert('版本过低请升级');
+                  }
+                },
+              });
+            });
+          }
+        });
+    },
+  },
+};
+</script>
+
+<style scoped>
+.cameraDiv1 {
+  position: relative;
+  height: 164px;
+  width: 100%;
+}
+
+.cameraDiv1 img {
+  position: absolute;
+  width: 100%;
+  display: block;
+  height: 164px;
+  top: 0;
+}
+
+.imgPre {
+  height: 164px;
+  width: 100%;
+  background-color: white;
+  border-radius: 6px;
+  overflow: hidden;
+}
+
+.photos1 {
+  margin: 70px auto;
+  left: 50%;
+  margin-left: -14px;
+}
+
+.photobrowsing {
+  position: absolute;
+  padding: 4px;
+  right: 0;
+  top: 0;
+  z-index: 99;
+  background-color: rgba(255, 255, 255, 0.8);
+  border-bottom-left-radius: 3px;
+  border-top-left-radius: 3px;
+}
+
+.coverImg {
+  text-align: center;
+  position: absolute;
+  top: 0;
+  left: 0;
+  height: 164px;
+  width: 100%;
+}
+
+.coverImg .ico {
+  top: 42%;
+}
+</style>

+ 67 - 0
src/components/taskTips.vue

@@ -0,0 +1,67 @@
+<template>
+  <div class="tips">
+    <span class="examples" v-if="examplePhoto" @click="openExamplesImg(examplePhoto)"
+      >拍摄要求</span
+    >
+    <span class="phone" v-if="contactPhone">
+      <van-icon name="phone" size="18px" /><a :href="'tel:' + contactPhone" class="call">{{
+        contactPhone
+      }}</a>
+    </span>
+  </div>
+</template>
+
+<script>
+import { ImagePreview } from 'vant';
+export default {
+  props: {
+    contactPhone: {
+      type: [String, Number],
+      default: '',
+    },
+    examplePhoto: {
+      type: [String, Number],
+      default: '',
+    },
+  },
+  data() {
+    return {};
+  },
+  methods: {
+    // 点击查看示例图片
+    openExamplesImg(examplePhoto) {
+      if (!examplePhoto) return;
+      ImagePreview([examplePhoto]);
+      // this.examplePhotoImg = examplePhoto;
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.tips {
+  /* //   position: absolute;
+  //   right: 0;
+  //   top: 11px; */
+  display: inline;
+  /* //   height: 25px;
+  //   line-height: 25px; */
+  .examples {
+    margin: 0 10px;
+    background: rgb(255, 151, 106);
+    color: #fff;
+    padding: 2px 4px;
+    border-radius: 2px 2px 8px 2px;
+    font-size: 14px;
+  }
+  .phone {
+    display: inline-block;
+    i {
+      vertical-align: -2px;
+    }
+    a {
+      color: #0057ba;
+      text-decoration: underline;
+    }
+  }
+}
+</style>

+ 465 - 0
src/components/uploadVNormal.vue

@@ -0,0 +1,465 @@
+<template>
+  <div class="questionNamep">
+    <div class="cameraDiv" @click="uploadImg">
+      <van-icon class="photo photos" name="photograph" size="22px" color="#969696" />
+    </div>
+    <div id="allmap"></div>
+    <div class="mask" v-if="progressFlag">
+      <el-progress
+        type="circle"
+        :percentage="percentage"
+        :show-text="true"
+        :width="110"
+        :format="format"></el-progress>
+      <div class="progressClose" @click="progressClose">取消</div>
+    </div>
+    <imageAIVerifyErr
+      v-if="imageAIVerifyFlag"
+      :imageAIVerifyFlag="imageAIVerifyFlag"
+      :imageAIVerifyData="imageAIVerifyData"
+      @confirmUpload="confirmUpload"
+      @uploadImgFun="uploadImg"
+      :source="'visit'"
+      @normalFlow="normalFlow"
+      @close="close"></imageAIVerifyErr>
+  </div>
+</template>
+
+<script>
+import { addstorePhoto, addVisitsPosition, addPhotoToDB } from '@/api/index';
+import imageAIVerifyErr from './imageAIVerifyErr';
+import axios from 'axios';
+
+export default {
+  name: 'uploadImg',
+  components: { imageAIVerifyErr },
+  props: {
+    uploadid: {
+      type: String,
+      default: '',
+    },
+    storeGroupId: {
+      type: String,
+      default: '',
+    },
+    parentCollectionId: {
+      type: String,
+      default: '',
+    },
+    secondCollectionId: {
+      type: [String, Number],
+      default: '',
+    },
+    firstCollectionId: {
+      type: String,
+      default: '',
+    },
+    fourthCollectionId: {
+      type: String,
+      default: '',
+    },
+    thirdCollectionId: {
+      type: String,
+      default: '',
+    },
+    visitsId: {
+      type: String,
+      default: '',
+    },
+    taskId: {
+      type: String,
+      default: '',
+    },
+    collectionId: {
+      type: String,
+      default: '',
+    },
+    objectType: {
+      type: String,
+      default: '',
+    },
+    type: {
+      type: Number,
+      default: 1,
+    },
+    imgArr: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    visitModel: {
+      type: String,
+      default: '1',
+    },
+    deviceCode: {
+      type: String,
+      default: '',
+    },
+    putInCode: {
+      type: String,
+      default: '',
+    },
+    photoIdentifyType: {
+      // 图匠识别目的(1:店招内容识别,2:门店代码识别,3:调色机识别,4:更换店招)
+      type: String,
+      default: '',
+    },
+    pictureSource: {
+      // 是否允许从相册选择图片 1:允许;0:不允许
+      type: String,
+      default: '0',
+    },
+  },
+  data() {
+    return {
+      shows: false,
+      url: '',
+      progressFlag: false,
+      percentage: 0,
+      timeFlag: null,
+      imageAIVerifyFlag: false,
+      imageAIVerifyData: null, //图匠校验返回的数据
+      meidaId: '', //当前上传图片id
+      addressesRemark: '', //当前位置信息
+      controller: null, //取消请求状态
+    };
+  },
+  methods: {
+    uploadImg() {
+      var map = new TMap.Map('allmap', {
+        zoom: 14,
+        center: new TMap.LatLng(39.986785, 116.301012),
+      });
+
+      var geocoder = new TMap.service.Geocoder(); // 新建一个正逆地址解析类
+      var markers = new TMap.MultiMarker({
+        map: map,
+        geometries: [],
+      });
+      markers.setGeometries([]);
+
+      if (this.objectType == '' || this.objectType == null) {
+        this.$toast('请选择类型!');
+        return;
+      }
+      let url = window.location.href;
+      let that = this;
+      let wx = this.wx;
+      let qiyeData;
+      let addressesRemark = '';
+      const instance = axios.create();
+      instance.defaults.headers.common['userId'] = localStorage.getItem('loginName');
+      instance
+        .get(process.env.VUE_APP_BASE_API + 'mobile/wx/ticket', {
+          params: {
+            url: url,
+          },
+        })
+        .then((response) => {
+          if (response.status == 200) {
+            qiyeData = response.data.data;
+            wx.config({
+              beta: true, // 必须这么写,否则wx.invoke调用形式的jsapi会有问题
+              debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
+              appId: qiyeData.appId, // 必填,企业微信的corpID
+              timestamp: qiyeData.timestamp, // 必填,生成签名的时间戳
+              nonceStr: qiyeData.nonceStr, // 必填,生成签名的随机串
+              signature: qiyeData.signature, // 必填,签名,见 附录-JS-SDK使用权限签名算法
+              jsApiList: ['ready', 'chooseImage', 'uploadImage', 'getLocation'], // 必填,需要使用的JS接口列表,凡是要调用的接口都需要传进来
+            });
+            wx.ready(function () {
+              wx.getLocation({
+                type: 'gcj02',
+                success: function (res) {
+                  var location = new TMap.LatLng(res.latitude, res.longitude);
+                  map.setCenter(location);
+                  markers.updateGeometries([
+                    {
+                      id: 'main', // 点标注数据数组
+                      position: location,
+                    },
+                  ]);
+                  geocoder.getAddress({ location: location }).then(
+                    function (result) {
+                      var addresses = result.result.formatted_addresses;
+                      addressesRemark = addresses.recommend;
+                    },
+                    function (err) {
+                      addressesRemark = '';
+                    }
+                  );
+                },
+                fail: function () {
+                  that.$dialog.alert({
+                    message: 'GPS未开启',
+                  });
+                },
+              });
+              console.log(that.pictureSource);
+              let sourceType = that.pictureSource == '1' ? ['album', 'camera'] : ['camera'];
+              wx.chooseImage({
+                count: 1,
+                sizeType: ['original'], // 可以指定是原图还是压缩图,默认二者都有
+                sourceType: sourceType, // 可以指定来源是相册还是相机,默认二者都有
+                defaultCameraMode: 'normal', //表示进入拍照界面的默认模式,目前有normal与batch两种选择,normal表示普通单拍模式,batch表示连拍模式,不传该参数则为normal模式。从3.0.26版本开始支持front和batch_front两种值,其中front表示默认为前置摄像头单拍模式,batch_front表示默认为前置摄像头连拍模式。(注:用户进入拍照界面仍然可自由切换两种模式)
+                isSaveToAlbum: 0, //整型值,0表示拍照时不保存到系统相册,1表示自动保存,默认值是1
+                success: function (res) {
+                  var localIds = '';
+                  if (res.localIds != undefined) {
+                    localIds = res.localIds[0];
+                  } else {
+                    localIds = res.localId;
+                  }
+                  wx.uploadImage({
+                    localId: localIds, // 需要上传的图片的本地ID,由chooseImage接口获得
+                    isShowProgressTips: 1, // 默认为1,显示进度提示
+                    success: function (res) {
+                      that.uploadImagev(res.serverId, addressesRemark);
+                    },
+                  });
+                },
+              });
+            });
+          }
+        });
+    },
+    uploadImagev(meidaId, addressesRemark) {
+      // 初始化重置 图匠校验
+      this.resetProgress();
+      this.close();
+      var that = this;
+      var parentCollectionId = null;
+      if (that.parentCollectionId != null && that.parentCollectionId != 'null') {
+        parentCollectionId = that.parentCollectionId;
+      }
+      var secondCollectionId = null;
+      if (that.secondCollectionId != null && that.secondCollectionId != 'null') {
+        secondCollectionId = that.secondCollectionId;
+      }
+      var firstCollectionId = null;
+      if (that.firstCollectionId != null && that.firstCollectionId != 'null') {
+        firstCollectionId = that.firstCollectionId;
+      }
+      var fourthCollectionId = null;
+      if (that.fourthCollectionId != null && that.fourthCollectionId != 'null') {
+        fourthCollectionId = that.fourthCollectionId;
+      }
+      var thirdCollectionId = null;
+      if (that.thirdCollectionId != null && that.thirdCollectionId != 'null') {
+        thirdCollectionId = that.thirdCollectionId;
+      }
+      this.meidaId = meidaId;
+      this.addressesRemark = addressesRemark;
+      var form = {
+        mediaId: meidaId,
+        collectionItemId: that.collectionId,
+        objectType: that.objectType,
+        storeGroupId: that.storeGroupId,
+        taskId: that.taskId,
+        visitsId: localStorage.getItem('visitId'),
+        visitModel: that.visitModel,
+        visitSource: '1',
+        locationRemark: addressesRemark,
+        parentCollectionId: parentCollectionId,
+        secondCollectionId: secondCollectionId,
+        firstCollectionId: firstCollectionId,
+        fourthCollectionId: fourthCollectionId,
+        thirdCollectionId: thirdCollectionId,
+        deviceCode: that.deviceCode, //设备编号
+        putInCode: that.putInCode, //投放编号
+      };
+      this.controller = null;
+      // 需要图匠校验的添加参数和loading
+      if (this.photoIdentifyType) {
+        form.photoIdentifyType = this.photoIdentifyType;
+        this.progress();
+        this.controller = new AbortController(); //取消请求
+      } else {
+        this.toastLoading(0, '上传中...', true);
+      }
+      addstorePhoto(form, this.controller ? this.controller.signal : null)
+        .then((res) => {
+          this.toastLoading().clear();
+          if (res.code == -1) {
+            // 图匠图片校验接口超时
+            this.requestTimeOut(res);
+          } else if (res.code == 200) {
+            // 图匠校验结果返回
+            if (this.photoIdentifyType) {
+              // 重置loaidng状态
+              this.resetProgress();
+              this.imageAIVerifyFlag = true;
+              this.imageAIVerifyData = res.data;
+            } else {
+              // 正常流程
+              this.normalFlow(res);
+            }
+          } else {
+            this.resetProgress();
+            that.$toast('上传失败!');
+          }
+        })
+        .catch((error) => {
+          if (error.message === 'canceled') {
+            this.$toast('取消上传');
+            console.log('请求被取消:', error.message);
+          }
+          this.resetProgress();
+        });
+    },
+    // 正常流程
+    normalFlow(res) {
+      this.$toast('上传成功!');
+      this.$emit('newimgarr', {
+        fileUrl: res.data.url,
+        id: res.data.fileId,
+        type: 2,
+        photoIdentifyType: this.photoIdentifyType,
+      });
+    },
+    progress() {
+      // 后端接口20000ms后失效,每1000m progress加10,到90停止;
+      this.progressFlag = true;
+      this.percentage = 10;
+      this.timeFlag = setInterval(() => {
+        this.percentage = this.percentage + 10;
+        if (this.percentage == 90) clearInterval(this.timeFlag);
+      }, 1000);
+    },
+    format(percentage) {
+      return `${percentage} %\n图像识别中`;
+    },
+    // 重置loaidng状态
+    resetProgress() {
+      this.percentage = 100;
+      clearInterval(this.timeFlag);
+      this.progressFlag = false;
+      this.percentage = 0;
+    },
+    // 照片是否入库,1.照片识别三次不通过仍要上传,2.照片识别通过
+    // isUpdate:是否更新店招照片,只有门店店招需要更新
+    confirmUpload(res) {
+      if (this.photoIdentifyType) {
+        var form = {
+          mediaId: this.meidaId, //	string	图片素材id
+          visitSource: '1', //	Long	拜访模式
+          storeGroupId: this.storeGroupId, //	string	门店任务组,多个用逗号隔开
+          visitsId: localStorage.getItem('visitId'), //	string	拜访id
+          taskId: this.taskId, //	string	任务id
+          objectType: this.objectType, //	string	照片类型,取任务上的照片类型,如果没有则取手动选择的照片类型
+          locationRemark: this.addressesRemark, //	String	当前地址信息
+          firstCollectionId: this.firstCollectionId, //	Long	第一级采集项id,取当前采集项的字段就行
+          secondCollectionId: this.secondCollectionId, //	Long	第二级采集项id,取当前采集项的字段就行
+          putInCode: this.putInCode, //	String	当前任务对应的投放编号
+          deviceCode: this.deviceCode, //	String	当前任务对应的设备编号
+          collectionItemId: this.collectionId,
+          url: res.data.url, //	String	当前拍摄图片的url
+          businessId: res.data.businessId, // 当前拍摄图片id
+        };
+        if (res.isUpdate) {
+          form.isUpdate = 'true';
+          form.feedbackMessage = res.feedbackMessage;
+        }
+        addPhotoToDB(form).then((resData) => {
+          if (resData.code == 200) {
+            console.log(resData);
+            res.data.fileId = resData.data.fileId;
+            this.normalFlow(res);
+          }
+        });
+      }
+    },
+    close() {
+      this.imageAIVerifyFlag = false;
+    },
+    requestTimeOut(res) {
+      this.resetProgress();
+      this.close();
+      this.$dialog
+        .confirm({
+          title: '系统提示',
+          message: res.msg,
+          showCancelButton: false,
+        })
+        .then(() => {
+          this.confirmUpload(res);
+        });
+    },
+    // 取消图片上传
+    progressClose() {
+      this.controller.abort();
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.questionNamep {
+  font-size: 16px;
+  color: #484848;
+  line-height: 40px;
+  padding: 0 15px;
+  box-sizing: border-box;
+  position: relative;
+
+  .cameraDivp {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    .photo {
+      /*margin-top: 9px;*/
+      float: right;
+    }
+    .camera {
+      width: 60px;
+      height: 100%;
+      position: absolute;
+      right: 0;
+      top: 0;
+      opacity: 0;
+      z-index: 89;
+    }
+  }
+  .mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    width: 100%;
+    height: 100%;
+    background: rgba(255, 255, 255, 1);
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    z-index: 99999999;
+    display: flex;
+    flex-direction: column;
+    .progressClose {
+      width: 70px;
+      text-align: center;
+      background: #67c23a;
+      color: #fff;
+      height: 30px;
+      line-height: 30px;
+      border-radius: 5px;
+      margin-top: 5px;
+      font-size: 12px;
+    }
+  }
+}
+#allmap {
+  width: 10px;
+  height: 10px;
+  left: -1000px;
+  position: relative;
+}
+</style>
+<style lang="scss">
+.mask {
+  .el-progress__text {
+    white-space: pre-wrap;
+  }
+}
+</style>

+ 110 - 0
src/components/zCheckbox.vue

@@ -0,0 +1,110 @@
+<template>
+  <div class="zSelect">
+    <div>
+      <div class="checkbox">
+        <van-checkbox-group v-model="zSelectValuec" @change="checkboxclick">
+          <van-checkbox
+            :name="item.collectionOptionId + ''"
+            v-for="(item, index) in zCheckboxcolumns"
+            :key="index"
+            shape="square"
+            >{{ item.collectionOption }}
+          </van-checkbox>
+        </van-checkbox-group>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'zSelect',
+  props: {
+    zCheckboxcolumns: [],
+    checkboxval: '',
+    textc: '',
+    rules: false,
+    answerType: '',
+    collectionType: '',
+    childindex: '',
+    childindex1: '',
+    childindex2: '',
+    childindex4: '',
+    childindex3: '',
+    level: '',
+  },
+  data() {
+    return {
+      zSelect: false,
+      zSelectValuec: '',
+    };
+  },
+  created() {
+    this.checkboxvalFn();
+  },
+  methods: {
+    checkboxvalFn() {
+      if (this.checkboxval == '' || this.checkboxval == undefined) {
+        this.zSelectValuec = [];
+      } else {
+        this.zSelectValuec = this.checkboxval.split(',');
+      }
+    },
+    checkboxclick(value) {
+      var typeval = [];
+      var index = '';
+      for (let k = 0; k < this.zCheckboxcolumns.length; k++) {
+        for (let kk = 0; kk < value.length; kk++) {
+          if (this.zCheckboxcolumns[k].collectionOptionId == value[kk]) {
+            typeval.push(this.zCheckboxcolumns[k]);
+          }
+        }
+      }
+      let datalist = {
+        type: this.textc,
+        answerType: this.answerType,
+        collectionType: this.collectionType,
+        childindex: this.childindex,
+        childindex1: this.childindex1,
+        childindex2: this.childindex2,
+        childindex3: this.childindex3,
+        childindex4: this.childindex4,
+        level: this.level,
+        value: typeval,
+      };
+      this.zSelectValuec = value;
+      this.$emit('zSelectVal', datalist);
+      this.zSelect = false;
+    },
+  },
+};
+</script>
+
+<style scoped>
+.van-f-red {
+  color: red;
+  width: 4px;
+  display: inline-block;
+}
+
+.zSelect .z-cell {
+  padding: 10px 16px 0 16px;
+  font-size: 16px;
+}
+
+/*.checkbox{padding: 10px 16px 0 16px;background-color: white;}*/
+.checkbox .van-checkbox {
+  padding-bottom: 10px;
+}
+</style>
+<style>
+.checkbox .van-checkbox__icon .van-icon {
+  border: 1px solid #333 !important;
+}
+
+.checkbox .van-checkbox__icon--checked .van-icon {
+  border: 1px solid #1989fa !important;
+  color: #1989fa;
+  background-color: #fff;
+}
+</style>

+ 135 - 0
src/components/zRadio.vue

@@ -0,0 +1,135 @@
+<template>
+  <div class="zSelect">
+    <div class="checkbox">
+      <van-radio-group v-model="zradioc" @change="radiofn" :disabled="relevancyItem">
+        <van-radio
+          :name="item.collectionOptionId + ''"
+          :disabled="item.unableChoose"
+          @click="radioclick(item.unableChoose)"
+          v-for="(item, index) in zRadiocolumns"
+          :key="index"
+          >{{ item.collectionOption }}
+        </van-radio>
+      </van-radio-group>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'zSelect',
+  props: {
+    radio: '',
+    textc: '',
+    zRadiocolumns: [],
+    answerType: '',
+    collectionType: '',
+    childindex: '',
+    childindex1: '',
+    childindex2: '',
+    childIndex4: '',
+    childindex3: '',
+    childindex5: '',
+    childindex6: '',
+    childindex7: '',
+    childindex8: '',
+    childindex9: '',
+    relevancyItem: false, //当前单选框是否为禁用状态,特殊情况(扫描识别结果是否一致)根据扫描结果匹配选择项,禁止手动选择
+  },
+  data() {
+    return {
+      radioChange: false,
+      zradioc: '',
+    };
+  },
+  created() {
+    this.zradioc = this.radio;
+  },
+  methods: {
+    radiofn(value) {
+      this.radioChange = true;
+      var typeval = [];
+      var index = -1;
+      for (let k = 0; k < this.zRadiocolumns.length; k++) {
+        if (this.zRadiocolumns[k].collectionOptionId == value) {
+          typeval.push(this.zRadiocolumns[k]);
+          index = k;
+        }
+      }
+      let datalist = {
+        type: this.textc,
+        answerType: this.answerType,
+        collectionType: this.collectionType,
+        value: typeval,
+        index: index,
+        childindex: this.childindex,
+        childindex1: this.childindex1,
+        childindex2: this.childindex2,
+        childIndex4: this.childIndex4,
+        childindex3: this.childindex3,
+        childindex5: this.childindex5,
+        childindex6: this.childindex6,
+        childindex7: this.childindex7,
+        childindex8: this.childindex8,
+        childindex9: this.childindex9,
+      };
+      this.$emit('input', value);
+      this.$emit('zSelectVal', datalist);
+    },
+    radioclick(val) {
+      if (this.relevancyItem) return;
+      if (!val) {
+        if (!this.radioChange) {
+          this.zradioc = '';
+        }
+        this.radioChange = false;
+      }
+    },
+  },
+};
+</script>
+
+<style scoped>
+.van-f-red {
+  color: red;
+  width: 4px;
+  display: inline-block;
+}
+
+.zSelect .z-cell {
+  padding: 10px 16px 0 16px;
+  font-size: 16px;
+}
+
+.checkbox .van-radio {
+  padding-bottom: 10px;
+}
+</style>
+<style>
+.checkbox .van-radio__icon {
+  border: 1px solid #333;
+  border-radius: 80px;
+  width: 1em;
+}
+
+.checkbox .van-radio__icon .van-icon {
+  border: 0 !important;
+  height: 1em;
+  width: 1em;
+}
+
+.checkbox .van-radio__icon--checked .van-icon {
+  color: #1989fa;
+  background-color: #fff;
+  display: block;
+  height: 14px;
+  width: 14px;
+  margin: 2px auto;
+  background-color: #1989fa;
+  color: transparent;
+}
+
+.checkbox .van-radio__icon--checked {
+  border: 1px solid #1989fa;
+}
+</style>

+ 32 - 8
src/router/index.js

@@ -33,23 +33,47 @@ const router = new VueRouter({
           },
           },
         },
         },
         {
         {
-          path: '/err',
-          name: 'err',
-          component: () => import('@/views/home/err.vue'),
+          path: '/visitPage',
+          name: 'visitPage',
+          component: () => import('@/views/home/visitPage.vue'),
           meta: {
           meta: {
-            title: '404',
+            title: '拜访详情',
           },
           },
         },
         },
         {
         {
-          path: '/login',
-          name: 'login',
-          component: () => import('@/views/home/login.vue'),
+          path: '/visitTask',
+          name: 'visitTask',
+          component: () => import('@/views/home/visitTask.vue'),
           meta: {
           meta: {
-            title: '登录',
+            title: '拜访任务',
+          },
+        },
+        {
+          path: '/visitHistory',
+          name: 'visitHistory',
+          component: () => import('@/views/home/visitHistory.vue'),
+          meta: {
+            title: '拜访历史',
           },
           },
         },
         },
       ],
       ],
     },
     },
+    {
+      path: '/err',
+      name: 'err',
+      component: () => import('@/views/err.vue'),
+      meta: {
+        title: '404',
+      },
+    },
+    {
+      path: '/login',
+      name: 'login',
+      component: () => import('@/views/login.vue'),
+      meta: {
+        title: '登录',
+      },
+    },
   ],
   ],
 });
 });
 export default router;
 export default router;

src/views/home/err.vue → src/views/err.vue


+ 15 - 278
src/views/home/index.vue

@@ -1,7 +1,6 @@
 <template>
 <template>
   <div class="bgcolor deviceOutside">
   <div class="bgcolor deviceOutside">
     <div class="navBarTOP">
     <div class="navBarTOP">
-      <!--        顶部条-->
       <van-nav-bar class="navBar" :title="$route.meta.title">
       <van-nav-bar class="navBar" :title="$route.meta.title">
         <template #right>
         <template #right>
           <span @click="searchFn">筛选<van-icon name="arrow-down" /></span>
           <span @click="searchFn">筛选<van-icon name="arrow-down" /></span>
@@ -280,8 +279,8 @@ import {
   getCustomerList,
   getCustomerList,
   buryingPoint,
   buryingPoint,
   ProductItemImge,
   ProductItemImge,
+  getUserOutPlaList,
 } from '@/api/index';
 } from '@/api/index';
-import axios from 'axios';
 import request from '@/utils/request';
 import request from '@/utils/request';
 import { checkStoreAddressByStoreCode } from '@/api/visitstore';
 import { checkStoreAddressByStoreCode } from '@/api/visitstore';
 import { getPosition, getMapPoi, getkeywordPoi, getTicketFun } from '@/utils/TXApiFun';
 import { getPosition, getMapPoi, getkeywordPoi, getTicketFun } from '@/utils/TXApiFun';
@@ -298,7 +297,6 @@ export default {
   },
   },
   data() {
   data() {
     return {
     return {
-      typeShow: false,
       otherShow: false,
       otherShow: false,
       chainName: '',
       chainName: '',
       chainCode: '',
       chainCode: '',
@@ -342,7 +340,6 @@ export default {
       CustomerName: '',
       CustomerName: '',
       lat: '',
       lat: '',
       lon: '',
       lon: '',
-      timeData: '',
       objectPath: '',
       objectPath: '',
       isLoading: false,
       isLoading: false,
       monthVisited: '', //本月是否拜访
       monthVisited: '', //本月是否拜访
@@ -406,7 +403,6 @@ export default {
         this.otherShow = false; //筛选-其他
         this.otherShow = false; //筛选-其他
       }
       }
       this.onSearch();
       this.onSearch();
-      this.getMonth();
     },
     },
     setStroeNameStyle(item) {
     setStroeNameStyle(item) {
       return { color: '#0057ba', 'text-decoration': 'underline' };
       return { color: '#0057ba', 'text-decoration': 'underline' };
@@ -415,54 +411,8 @@ export default {
       this.storeName = '';
       this.storeName = '';
       localStorage.setItem('outvstoreName', '');
       localStorage.setItem('outvstoreName', '');
     },
     },
-    getMonth() {
-      // 获取当前日期
-      var currentDate = new Date();
-
-      // 获取当前月份
-      var currentMonth = currentDate.getMonth();
-
-      // 获取当前年份
-      // var currentYear = currentDate.getFullYear();
-
-      var previousMonthDate1 = new Date();
-      if (currentDate.getDate() == 1) {
-        previousMonthDate1.setMonth(currentMonth - 1);
-      } else {
-      }
-      var previousMonth1 = previousMonthDate1.getMonth();
-      var previousYear1 = previousMonthDate1.getFullYear();
-
-      // 计算前三个月的年份和月份
-      var previousMonthDate = new Date();
-      if (currentDate.getDate() == 1) {
-        previousMonthDate.setMonth(currentMonth - 3);
-      } else {
-        previousMonthDate.setMonth(currentMonth - 2);
-      }
-      1;
-      var previousMonth = previousMonthDate.getMonth();
-      var previousYear = previousMonthDate.getFullYear();
-
-      //前三个月
-      if (previousYear1 == previousYear) {
-        var formattedPreviousMonth1 = previousYear1 + '-' + (previousMonth1 + 1);
-        // 格式化年份和月份
-        var formattedPreviousMonth = previousYear + '-' + (previousMonth + 1);
-        this.timeData =
-          formattedPreviousMonth.split('-')[1] + '-' + formattedPreviousMonth1.split('-')[1] + '月';
-      } else {
-        var formattedPreviousMonth1 = previousYear1 + '年' + (previousMonth1 + 1) + '月';
-        // .toString().padStart(2, '0');
-        // 格式化年份和月份
-        var formattedPreviousMonth = previousYear + '年' + (previousMonth + 1) + '月';
-        this.timeData = formattedPreviousMonth + '-' + formattedPreviousMonth1;
-      }
-    },
     moreTypeShowFn() {
     moreTypeShowFn() {
       this.moreTypeShow = true;
       this.moreTypeShow = true;
-      // this.CustomerName=""
-      // this.chainsData=[]
       this.getCustomer();
       this.getCustomer();
     },
     },
     buryingPoint(val) {
     buryingPoint(val) {
@@ -496,28 +446,12 @@ export default {
         });
         });
       }
       }
     },
     },
-    searchType(val) {
-      this.storeTypeLists = [];
-      if (val != '') {
-        let filterArr = this.storeTypeList.filter((item) => {
-          return item.dictLabel.toLowerCase().includes(val.toLowerCase());
-        });
-        this.storeTypeLists = filterArr;
-      } else {
-        this.storeTypeLists = this.storeTypeList;
-      }
-    },
     onConfirm(value) {
     onConfirm(value) {
       this.storeCategoryList = this.result.join(',');
       this.storeCategoryList = this.result.join(',');
       // this.typeName=value.dictLabel
       // this.typeName=value.dictLabel
       this.showPicker = false;
       this.showPicker = false;
       this.onSearchm();
       this.onSearchm();
     },
     },
-    moreTypeShowclearableFn() {
-      this.chainName = '';
-      this.chainCode = '';
-      this.chainsData = [];
-    },
     onsets() {
     onsets() {
       this.result = [];
       this.result = [];
       this.storeLabelTypes = [];
       this.storeLabelTypes = [];
@@ -535,10 +469,6 @@ export default {
         });
         });
       }
       }
     },
     },
-    //取消搜索
-    cancelSearch() {
-      this.$refs.item.toggle();
-    },
     searchFn() {
     searchFn() {
       //获取门店类型  //获取门店标签
       //获取门店类型  //获取门店标签
       Promise.all([this.getStoreTypeList(), this.getStoreLabels()]).then(() => {
       Promise.all([this.getStoreTypeList(), this.getStoreLabels()]).then(() => {
@@ -546,10 +476,6 @@ export default {
         this.CustomerName = '';
         this.CustomerName = '';
       });
       });
     },
     },
-    moreSearch() {
-      this.onSearch();
-      this.$refs.item.toggle();
-    },
     getUserOrgStoreList() {
     getUserOrgStoreList() {
       this.storeType = localStorage.getItem('storeType');
       this.storeType = localStorage.getItem('storeType');
       this.endShow = false;
       this.endShow = false;
@@ -604,7 +530,7 @@ export default {
         this.list = [];
         this.list = [];
         this.refreshing = false;
         this.refreshing = false;
       }
       }
-      queryMyChainsGroupList({
+      getUserOutPlaList({
         lat: this.lat,
         lat: this.lat,
         lon: this.lon,
         lon: this.lon,
         chainCode: this.chainCode ? this.chainCode : '',
         chainCode: this.chainCode ? this.chainCode : '',
@@ -643,30 +569,20 @@ export default {
       localStorage.setItem('tabVal', this.tabVal);
       localStorage.setItem('tabVal', this.tabVal);
       localStorage.removeItem('visitId');
       localStorage.removeItem('visitId');
       checkVisit({ storeId: val.storeId }).then((res) => {
       checkVisit({ storeId: val.storeId }).then((res) => {
-        if (this.tabVal == 1) {
-          this.buryingPoint({
-            systemModel: '计划外',
-            buryingPointType: 1,
-            buryingPointValue: val.storeName + '(' + val.storeCode + ')',
-            buryingPointName: '进店拜访',
-            buryingPointPosition: '我的',
-          });
-        } else {
-          this.buryingPoint({
-            systemModel: '计划外',
-            buryingPointType: 1,
-            buryingPointValue: val.storeName + '(' + val.storeCode + ')',
-            buryingPointName: '进店拜访',
-            buryingPointPosition: '销售部',
-          });
-        }
+        this.buryingPoint({
+          systemModel: '计划外',
+          buryingPointType: 1,
+          buryingPointValue: val.storeName + '(' + val.storeCode + ')',
+          buryingPointName: '进店拜访',
+          buryingPointPosition: this.tabVal == 1 ? '我的' : '销售部',
+        });
         if (res.code == 200 || val.stateString.indexOf('拜访中') != -1) {
         if (res.code == 200 || val.stateString.indexOf('拜访中') != -1) {
           if (val.stateString.indexOf('拜访中') != -1) {
           if (val.stateString.indexOf('拜访中') != -1) {
             localStorage.setItem('startTime', new Date());
             localStorage.setItem('startTime', new Date());
             localStorage.setItem('ORGName', val.deptName);
             localStorage.setItem('ORGName', val.deptName);
             localStorage.setItem('chainNameR', val.storeName);
             localStorage.setItem('chainNameR', val.storeName);
             this.$router.push({
             this.$router.push({
-              path: '/suishenbangOutstoreVisit',
+              path: '/visitPage',
               query: {
               query: {
                 storeId: val.storeId,
                 storeId: val.storeId,
                 rdId: val.rdId,
                 rdId: val.rdId,
@@ -843,7 +759,7 @@ export default {
         // 进入拜访之前先刷新页面
         // 进入拜访之前先刷新页面
         store.dispatch('setDeviceOutsidePage', true);
         store.dispatch('setDeviceOutsidePage', true);
         this.$router.push({
         this.$router.push({
-          path: '/suishenbangOutstoreVisit',
+          path: '/visitPage',
           query: {
           query: {
             storeId: val.storeId,
             storeId: val.storeId,
             rdId: val.rdId,
             rdId: val.rdId,
@@ -973,26 +889,12 @@ export default {
       this.$router.go(-1);
       this.$router.go(-1);
     },
     },
     onSearch() {
     onSearch() {
-      // window.scrollTo(0, 0);
       this.pageNum = 1;
       this.pageNum = 1;
       this.list = [];
       this.list = [];
       this.finished = true;
       this.finished = true;
-      var postType = localStorage.getItem('postType');
-      if (postType == 'GZ') {
-        this.typeShow = false;
-      } else {
-        this.typeShow = true;
-      }
       this.onLoad();
       this.onLoad();
     },
     },
     onSearchm() {
     onSearchm() {
-      var postType = localStorage.getItem('postType');
-
-      if (postType == 'GZ') {
-        this.typeShow = false;
-      } else {
-        this.typeShow = true;
-      }
       var StoreLabelsArr = [];
       var StoreLabelsArr = [];
       for (var k = 0; k < this.storeLabelTypes.length; k++) {
       for (var k = 0; k < this.storeLabelTypes.length; k++) {
         for (var k1 = 0; k1 < this.StoreLabels.length; k1++) {
         for (var k1 = 0; k1 < this.StoreLabels.length; k1++) {
@@ -1009,81 +911,6 @@ export default {
           }
           }
         }
         }
       }
       }
-      if (this.tabVal == 1) {
-        if (this.storeLabelTypes.length > 0) {
-          this.buryingPoint({
-            systemModel: '计划外',
-            buryingPointType: 1,
-            buryingPointValue: StoreLabelsArr.join(','),
-            buryingPointName: '标签',
-            buryingPointPosition: '我的筛选',
-          });
-        }
-        if (this.storeCategoryList.length > 0) {
-          this.buryingPoint({
-            systemModel: '计划外',
-            buryingPointType: 1,
-            buryingPointValue: storeCategoryList.join(','),
-            buryingPointName: '类型',
-            buryingPointPosition: '我的筛选',
-          });
-        }
-        if (this.chainName != '') {
-          this.buryingPoint({
-            systemModel: '计划外',
-            buryingPointType: 1,
-            buryingPointValue: this.chainName,
-            buryingPointName: '经销商筛选',
-            buryingPointPosition: '我的筛选',
-          });
-        }
-        if (this.storeName != '') {
-          this.buryingPoint({
-            systemModel: '计划外',
-            buryingPointType: 1,
-            buryingPointValue: this.storeName,
-            buryingPointName: '搜索名称/编号/地址',
-            buryingPointPosition: '我的筛选',
-          });
-        }
-      } else {
-        if (this.storeLabelTypes.length > 0) {
-          this.buryingPoint({
-            systemModel: '计划外',
-            buryingPointType: 1,
-            buryingPointValue: StoreLabelsArr.join(','),
-            buryingPointName: '标签',
-            buryingPointPosition: '销售部的门店筛选',
-          });
-        }
-        if (this.storeCategoryList != '') {
-          this.buryingPoint({
-            systemModel: '计划外',
-            buryingPointType: 1,
-            buryingPointValue: storeCategoryList.join(','),
-            buryingPointName: '类型',
-            buryingPointPosition: '销售部的门店筛选',
-          });
-        }
-        if (this.chainName != '') {
-          this.buryingPoint({
-            systemModel: '计划外',
-            buryingPointType: 1,
-            buryingPointValue: this.chainName,
-            buryingPointName: '经销商筛选',
-            buryingPointPosition: '销售部的门店筛选',
-          });
-        }
-        if (this.storeName != '') {
-          this.buryingPoint({
-            systemModel: '计划外',
-            buryingPointType: 1,
-            buryingPointValue: this.storeName,
-            buryingPointName: '搜索名称/编号/地址',
-            buryingPointPosition: '销售部的门店筛选',
-          });
-        }
-      }
       localStorage.setItem('outvstoreName', this.storeName);
       localStorage.setItem('outvstoreName', this.storeName);
       localStorage.setItem('outvchainName', this.chainName);
       localStorage.setItem('outvchainName', this.chainName);
       localStorage.setItem('outvstoreLabelTypes', this.storeLabelTypes);
       localStorage.setItem('outvstoreLabelTypes', this.storeLabelTypes);
@@ -1092,9 +919,7 @@ export default {
       this.onSearch();
       this.onSearch();
     },
     },
     tabChange(name) {
     tabChange(name) {
-      // window.scrollTo(0, 0);
       this.finished = true;
       this.finished = true;
-
       this.pageNum = 1;
       this.pageNum = 1;
       this.list = [];
       this.list = [];
       this.tabVal = name;
       this.tabVal = name;
@@ -1107,19 +932,13 @@ export default {
       // 授权
       // 授权
       getTicketFun()
       getTicketFun()
         .then(() => {
         .then(() => {
-          var postType = localStorage.getItem('postType');
-          if (postType == 'GZ') {
-            this.typeShow = false;
-          } else {
-            this.typeShow = true;
-          }
           getPosition(true)
           getPosition(true)
             .then((res) => {
             .then((res) => {
               let { TXisBD } = res;
               let { TXisBD } = res;
               this.lat = TXisBD.lat;
               this.lat = TXisBD.lat;
               this.lon = TXisBD.lon;
               this.lon = TXisBD.lon;
               if (this.tabVal == '1') {
               if (this.tabVal == '1') {
-                // this.getUserOutPlaListFun();
+                this.getUserOutPlaListFun();
               } else {
               } else {
                 this.getUserOrgStoreList();
                 this.getUserOrgStoreList();
               }
               }
@@ -1162,22 +981,6 @@ export default {
   color: #333;
   color: #333;
   line-height: 22px;
   line-height: 22px;
   padding-right: 52px;
   padding-right: 52px;
-  .statusIcon {
-    padding: 3px;
-    font-size: 12px;
-    margin: 0 3px;
-    color: #fff;
-    display: inline-block;
-    height: 20px;
-    line-height: 16px;
-    vertical-align: -1px;
-  }
-  .submit {
-    background: #ffba13;
-  }
-  .noSubmit {
-    background: #f11818;
-  }
 }
 }
 .card .info {
 .card .info {
   font-size: 14px;
   font-size: 14px;
@@ -1195,27 +998,6 @@ export default {
   z-index: 2;
   z-index: 2;
   top: 0;
   top: 0;
 }
 }
-.cellcontent .centerBtn {
-  margin: 0 auto 10px;
-  display: block;
-  width: 92%;
-  color: #0057ba;
-  border-radius: 5px;
-  padding: 0 2px;
-}
-.cellcontent .centerBtn1 {
-  background-color: #0057ba;
-  color: #fff;
-  border-color: #0057ba;
-}
-.cellcontent .centerBtn2 {
-  margin: 0 auto 10px;
-  display: block;
-  width: 92%;
-  color: #0057ba;
-  border-radius: 5px;
-  padding: 0;
-}
 .statstext {
 .statstext {
   background-color: #0057ba;
   background-color: #0057ba;
   position: absolute;
   position: absolute;
@@ -1232,12 +1014,6 @@ export default {
 .statstext .van-icon__image {
 .statstext .van-icon__image {
   height: 0.7em;
   height: 0.7em;
 }
 }
-.tipsTitle {
-  padding: 5px 0;
-  text-align: center;
-  font-size: 16px;
-  font-weight: 600;
-}
 .deviceOutside {
 .deviceOutside {
   height: 100%;
   height: 100%;
   width: 100%;
   width: 100%;
@@ -1248,9 +1024,9 @@ export default {
     flex: 1;
     flex: 1;
     overflow-y: auto;
     overflow-y: auto;
     padding-bottom: 50px;
     padding-bottom: 50px;
-  }
-  .tabBar {
-    height: 50px;
+    .van-pull-refresh {
+      height: 100%;
+    }
   }
   }
 }
 }
 .monthVisited {
 .monthVisited {
@@ -1265,45 +1041,6 @@ export default {
 .van-tabs__nav--card .van-tab.van-tab--active {
 .van-tabs__nav--card .van-tab.van-tab--active {
   background-color: #0057ba !important;
   background-color: #0057ba !important;
 }
 }
-.visitSearch {
-  width: 68px;
-  color: #0057ba;
-  font-size: 14px;
-}
-.visitSearch .van-dropdown-menu__bar {
-  box-shadow: 0 0 0 #fff;
-  height: 52px;
-}
-.visitSearch .van-dropdown-menu__item {
-  justify-content: normal;
-}
-.visitSearch .van-dropdown-menu__title {
-  border-left: 1px solid #ccc;
-}
-.visitSearch .van-cell {
-  border: 1px solid #ccc;
-  border-radius: 5px;
-  padding: 6px;
-}
-.positionContent {
-  position: fixed;
-  color: #666;
-  display: inline-block;
-  box-shadow: 0px 2px 7px -5px #000;
-  border-radius: 100px;
-  overflow: hidden;
-  right: 14px;
-  cursor: pointer;
-  bottom: 96px;
-  background-color: white;
-}
-.positionContent .img {
-  border-radius: 100px;
-  float: left;
-}
-.positionContent .img .van-icon__image {
-  border-radius: 100px;
-}
 .zDialog .van-dialog__header {
 .zDialog .van-dialog__header {
   padding: 10px;
   padding: 10px;
   border-bottom: 1px solid #f5f5f5;
   border-bottom: 1px solid #f5f5f5;

+ 139 - 0
src/views/home/visitHistory.vue

@@ -0,0 +1,139 @@
+<template>
+  <div class="visitHistory">
+    <div class="headers">
+      <van-nav-bar class="navBar" :title="$route.meta.title" left-arrow @click-left="onClickLeft" />
+    </div>
+    <div class="container">
+      <div class="card" v-if="data">
+        <div class="title f-blue">
+          {{ data.storeName }}(<span style="color: #0057ba">{{ data.storeCode }}</span
+          >)
+        </div>
+        <div class="info1">类型:{{ data.storeCategory }}</div>
+        <div class="info1">地址:{{ data.addressLine }}</div>
+        <div class="info1">上次拜访备注:{{ data.notes }}</div>
+      </div>
+      <div style="color: #999; font-size: 12px; padding: 10px; background-color: #f5f5f5">
+        <van-icon name="info-o" />&nbsp;今天拜访拍照内容,将同步传给部主管查阅。
+      </div>
+      <div class="card">
+        <div
+          class="info"
+          v-for="(item, index) in list"
+          :key="index"
+          @click="examineHistory(item, index)"></div>
+      </div>
+    </div>
+    <!-- 拜访历史详情 -->
+    <div class="visitHistoryDetail"></div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'visitPage',
+  data() {
+    return {
+      data: null,
+      storeId: '',
+    };
+  },
+  created() {
+    this.storeId = this.$route.query.storeId;
+  },
+  mounted() {},
+  methods: {
+    // 查看拜访历史详情
+    examineHistory(item) {},
+    onClickLeft() {
+      this.$router.go(-1);
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.visitHistory {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+  .container {
+    overflow-y: auto;
+    flex: 1;
+    margin-bottom: 10px;
+    background-color: white;
+  }
+}
+.card {
+  background: #fff;
+  box-sizing: border-box;
+  padding: 10px 16px;
+  .title {
+    line-height: 32px;
+    font-size: 16px;
+    font-weight: bold;
+    color: #333;
+  }
+  .subtitle {
+    line-height: 24px;
+    font-size: 14px;
+    color: #7b7b7b;
+    .status {
+      float: right;
+    }
+  }
+  .info {
+    font-size: 14px;
+    color: #484848;
+    padding: 14px;
+    border-bottom: 1px solid #f1f1f1;
+    position: relative;
+    .arrow {
+      float: right;
+      display: inline-block;
+      height: 20px;
+      width: 20px;
+      line-height: 20px;
+      text-align: center;
+      border-radius: 50%;
+      background: #0057ba;
+      color: #fff;
+      font-weight: bold;
+      font-size: 14px;
+      position: absolute;
+      margin-top: -10px;
+      right: 0;
+      top: 50%;
+    }
+  }
+  .info1 {
+    font-size: 14px;
+    color: #666;
+    line-height: 18px;
+    padding: 4px 0;
+    position: relative;
+    .arrow {
+      float: right;
+      display: inline-block;
+      height: 20px;
+      width: 20px;
+      line-height: 20px;
+      text-align: center;
+      border-radius: 50%;
+      background: #0057ba;
+      color: #fff;
+      font-weight: bold;
+      font-size: 14px;
+      margin-top: 9px;
+      position: absolute;
+      right: 0;
+      top: 50%;
+      margin-top: -10px;
+    }
+  }
+}
+.card .f-blue {
+  color: #0057ba;
+}
+</style>

+ 795 - 0
src/views/home/visitPage.vue

@@ -0,0 +1,795 @@
+<template>
+  <div class="visitPage">
+    <div class="headers">
+      <van-nav-bar class="navBar" :title="$route.meta.title" left-arrow @click-left="onClickLeft" />
+    </div>
+    <div class="container">
+      <div class="card">
+        <div class="title f-blue">
+          {{ storeName }}(<span style="color: #0057ba">{{ urlParameter.storeCode }}</span
+          >)
+        </div>
+        <div class="info1" v-if="addressLine != null">类型:{{ storeCategory }}</div>
+        <div class="info1" v-if="addressLine != 'null'">地址:{{ addressLine }}</div>
+        <div class="info1" v-if="notes != null">上次拜访备注:{{ notes }}</div>
+        <div class="info1">拜访时长:{{ showTime }}</div>
+        <div class="info1">
+          <span v-if="urlParameter.hisTime">
+            上次拜访时间:{{ parseTime(urlParameter.hisTime) }}
+          </span>
+          <span @click="shows = true" class="f-blue" v-if="visitsRemarks" style="font-weight: bold">
+            <van-icon :name="require('@/assets/icon/history.png')" />
+            历史拜访记录
+          </span>
+          <!-- <span @click="shows = true" class="f-blue" v-if="visitsRemarks" style="font-weight: bold">
+            <van-icon name="browsing-history-o" />
+            查看最近三次
+          </span> -->
+        </div>
+        <!-- <van-button
+          type="info"
+          style="background: rgb(0, 87, 186); color: #fff; margin: 10px 0; border-radius: 5px"
+          size="small"
+          plain
+          class="centerBtn"
+          @click="visitFn(urlParameter.storeCode)"
+          >经营情况</van-button
+        > -->
+        <!-- <van-button
+          type="info"
+          style="background: rgb(0, 87, 186); color: #fff; margin: 10px; border-radius: 5px"
+          size="small"
+          plain
+          v-if="showOrderButton"
+          class="centerBtn"
+          @click="overbookingFn(urlParameter)"
+          >去下单</van-button
+        > -->
+        <van-button
+          type="info"
+          style="
+            float: right;
+            background: #ed5565;
+            border-color: #ed5565;
+            color: #fff;
+            margin: 10px 0;
+            border-radius: 5px;
+          "
+          size="small"
+          plain
+          class="centerBtn"
+          @click="onstopVisit"
+          >取消拜访</van-button
+        >
+      </div>
+      <div
+        v-if="addShow1"
+        style="color: #999; font-size: 12px; padding: 10px; background-color: #f5f5f5">
+        <van-icon name="info-o" />&nbsp;今天拜访拍照内容,将同步传给部主管查阅。
+      </div>
+      <div class="card">
+        <div
+          class="info"
+          v-for="(item, index) in list"
+          :key="index"
+          @click="visitTask(item, index)">
+          <span class="must" v-show="item.isMust == '0' || item.isMust == '2'">*</span>
+          <span class="must" v-show="item.isMust != '0' && item.isMust != '2'">&nbsp;</span>
+          <p style="width: 74%; margin: 0; line-height: 24px; display: inline-block">
+            {{ item.taskName }}
+          </p>
+          <span v-show="item.processKey != null" class="processIco">
+            <van-icon :name="require('@/assets/icon/sp.png')" size="16" />
+          </span>
+          <span v-show="!item.success" class="arrow" style="background-color: #fff; color: #444"
+            ><van-icon name="arrow"
+          /></span>
+          <span v-show="item.success" class="arrow" tyle="background-color: #0057ba"
+            ><van-icon name="success"
+          /></span>
+        </div>
+      </div>
+    </div>
+    <div class="tc" style="padding: 0 16px">
+      <van-button class="submitBtn" block type="info" color="#0057ba" @click="endVisitsFn">
+        提交拜访
+      </van-button>
+    </div>
+    <br />
+    <van-dialog v-model="shows">
+      <div class="tipTitleBox" style="padding: 10px">
+        <p class="p">近三次拜访备注</p>
+        <div
+          v-for="item in visitsRemarks"
+          style="border-bottom: 1px solid #e8e8e8; font-size: 14px; padding: 10px 0">
+          <p>拜访时间:{{ item.stopTime }}</p>
+          <p>备注:{{ item.visitRemark }}</p>
+        </div>
+      </div>
+    </van-dialog>
+    <div id="allmap"></div>
+  </div>
+</template>
+
+<script>
+import {
+  getStoreGroupTask,
+  endVisits,
+  editDwellTime,
+  suishenbangStoreSale,
+  stopVisit,
+  buryingPoint,
+} from '@/api/index';
+import { saveVisitsParams, getOrderUrlByStoreId } from '@/api/inventory';
+import store from '@/store';
+export default {
+  name: 'visitPage',
+  data() {
+    return {
+      notes: '',
+      visitModel: '1',
+      shows: false,
+      flag: true,
+      questionsshow: false,
+      uploadImgshow: false,
+      imgs: [],
+      uploadImages: [],
+      uploadid1: 'uploadid1',
+      uploadid2: 'uploadid2',
+      iscuxiao: false,
+      text: '',
+      radio: '',
+      uploadImgEditText: '编辑',
+      isEdit: false,
+      storeId: '',
+      rdId: '',
+      lat: '',
+      lon: '',
+      list: [],
+      storeGroupId: '',
+      addShow1: false,
+      visitId: '',
+      addressLine: '',
+      storeCategory: '',
+      storeName: '',
+      contactName: '',
+      urlParameter: '',
+      uType: '-1',
+      showOrderButton: null,
+
+      visitsRemarks: [],
+      location: {
+        lat: '34.6174',
+        lon: '112.44039',
+      },
+      address: '',
+      showTime: '00:00:00',
+      city: '',
+      locationAccuracy: '',
+      id: '89',
+      startTime: null,
+      timeN: null,
+    };
+  },
+  created() {
+    this.urlParameter = this.$route.query;
+    this.storeId = this.$route.query.storeId + '';
+    this.visitId = localStorage.getItem('visitId') || this.$route.query.visitId;
+    this.storeCode = this.$route.query.storeCode;
+    this.rdId = this.$route.query.rdId + '';
+    this.addressLine = this.$route.query.addressLine;
+    this.storeCategory = this.$route.query.storeCategory;
+    this.storeName = this.$route.query.storeName;
+    this.contactName = this.$route.query.contactName;
+    this.lat = this.$route.query.lat + '';
+    this.lon = this.$route.query.lon + '';
+    this.visitModel = this.$route.query.visitModel + '';
+    this.uType = localStorage.getItem('uType');
+  },
+  mounted() {
+    this.addVisits();
+  },
+  methods: {
+    animation() {
+      //前时间减去上次开启时间减去暂停累计时间
+      var times = new Date().getTime() - new Date(this.startTime).getTime();
+      var house = Math.floor(times / 3600000); //毫秒转化为分钟
+      var minutes = Math.floor(times / 60000 - house * 60); //毫秒转化为分钟
+      var minutes1 = Math.floor(times / 60000); //毫秒转化为分钟
+      var seconds = Math.floor((times - minutes1 * 60000) / 1000); //已知分钟将time减去分钟 除去1000得出 秒
+      var ms = Math.floor((times - minutes1 * 60000 - seconds * 1000) / 10); //
+      this.showTime =
+        (house < 10 ? '0' + house : house) +
+        ':' +
+        (minutes < 10 ? '0' + minutes : minutes) +
+        ':' +
+        (seconds < 10 ? '0' + seconds : seconds);
+      // +":"
+      // +(ms<10 ? "0"+ms : ms);
+    },
+    // 结束拜访
+    onstopVisit() {
+      this.$dialog
+        .confirm({
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          title: '系统提示',
+          message: '取消拜访会清空填写的拜访内容和照片,是否确认?',
+        })
+        .then(() => {
+          stopVisit({ visitsId: this.visitId }).then((res) => {
+            if (res.code == 200) {
+              this.$dialog
+                .alert({
+                  title: '系统提示',
+                  message: '拜访中任务结束成功!',
+                })
+                .then(() => {
+                  store.dispatch('setDeviceOutsidePage', true);
+                  this.onClickLeft();
+                });
+            } else {
+              this.$dialog.alert({
+                title: '系统提示',
+                message: res.msg,
+              });
+            }
+          });
+        });
+    },
+    overbookingFn(val) {
+      buryingPoint({
+        systemModel: '拜访页',
+        buryingPointType: 1,
+        buryingPointValue: val.storeName + '(' + val.storeCode + ')',
+        buryingPointName: '去下单',
+        buryingPointPosition: '拜访页',
+      });
+      this.toastLoading(0, '加载中...', true);
+      getOrderUrlByStoreId({
+        storeId: this.$route.query.storeId,
+        from: this.$route.query.from,
+      }).then((res) => {
+        this.toastLoading().clear();
+        if (res.code == 200 && res.data) {
+          window.location.href = res.data;
+        } else {
+          this.Toast({
+            message: res.msg,
+            duration: 5000,
+          });
+        }
+      });
+    },
+    visitFn(val) {
+      var that = this;
+      suishenbangStoreSale({ storeCode: val }).then((res) => {
+        if (res.code == 200) {
+          if (res.data.num != '0') {
+            window.location.href =
+              process.env.VUE_APP_SSB_LINK + '/order/storeDetail/index?shopCode=' + val;
+          } else {
+            that.$toast(res.data.msg);
+          }
+        } else {
+          that.$toast(res.msg);
+        }
+      });
+    },
+    getLocation() {
+      this.toastLoading(0, '加载中...', true);
+      // 授权
+      getTicketFun()
+        .then(() => {
+          getPosition(true)
+            .then((res) => {
+              this.toastLoading().clear();
+              let { TXisBD } = res;
+              this.lat = TXisBD.lat;
+              this.lon = TXisBD.lon;
+              this.addVisits();
+            })
+            .catch((error) => {
+              this.toastLoading().clear();
+              this.$dialog.alert({
+                message: error,
+              });
+            });
+        })
+        .catch(() => {
+          this.toastLoading().clear();
+          this.finished = true;
+        });
+    },
+    editDwellTimes() {
+      let dwellTime = this.weekend(localStorage.getItem('startTime'), new Date()) + '';
+      editDwellTime({ dwellTime: dwellTime, visitsId: this.visitId }).then((res) => {
+        if (res.code == 200) {
+          localStorage.removeItem('visitId');
+        }
+      });
+    },
+
+    weekend(time1) {
+      var arrtime1 = new Date(time1).getTime();
+      var arrtime2 = new Date().getTime();
+      return Math.round((arrtime2 - arrtime1) / 1000);
+    },
+    addVisits() {
+      var postType = localStorage.getItem('postType');
+      if (postType == 'GZ') {
+        this.addShow1 = false;
+      } else {
+        this.addShow1 = true;
+      }
+      var visitEntry = '';
+      if (this.urlParameter.tabVal == '0') {
+        visitEntry = '2';
+      } else {
+        visitEntry = '1';
+      }
+      if (this.$route.query.shopCode != undefined) {
+        this.storeCode = this.$route.query.shopCode;
+      }
+      var that = this;
+
+      var map = new TMap.Map('allmap', {
+        zoom: 14,
+        center: new TMap.LatLng(39.986785, 116.301012),
+      });
+
+      var geocoder = new TMap.service.Geocoder();
+      var markers = new TMap.MultiMarker({
+        map: map,
+        geometries: [],
+      });
+      markers.setGeometries([]);
+      var input = [that.urlParameter.marklat, that.urlParameter.marklon];
+      var location = new TMap.LatLng(Number(input[0]), Number(input[1]));
+      geocoder.getAddress({ location: location }).then(
+        function (result) {
+          var addresses = result.result.formatted_addresses;
+          let address_component = result.result.address_component;
+          let province = address_component.province;
+          let city = address_component.city;
+          let district = address_component.district;
+          console.log('province=' + province);
+          console.log('city=' + city);
+          console.log('district=' + district);
+          var params = {
+            storeId: that.storeId,
+            storeCode: that.storeCode,
+            visitEntry: visitEntry,
+            lat: that.urlParameter.latNew,
+            lon: that.urlParameter.lonNew,
+            visitModel: that.visitModel,
+            routeDetailsId: that.rdId,
+            visitSource: '1',
+            locationCity: '',
+            locationRemark: addresses.recommend,
+            locationAccuracy: that.urlParameter.PointSum,
+            province: address_component.province,
+            city: address_component.city,
+            district: address_component.district,
+          };
+          that.locationAccuracy = that.urlParameter.PointSum;
+          that.city = '';
+          that.address = addresses.recommend;
+          localStorage.setItem('address', '');
+          if (that.visitId != null) {
+            params.id = that.visitId;
+          }
+          let loading2 = that.$toast.loading({
+            duration: 0,
+            message: '加载中...',
+            forbidClick: true,
+          });
+          getStoreGroupTask(params).then((res) => {
+            loading2.clear();
+            if (res.code == 200) {
+              localStorage.setItem('visitId', res.data.visitId);
+              that.notes = res.data.notes;
+              that.visitId = res.data.visitId;
+              that.list = res.data.sfaTaskList;
+              that.storeGroupId = res.data.storeGroupId;
+              that.showOrderButton = res.data.showOrderButton;
+              that.startTime = res.data.startTime;
+              that.timeN = setInterval(that.animation, 16);
+              that.visitsRemarks = res.data.visitsRemarks;
+            } else {
+              that.$toast(res.msg);
+            }
+          });
+        },
+        function (err) {
+          var params = {
+            storeId: that.storeId,
+            storeCode: that.storeCode,
+            visitEntry: visitEntry,
+            lat: that.urlParameter.latNew,
+            lon: that.urlParameter.lonNew,
+            visitModel: that.visitModel,
+            routeDetailsId: that.rdId,
+            visitSource: '1',
+            locationCity: '',
+            locationRemark: '',
+            locationAccuracy: that.urlParameter.PointSum,
+          };
+          that.locationAccuracy = that.urlParameter.PointSum;
+          that.city = '';
+          that.address = '';
+          localStorage.setItem('address', '');
+          if (that.visitId != null) {
+            params.id = that.visitId;
+          }
+          let loading2 = that.$toast.loading({
+            duration: 0,
+            message: '加载中...',
+            forbidClick: true,
+          });
+          getStoreGroupTask(params).then((res) => {
+            loading2.clear();
+            if (res.code == 200) {
+              localStorage.setItem('visitId', res.data.visitId);
+              that.notes = res.data.notes;
+              that.visitId = res.data.visitId;
+              that.list = res.data.sfaTaskList;
+              that.storeGroupId = res.data.storeGroupId;
+              that.showOrderButton = res.data.showOrderButton;
+              that.startTime = res.data.startTime;
+              that.timeN = setInterval(that.animation, 16);
+              that.visitsRemarks = res.data.visitsRemarks;
+            } else {
+              that.$toast(res.msg);
+            }
+          });
+        }
+      );
+    },
+    visitTask(val, index) {
+      this.$router.push({
+        path: '/visitTask',
+        query: {
+          storeId: this.storeId,
+          storeCode: this.urlParameter.storeCode,
+          visitId: this.visitId,
+          ids: index,
+          taskId: val.taskId,
+          storeGroupId: this.storeGroupId,
+          taskType: val.taskType,
+          photoType: val.photoType,
+          lat: this.lat,
+          lon: this.lon,
+          visitSource: '1',
+          visitModel: this.visitModel,
+          locationCity: this.city,
+          locationRemark: this.address,
+          locationAccuracy: this.locationAccuracy,
+          photoIdentifyType: val.photoIdentifyType,
+        },
+      });
+    },
+    onClickLeft() {
+      if (this.$route.query.urltype == 1) {
+        window.location.replace(window.location.origin + '/mobile/home');
+      } else {
+        // 返回上一页不会刷新页面
+        this.$router.go(-1);
+      }
+    },
+    onshouow() {
+      this.uploadshow = false;
+      this.questionsshow = false;
+    },
+    uploadImgEdit() {
+      if (this.uploadImgEditText == '编辑') {
+        this.uploadImgEditText = '完成';
+      } else {
+        this.uploadImgEditText = '编辑';
+        this.uploadImgshow = false;
+      }
+    },
+    deleteImg(index) {
+      this.imgs.splice(index, 1);
+    },
+    questionClick(item) {
+      console.log(item);
+      if (item.isUpload) {
+        this.uploadshow = true;
+      } else if (item.isQuestion) {
+        this.questionsshow = true;
+      }
+    },
+    endVisitsFn() {
+      if (this.list.length == 0) {
+        this.$toast('暂无任务提交');
+        return;
+      }
+      for (var vl = 0; vl < this.list.length; vl++) {
+        if (this.list[vl].isMust == '0') {
+          if (!this.list[vl].success) {
+            this.$toast(this.list[vl].taskName + '任务未完成');
+            return;
+          }
+        }
+      }
+      let loading1 = this.$toast.loading({
+        duration: 0,
+        message: '加载中...',
+        forbidClick: true,
+      });
+      let dwellTime = this.weekend(localStorage.getItem('startTime'), new Date());
+      let storeCode = this.storeCode;
+      if (this.$route.query.shopCode != undefined) {
+        storeCode = this.$route.query.shopCode;
+      }
+      if (this.flag) {
+        this.flag = false;
+        this.timer = null;
+        this.timer = setTimeout(() => {
+          this.flag = true;
+        }, 5000);
+        endVisits({
+          visitSource: '1',
+          storeGroupId: this.storeGroupId,
+          id: this.visitId,
+          storeCode: storeCode,
+          dwellTime: dwellTime,
+          visitModel: this.$route.query.visitModel,
+        }).then((res) => {
+          this.flag = true;
+          loading1.clear();
+          if (res.code == 200) {
+            this.editDwellTimes();
+            store.dispatch('setDeviceOutsidePage', true);
+            if (this.$route.query.linkType == 6) {
+              window.location.replace(window.location.origin + '/mobile/topStore?info=y');
+            } else {
+              if (this.$route.query.urltype == 1) {
+                window.location.replace(window.location.origin + '/mobile/home');
+              } else {
+                this.onClickLeft();
+                // window.location.replace(
+                //   window.location.origin + '/mobile/outsidelist/index?info=y'
+                // );
+              }
+            }
+          } else {
+            this.$toast({
+              message: res.msg,
+              duration: 5000,
+            });
+          }
+        });
+      }
+    },
+    newimgarr1(val) {
+      this.imgs = val;
+    },
+    uploadImgShowFn() {
+      this.uploadImgshow = true;
+      if (this.uploadImages.length <= 0) {
+        this.uploadImgEditText = '';
+      }
+    },
+    previewsImg(index) {
+      ImagePreview({
+        images: this.uploadImages,
+        startPosition: index,
+        onClose() {
+          // do something
+        },
+      });
+    },
+  },
+  destroyed() {
+    this.timeN = null;
+    clearInterval(this.timeN);
+  },
+};
+</script>
+<style lang="scss" scoped>
+.visitPage {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+  .container {
+    overflow-y: auto;
+    flex: 1;
+    margin-bottom: 10px;
+    background-color: white;
+  }
+}
+.navBarOverlay {
+  background: #fff;
+}
+.card {
+  background: #fff;
+  box-sizing: border-box;
+  padding: 10px 16px;
+  .title {
+    line-height: 32px;
+    font-size: 16px;
+    font-weight: bold;
+    color: #333;
+  }
+  .subtitle {
+    line-height: 24px;
+    font-size: 14px;
+    color: #7b7b7b;
+    .status {
+      float: right;
+    }
+  }
+  .info {
+    font-size: 14px;
+    color: #484848;
+    padding: 14px;
+    border-bottom: 1px solid #f1f1f1;
+    position: relative;
+    .arrow {
+      float: right;
+      display: inline-block;
+      height: 20px;
+      width: 20px;
+      line-height: 20px;
+      text-align: center;
+      border-radius: 50%;
+      background: #0057ba;
+      color: #fff;
+      font-weight: bold;
+      font-size: 14px;
+      position: absolute;
+      margin-top: -10px;
+      right: 0;
+      top: 50%;
+    }
+  }
+  .info1 {
+    font-size: 14px;
+    color: #666;
+    line-height: 18px;
+    padding: 4px 0;
+    position: relative;
+    .arrow {
+      float: right;
+      display: inline-block;
+      height: 20px;
+      width: 20px;
+      line-height: 20px;
+      text-align: center;
+      border-radius: 50%;
+      background: #0057ba;
+      color: #fff;
+      font-weight: bold;
+      font-size: 14px;
+      margin-top: 9px;
+      position: absolute;
+      right: 0;
+      top: 50%;
+      margin-top: -10px;
+    }
+  }
+}
+.must {
+  font-size: 18px;
+  color: #f56c6c;
+  margin-right: 2px;
+}
+.zw {
+  display: inline-block;
+  width: 7px;
+  height: 100%;
+}
+.lineGrey {
+  height: 10px;
+  width: 100%;
+  background: #f1f1f1;
+}
+.submitBtn {
+  margin: 16px 0;
+  font-size: 18px;
+}
+.wrapper {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 100%;
+  .block {
+    width: 100%;
+    height: 100%;
+    background-color: #fff;
+    overflow: auto;
+  }
+}
+.questionName {
+  font-size: 16px;
+  color: #484848;
+  /*line-height: 40px;*/
+  background: #f4f4f4;
+  padding: 10px 15px;
+  box-sizing: border-box;
+  position: relative;
+  display: flex;
+  justify-content: center;
+  .text {
+    flex: 9;
+  }
+}
+.answerDiv {
+  background: #fff;
+  padding: 0 15px 10px;
+  .answerItem {
+    padding: 10px 0;
+    border-bottom: 1px solid #dedede;
+    .name {
+      line-height: 36px;
+      font-size: 14px;
+      color: #8b8b8b;
+    }
+  }
+}
+.border {
+  border: 1px solid #dedede;
+}
+.ht30 {
+  height: 30px;
+}
+.bodrder-b {
+  border-bottom: 1px solid #dedede;
+}
+.img-box {
+  width: 50%;
+  /*height: 100%;*/
+  position: relative;
+  padding: 10px;
+  display: inline-block;
+  i {
+    position: absolute;
+    right: 2px;
+    top: 2px;
+  }
+  img {
+    width: 100%;
+    height: 100%;
+  }
+}
+.imgNull {
+  text-align: center;
+  padding-top: 100px;
+  i {
+    color: #dedede;
+  }
+  div {
+    padding-top: 30px;
+    font-size: 18px;
+    font-weight: bold;
+  }
+}
+.card .f-blue {
+  color: #0057ba;
+}
+</style>
+<style>
+.navBarOverlay .van-nav-bar__left .van-icon {
+  color: #8b8b8b;
+}
+.navBarOverlay .van-nav-bar__right .van-nav-bar__text {
+  color: #333;
+}
+.ht30 .van-radio__label {
+  color: #8b8b8b;
+}
+.van-dialog__confirm,
+.van-dialog__confirm:active {
+  color: #0057ba;
+}
+#allmap {
+  width: 20px;
+  height: 20px;
+  left: -1000px;
+  position: relative;
+}
+</style>

Datei-Diff unterdrückt, da er zu groß ist
+ 4848 - 0
src/views/home/visitTask.vue


src/views/home/login.vue → src/views/login.vue