Pārlūkot izejas kodu

Merge branch 'feature_20260108_陈列奖励案任务合并' into release

zhujindu 4 dienas atpakaļ
vecāks
revīzija
fb81bfa8e4

+ 36 - 0
src/api/index.js

@@ -1115,3 +1115,39 @@ export function confirmPhone(query) {
     params: query,
   });
 }
+
+// 陈列奖励案门店获取拜访详情
+export function getCollectionInfosBatch(data) {
+  return request({
+    url: 'mobile/storeGroup/getCollectionInfosBatch',
+    method: 'post',
+    data: data,
+  });
+}
+
+// 陈列奖励按拜访拍照
+export function addPhotoBatch(data) {
+  return request({
+    url: 'mobile/storeGroup/addPhotoBatch',
+    method: 'post',
+    data: data,
+  });
+}
+
+// 陈列奖励案拜访照片删除
+export function removePhotoBatch(data) {
+  return request({
+    url: 'mobile/storeGroup/removePhotoBatch',
+    method: 'post',
+    data: data,
+  });
+}
+
+//
+export function addCollectionAnswerBatch(data) {
+  return request({
+    url: 'mobile/storeGroup/addCollectionAnswerBatch',
+    method: 'post',
+    data,
+  });
+}

+ 185 - 0
src/components/deleteUploadImgTaskPhoto.vue

@@ -0,0 +1,185 @@
+<template>
+  <div class="deleteUploadImgTaskPhoto">
+    <van-row gutter="10">
+      <van-col span="6" style="background: #f5f5f5" v-if="insert == '1'">
+        <div class="addImg">
+          <uploadVNormalTaskPhoto
+            :imgArr="imgs"
+            :shouws="true"
+            :storeGroupId="storeGroupId"
+            :taskList="taskIds.split(',')"
+            :collectionItemId="collectionItemId"
+            :visitModel="1 + ''"
+            :visitsId="visitsId"
+            :putInCode="putInCode"
+            :photoIdentifyType="photoIdentifyType"
+            :pictureSource="pictureSource"
+            :continuousShoot="continuousShoot"
+            :objectType="objectType"
+            @newimgarr="newimgarr"
+            ref="uploadVNormal" />
+        </div>
+      </van-col>
+      <van-col span="6" v-for="(urls, index) in imgs" :key="urls.id">
+        <div class="imgview">
+          <van-icon
+            v-if="(photoIdentifyType != 6 || photoIdentifyType != 7) && insert == '1'"
+            name="close"
+            size="16"
+            v-on:click="deleteImg(index, urls.fileIdSplicing)" />
+          <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 { removePhotoBatch } from '@/api/index';
+import uploadVNormalTaskPhoto from '@/components/uploadVNormalTaskPhoto';
+export default {
+  name: 'deleteUploadImgTaskPhoto',
+  components: { uploadVNormalTaskPhoto },
+  props: {
+    imgs: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    photoIdentifyType: {
+      // 图匠识别目的(1:店招内容识别,2:门店代码识别,3:调色机识别,4:更换店招,6:sku陈列照)
+      type: String,
+      default: '',
+    },
+    storeGroupId: {
+      type: String,
+    },
+    taskIds: {
+      type: [Array, String],
+      default() {
+        return [];
+      },
+    },
+    collectionItemId: {
+      type: [String, Number],
+    },
+    visitsId: {
+      type: String,
+      default: '',
+    },
+    putInCode: {
+      type: String,
+      default: '',
+    },
+    pictureSource: {
+      // 是否允许从相册选择图片 1:允许;0:不允许
+      type: String,
+      default: '0',
+    },
+    continuousShoot: {
+      // 是否允许连拍/相册多选 1:允许;0:不允许
+      type: String,
+      default: '0',
+    },
+    objectType: {
+      type: String,
+      default: '',
+    },
+    insert: {
+      type: String,
+      default: '0',
+    },
+  },
+  watch: {
+    imgs: {
+      handler(val) {},
+      deep: true,
+      immediate: true,
+    },
+  },
+  data() {
+    return {
+      url: process.env.VUE_APP_Target1 + process.env.VUE_APP_BASE_API,
+    };
+  },
+  methods: {
+    deleteImg(index, fileIdList) {
+      removePhotoBatch({ fileIdList: fileIdList.split(',') }).then((res) => {
+        if (res.code == 200) {
+          this.$toast('删除成功!');
+          this.$emit('upDataDetail');
+        } 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
+        },
+      });
+    },
+    newimgarr() {
+      this.$emit('upDataDetail');
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.deleteUploadImgTaskPhoto {
+}
+.addImg {
+  width: 100%;
+  height: 72px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.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>

+ 539 - 0
src/components/uploadVNormalTaskPhoto.vue

@@ -0,0 +1,539 @@
+<template>
+  <div class="questionNamep">
+    <!-- 0=企业微信,1=H5相机 -->
+    <!-- 企业微信拍照 -->
+    <div class="cameraDiv" @click="uploadImg" v-if="userInfo.photoMethod == '0'">
+      <van-icon class="photo photos" name="plus" size="22px" color="#969696" />
+    </div>
+    <!-- 原生自带拍照 -->
+    <H5Camera
+      @getImg="getImg"
+      ref="H5Camera"
+      :objectType="objectType"
+      :capture="pictureSource == '1' ? '' : 'camera'"
+      v-else />
+    <div id="allmap"></div>
+    <imageAIVerifyErr
+      v-if="imageAIVerifyFlag"
+      :imageAIVerifyFlag="imageAIVerifyFlag"
+      :imageAIVerifyData="imageAIVerifyData"
+      @confirmUpload="confirmUpload"
+      @uploadImgFun="uploadImgFun"
+      :source="'visit'"
+      @normalFlow="normalFlow"
+      @close="close"></imageAIVerifyErr>
+    <!-- 图像识别白名单弹框提示 -->
+    <imageWhiteStore
+      v-if="imageWhiteStoreFlag"
+      :imageWhiteStoreFlag="imageWhiteStoreFlag"
+      :imageWhiteStoreData="imageWhiteStoreData"
+      @normalFlow="normalFlow"
+      @close="close">
+    </imageWhiteStore>
+  </div>
+</template>
+
+<script>
+import { addPhotoBatch, addVisitsPosition, addPhotoToDB } from '@/api/index';
+import imageAIVerifyErr from './imageAIVerifyErr';
+import imageWhiteStore from './imageWhiteStore';
+import H5Camera from '@/components/H5Camera';
+import axios from 'axios';
+import uploadAliOss from '@/utils/uploadAliOss';
+import { addH5Photo } from '@/api/H5Camera';
+import { mapState } from 'vuex';
+
+export default {
+  name: 'uploadImg',
+  components: { imageAIVerifyErr, H5Camera, imageWhiteStore },
+  props: {
+    storeGroupId: {
+      type: String,
+      default: '',
+    },
+    visitsId: {
+      type: String,
+      default: '',
+    },
+    taskList: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    objectType: {
+      type: String,
+      default: '',
+    },
+    putInCode: {
+      type: String,
+      default: '',
+    },
+    photoIdentifyType: {
+      // 图匠识别目的(1:店招内容识别(不能连拍和多选),3:调色机识别(不能连拍和多选),6:陈列SKU图片识别(不需要图匠实时识别))
+      type: String,
+      default: '',
+    },
+    pictureSource: {
+      // 是否允许从相册选择图片 1:允许;0:不允许
+      type: String,
+      default: '0',
+    },
+    continuousShoot: {
+      // 是否允许连拍/相册多选 1:允许;0:不允许
+      type: String,
+      default: '0',
+    },
+    collectionItemId: {
+      type: [String, Number],
+      default: '',
+    },
+    // uploadid: {
+    //   type: String,
+    //   default: '',
+    // },
+    // secondCollectionId: {
+    //   type: [String, Number],
+    //   default: '',
+    // },
+    // firstCollectionId: {
+    //   type: String,
+    //   default: '',
+    // },
+    // fourthCollectionId: {
+    //   type: String,
+    //   default: '',
+    // },
+    // thirdCollectionId: {
+    //   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: '',
+    // },
+    // equipmentCode: {
+    //   // 当前任务对应的资产编号
+    //   type: String,
+    //   default: '',
+    // },
+    // inStore: {
+    //   // 调色机是否在店
+    //   type: String,
+    //   default: '否',
+    // },
+  },
+  computed: {
+    ...mapState({
+      userInfo: (state) => state.user.userInfo,
+    }),
+  },
+  data() {
+    return {
+      shows: false,
+      url: '',
+      imageAIVerifyFlag: false,
+      imageAIVerifyData: null, //图匠校验返回的数据
+      mediaId: '', //当前上传图片id
+      addressesRemark: '', //当前位置信息
+      controller: null, //取消请求状态
+      fileUrl: '',
+      imageWhiteStoreData: null,
+      imageWhiteStoreFlag: false,
+      localIdsArr: [],
+    };
+  },
+  methods: {
+    // 原生H5拍照图片
+    // url: base64
+    getImg(base64) {
+      // 图片名称:用户名-时间戳
+      let username = localStorage.getItem('loginName');
+      let imgName = username + '-' + new Date().getTime();
+      uploadAliOss(base64, imgName)
+        .then((res) => {
+          if (res.url && res.url.indexOf('http') != -1) {
+            this.fileUrl = res.url;
+            this.uploadImagev();
+          }
+        })
+        .catch((err) => {
+          console.log('err:' + err);
+        });
+    },
+    uploadImgFun() {
+      // 0=企业微信,1=H5相机
+      if (this.userInfo.photoMethod == '0') {
+        this.uploadImg();
+      } else {
+        this.$refs.H5Camera.camera();
+      }
+    },
+    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([]);
+
+      let url = window.location.href;
+      let that = this;
+      let wx = this.wx;
+      let qiyeData;
+      this.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;
+                      that.addressesRemark = addresses.recommend;
+                    },
+                    function (err) {
+                      that.addressesRemark = '';
+                    }
+                  );
+                },
+                fail: function () {
+                  that.$dialog.alert({
+                    message: 'GPS未开启',
+                  });
+                },
+              });
+              console.log(that.pictureSource);
+              let sourceType = that.pictureSource == '1' ? ['album', 'camera'] : ['camera'];
+              let count = 1;
+              // 1:店招内容识别(不能连拍和多选),3:调色机识别(不能连拍和多选) 需要实时识别的不支持连拍和多选
+              if (that.photoIdentifyType != 1 && that.photoIdentifyType != 3) {
+                count = that.continuousShoot == '1' ? 5 : 1; //是否允许连拍/相册多选 最多5张
+              }
+              wx.chooseImage({
+                count: count,
+                sizeType: ['original'], // 可以指定是原图还是压缩图,默认二者都有
+                sourceType: sourceType, // 可以指定来源是相册还是相机,默认二者都有
+                defaultCameraMode: count == 1 ? 'normal' : 'batch', //表示进入拍照界面的默认模式,目前有normal与batch两种选择,normal表示普通单拍模式,batch表示连拍模式,不传该参数则为normal模式。从3.0.26版本开始支持front和batch_front两种值,其中front表示默认为前置摄像头单拍模式,batch_front表示默认为前置摄像头连拍模式。(注:用户进入拍照界面仍然可自由切换两种模式)
+                // defaultCameraMode: 'normal', //表示进入拍照界面的默认模式,目前有normal与batch两种选择,normal表示普通单拍模式,batch表示连拍模式,不传该参数则为normal模式。从3.0.26版本开始支持front和batch_front两种值,其中front表示默认为前置摄像头单拍模式,batch_front表示默认为前置摄像头连拍模式。(注:用户进入拍照界面仍然可自由切换两种模式)
+                isSaveToAlbum: 0, //整型值,0表示拍照时不保存到系统相册,1表示自动保存,默认值是1
+                success: function (res) {
+                  let localIds = res.localIds;
+                  that.localIdsArr = [];
+                  that.syncUpload(localIds);
+                  // var localIds = '';
+                  // if (res.localIds != undefined) {
+                  //   localIds = res.localIds[0];
+                  // } else {
+                  //   localIds = res.localId;
+                  // }
+                  // wx.uploadImage({
+                  //   localId: localIds, // 需要上传的图片的本地ID,由chooseImage接口获得
+                  //   isShowProgressTips: 0, // 默认为1,显示进度提示
+                  //   success: function (res) {
+                  //     that.mediaId = res.serverId;
+                  //     that.uploadImagev(addressesRemark);
+                  //   },
+                  //   fail: (err) => {
+                  //     that.$toast(err.errMsg);
+                  //     that.$toast(err.errCode);
+                  //   },
+                  // });
+                },
+              });
+            });
+          }
+        });
+    },
+    syncUpload(localIds) {
+      if (!localIds.length) {
+        this.uploadImagev();
+      } else {
+        var localId = localIds.pop();
+        wx.uploadImage({
+          localId: localId,
+          isShowProgressTips: 1, // 默认为1,显示进度提示
+          success: (res) => {
+            this.localIdsArr.push(res.serverId);
+            this.syncUpload(localIds);
+          },
+        });
+      }
+    },
+    uploadImagev() {
+      this.close();
+      var that = this;
+      var form = {
+        // mediaIds: [],
+        // fileUrl: '',
+        // objectType: that.objectType,
+        // storeGroupId: that.storeGroupId,
+        // taskList: that.taskList,
+        // visitsId: that.visitsId,
+        // visitSource: '1',
+        // locationRemark: that.addressesRemark,
+        // deviceCode: that.deviceCode, //设备编号
+        // putInCode: that.putInCode, //投放编号
+        // equipmentCode: that.equipmentCode,
+        // inStore: that.inStore,
+
+        mediaIds: [], //	是	List<String>	图片素材id集合
+        visitSource: '1', //	是	Long	拜访模式
+        storeGroupId: that.storeGroupId, //	是	string	门店任务组,多个用逗号隔开
+        visitsId: that.visitsId, //	是	string	拜访id
+        taskList: that.taskList, //	是	List	任务id数组
+        collectionItemId: that.collectionItemId, //	是	string	采集项id
+        objectType: that.objectType, //	是	string	照片类型,取任务上的照片类型,如果没有则取手动选择的照片类型
+        locationRemark: that.addressesRemark, //	是	String	当前地址信息
+        firstCollectionId: '', //	否	Long	第一级采集项id,取当前采集项的字段就行
+        secondCollectionId: '', //	否	Long	第二级采集项id,取当前采集项的字段就行
+        putInCode: that.putInCode, //投放编号
+        deviceCode: '', //	否	String	当前任务对应的设备编号
+        photoIdentifyType: that.photoIdentifyType, //	否	String	图片识别类型:字典-photo_identify_type
+        equipmentCode: '', //	否	String	当前任务对应的资产编号
+        inStore: '否', //	否	String	机器是否在店:传选项中文内容,是、否
+      };
+      // 0=企业微信,1=H5相机
+      if (this.userInfo.photoMethod == '0') {
+        form.mediaIds = this.localIdsArr; //	string	图片素材id
+      } else {
+        form.fileUrl = this.fileUrl; //	string	图片素材id
+      }
+      this.controller = null;
+      // 需要图匠校验的添加参数和loading
+      if (
+        this.photoIdentifyType &&
+        (this.photoIdentifyType == '1' || this.photoIdentifyType == '3')
+      ) {
+        form.photoIdentifyType = this.photoIdentifyType;
+        this.controller = new AbortController(); //取消请求
+      } else {
+        this.toastLoading(0, '上传中...', true);
+      }
+      addPhotoBatch(form, this.controller ? this.controller.signal : null)
+        .then((res) => {
+          this.requestThen(res);
+        })
+        .catch((error) => {
+          this.requestCatch(error);
+        });
+    },
+    // 公用请求then
+    requestThen(res) {
+      this.toastLoading().clear();
+      if (res.code == -1) {
+        // 图匠图片校验接口超时
+        this.requestTimeOut(res);
+      } else if (res.code == 200) {
+        // 图匠校验结果返回
+        if (
+          this.photoIdentifyType &&
+          (this.photoIdentifyType == '1' || this.photoIdentifyType == '3')
+        ) {
+          this.imageAIVerifyFlag = true;
+          this.imageAIVerifyData = res.data[0];
+        } else {
+          // 正常流程
+          // 图像识别白名单用户弹出框提示
+          if (res.data[0].whiteStore) {
+            this.imageWhiteStoreFlag = true;
+            this.imageWhiteStoreData = res.data[0];
+          } else {
+            this.normalFlow(res);
+          }
+        }
+      } else {
+        that.$toast('上传失败!');
+      }
+    },
+    // 公用请求catch
+    requestCatch(error) {
+      if (error.message === 'canceled') {
+        this.$toast('取消上传');
+        console.log('请求被取消:', error.message);
+      }
+    },
+    // 正常流程
+    normalFlow(res) {
+      this.$toast('上传成功!');
+      let fileInfoList = [];
+      res.data.forEach((val) => {
+        fileInfoList.push({
+          fileUrl: val.url,
+          id: val.fileId,
+          type: 2,
+        });
+      });
+      this.$emit('newimgarr', {
+        fileInfoList: fileInfoList,
+        // fileUrl: res.data.url,
+        // id: res.data.fileId,
+        // type: 2,
+        photoIdentifyType: this.photoIdentifyType,
+      });
+    },
+    // 照片是否入库,1.照片识别三次不通过仍要上传,2.照片识别通过
+    // isUpdate:是否更新店招照片,只有门店店招需要更新
+    confirmUpload(res) {
+      if (
+        this.photoIdentifyType &&
+        (this.photoIdentifyType != '6' || this.photoIdentifyType != '7')
+      ) {
+        var form = {
+          // mediaIds: [],
+          // fileUrl: '',
+          // objectType: that.objectType,
+          // visitSource: '1', //	Long	拜访模式
+          // storeGroupId: this.storeGroupId, //	string	门店任务组,多个用逗号隔开
+          // visitsId: that.visitsId,
+          // taskList: this.taskList, //	string	任务id
+          // locationRemark: this.addressesRemark, //	String	当前地址信息
+          // // firstCollectionId: this.firstCollectionId, //	Long	第一级采集项id,取当前采集项的字段就行
+          // // secondCollectionId: this.secondCollectionId, //	Long	第二级采集项id,取当前采集项的字段就行
+          // // putInCode: this.putInCode, //	String	当前任务对应的投放编号
+          // // deviceCode: this.deviceCode, //	String	当前任务对应的设备编号
+          // url: res.data.url, //	String	当前拍摄图片的url
+          // businessId: res.data.businessId, // 当前拍摄图片id
+          // feedbackMessage: res.feedbackMessage,
+          // equipmentCode: this.equipmentCode,
+          // inStore: this.inStore,
+          mediaIds: [], //	是	List<String>	图片素材id集合
+          visitSource: '1', //	是	Long	拜访模式
+          storeGroupId: this.storeGroupId, //	是	string	门店任务组,多个用逗号隔开
+          visitsId: that.visitsId, //	是	string	拜访id
+          taskList: this.taskList, //	是	List	任务id数组
+          collectionItemId: that.collectionItemId, //	是	string	采集项id
+          objectType: that.objectType, //	是	string	照片类型,取任务上的照片类型,如果没有则取手动选择的照片类型
+          locationRemark: this.addressesRemark, //	是	String	当前地址信息
+          firstCollectionId: '', //	否	Long	第一级采集项id,取当前采集项的字段就行
+          secondCollectionId: '', //	否	Long	第二级采集项id,取当前采集项的字段就行
+          putInCode: that.putInCode, //投放编号
+          deviceCode: '', //	否	String	当前任务对应的设备编号
+          photoIdentifyType: that.photoIdentifyType, //	否	String	图片识别类型:字典-photo_identify_type
+          equipmentCode: '', //	否	String	当前任务对应的资产编号
+          inStore: '否', //	否	String	机器是否在店:传选项中文内容,是、否
+        };
+        // 0=企业微信,1=H5相机
+        if (this.userInfo.photoMethod == '0') {
+          form.mediaIds = this.localIdsArr; //	string	图片素材id
+        } else {
+          form.fileUrl = this.fileUrl; //	string	图片素材id
+        }
+        if (res.isUpdate) {
+          form.isUpdate = 'true';
+        }
+        addPhotoToDB(form).then((resData) => {
+          if (resData.code == 200) {
+            console.log(resData);
+            res.data.fileId = resData.data[0].fileId;
+            res.data = [res.data];
+            this.normalFlow(res);
+          }
+        });
+      }
+    },
+    close() {
+      this.imageAIVerifyFlag = false;
+      this.imageWhiteStoreFlag = false;
+    },
+    requestTimeOut(res) {
+      this.close();
+      this.$dialog
+        .confirm({
+          title: '系统提示',
+          message: res.msg,
+          showCancelButton: false,
+        })
+        .then(() => {
+          this.confirmUpload(res);
+        });
+    },
+  },
+};
+</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;
+    }
+  }
+}
+#allmap {
+  width: 10px;
+  height: 10px;
+  left: -1000px;
+  position: absolute;
+}
+</style>

+ 5 - 1
src/router/index.js

@@ -305,7 +305,11 @@ const router = new VueRouter({
           name: 'addStoreVisit',
           component: () => import('@/views/deviceWithin/addStoreVisit.vue'),
         },
-
+        {
+          path: '/taskPhotoTaking',
+          name: 'taskPhotoTaking',
+          component: () => import('@/views/deviceWithin/taskPhotoTaking.vue'),
+        },
         {
           path: '/addStoreVisitd',
           name: 'addStoreVisitd',

+ 61 - 27
src/views/deviceOutside/suishenbangOutstoreVisit.vue

@@ -526,7 +526,7 @@ export default {
               localStorage.setItem('visitId', res.data.visitId);
               that.notes = res.data.notes;
               that.visitId = res.data.visitId;
-              that.list = res.data.sfaTaskList;
+              that.list = that.filterSfaTaskList(res.data.sfaTaskList);
               that.storeGroupId = res.data.storeGroupId;
               that.showOrderButton = res.data.showOrderButton;
               that.startTime = res.data.startTime;
@@ -579,7 +579,7 @@ export default {
               localStorage.setItem('visitId', res.data.visitId);
               that.notes = res.data.notes;
               that.visitId = res.data.visitId;
-              that.list = res.data.sfaTaskList;
+              that.list = that.filterSfaTaskList(res.data.sfaTaskList);
               that.storeGroupId = res.data.storeGroupId;
               that.showOrderButton = res.data.showOrderButton;
               that.startTime = res.data.startTime;
@@ -603,34 +603,68 @@ export default {
         }
       );
     },
+    filterSfaTaskList(list) {
+      let taskTypeArr = list.filter((val) => val.taskType !== '5');
+      let taskType5Index = list.findIndex((val) => val.taskType == '5');
+      if (taskType5Index != -1) {
+        let taskType5Arr = list.filter((val) => val.taskType == '5');
+        let taskIds = [];
+        taskType5Arr.forEach((val) => {
+          taskIds.push(val.taskId);
+        });
+        let taskType5 = {
+          ...list[taskType5Index],
+          taskIds: taskIds,
+        };
+        taskType5.taskName = '生动化陈列';
+        taskTypeArr.splice(taskType5Index, 0, taskType5);
+      }
+      console.log(taskTypeArr);
+      return taskTypeArr;
+    },
     addStoreVisit(val, index) {
       localStorage.setItem('getRequestFlage', 'false');
       console.log(this.visitId);
-      this.$router.push({
-        path: '/addStoreVisit',
-        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,
-          deviceCode: val.deviceCode,
-          putInCode: val.putInCode,
-          equipmentCode: val.equipmentCode,
-          inspectionType: val.inspectionType,
-        },
-      });
+      if (val.taskType == '5') {
+        this.$router.push({
+          path: '/taskPhotoTaking',
+          query: {
+            storeCode: this.urlParameter.storeCode,
+            visitsId: this.visitId,
+            taskIds: val.taskIds.join(','),
+            storeGroupId: this.storeGroupId,
+            photoType: val.photoType,
+            insert: 1,
+            storeId: this.storeId,
+          },
+        });
+      } else {
+        this.$router.push({
+          path: '/addStoreVisit',
+          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,
+            deviceCode: val.deviceCode,
+            putInCode: val.putInCode,
+            equipmentCode: val.equipmentCode,
+            inspectionType: val.inspectionType,
+          },
+        });
+      }
     },
     onClickLeft() {
       localStorage.setItem('getRequestFlage', 'true');

+ 65 - 32
src/views/deviceWithin/storeVisit.vue

@@ -480,7 +480,7 @@ export default {
                   localStorage.setItem('visitId', res.data.visitId);
                   that.visitId = res.data.visitId;
                 }
-                that.list = res.data.sfaTaskList;
+                that.list = that.filterSfaTaskList(res.data.sfaTaskList);
                 that.storeGroupId = res.data.storeGroupId;
                 that.showOrderButton = res.data.showOrderButton;
                 that.startTime = res.data.startTime;
@@ -538,7 +538,7 @@ export default {
                   localStorage.setItem('visitId', res.data.visitId);
                   that.visitId = res.data.visitId;
                 }
-                that.list = res.data.sfaTaskList;
+                that.list = that.filterSfaTaskList(res.data.sfaTaskList);
                 that.storeGroupId = res.data.storeGroupId;
                 that.showOrderButton = res.data.showOrderButton;
                 that.startTime = res.data.startTime;
@@ -598,7 +598,7 @@ export default {
                   localStorage.setItem('visitId', res.data.visitId);
                   that.visitId = res.data.visitId;
                 }
-                that.list = res.data.sfaTaskList;
+                that.list = that.filterSfaTaskList(res.data.sfaTaskList);
                 that.storeGroupId = res.data.storeGroupId;
                 that.showOrderButton = res.data.showOrderButton;
                 that.startTime = res.data.startTime;
@@ -655,7 +655,7 @@ export default {
                   localStorage.setItem('visitId', res.data.visitId);
                   that.visitId = res.data.visitId;
                 }
-                that.list = res.data.sfaTaskList;
+                that.list = that.filterSfaTaskList(res.data.sfaTaskList);
                 that.storeGroupId = res.data.storeGroupId;
                 that.showOrderButton = res.data.showOrderButton;
                 that.startTime = res.data.startTime;
@@ -762,6 +762,25 @@ export default {
           }
         });
     },
+    filterSfaTaskList(list) {
+      let taskTypeArr = list.filter((val) => val.taskType !== '5');
+      let taskType5Index = list.findIndex((val) => val.taskType == '5');
+      if (taskType5Index != -1) {
+        let taskType5Arr = list.filter((val) => val.taskType == '5');
+        let taskIds = [];
+        taskType5Arr.forEach((val) => {
+          taskIds.push(val.taskId);
+        });
+        let taskType5 = {
+          ...list[taskType5Index],
+          taskIds: taskIds,
+        };
+        taskType5.taskName = '生动化陈列';
+        taskTypeArr.splice(taskType5Index, 0, taskType5);
+      }
+      console.log(taskTypeArr);
+      return taskTypeArr;
+    },
     addStoreVisit(val, index) {
       if (this.flag) {
         this.flag = false;
@@ -770,34 +789,48 @@ export default {
           this.flag = true;
         }, 2000);
         localStorage.setItem('getRequestFlage', 'false');
-        this.$router.push({
-          path: '/addStoreVisit',
-          query: {
-            visitSource: '1',
-            storeId: this.storeId,
-            storeCode: this.urlParameter.storeCode,
-            visitId: this.visitId,
-            ids: index,
-            taskId: val.taskId,
-            type: this.urlParameter.type,
-            storeGroupId: this.storeGroupId,
-            taskType: val.taskType,
-            photoType: val.photoType,
-            lat: this.lat,
-            lon: this.lon,
-            visitModel: this.visitModel,
-            locationCity: this.city,
-            locationRemark: this.address,
-            types: this.$route.query.type,
-            locationAccuracy: this.locationAccuracy,
-            insert: this.insert,
-            photoIdentifyType: val.photoIdentifyType,
-            deviceCode: val.deviceCode,
-            putInCode: val.putInCode,
-            equipmentCode: val.equipmentCode,
-            inspectionType: val.inspectionType,
-          },
-        });
+        if (val.taskType == '5') {
+          this.$router.push({
+            path: '/taskPhotoTaking',
+            query: {
+              storeCode: this.urlParameter.storeCode,
+              visitsId: this.visitId,
+              taskIds: val.taskIds.join(','),
+              storeGroupId: this.storeGroupId,
+              photoType: val.photoType,
+              insert: 1,
+            },
+          });
+        } else {
+          this.$router.push({
+            path: '/addStoreVisit',
+            query: {
+              visitSource: '1',
+              storeId: this.storeId,
+              storeCode: this.urlParameter.storeCode,
+              visitId: this.visitId,
+              ids: index,
+              taskId: val.taskId,
+              type: this.urlParameter.type,
+              storeGroupId: this.storeGroupId,
+              taskType: val.taskType,
+              photoType: val.photoType,
+              lat: this.lat,
+              lon: this.lon,
+              visitModel: this.visitModel,
+              locationCity: this.city,
+              locationRemark: this.address,
+              types: this.$route.query.type,
+              locationAccuracy: this.locationAccuracy,
+              insert: this.insert,
+              photoIdentifyType: val.photoIdentifyType,
+              deviceCode: val.deviceCode,
+              putInCode: val.putInCode,
+              equipmentCode: val.equipmentCode,
+              inspectionType: val.inspectionType,
+            },
+          });
+        }
       }
       // this.$router.push({path: "/addStoreVisit", query:
       // 		{storeId:this.storeId,storeCode:that.urlParameter.storeCode,visitId:this.visitId,ids:index,taskId:val.taskId,storeGroupId:this.storeGroupId,taskType:val.taskType,photoType:val.photoType}})

+ 336 - 0
src/views/deviceWithin/taskPhotoTaking.vue

@@ -0,0 +1,336 @@
+<template>
+  <div class="taskPhotoTaking">
+    <van-nav-bar class="navBar" left-arrow title="拜访任务" @click-left="onClickLeft">
+      <template #right>
+        <span
+          v-if="isEdit && insert == '1'"
+          @click="onSubmit"
+          style="
+            color: white;
+            background: rgb(0, 87, 186);
+            display: block;
+            padding: 6px 10px;
+            border-radius: 6px;
+          "
+          >保存</span
+        >
+      </template>
+    </van-nav-bar>
+    <div class="content" v-if="formData">
+      <div class="container">
+        <van-form ref="tabstoreVal">
+          <div v-for="(item, index) in formData.collectionItemList" :key="index">
+            <div v-if="item.answerType == 'zp'" class="formLabel z-cell">
+              <van-cell>
+                <template #title>
+                  <span v-if="item.isMust == 0" class="van-f-red">*</span>
+                  <span>1.</span>
+                  {{ item.collectionName }}
+                  <!-- 操作说明图片和电话 -->
+                  <taskTips
+                    v-if="item.contactPhone || item.examplePhoto"
+                    :contactPhone="item.contactPhone"
+                    :examplePhoto="item.examplePhoto">
+                  </taskTips>
+                </template>
+              </van-cell>
+              <delete-upload-img
+                :imgs="item.fileInfoList"
+                :storeGroupId="storeGroupId"
+                :taskIds="taskIds"
+                :visitsId="visitsId"
+                :collectionItemId="item.collectionId"
+                :putInCode="formData.putInCode"
+                :photoIdentifyType="formData.photoIdentifyType"
+                @upDataDetail="getDetaile"
+                :pictureSource="item.pictureSource"
+                :continuousShoot="item.continuousShoot"
+                :insert="insert"
+                :objectType="objectType"></delete-upload-img>
+            </div>
+          </div>
+        </van-form>
+      </div>
+      <div class="dataList" v-if="dataList">
+        <div class="dataItem" v-for="(item, index) in dataList">
+          <div class="itemTop">
+            <div class="itemIndex">
+              <p>{{ index + 1 }}、</p>
+            </div>
+            <div v-html="item.displayInstructions"></div>
+          </div>
+          <div class="itemBottom" v-if="insert == '0'">
+            <img
+              @click="openDialog(item)"
+              :src="
+                item.taskPhotoConditionPassed == 1
+                  ? require('@/assets/taskPhotoSu.png')
+                  : require('@/assets/taskPhotoErr.png')
+              " />
+            <!-- <img
+              v-if="item.taskPhotoConditionPassed == 0"
+              :src="require('@/assets/taskPhotoErr.png')" /> -->
+          </div>
+        </div>
+      </div>
+    </div>
+    <el-dialog
+      title="识别结果"
+      :visible.sync="vanPopup"
+      width="80%"
+      :append-to-body="true"
+      :close-on-click-modal="false"
+      @close="vanPopup == false"
+      custom-class="identifyResultdialog">
+      <!-- 识别结果 -->
+      <div class="identifyResult" v-if="taskPhotoRecognitionResult" style="padding: 0 10px">
+        <div class="resultContent">
+          <el-table
+            :data="taskPhotoRecognitionResult"
+            border
+            class="table-headermd1"
+            style="width: 100%">
+            <el-table-column label="" type="index" width="50px" align="center" />
+            <el-table-column label="产品" prop="skuProductName" align="center" />
+            <el-table-column label="要求" prop="conditionIdentifyNum" align="center" width="60px">
+            </el-table-column>
+            <el-table-column
+              label="识别排面数"
+              prop="identifyTheNumberOfCards"
+              width="70px"
+              align="center"
+              >meetTheStandard
+              <template slot-scope="scope">
+                <span :style="{ color: scope.row.meetTheStandard == 1 ? '#07c160' : 'red' }">
+                  {{ scope.row.identifyTheNumberOfCards }}
+                </span>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import { getCollectionInfosBatch, addCollectionAnswerBatch, getVisitsDetail } from '@/api/index';
+import taskTips from './taskTips';
+import deleteUploadImg from '@/components/deleteUploadImgTaskPhoto';
+export default {
+  name: 'abnortaskPhotoTakingmalVisit',
+  components: { taskTips, deleteUploadImg },
+  data() {
+    return {
+      isEdit: true,
+      formData: null,
+      dataList: null,
+      taskIds: [],
+      visitsId: null,
+      storeGroupId: '',
+      objectType: '',
+      insert: '',
+      vanPopup: false,
+      taskPhotoRecognitionResult: null,
+    };
+  },
+  activated() {
+    this.taskIds = this.$route.query.taskIds || [];
+    this.visitsId = this.$route.query.visitsId || '';
+    this.storeGroupId = this.$route.query.storeGroupId || '';
+    this.objectType = this.$route.query.photoType || '';
+    this.insert = this.$route.query.insert;
+    if (this.$route.query.source == 'historicalDetails') {
+      this.getVisitsDetailFun();
+    } else {
+      this.getDetaile();
+    }
+  },
+  methods: {
+    getVisitsDetailFun() {
+      this.toastLoading(0, '加载中...', true);
+      getVisitsDetail({ visitsId: this.visitsId }).then((res) => {
+        this.toastLoading().clear();
+        if (res.data.sfaTaskList) {
+          this.dataList = res.data.sfaTaskList.filter((val) => val.taskType == '5');
+          this.formData = this.dataList[0];
+        } else {
+          this.formData = null;
+        }
+      });
+    },
+    getDetaile() {
+      console.log(this.$route.query);
+      getCollectionInfosBatch({
+        storeCode: this.$route.query.storeCode,
+        insert: this.insert == '1' ? true : false,
+        id: this.visitsId,
+        taskIds: this.taskIds.split(','),
+      }).then((res) => {
+        if (res.data && res.data.length) {
+          this.dataList = res.data;
+          this.formData = res.data[0];
+        } else {
+          this.formData = null;
+        }
+      });
+    },
+    openDialog(item) {
+      this.vanPopup = true;
+      this.taskPhotoRecognitionResult = item.taskPhotoRecognitionResult;
+    },
+    onSubmit() {
+      let formData = {
+        storeId: this.$route.query.storeId,
+        storeCode: this.$route.query.storeCode,
+        storeGroupId: this.$route.query.storeGroupId,
+        visitsId: this.visitsId,
+        taskList: this.taskIds.split(',').map((val) => Number(val)),
+        insert: true,
+        collectionAnswers: [],
+        checkUnManage: 'N',
+        deviceCode: '',
+        putInCode: '',
+        equipmentCode: '',
+      };
+      addCollectionAnswerBatch(formData).then((res) => {
+        if (res.code == 200) {
+          localStorage.setItem('getRequestFlage', 'true');
+          this.$router.go(-1);
+        }
+      });
+    },
+    onClickLeft() {
+      this.$router.go(-1);
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.taskPhotoTaking {
+  display: flex;
+  flex-direction: column;
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  .content {
+    padding: 10px;
+    flex: 1;
+    width: 100%;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    padding-bottom: 46px;
+    .container {
+      background: #fff;
+      width: 100%;
+      border-radius: 6px;
+      padding: 10px;
+    }
+    .formLabel {
+      margin-left: 20px;
+      border-bottom: 1px solid #f1f1f1;
+    }
+    .formLabel .van-cell {
+      padding: 10px 0;
+    }
+    .formLabel .van-cell::after {
+      border: 0;
+    }
+    .formLabel .van-field {
+      border: 1px solid #f1f1f1;
+      padding: 6px;
+      width: 100%;
+      border-radius: 4px;
+      overflow: hidden;
+    }
+    .formLabel .van-field__control {
+      padding: 0 10px;
+    }
+    .formLabel .formLabeltitle {
+      position: absolute;
+      top: 8px;
+    }
+    .z-cell .van-cell__title {
+      font-size: 16px;
+    }
+    .van-f-red {
+      color: red;
+      width: 8px;
+      display: inline-block;
+      line-height: 26px;
+    }
+  }
+  .dataList {
+    width: 100%;
+    margin-top: 10px;
+    overflow-y: auto;
+    .dataItem {
+      display: flex;
+      background: #fff;
+      border-radius: 6px;
+      flex-direction: column;
+      margin-bottom: 10px;
+      padding: 10px;
+      font-size: 16px;
+      padding-left: 20px;
+      .itemIndex {
+      }
+      .itemTop {
+        flex: 1;
+      }
+      .itemTop,
+      .itemBottom {
+        display: flex;
+        flex-direction: row;
+      }
+      .itemBottom {
+        justify-content: end;
+      }
+    }
+  }
+}
+</style>
+<style lang="scss">
+.identifyResultdialog {
+  width: vw(690) !important;
+  margin-top: 1vh !important;
+  border-radius: 8px !important;
+  font-size: vw(32) !important;
+  height: 70% !important;
+  display: flex;
+  flex-direction: column;
+  .el-dialog__headerbtn {
+    width: vw(44);
+    height: vw(44);
+    background-color: #e1e1e1;
+    border-radius: 50%;
+    margin-top: -3px;
+  }
+  .el-dialog__body {
+    flex: 1;
+    overflow-y: auto;
+  }
+}
+.table-headermd1 {
+  font-size: 14px;
+  text-align: center;
+  position: initial;
+  width: 98% !important;
+  margin: 0 auto;
+  border-right: 0;
+  border-radius: 8px;
+  th {
+    color: #000;
+    font-weight: bold;
+  }
+  td {
+    color: #000;
+  }
+  .el-table__cell {
+    padding: 6px 0 !important;
+    .cell {
+      padding: 0;
+    }
+  }
+}
+</style>

+ 39 - 4
src/views/historicalVisit/historicalDetails.vue

@@ -398,6 +398,7 @@ export default {
         this.toastLoading().clear();
         if (res.code == 200) {
           this.list = res.data;
+          this.list.sfaTaskList = this.filterSfaTaskList(this.list.sfaTaskList);
           if (res.data.visitSource != 2) {
             this.getListHistoryList(res.data.instanceId);
           }
@@ -438,11 +439,45 @@ export default {
         }
       });
     },
+    filterSfaTaskList(list) {
+      let taskTypeArr = list.filter((val) => val.taskType !== '5');
+      let taskType5Index = list.findIndex((val) => val.taskType == '5');
+      if (taskType5Index != -1) {
+        let taskType5Arr = list.filter((val) => val.taskType == '5');
+        let taskIds = [];
+        taskType5Arr.forEach((val) => {
+          taskIds.push(val.taskId);
+        });
+        let taskType5 = {
+          ...list[taskType5Index],
+          taskIds: taskIds,
+          taskPhotoConditionPassed: null,
+        };
+        taskType5.taskName = '生动化陈列';
+        taskTypeArr.splice(taskType5Index, 0, taskType5);
+      }
+      console.log(taskTypeArr);
+      return taskTypeArr;
+    },
     historiStoreVisit(val, index) {
-      this.$router.push({
-        path: '/historiStoreVisit',
-        query: { visitId: this.visitsId, ids: index, taskType: val.taskType },
-      });
+      if (val.taskType == '5') {
+        this.$router.push({
+          path: '/taskPhotoTaking',
+          query: {
+            storeCode: this.$route.query.storeCode || this.list.storeCode,
+            visitsId: this.visitsId,
+            taskIds: val.taskIds.join(','),
+            storeGroupId: this.list.storeGroupId,
+            insert: 0,
+            source: 'historicalDetails',
+          },
+        });
+      } else {
+        this.$router.push({
+          path: '/historiStoreVisit',
+          query: { visitId: this.visitsId, ids: index, taskType: val.taskType },
+        });
+      }
       sessionStorage.setItem('collectionItemList', JSON.stringify(val.collectionItemList));
     },
     toSkuRecognize() {