Browse Source

Merge branch 'feature_20260203_完美门店' into release

zhujindu 12 hours ago
parent
commit
bef01dafd8

+ 9 - 0
src/api/index.js

@@ -1151,3 +1151,12 @@ export function addCollectionAnswerBatch(data) {
     data,
   });
 }
+
+// 完美门店
+export function getVisitsDetailPerfectStore(query) {
+  return request({
+    url: 'mobile/storeGroup/getVisitsDetailPerfectStore',
+    method: 'get',
+    params: query,
+  });
+}

BIN
src/assets/shouzhi.png


+ 0 - 1
src/components/uploadVNormalTaskPhoto.vue

@@ -510,7 +510,6 @@ export default {
   // padding: 0 15px;
   box-sizing: border-box;
   position: relative;
-  width: 100%;
 
   .cameraDiv {
     flex: 1;

+ 2 - 0
src/main.js

@@ -19,6 +19,7 @@ import {
   validatePhone,
   formatChineseDate,
   shareVedioLinks,
+  convertToChinese,
 } from '@/utils/index';
 import { toastLoading } from '@/utils/commonVant';
 import '@vant/touch-emulator';
@@ -66,6 +67,7 @@ Vue.prototype.verifyStoreType = verifyStoreType;
 Vue.prototype.validatePhone = validatePhone;
 Vue.prototype.formatChineseDate = formatChineseDate;
 Vue.prototype.shareVedioLinks = shareVedioLinks;
+Vue.prototype.convertToChinese = convertToChinese;
 Vue.prototype.Toast = Toast;
 Vue.prototype.notify = Notify;
 var clipboard = new ClipboardJS('.btn');

+ 25 - 0
src/router/index.js

@@ -273,6 +273,21 @@ const router = new VueRouter({
           name: 'historicalDetails',
           component: () => import('@/views/historicalVisit/historicalDetails.vue'),
         },
+        {
+          path: '/perfectStore',
+          name: 'perfectStore',
+          component: () => import('@/views/historicalVisit/perfectStore.vue'),
+        },
+        {
+          path: '/perfectStoreTask',
+          name: 'perfectStoreTask',
+          component: () => import('@/views/historicalVisit/perfectStoreTask.vue'),
+        },
+        {
+          path: '/perfectStoreSku',
+          name: 'perfectStoreSku',
+          component: () => import('@/views/historicalVisit/perfectStoreSku.vue'),
+        },
         {
           path: '/historiStoreVisit',
           name: 'historiStoreVisit',
@@ -283,6 +298,16 @@ const router = new VueRouter({
           name: 'skuRecognize',
           component: () => import('@/views/historicalVisit/skuRecognize.vue'),
         },
+        {
+          path: '/perfectStoreSign',
+          name: 'perfectStoreSign',
+          component: () => import('@/views/historicalVisit/perfectStoreSign.vue'),
+        },
+        {
+          path: '/perfectStoreTSJ',
+          name: 'perfectStoreTSJ',
+          component: () => import('@/views/historicalVisit/perfectStoreTSJ.vue'),
+        },
       ],
     },
     {

+ 10 - 1
src/utils/index.js

@@ -128,7 +128,7 @@ export function parseTimeParagraph(dayTime) {
         ' ' +
         ['周日', '周一', '周二', '周三', '周四', '周五', '周六'][
           new Date(dataTime.toString().replace(/-/g, '/')).getDay()
-        ]
+        ],
     );
   }
   tabTime.push(dates[0]);
@@ -325,3 +325,12 @@ export function shareVedioLinks() {
   window.location.href =
     'https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww5444eb205d75e730&redirect_uri=https%3A%2F%2Fknowledgewiki.nipponpaint.com.cn%2Fapi%2Fauth%2Fwx%2FshareOuth%3Fguid%3Dd4ac9b85658570389cfebe70e4505071%26shareId%3DSHARE21482&response_type=code&scope=snsapi_base&state=ZyKPSJuKA6-ZikabG6WSBqgGRsjsYK8j6P5I2bVdqOs&agentid=1000291#wechat_redirect';
 }
+
+export function convertToChinese(num) {
+  const digitMap = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
+  return num
+    .toString()
+    .split('')
+    .map((digit) => digitMap[parseInt(digit)])
+    .join('');
+}

+ 61 - 26
src/views/deviceOutside/index.vue

@@ -86,8 +86,15 @@
                   >
                 </template>
               </div>
-              <div class="info" style="position: relative">
-                联系人:{{ item.contactName }}
+              <div class="info" style="position: relative">联系人:{{ item.contactName }}</div>
+              <div class="info">类型:{{ item.storeCategory }}&nbsp;</div>
+              <div class="info" style="position: relative" @click="buryingPointFn(item)">
+                联系电话:<a
+                  v-if="item.telephone"
+                  style="color: #0057ba; font-weight: bold; text-decoration: underline"
+                  :href="'tel:' + item.telephone"
+                  >{{ item.telephone }}<van-icon name="phone"
+                /></a>
                 <div style="position: absolute; bottom: 0px; right: 0px">
                   <!-- 凤凰客户 -->
                   <el-popover
@@ -295,26 +302,6 @@
                   </el-popover>
                 </div>
               </div>
-              <div class="info">
-                类型:{{ item.storeCategory }}&nbsp;
-                <!-- 以后需要再打开 -->
-                <!-- <el-popover popper-class="zpover zpover6" placement="bottom-start" trigger="click">
-                  <div>
-                    <p>
-                      本店经营品项指导:
-                      <a @click="linkimg(item)" style="text-decoration: underline">点击查看</a>
-                    </p>
-                  </div>
-                  <van-icon name="question-o" size="18" slot="reference" />
-                </el-popover> -->
-              </div>
-              <div class="info" v-if="item.telephone" @click="buryingPointFn(item)">
-                联系电话:<a
-                  style="color: #0057ba; font-weight: bold; text-decoration: underline"
-                  :href="'tel:' + item.telephone"
-                  >{{ item.telephone }}<van-icon name="phone"
-                /></a>
-              </div>
               <div class="info">
                 地址:{{ item.addressLine }}
                 <img
@@ -376,7 +363,37 @@
               style="background-color: white">
               <van-icon :name="times" color="#ee0a24" size="32" />
             </div>
-            <div class="statstext" v-if="item.stateString == '已拜访'">已拜访</div>
+            <template v-if="item.stateString == '已拜访'">
+              <template v-if="item.visitSource == 1">
+                <!-- 金牌店+同城分销店+可控店 -->
+                <template v-if="item.jinpaiStore || item.fenxiaoStore || item.kekongStore">
+                  <div class="statstext" style="background-color: #e3f0fe">
+                    <span style="color: #387bca">已拜访</span>
+                    <div
+                      class="statstextIcon"
+                      style="background-color: #0057ba"
+                      @click="openPerfectStore(item)">
+                      <div style="margin: 4px; font-size: 14px; font-weight: 600">
+                        <img
+                          style="width: 18px; height: 20px; margin: 0 5px; vertical-align: -5px"
+                          :src="require('@/assets/shouzhi.png')" />完美门店报告
+                      </div>
+                    </div>
+                  </div>
+                </template>
+                <template v-else>
+                  <div class="statstext">
+                    <span>已拜访</span>
+                  </div>
+                </template>
+              </template>
+              <template v-else>
+                <!-- 异常拜访 -->
+                <div class="statstext">
+                  <span>已拜访</span>
+                </div>
+              </template>
+            </template>
             <div class="btnbox">
               <van-row>
                 <van-col
@@ -2354,6 +2371,17 @@ export default {
         });
       }
     },
+    // 完美门店
+    openPerfectStore(val) {
+      this.$router.push({
+        path: '/perfectStore',
+        query: {
+          visitId: val.visitId,
+          storeId: val.storeId,
+          storeCode: val.storeCode,
+        },
+      });
+    },
   },
 };
 </script>
@@ -2425,8 +2453,8 @@ export default {
   font-size: 15px;
   font-weight: bold;
   color: #333;
-  line-height: 22px;
-  padding-right: 52px;
+  line-height: 28px;
+  padding-right: 55px;
   .JPABC {
     width: 20px;
     position: relative;
@@ -2491,7 +2519,7 @@ export default {
   background-color: #0057ba;
   position: absolute;
   right: 0;
-  top: 6px;
+  top: 11px;
   padding: 2px 6px 2px 12px;
   border-bottom-left-radius: 60px;
   border-top-left-radius: 60px;
@@ -2503,6 +2531,13 @@ export default {
 .statstext .van-icon__image {
   height: 0.7em;
 }
+.statstextIcon {
+  width: 121px;
+  position: absolute;
+  left: -62px;
+  top: 31px;
+  border-radius: 15px 0 0 15px;
+}
 .tipsTitle {
   padding: 5px 0;
   text-align: center;

+ 87 - 75
src/views/deviceWithin/addStoreVisit.vue

@@ -411,7 +411,7 @@
                 </taskTips>
               </template>
               <template #right-icon>
-                <template v-if="isEditSDHCL">
+                <template v-if="isEditSDHCL && processKey">
                   <span v-if="item.isMustPicture == '0'" class="van-f-red">*</span>
                   <van-icon
                     v-if="item.isPicture == 0"
@@ -1089,13 +1089,15 @@
                           </taskTips
                         ></template>
                         <template #right-icon>
-                          <span v-if="childitem.isMustPicture == '0'" class="van-f-red">*</span>
-                          <van-icon
-                            v-if="childitem.isPicture == 0"
-                            color="#666"
-                            name="photograph"
-                            size="24"
-                            @click="imgClick(childitem, 'B', index, childIndex)" />
+                          <template v-if="processKey">
+                            <span v-if="childitem.isMustPicture == '0'" class="van-f-red">*</span>
+                            <van-icon
+                              v-if="childitem.isPicture == 0"
+                              color="#666"
+                              name="photograph"
+                              size="24"
+                              @click="imgClick(childitem, 'B', index, childIndex)" />
+                          </template>
                         </template>
                       </van-cell>
                       <!-- 生动化陈列备注 只能有一层采集项 -->
@@ -1107,6 +1109,7 @@
                       </div>
                       <deleteUploadImg
                         :photoIdentifyType="photoIdentifyType"
+                        :types="$route.query.types"
                         :imgs="childitem.fileInfoList"></deleteUploadImg>
                     </div>
                     <div v-if="childitem.answerType == 'duox'" class="formLabel z-cell">
@@ -2336,29 +2339,31 @@
                                               </taskTips
                                             ></template>
                                             <template #right-icon>
-                                              <span
-                                                v-if="child33item1.isMustPicture == '0'"
-                                                class="van-f-red"
-                                                >*</span
-                                              >
-                                              <van-icon
-                                                v-if="child33item1.isPicture == 0"
-                                                color="#666"
-                                                name="photograph"
-                                                size="24"
-                                                @click="
-                                                  imgClick(
-                                                    child33item1,
-                                                    'D',
-                                                    index,
-                                                    childIndex,
-                                                    indexc,
-                                                    indexc1,
-                                                    childIndex1,
-                                                    indexc33,
-                                                    child33Index1,
-                                                  )
-                                                " />
+                                              <template v-if="processKey">
+                                                <span
+                                                  v-if="child33item1.isMustPicture == '0'"
+                                                  class="van-f-red"
+                                                  >*</span
+                                                >
+                                                <van-icon
+                                                  v-if="child33item1.isPicture == 0"
+                                                  color="#666"
+                                                  name="photograph"
+                                                  size="24"
+                                                  @click="
+                                                    imgClick(
+                                                      child33item1,
+                                                      'D',
+                                                      index,
+                                                      childIndex,
+                                                      indexc,
+                                                      indexc1,
+                                                      childIndex1,
+                                                      indexc33,
+                                                      child33Index1,
+                                                    )
+                                                  " />
+                                              </template>
                                             </template>
                                           </van-cell>
                                           <!-- 生动化陈列备注 只能有一层采集项 -->
@@ -2370,6 +2375,7 @@
                                           </div>
                                           <deleteUploadImg
                                             :photoIdentifyType="photoIdentifyType"
+                                            :types="$route.query.types"
                                             :imgs="child33item1.fileInfoList"></deleteUploadImg>
                                         </div>
                                         <div
@@ -3242,31 +3248,33 @@
                                                         </taskTips>
                                                       </template>
                                                       <template #right-icon>
-                                                        <span
-                                                          v-if="child44item1.isMustPicture == '0'"
-                                                          class="van-f-red"
-                                                          >*</span
-                                                        >
-                                                        <van-icon
-                                                          v-if="child44item1.isPicture == 0"
-                                                          color="#666"
-                                                          name="photograph"
-                                                          size="24"
-                                                          @click="
-                                                            imgClick(
-                                                              child44item1,
-                                                              'E',
-                                                              index,
-                                                              childIndex,
-                                                              indexc,
-                                                              indexc1,
-                                                              childIndex1,
-                                                              indexc33,
-                                                              child33Index1,
-                                                              indexc44,
-                                                              child44Index1,
-                                                            )
-                                                          " />
+                                                        <template v-if="processKey">
+                                                          <span
+                                                            v-if="child44item1.isMustPicture == '0'"
+                                                            class="van-f-red"
+                                                            >*</span
+                                                          >
+                                                          <van-icon
+                                                            v-if="child44item1.isPicture == 0"
+                                                            color="#666"
+                                                            name="photograph"
+                                                            size="24"
+                                                            @click="
+                                                              imgClick(
+                                                                child44item1,
+                                                                'E',
+                                                                index,
+                                                                childIndex,
+                                                                indexc,
+                                                                indexc1,
+                                                                childIndex1,
+                                                                indexc33,
+                                                                child33Index1,
+                                                                indexc44,
+                                                                child44Index1,
+                                                              )
+                                                            " />
+                                                        </template>
                                                       </template>
                                                     </van-cell>
                                                     <!-- 生动化陈列备注 只能有一层采集项 -->
@@ -3279,6 +3287,7 @@
                                                       请补充拍摄除陈列奖励案产品外,本店经营的其他立邦产品,以便准确识别SKU数量
                                                     </div>
                                                     <deleteUploadImg
+                                                      :types="$route.query.types"
                                                       :photoIdentifyType="photoIdentifyType"
                                                       :imgs="
                                                         child44item1.fileInfoList
@@ -3599,25 +3608,27 @@
                                     </taskTips>
                                   </template>
                                   <template #right-icon>
-                                    <span v-if="childitem1.isMustPicture == '0'" class="van-f-red"
-                                      >*</span
-                                    >
-                                    <van-icon
-                                      v-if="childitem1.isPicture == 0"
-                                      color="#666"
-                                      name="photograph"
-                                      size="24"
-                                      @click="
-                                        imgClick(
-                                          childitem1,
-                                          'C',
-                                          index,
-                                          childIndex,
-                                          indexc,
-                                          indexc1,
-                                          childIndex1,
-                                        )
-                                      " />
+                                    <template v-if="processKey">
+                                      <span v-if="childitem1.isMustPicture == '0'" class="van-f-red"
+                                        >*</span
+                                      >
+                                      <van-icon
+                                        v-if="childitem1.isPicture == 0"
+                                        color="#666"
+                                        name="photograph"
+                                        size="24"
+                                        @click="
+                                          imgClick(
+                                            childitem1,
+                                            'C',
+                                            index,
+                                            childIndex,
+                                            indexc,
+                                            indexc1,
+                                            childIndex1,
+                                          )
+                                        " />
+                                    </template>
                                   </template>
                                 </van-cell>
                                 <!-- 生动化陈列备注 只能有一层采集项 -->
@@ -3629,6 +3640,7 @@
                                 </div>
                                 <deleteUploadImg
                                   :photoIdentifyType="photoIdentifyType"
+                                  :types="$route.query.types"
                                   :imgs="childitem1.fileInfoList"></deleteUploadImg>
                               </div>
                             </div>

+ 59 - 11
src/views/deviceWithin/index.vue

@@ -103,6 +103,7 @@
                 >
               </template>
             </div>
+            <div class="info" style="position: relative">联系人:{{ item.contactName }}</div>
             <div class="info">
               类型:{{ item.storeCategory }} &nbsp;
               <!-- <el-popover popper-class="zpover zpover6" placement="bottom-start" trigger="click">
@@ -115,8 +116,13 @@
                 <van-icon name="question-o" size="18" slot="reference" />
               </el-popover> -->
             </div>
-            <div class="info" style="position: relative">
-              联系人:{{ item.contactName }}
+            <div class="info" style="position: relative" @click="buryingPointFn(item)">
+              联系电话:<a
+                v-if="item.telephone"
+                style="color: #0057ba; font-weight: bold; text-decoration: underline"
+                :href="'tel:' + item.telephone"
+                >{{ item.telephone }}<van-icon name="phone"
+              /></a>
               <div style="position: absolute; bottom: 0; right: 14px">
                 <el-popover
                   popper-class="zpover"
@@ -314,13 +320,6 @@
                 </el-popover>
               </div>
             </div>
-            <div class="info" v-if="item.telephone" @click="buryingPointFn(item)">
-              联系电话:<a
-                style="color: #0057ba; font-weight: bold; text-decoration: underline"
-                :href="'tel:' + item.telephone"
-                >{{ item.telephone }}<van-icon name="phone"
-              /></a>
-            </div>
             <div class="info" v-if="item.addressLine">
               地址:{{ item.addressLine
               }}<img
@@ -378,7 +377,38 @@
             style="background-color: white">
             <van-icon :name="times" color="#ee0a24" size="32" />
           </div>
-          <div class="statstext" v-if="item.stateString == '已拜访'">已拜访</div>
+          <template v-if="item.stateString == '已拜访'">
+            <!-- 正常拜访 -->
+            <template v-if="item.visitSource == 1">
+              <!-- 金牌店+同城分销店+可控店 -->
+              <template v-if="item.jinpaiStore || item.fenxiaoStore || item.kekongStore">
+                <div class="statstext" style="background-color: #e3f0fe">
+                  <span style="color: #387bca">已拜访</span>
+                  <div
+                    class="statstextIcon"
+                    style="background-color: #0057ba"
+                    @click="openPerfectStore(item)">
+                    <div style="margin: 4px; font-size: 14px; font-weight: 600">
+                      <img
+                        style="width: 18px; height: 20px; margin: 0 5px; vertical-align: -5px"
+                        :src="require('@/assets/shouzhi.png')" />完美门店报告
+                    </div>
+                  </div>
+                </div>
+              </template>
+              <template v-else>
+                <div class="statstext">
+                  <span>已拜访</span>
+                </div>
+              </template>
+            </template>
+            <template v-else>
+              <!-- 异常拜访 -->
+              <div class="statstext">
+                <span>已拜访</span>
+              </div>
+            </template>
+          </template>
           <div class="btnbox">
             <van-row>
               <van-col
@@ -1609,6 +1639,17 @@ export default {
         });
       }
     },
+    // 完美门店
+    openPerfectStore(val) {
+      this.$router.push({
+        path: '/perfectStore',
+        query: {
+          visitId: val.visitId,
+          storeId: val.storeId,
+          storeCode: val.storeCode,
+        },
+      });
+    },
   },
 };
 </script>
@@ -1675,7 +1716,7 @@ export default {
     font-weight: bold;
     color: #333;
     line-height: 22px;
-    padding-right: 52px;
+    padding-right: 72px;
     /*word-break: break-all;*/
     .JPABC {
       width: 20px;
@@ -1758,6 +1799,13 @@ export default {
 .statstext .van-icon__image {
   height: 0.7em;
 }
+.statstextIcon {
+  width: 121px;
+  position: absolute;
+  left: -62px;
+  top: 31px;
+  border-radius: 15px 0 0 15px;
+}
 .visitStoreIco {
   float: left;
   float: left;

+ 7 - 1
src/views/deviceWithin/taskPhotoTaking.vue

@@ -172,7 +172,7 @@ export default {
           this.pos = 0;
         } else {
           // 判断当前值是否与上一行的【名称】相等,相等则进行合并
-          if (data[i].conditionIdentifyNum === data[i - 1].conditionIdentifyNum) {
+          if (data[i].conditionDetailId === data[i - 1].conditionDetailId) {
             this.spanArr[this.pos] += 1; // 合并单元格:合并的行数 +1
             this.spanArr.push(0); // 0代表单元格是不需要显示, 已经被合并的单元格
           } else {
@@ -362,6 +362,12 @@ export default {
           width: 100%;
           height: 30px;
         }
+        button {
+          width: 55px;
+          height: 25px;
+          padding: 0;
+          font-size: 12px;
+        }
       }
     }
   }

+ 48 - 34
src/views/historicalVisit/historAllVisit.vue

@@ -59,7 +59,9 @@
         </van-search>
       </div>
       <div class="lineGrey"></div>
-      <div v-if="refreshTotal" class="refreshBtn" @click="onSearch">检测到 {{ refreshTotal }} 条更新,点击刷新</div>
+      <div v-if="refreshTotal" class="refreshBtn" @click="onSearch">
+        检测到 {{ refreshTotal }} 条更新,点击刷新
+      </div>
       <div v-if="refreshTotal" class="lineGrey"></div>
     </div>
     <!--        主体内容-->
@@ -207,8 +209,8 @@ export default {
   name: 'index.vue',
   data() {
     return {
-      latestUpdateTime:null,
-      refreshTotal:0,
+      latestUpdateTime: null,
+      refreshTotal: 0,
       timeico: timeico,
       defaultDate: new Date(),
       searchValue: '',
@@ -270,15 +272,15 @@ export default {
   },
   activated() {
     let typeQuery = localStorage.getItem('typeQuery');
-    if(this.latestUpdateTime!=null && typeQuery == 1){ 
-        this.getListTotalFn();
-    }else{
+    if (this.latestUpdateTime != null && typeQuery == 1) {
+      this.getListTotalFn();
+    } else {
       setTimeout(() => {
         this.onSearch();
       }, 1000);
     }
   },
-  deactivated(){
+  deactivated() {
     localStorage.setItem('typeQuery', 1);
   },
   created() {
@@ -317,16 +319,16 @@ export default {
     }
   },
   methods: {
-    getListTotalFn(){
+    getListTotalFn() {
       getListTotal({
-        startTime: this.startTime + ' 00:00:00', 
-        stopTime: this.endTime + ' 24:00:00', 
+        startTime: this.startTime + ' 00:00:00',
+        stopTime: this.endTime + ' 24:00:00',
         storeRequest: this.storeName.trim(),
         companyId: this.companyCode,
         regionId: this.regionCode,
         userId: this.userCode,
         deptId: this.deptCode,
-        queryStartTime:this.latestUpdateTime
+        queryStartTime: this.latestUpdateTime,
       }).then((res) => {
         if (res.code == 200) {
           this.refreshTotal = res.data;
@@ -346,17 +348,29 @@ export default {
     },
     detilsFn(val) {
       console.log(val.id);
-      this.$router.push({
-        path: '/historicalDetails',
-        query: {
-          visitId: val.id,
-          storeId: val.storeId,
-          storeCode: val.storeCode,
-          taskId: val.taskId,
-          userId: val.userId,
-          storeCategory: val.storeCategory,
-        },
-      });
+      if ((val.jinpaiStore || val.fenxiaoStore || val.kekongStore) && val.visitSource == 1) {
+        // 金牌店+同城分销店+可控店 -完美门店
+        this.$router.push({
+          path: '/perfectStore',
+          query: {
+            visitId: val.id,
+            storeId: val.storeId,
+            storeCode: val.storeCode,
+          },
+        });
+      } else {
+        this.$router.push({
+          path: '/historicalDetails',
+          query: {
+            visitId: val.id,
+            storeId: val.storeId,
+            storeCode: val.storeCode,
+            taskId: val.taskId,
+            userId: val.userId,
+            storeCategory: val.storeCategory,
+          },
+        });
+      }
     },
     timeBefore7(date) {
       if (!date) {
@@ -406,7 +420,7 @@ export default {
     },
     onClickLeft() {
       this.$router.push({
-          path: '/My/index',
+        path: '/My/index',
       });
     },
     onSearch() {
@@ -440,7 +454,7 @@ export default {
         loading1.clear();
         if (res.code == 200) {
           this.loading = false;
-          if(this.pageNum == 1){
+          if (this.pageNum == 1) {
             this.latestUpdateTime = res.dataTime;
           }
           this.list = this.list.concat(res.data);
@@ -576,16 +590,16 @@ export default {
 };
 </script>
 <style lang="scss">
-.refreshBtn{
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    cursor: pointer;
-    width: 100%;
-    color: #ff976a;
-    padding: 5px;
-    font-size: 14px;
-    background-color: #fff;
+.refreshBtn {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+  width: 100%;
+  color: #ff976a;
+  padding: 5px;
+  font-size: 14px;
+  background-color: #fff;
 }
 .searchDiv {
   .van-search {

+ 1 - 1
src/views/historicalVisit/hisvistdeils.vue

@@ -456,7 +456,7 @@ export default {
           this.pos = 0;
         } else {
           // 判断当前值是否与上一行的【名称】相等,相等则进行合并
-          if (data[i].conditionIdentifyNum === data[i - 1].conditionIdentifyNum) {
+          if (data[i].conditionDetailId === data[i - 1].conditionDetailId) {
             this.spanArr[this.pos] += 1; // 合并单元格:合并的行数 +1
             this.spanArr.push(0); // 0代表单元格是不需要显示, 已经被合并的单元格
           } else {

+ 757 - 0
src/views/historicalVisit/perfectStore.vue

@@ -0,0 +1,757 @@
+<template>
+  <div class="perfectStore">
+    <!--        顶部条-->
+    <van-nav-bar class="navBar" title="AI完美门店报告" left-arrow @click-left="onClickLeft">
+      <template #right>
+        <span
+          style="
+            color: white;
+            background: #74a4d9;
+            display: block;
+            padding: 6px 10px;
+            border-radius: 6px;
+          "
+          @click="editorFn"
+          v-if="!remarkShow && sameDay"
+          >编辑</span
+        >
+      </template>
+    </van-nav-bar>
+    <!--        主体内容-->
+    <div class="container" v-if="list">
+      <div class="lineGrey"></div>
+      <div class="card mt10">
+        <div class="title">
+          {{ list.storeName }}(<span style="color: #1989fa">{{ list.storeCode }}</span
+          >)
+        </div>
+        <div class="subtitle">地址:{{ list.addressLine }}</div>
+        <div class="subtitle">拜访人:{{ list.nickName }}</div>
+        <div class="subtitle">拜访日期:{{ list.startTime }}~{{ list.stopTime }}</div>
+        <div class="subtitle" v-if="list.dwellTime">拜访时长:{{ list.dwellTime }}</div>
+        <!-- 分销店 -->
+        <template
+          v-if="
+            verifyStoreType(list.storeCategory) && verifyStoreType(list.storeCategory).type == 'fxd'
+          ">
+          <div class="subtitle" style="display: flex">
+            <div class="label" style="width: 75px">经销商:</div>
+            <div class="valuue TCFXList">
+              <div
+                class="sfaStoreChainsContactList"
+                v-for="(item, index) in list.sfaStoreChainsContactList"
+                :key="index">
+                {{ item.categoryDescribe }}
+                {{ item.chainCode }}
+                {{ item.chainName }}
+              </div>
+            </div>
+          </div>
+        </template>
+        <template v-else>
+          <div class="subtitle">经销商:{{ list.chainName }}</div>
+        </template>
+        <div class="subtitle" v-if="updateTimeShow">更新时间:{{ list.updateTime }}</div>
+      </div>
+      <!-- <p
+        style="padding: 0 10px; font-size: 14px; color: #222; font-weight: bold"
+        v-if="list.visitSource != 2 && ListHistoryList.length > 0">
+        审批历史
+      </p> -->
+      <!-- <div
+        v-for="(item1, index1) in ListHistoryList"
+        :key="index1"
+        style="background-color: white; padding-top: 14px">
+        <p style="padding: 0 16px; font-size: 14px; color: #222; margin: 0">
+          流程名称:{{ item1.modelName }}
+        </p>
+        <van-steps direction="vertical" :active="item1.processList.length">
+          <van-step v-for="(item, index) in item1.processList" :key="index">
+            <h3 style="font-size: 14px">{{ item.activityName }} &nbsp;{{ item.assigneeName }}</h3>
+            <p>{{ item.comment }}</p>
+          </van-step>
+        </van-steps>
+        <div style="border-bottom: 2px solid #f5f5f5; margin: 0 16px 16px"></div>
+      </div> -->
+      <!-- <van-collapse
+        v-model="active"
+        class="fontWeit"
+        v-if="managerRemarkContents != null && managerRemarkContents.length > 0">
+        <van-collapse-item name="1" title="点评">
+          <p>
+            {{ managerRemarkContents[0].deptName }} - {{ managerRemarkContents[0].postName }} -
+            {{ managerRemarkContents[0].nickName }}的点评
+          </p>
+          <p class="contern">
+            <van-field
+              v-model="managerRemarkContents[0].remarkContent"
+              rows="4"
+              autosize
+              readonly
+              type="textarea" />
+          </p>
+          <p style="text-align: right">点评时间:{{ managerRemarkContents[0].createTime }}</p>
+        </van-collapse-item>
+      </van-collapse> -->
+      <!-- 特殊任务展示 -->
+      <!-- 店招 -->
+      <div class="shopSign specialTask" v-if="shopSignDetail && shopSignDetail.qualifiedState">
+        <div class="specialTaskLeft" @click="openPerfectStoreSign">
+          <div class="SignText">AI 店招识别</div>
+          <div class="signContent">
+            <div class="" style="display: flex">
+              <van-button round type="primary" v-if="shopSignDetail.qualifiedState == '1'"
+                >通过</van-button
+              >
+              <van-button round type="danger" v-else>不通过</van-button>
+              <div class="jiantou">
+                <van-icon name="arrow" />
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <!-- 调色机 -->
+      <div class="TSJBox specialTask" v-if="tiaoSJDetail && tiaoSJDetail.qualifiedState">
+        <div class="specialTaskLeft" @click="openPerfectStoreTSJ">
+          <div class="SignText">AI 调色机识别</div>
+          <div class="signContent">
+            <div class="" style="display: flex">
+              <van-button round type="primary" v-if="tiaoSJDetail.qualifiedState == '1'"
+                >通过</van-button
+              >
+              <van-button round type="danger" v-else>不通过</van-button>
+              <div class="jiantou">
+                <van-icon name="arrow" />
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <!-- 陈列SKU个数: -->
+      <div class="TSJBox specialTask" v-if="list.isSku == '是'">
+        <div class="specialTaskLeft">
+          <div class="SignText">
+            AI SKU个数识别: <span v-if="list.skuNum">{{ list.skuNum }}个</span>
+          </div>
+          <div class="signContent" @click="toSkuRecognize">
+            <div class="" style="display: flex">
+              <span style="color: rgb(25, 137, 250)">查看详情</span>
+              <div class="jiantou">
+                <van-icon name="arrow" />
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <!-- 目前陈列任务 -->
+      <div
+        class="TSJBox specialTask"
+        v-if="list.isSku == '是' && taskTypeArr && taskTypeArr.length">
+        <div class="specialTaskLeft">
+          <div class="SignText">AI 陈列任务识别</div>
+        </div>
+      </div>
+      <div class="SKUBox" v-if="taskTypeArr && taskTypeArr.length">
+        <div class="SKUList">
+          <div
+            class="itemList"
+            v-for="(value, index) in taskTypeArr"
+            @click="historiStoreVisit(value)">
+            <div class="itemTitle">{{ convertToChinese(index + 1) }}、{{ value.taskName }}</div>
+            <div class="" style="display: flex">
+              <van-button round type="primary" v-if="value.taskPhotoConditionPassed == 1"
+                >通过</van-button
+              >
+              <van-button round type="danger" v-else>不通过</van-button>
+              <!-- <van-icon name="success" color="#07c160" v-if="value.taskPhotoConditionPassed == 1" />
+              <van-icon name="cross" color="#ee0a24" v-else /> -->
+              <div class="jiantou">
+                <van-icon name="arrow" />
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div style="padding: 15px 16px; font-size: 16px; font-weight: bold; background: #f5f5f5">
+        其他拜访任务
+      </div>
+      <div class="card" v-if="list.visitSource != 2">
+        <div
+          class="info"
+          style="
+            font-size: 14px;
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            padding: 3px;
+          "
+          v-for="(item, index) in list.sfaTaskList"
+          :key="index"
+          v-if="
+            item.photoIdentifyType != '1' && item.photoIdentifyType != '3' && item.taskType != '5'
+          "
+          @click="historiStoreVisit(item, index)">
+          <p style="flex: 1; margin: 0">
+            {{ item.taskName }}
+          </p>
+
+          <div class="taskPhotoConditionPassed" @click.stop>
+            <el-popover
+              :popper-class="item.taskPhotoConditionPassed == 1 ? 'zpoverSuccess' : 'zpover'"
+              placement="bottom"
+              width="120"
+              trigger="click"
+              :content="
+                item.taskPhotoConditionPassed == 1
+                  ? '陈列奖励案拍照AI识别通过'
+                  : '陈列奖励案拍照AI识别不通过'
+              ">
+              <div class="taskPhotoConditionPassed" slot="reference">
+                <img
+                  v-if="item.taskPhotoConditionPassed == 1"
+                  :src="require('@/assets/taskPhotoSu.png')" />
+                <img
+                  v-if="item.taskPhotoConditionPassed == 0"
+                  :src="require('@/assets/taskPhotoErr.png')" />
+              </div>
+            </el-popover>
+          </div>
+          <p class="arrowdetils1">
+            <van-icon name="arrow" />
+          </p>
+        </div>
+      </div>
+      <!-- <div v-if="list.visitSource == 2" style="background-color: #fff">
+        <van-cell title="异常事由" :value="selectDictLabel(typeList, list.abnormalReason)" />
+        <van-cell title="异常信息照" />
+        <div style="padding: 10px 16px 0">
+          <delete-upload-img :imgs="imgs"></delete-upload-img>
+        </div>
+        <van-cell title="异常信息" :value="list.remark" />
+      </div> -->
+
+      <!-- <div style="padding: 10px 16px; font-size: 16px; font-weight: bold">更多记录</div>
+      <van-cell-group>
+        <van-cell v-for="(item1, index1) in list.visitsMore" :key="index1">
+          <template #title>
+            <van-row>
+              <van-col span="6">拜访人:</van-col>
+              <van-col span="18" class="custom-titles">{{ item1.userName }}</van-col>
+            </van-row>
+          </template>
+          <template #right-icon>
+            <span>{{ item1.visitTime }}</span>
+          </template>
+        </van-cell>
+      </van-cell-group> -->
+      <!-- 业务员拜访记录回显部主管反馈内容 -->
+      <!-- <template v-if="list.sfaPhotoApproveList && list.sfaPhotoApproveList.length">
+        <div
+          class="sfaPhotoApproveList"
+          v-for="(item, index) in list.sfaPhotoApproveList"
+          :key="item.identifyType">
+          <template v-if="item.identifyType == 1 || item.identifyType == 3">
+            <div style="padding: 10px 16px; font-size: 16px; font-weight: bold">
+              {{ filterTitle(item.identifyType) }}
+            </div>
+            <template v-if="item.historyFeedback == '0'">
+              <van-cell-group>
+                <van-cell> AI识别结果: {{ item.resultCorrect == 1 ? '正确' : '不正确' }} </van-cell>
+                <van-cell>
+                  拜访照异常原因及解决方案: {{ item.feedbackError || item.reasonsSolutions }}
+                </van-cell>
+              </van-cell-group>
+            </template>
+            <template v-if="item.historyFeedback == '1'">
+              <van-cell-group>
+                <van-cell v-if="item.identifyType == 1">
+                  店招异常原因: {{ resultCorrect(item.resultCorrect) }}
+                </van-cell>
+                <van-cell> 反馈: {{ item.feedbackError || item.reasonsSolutions }} </van-cell>
+              </van-cell-group>
+            </template>
+          </template>
+        </div>
+      </template>
+      <div
+        style="padding: 10px 16px; font-size: 16px; font-weight: bold"
+        v-if="managerRemarkContents == null && remarkShow">
+        点评
+      </div>
+      <div class="comment" v-if="managerRemarkContents == null && remarkShow">
+        <van-field
+          v-model="dataform.remarkContent"
+          rows="4"
+          autosize
+          maxlength="800"
+          show-word-limit
+          type="textarea"
+          :formatter="formatter" />
+        <br />
+        <br />
+        <div class="contentborder">
+          <van-button type="info" size="small" plain class="Btn1" @click="submint"
+            >提交点评</van-button
+          >
+        </div>
+      </div> -->
+    </div>
+  </div>
+</template>
+
+<script>
+import deleteUploadImg from '@/components/deleteUploadImg';
+import {
+  getVisitsDetailPerfectStore,
+  getPhotoTypeList1,
+  insertVisitRemark,
+  getListHistoryList,
+} from '@/api/index';
+import { getDictOption } from '@/api/index';
+import { ImagePreview } from 'vant';
+export default {
+  components: { deleteUploadImg },
+  data() {
+    return {
+      userShow: false,
+      visitsId: '',
+      imgs: '',
+      typeList: [],
+      active: ['1'],
+      sameDay: false,
+      ListHistoryTOTLE: '',
+      managerRemarkContents: null,
+      managerRemarkContent: '',
+      CWShow: false,
+      dataform: {
+        remarkContent: '',
+        visitsId: 0,
+      },
+      updateTimeShow: false,
+      insert: true,
+      remarkShow: false,
+      ListHistoryList: [],
+      list: null,
+      AIResultOption: [],
+      shopSignDetail: null,
+      tiaoSJDetail: null,
+      taskTypeArr: null,
+    };
+  },
+  activated() {
+    this.list = null;
+    this.toastLoading(0, '加载中...', true);
+    this.visitsId = this.$route.query.visitId;
+    this.dataform.visitsId = this.$route.query.visitId;
+    this.getVisitsDetailFn();
+    // 获取店招异常原因字典
+    getDictOption({}, 'feedback_error_msg').then((res) => {
+      this.AIResultOption = res.data;
+    });
+    this.getPhotoTypeList();
+  },
+  methods: {
+    resultCorrect(resultCorrect) {
+      let data = this.AIResultOption.find((item) => item.dictValue == resultCorrect);
+      return data ? data.dictLabel : '';
+    },
+    filterTitle(item) {
+      switch (item) {
+        case 1:
+          return '店招识别异常,主管反馈:';
+        // case '2':
+        //   return '门店代码识别';
+        case 3:
+          return '调色机识别异常,主管反馈:';
+        // case '4':
+        //   return '更换店招';
+      }
+    },
+    getListHistoryList(instanceId) {
+      var form = { visitsId: this.$route.query.visitId, pageNum: 1, pageSize: 999 };
+      getListHistoryList(form).then((res) => {
+        this.ListHistoryList = res.data;
+      });
+    },
+    formatter(value) {
+      return value.replace(
+        /[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF][\u200D|\uFE0F]|[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF]|[0-9|*|#]\uFE0F\u20E3|[0-9|#]\u20E3|[\u203C-\u3299]\uFE0F\u200D|[\u203C-\u3299]\uFE0F|[\u2122-\u2B55]|\u303D|[\A9|\AE]\u3030|\uA9|\uAE|\u3030/gi,
+        '',
+      );
+    },
+    editorFn() {
+      if (this.list.hideStr != '' && this.list.hideStr != null) {
+        this.$toast(this.list.hideStr);
+      } else {
+        localStorage.setItem('ORGName', this.list.deptName);
+        localStorage.setItem('chainNameR', this.list.storeName);
+        if (this.list.visitSource == '2') {
+          this.$router.push({
+            path: '/abnormalVisit',
+            query: {
+              type: 'edit',
+              storeCode: this.$route.query.storeCode || this.list.storeCode,
+              rdId: this.$route.query.visitId,
+              visitId: this.$route.query.visitId,
+              storeId: this.list.storeId,
+              visitSource: this.list.visitSource,
+              visitModel: this.list.visitModel,
+              marklat: this.list.lat,
+              marklon: this.list.lon,
+            },
+          });
+        } else {
+          var LCshow = false;
+          if (this.$route.query.taskId != null) {
+            LCshow = true;
+          } else {
+            LCshow = false;
+          }
+          this.$router.push({
+            path: '/storeVisitpage',
+            query: {
+              type: 'edit',
+              storeGroupId: this.list.storeGroupId,
+              storeCode: this.$route.query.storeCode || this.list.storeCode,
+              storeName: this.list.storeName,
+              addressLine: this.list.addressLine,
+              rdId: this.$route.query.visitId,
+              visitId: this.$route.query.visitId,
+              storeId: this.list.storeId,
+              visitSource: this.list.visitSource,
+              visitModel: this.list.visitModel,
+              LCshow: LCshow,
+              instanceId: this.list.instanceId,
+              taskId: this.$route.query.taskId,
+              marklat: this.list.lat,
+              marklon: this.list.lon,
+              from: 'outPlan',
+            },
+          });
+        }
+      }
+    },
+    submint() {
+      if (this.dataform.remarkContent.trim() == '') {
+        this.$toast('请填写点评内容!');
+      } else {
+        insertVisitRemark(this.dataform).then((res) => {
+          if (res.code == 200) {
+            this.getVisitsDetailFn();
+          }
+        });
+      }
+    },
+    getPhotoTypeList() {
+      getPhotoTypeList1({}).then((res) => {
+        this.typeList = res.data;
+      });
+    },
+    getVisitsDetailFn() {
+      this.shopSignDetail = null;
+      this.tiaoSJDetail = null;
+      this.taskTypeArr = null;
+      getVisitsDetailPerfectStore({ visitsId: this.$route.query.visitId }).then((res) => {
+        this.toastLoading().clear();
+        if (res.code == 200) {
+          this.list = res.data;
+          this.filterSfaTaskList(this.list.sfaTaskList);
+          let shopSignArr = this.list.sfaTaskList.filter((val) => val.photoIdentifyType == '1');
+          if (shopSignArr.length) this.shopSignDetail = shopSignArr[0];
+          let tiaoSJArr = this.list.sfaTaskList.filter((val) => val.photoIdentifyType == '3');
+          if (tiaoSJArr.length) {
+            this.tiaoSJDetail = tiaoSJArr[0];
+            console.log(this.tiaoSJDetail);
+          }
+          if (res.data.visitSource != 2) {
+            this.getListHistoryList(res.data.instanceId);
+          }
+          if (res.data.stopTime != res.data.updateTime) {
+            this.updateTimeShow = true;
+          } else {
+            this.updateTimeShow = false;
+          }
+          if (localStorage.getItem('userId') == this.$route.query.userId) {
+            this.userShow = true;
+          } else {
+            this.userShow = false;
+          }
+          if (this.$route.query.taskId != null) {
+            this.CWShow = true;
+          } else {
+            this.CWShow = false;
+          }
+          this.sameDay = res.data.sameDay;
+          if (localStorage.getItem('userId') == res.data.userId) {
+            this.remarkShow = false;
+          } else {
+            this.remarkShow = true;
+          }
+          if (res.data.visitRemarks != null) {
+            if (res.data.visitRemarks.length > 0) {
+              this.managerRemarkContents = res.data.visitRemarks;
+            } else {
+              this.managerRemarkContents = null;
+            }
+          }
+
+          if (res.data.visitSource == 2) {
+            this.imgs = res.data.sysFileInfos;
+          }
+        } else {
+          this.$toast.fail(res.msg);
+        }
+      });
+    },
+    filterSfaTaskList(list) {
+      this.taskTypeArr = list.filter((val) => val.taskType == '5');
+    },
+    historiStoreVisit(val, index) {
+      if (val.taskType == '5') {
+        this.$router.push({
+          path: '/perfectStoreTask',
+          query: {
+            storeCode: this.$route.query.storeCode || this.list.storeCode,
+            visitsId: this.visitsId,
+            taskId: val.taskId,
+            storeGroupId: this.list.storeGroupId,
+            insert: 0,
+            source: 'historicalDetails',
+          },
+        });
+      } else {
+        this.$router.push({
+          path: '/historiStoreVisit',
+          query: { visitId: this.visitsId, ids: index, taskType: val.taskType, taskId: val.taskId },
+        });
+      }
+      sessionStorage.setItem('collectionItemList', JSON.stringify(val.collectionItemList));
+    },
+    toSkuRecognize() {
+      this.$router.push({
+        path: '/perfectStoreSku',
+        query: { visitId: this.visitsId },
+      });
+    },
+    onClickLeft() {
+      if (this.$route.query.token) {
+        this.$router.push({
+          path: '/historicalVisit',
+        });
+      } else {
+        this.$router.go(-1);
+      }
+    },
+    previewsImg(url) {
+      ImagePreview([url]);
+    },
+    openPerfectStoreSign() {
+      this.$router.push({
+        path: '/perfectStoreSign',
+        query: { visitId: this.visitsId },
+      });
+    },
+    openPerfectStoreTSJ() {
+      this.$router.push({
+        path: '/perfectStoreTSJ',
+        query: { visitId: this.visitsId },
+      });
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.perfectStore {
+  background: #fff;
+  .specialTask {
+    display: flex;
+    flex-direction: row;
+    margin: 10px;
+    border-radius: 10px;
+    // min-height: 90px;
+    padding: 10px 0px 10px 10px;
+    font-size: 16px;
+    justify-content: space-between;
+    background: #e5faff;
+    .specialTaskLeft {
+      display: flex;
+      flex-direction: row;
+      justify-content: space-between;
+      width: 100%;
+    }
+    .SignText {
+      font-weight: 600;
+    }
+    .signContent {
+      display: flex;
+      flex-direction: row;
+      margin: 0 8px;
+      .icon {
+        padding-top: 2px;
+        margin-right: 5px;
+      }
+    }
+  }
+  // .shopSign {
+  //   background: #e5faff;
+  // }
+  // .TSJBox {
+  //   background: #fff4e4;
+  //   margin-top: 20px;
+  // }
+  .SKUBox {
+    margin: 0px 10px 10px 10px;
+    border-radius: 10px;
+    // min-height: 90px;
+    padding: 5px 10px;
+    font-size: 16px;
+    // background: #ffecf4;
+    .SKUTotal {
+      display: flex;
+      justify-content: space-between;
+      width: 100%;
+      color: rgb(25, 137, 250);
+    }
+    .SKUList {
+      .itemList {
+        display: flex;
+        flex-direction: row;
+        justify-content: space-between;
+        align-items: center;
+        padding: 3px 0;
+        margin: 10px 0;
+      }
+    }
+  }
+  .itemList,
+  .signContent {
+    .itemTitle {
+      flex: 1;
+      // text-decoration: underline;
+      // color: rgb(25, 137, 250);
+    }
+    .jiantou {
+      margin-left: 5px;
+      color: rgb(25, 137, 250);
+      display: flex;
+      align-items: center;
+    }
+    button {
+      width: 55px;
+      height: 25px;
+      padding: 0;
+      font-size: 12px;
+    }
+  }
+}
+.container {
+  padding-bottom: 50px;
+}
+.container .custom-titles {
+  white-space: break-spaces;
+}
+.card {
+  background: #fff;
+  padding: 10px 15px;
+  box-sizing: border-box;
+  .title {
+    line-height: 30px;
+    font-size: 16px;
+    font-weight: bold;
+    color: #333;
+  }
+  .subtitle {
+    line-height: 24px;
+    font-size: 14px;
+    color: #7b7b7b;
+  }
+  .info {
+    font-size: 16px;
+    color: #484848;
+    line-height: 40px;
+    border-bottom: 1px solid #dedede;
+    position: relative;
+    &:last-child {
+      border-bottom: 0;
+    }
+    .arrow {
+      float: right;
+      display: inline-block;
+      height: 20px;
+      width: 20px;
+      line-height: 20px;
+      text-align: center;
+      border-radius: 50%;
+      background: #1989fa;
+      color: #fff;
+      font-weight: bold;
+      font-size: 14px;
+      margin-top: 9px;
+    }
+    .taskPhotoConditionPassed {
+      width: 33px;
+      margin: 0 5px;
+      display: inline-flex;
+      img {
+        width: 33px;
+        height: 25px;
+      }
+    }
+    .arrowdetils1 {
+      background: #fff;
+      color: #444;
+      margin: 0;
+      margin-left: 5px;
+    }
+  }
+}
+.TCFXList {
+  .van-field__control--custom {
+    flex-direction: column;
+    align-items: self-start;
+    .TCFXListTreeSelec {
+      padding: 3px;
+    }
+  }
+}
+</style>
+<style lang="scss">
+.fontWeit .van-cell__title {
+  font-weight: bold;
+  font-size: 16px;
+}
+.fontWeit .van-cell__title p {
+  margin: 0;
+}
+.comment .van-field__control {
+  background-color: #ebf4ff;
+  border-radius: 6px;
+}
+.contern .van-cell {
+  background-color: #ebf4ff;
+  border-radius: 6px;
+  overflow: hidden;
+}
+.perfectStore {
+  .card {
+    .el-popover__reference-wrapper {
+      display: flex;
+    }
+  }
+  .van-button--danger {
+    background-color: #ee0a24 !important;
+    border: 1px solid #ee0a24 !important;
+  }
+}
+.zpoverSuccess {
+  background-color: #28e978 !important;
+  color: #fff !important;
+  padding: 8px 10px !important;
+  z-index: 1 !important;
+  border-radius: 6px !important;
+  border: 0 !important;
+  box-shadow: none !important;
+}
+</style>

+ 176 - 0
src/views/historicalVisit/perfectStoreSign.vue

@@ -0,0 +1,176 @@
+<template>
+  <div class="perfectStoreSign">
+    <van-nav-bar class="navBar" title="AI 店招识别" left-arrow @click-left="onClickLeft" />
+    <div class="content">
+      <div class="contentBox">
+        <div class="shopSign specialTask" v-if="shopSignDetail && shopSignDetail.qualifiedState">
+          <div class="specialTaskLeft">
+            <div class="SignText">识别结果:</div>
+            <div class="signContent">
+              <div class="icon">
+                <van-icon
+                  name="checked"
+                  color="#07c160"
+                  v-if="shopSignDetail.qualifiedState == '1'" />
+                <van-icon name="warning" color="#ee0a24" v-else />
+              </div>
+              <div :style="{ color: shopSignDetail.qualifiedState == '1' ? '#07c160' : '#ee0a24' }">
+                {{
+                  shopSignDetail.qualifiedState == '1'
+                    ? '店招完整,授权号正确'
+                    : shopSignDetail.unqualifiedReason
+                }}
+              </div>
+            </div>
+            <div class="shopSignButton">
+              <div class="" style="display: flex">
+                <van-button round type="primary" v-if="shopSignDetail.qualifiedState == '1'"
+                  >通过</van-button
+                >
+                <van-button round type="danger" v-else>不通过</van-button>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="shopSignImg">
+          <div class="text">店招照片</div>
+          <div class="imgBox">
+            <img
+              v-if="shopSignDetail && shopSignDetail.qualifiedState"
+              :src="shopSignDetail.fileUrl"
+              @click="previewsImg(shopSignDetail.fileUrl)" />
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import deleteUploadImg from '@/components/deleteUploadImg';
+import { getVisitsDetailPerfectStore } from '@/api/index';
+import { ImagePreview } from 'vant';
+export default {
+  name: 'perfectStoreSign',
+  components: { deleteUploadImg },
+  data() {
+    return {
+      visitsId: '',
+      detail: null,
+      shopSignDetail: null,
+    };
+  },
+  activated() {
+    this.visitsId = this.$route.query.visitId || '';
+    this.detail = null;
+    this.getVisitsDetailFn();
+  },
+  methods: {
+    getVisitsDetailFn() {
+      this.shopSignDetail = null;
+      getVisitsDetailPerfectStore({ visitsId: this.visitsId })
+        .then((res) => {
+          this.toastLoading().clear();
+          if (res.code == 200) {
+            this.detail = res.data;
+            let shopSignArr = this.detail.sfaTaskList.filter((val) => val.photoIdentifyType == '1');
+            if (shopSignArr.length) this.shopSignDetail = shopSignArr[0];
+          } else {
+            this.$dialog.alert({
+              message: res.msg,
+            });
+          }
+        })
+        .catch((err) => {
+          this.$dialog.alert({
+            message: err.msg,
+          });
+        });
+    },
+    previewsImg(url) {
+      ImagePreview([url]);
+    },
+    onClickLeft() {
+      this.$router.go(-1);
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.perfectStoreSign {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  overflow: hidden;
+  .content {
+    flex: 1;
+    overflow-y: auto;
+    padding: 10px 15px;
+    .contentBox {
+      width: 100%;
+      height: 100%;
+      background: #fff;
+      // padding-top: 15px;
+    }
+    .specialTask {
+      display: flex;
+      flex-direction: row;
+      padding: 10px;
+      font-size: 16px;
+      justify-content: space-between;
+      background: #e5faff;
+      .specialTaskLeft {
+        display: flex;
+        flex-direction: row;
+        width: 100%;
+      }
+      .SignText {
+        width: 80px;
+        font-weight: 600;
+      }
+      .signContent {
+        flex: 1;
+        display: flex;
+        flex-direction: row;
+        margin: 0 8px;
+        .icon {
+          padding-top: 2px;
+          margin-right: 5px;
+        }
+      }
+    }
+    .shopSignButton {
+      width: 56px;
+      button {
+        width: 55px;
+        height: 28px;
+        padding: 0;
+        font-size: 12px;
+      }
+    }
+    .shopSignImg {
+      .text {
+        font-size: 16px;
+        font-weight: 600;
+        padding: 15px 10px;
+      }
+      .imgBox {
+        width: 100%;
+        text-align: center;
+        img {
+          width: 60%;
+        }
+      }
+    }
+  }
+}
+</style>
+<style lang="scss">
+.perfectStoreSign {
+  .van-button--danger {
+    background-color: #ee0a24 !important;
+    border: 1px solid #ee0a24 !important;
+  }
+}
+</style>

+ 337 - 0
src/views/historicalVisit/perfectStoreSku.vue

@@ -0,0 +1,337 @@
+<template>
+  <div class="perfectStoreSku">
+    <van-nav-bar class="navBar" title="拜访任务详情" left-arrow @click-left="onClickLeft">
+      <template #right> </template>
+    </van-nav-bar>
+    <div class="content" v-if="detail">
+      <div class="container">
+        <div class="headline">
+          <span class="headlineIcon"></span>
+          <span class="headlineTitle">生动化陈列</span>
+        </div>
+        <div style="padding: 10px">
+          <div class="imgBox" v-for="(urls, index) in detail.fileUrlList" :key="index">
+            <img :src="urls" @click="previewsImg(index)" />
+          </div>
+          <!-- <van-row gutter="5" class="imgEow">
+            <van-col span="6" v-for="(urls, index) in detail.fileUrlList" :key="index">
+              <div class="img-box">
+                <img :src="urls" @click="previewsImg(index)" />
+              </div>
+            </van-col>
+          </van-row> -->
+        </div>
+      </div>
+      <div class="skuDeatil" v-if="skuList">
+        <div class="headline" style="margin-top: 10px">
+          <span class="headlineIcon"></span>
+          <span class="headlineTitle">SKU图像识别结果:{{ detail.skuNum }}个</span>
+        </div>
+        <el-table
+          :data="skuList"
+          style="width: 100%; border-radius: 10px"
+          border
+          class="table-headermd1">
+          <el-table-column label="序号" type="index" align="center" width="40"> </el-table-column>
+          <el-table-column
+            label="品类"
+            prop="skuProductType"
+            align="center"
+            width="60"></el-table-column>
+          <el-table-column label="SKU名称" prop="name" align="center">
+            <template slot-scope="scope">
+              <span class="tipTitle">{{ scope.row.name }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="排面数" prop="count" align="center" width="50"></el-table-column>
+        </el-table>
+      </div>
+      <div class="skuDeatil" v-if="daojuList">
+        <div class="headline" style="margin-top: 10px">
+          <span class="headlineIcon"></span>
+          <span class="headlineTitle">道具识别结果:{{ daojuNum }}个</span>
+        </div>
+        <el-table
+          :data="daojuList"
+          style="width: 100%; border-radius: 10px"
+          border
+          class="table-headermd1">
+          <el-table-column label="序号" type="index" align="center" width="40"> </el-table-column>
+          <el-table-column
+            label="品类"
+            prop="skuProductType"
+            align="center"
+            width="60"></el-table-column>
+          <el-table-column label="道具名称" prop="name" align="center">
+            <template slot-scope="scope">
+              <span class="tipTitle">{{ scope.row.name }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="数量" prop="count" align="center" width="50"></el-table-column>
+        </el-table>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import deleteUploadImg from '@/components/deleteUploadImg';
+import { photoSkuImgSummary, photoSkuFeedback } from '@/api/historicalVisit.js';
+import { ImagePreview } from 'vant';
+export default {
+  name: 'perfectStoreSku',
+  components: { deleteUploadImg },
+  data() {
+    return {
+      visitsId: '',
+      detail: null,
+      daojuNum: 0,
+      skuList: [],
+      daojuList: [],
+    };
+  },
+  activated() {
+    this.visitsId = this.$route.query.visitId || '';
+    this.detail = null;
+    this.getDetail();
+  },
+  methods: {
+    getDetail() {
+      this.toastLoading(0, '加载中...', true);
+      photoSkuImgSummary({ visitsId: this.visitsId })
+        .then((res) => {
+          this.toastLoading().clear();
+          if (res.code == 200) {
+            this.detail = res.data;
+            this.skuList = [];
+            this.daojuList = [];
+            this.detail.skuList.forEach((val) => {
+              if (val.skuProductType == '道具') {
+                this.daojuList.push(val);
+              } else {
+                this.skuList.push(val);
+              }
+            });
+            if (this.detail.skuTotal != null && this.detail.skuNum != null) {
+              this.daojuNum = this.detail.skuTotal - this.detail.skuNum;
+            } else {
+              this.daojuNum = 0;
+            }
+          } else {
+            this.$dialog.alert({
+              message: res.msg,
+            });
+          }
+        })
+        .catch((err) => {
+          this.$dialog.alert({
+            message: err.msg,
+          });
+        });
+    },
+    previewsImg(index) {
+      ImagePreview({
+        images: this.detail.fileUrlList,
+        startPosition: index,
+      });
+    },
+    onClickLeft() {
+      this.$router.go(-1);
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.perfectStoreSku {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  overflow: hidden;
+  .content {
+    flex: 1;
+    overflow-y: auto;
+    // background: #fff;
+    padding: 10px 15px;
+    // margin-top: 10px;
+    .container {
+      background: #fff;
+      width: 100%;
+      border-radius: 6px;
+      // padding: 10px;
+      padding: 0 10px 10px 0px;
+      .imgEow {
+        .van-col {
+          &:last-child {
+          }
+        }
+      }
+      .imgBox {
+        width: 22%;
+        height: 80px;
+        position: relative;
+        display: inline-block;
+        border-radius: 6px;
+        overflow: hidden;
+        margin: 3px 1.5%;
+        img {
+          width: 100%;
+          height: 100%;
+        }
+      }
+    }
+    .title {
+      font-size: 16px;
+      padding-bottom: 10px;
+      font-weight: bold;
+    }
+    .tipsTitle {
+      font-size: 12px;
+      padding-bottom: 10px;
+    }
+    .tableTitle {
+      padding: 10px 0;
+      font-size: 16px;
+      font-weight: bold;
+      background: #f5f5f5;
+      margin: 15px 0;
+    }
+    .skuDeatil {
+    }
+    .feedbackHistorical {
+      .historicalContent {
+        flex: 1;
+        overflow-y: auto;
+        .rejectMsgItem {
+          margin-bottom: 20px;
+          border: 1px solid #ccc;
+          padding: 10px;
+          .item {
+            padding: 5px 0;
+            span {
+              display: inline-block;
+            }
+          }
+          .label {
+            width: 80px;
+            font-size: 14px;
+            font-weight: 600;
+          }
+          .value {
+            font-size: 14px;
+          }
+        }
+      }
+    }
+    .img-box {
+      width: 100%;
+      height: 80px;
+      position: relative;
+      display: inline-block;
+      border-radius: 6px;
+      overflow: hidden;
+      img {
+        width: 100%;
+        height: 100%;
+      }
+    }
+  }
+  .feedbackMsgBox {
+    min-height: 30%;
+    width: 90%;
+    padding: 10px 20px;
+    display: flex;
+    flex-direction: column;
+    overflow: hidden;
+    .feedbackTitle {
+      padding: 10px 0;
+      text-align: center;
+      font-size: 16px;
+      font-weight: 600px;
+    }
+    .feedbackContent {
+      flex: 1;
+      overflow-y: auto;
+      .van-field__control {
+        color: #666 !important;
+      }
+    }
+    .btnBox {
+      margin-bottom: 10px;
+      height: 44px;
+      display: flex;
+      justify-content: space-between;
+      button {
+        width: 45%;
+        border-radius: 10px;
+      }
+    }
+  }
+  .headline {
+    font-weight: 600;
+    font-size: 16px;
+    position: relative;
+    display: flex;
+    align-items: center;
+    padding-top: 10px;
+    .headlineIcon {
+      display: inline-block;
+      position: absolute;
+      width: 3px;
+      height: 60%;
+      background: #3875c6;
+      border-radius: 5px;
+    }
+    .headlineTitle {
+      display: inline-block;
+      padding: 0px 20px;
+      background: #eef5ff;
+      border-radius: 0 18px 18px 0;
+      height: 36px;
+      line-height: 36px;
+    }
+  }
+}
+</style>
+<style lang="scss">
+.skuDeatil {
+  width: 100%;
+  margin-top: 10px;
+  background: #fff;
+  border-radius: 6px;
+  .table-headermd1 {
+    font-size: 14px;
+    text-align: center;
+    position: initial;
+    width: 96% !important;
+    margin: 0 auto;
+    border-right: 0;
+    border-radius: 8px;
+    margin-top: 10px;
+    th {
+      color: #000;
+      font-weight: bold;
+    }
+    td {
+      color: #000;
+    }
+    .el-table__cell {
+      padding: 6px 0 !important;
+      .cell {
+        padding: 0;
+      }
+    }
+  }
+  .table-headermd1 th.el-table__cell {
+    background-color: #f5f5f5;
+  }
+}
+.feedbackMsgBox {
+  .van-cell {
+    border: 1px solid #ccc;
+  }
+  .van-field__control {
+    color: #666;
+  }
+}
+</style>

+ 496 - 0
src/views/historicalVisit/perfectStoreTSJ.vue

@@ -0,0 +1,496 @@
+<template>
+  <div class="perfectStoreTSJ">
+    <van-nav-bar class="navBar" title="AI 调色机识别" left-arrow @click-left="onClickLeft" />
+    <div class="content">
+      <div class="contentBox" v-for="val in tiaoSJArr">
+        <div class="deviceCode">
+          <div class="vertical"></div>
+          <div class="codeData">
+            <p style="margin: 13px 0">设备编号:{{ val.deviceCode || '' }}</p>
+            <p style="margin: 13px 0">投放编号:{{ val.putInCode || '' }}</p>
+          </div>
+        </div>
+        <div class="shopSign specialTask" v-if="val && val.qualifiedState">
+          <div class="specialTaskLeft">
+            <div class="SignText">识别结果:</div>
+            <div class="signContent">
+              <div class="icon">
+                <van-icon name="checked" color="#07c160" v-if="val.qualifiedState == '1'" />
+                <van-icon name="warning" color="#ee0a24" v-else />
+              </div>
+              <div :style="{ color: val.qualifiedState == '1' ? '#07c160' : '#ee0a24' }">
+                {{ val.qualifiedState == '1' ? '调色机完整,投放号正确' : val.unqualifiedReason }}
+              </div>
+            </div>
+            <div class="shopSignButton">
+              <div class="" style="display: flex">
+                <van-button round type="primary" v-if="val.qualifiedState == '1'">通过</van-button>
+                <van-button round type="danger" v-else>不通过</van-button>
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <div
+          class="container containert"
+          style="width: 100%; margin: 0 auto; padding-bottom: 10px"
+          v-if="val.collectionItemList.length">
+          <van-form ref="tabstoreVal">
+            <div v-for="(item, index) in val.collectionItemList" :key="index">
+              <div v-if="item.answerType == 'tel_send_code'" class="formLabel z-cell z-cells">
+                <van-cell>
+                  <template #title> {{ index + 1 }}.{{ item.collectionName }} </template>
+                </van-cell>
+                <div class="selesetText">
+                  <p class="mg0">{{ item.answerValue }}</p>
+                </div>
+              </div>
+              <div v-if="item.answerType == 'nyr'" class="formLabel z-cell z-cells">
+                <van-cell>
+                  <template #title> {{ index + 1 }}.{{ item.collectionName }} </template>
+                </van-cell>
+                <div class="selesetText">
+                  <p class="mg0">{{ item.answerValue }}</p>
+                </div>
+              </div>
+              <div class="formLabel z-cell z-cells" v-if="item.answerType == 'sz'">
+                <van-cell>
+                  <template #title> {{ index + 1 }}.{{ item.collectionName }} </template>
+                </van-cell>
+                <p class="mg0">{{ item.answerValue }}</p>
+                <p
+                  style="
+                    color: #444;
+                    font-size: 12px;
+                    margin: 0;
+                    padding: 10px 0;
+                    text-align: right;
+                  ">
+                  <van-field
+                    class="mobile-input"
+                    v-model="item.collectionOptionList[0].collectionOption"
+                    autosize
+                    readonly
+                    type="textarea" />
+                </p>
+                <div v-if="item.fileInfoList" class="imgBox">
+                  <img
+                    v-for="value in item.fileInfoList"
+                    :src="value.fileUrl"
+                    @click="previewsImg(item.fileInfoList)" />
+                </div>
+              </div>
+              <div class="formLabel z-cell z-cells" v-if="item.answerType == 'zp'">
+                <van-cell>
+                  <template #title> {{ index + 1 }}.{{ item.collectionName }} </template>
+                </van-cell>
+                <div v-if="item.fileInfoList" class="imgBox">
+                  <img
+                    v-for="value in item.fileInfoList"
+                    :src="value.fileUrl"
+                    @click="previewsImg(item.fileInfoList)" />
+                </div>
+              </div>
+              <div
+                class="formLabel z-cell z-cells"
+                v-if="item.answerType == 'wb' || item.answerType == 'dhwb'">
+                <van-cell>
+                  <template #title>
+                    {{ index + 1 }}.{{ item.collectionName }}
+                    <span
+                      style="color: #00afff; position: absolute; top: 8px; right: 0px"
+                      v-if="item.showHistory == 1"
+                      @click="getCollectionShowHistory(item)"
+                      >回显历史</span
+                    >
+                  </template>
+                </van-cell>
+                <div class="selesetText">
+                  <p class="mg0">{{ item.answerValue }}</p>
+                </div>
+                <p style="color: #444; font-size: 12px; margin: 0; text-align: right">
+                  <van-field
+                    class="mobile-input"
+                    v-model="item.collectionOptionList[0].collectionOption"
+                    autosize
+                    readonly
+                    type="textarea" />
+                </p>
+                <div v-if="item.fileInfoList" class="imgBox">
+                  <img
+                    v-for="value in item.fileInfoList"
+                    :src="value.fileUrl"
+                    @click="previewsImg(item.fileInfoList)" />
+                </div>
+              </div>
+              <div class="formLabel z-cell z-cells" v-if="item.answerType == 'tel'">
+                <van-cell>
+                  <template #title> {{ index + 1 }}.{{ item.collectionName }} </template>
+                </van-cell>
+                <div class="selesetText">
+                  <p class="mg0">{{ item.answerValue }}</p>
+                </div>
+                <p style="color: #444; font-size: 12px; margin: 0; text-align: right">
+                  <van-field
+                    class="mobile-input"
+                    v-model="item.collectionOptionList[0].collectionOption"
+                    autosize
+                    readonly
+                    type="textarea" />
+                </p>
+                <div v-if="item.fileInfoList" class="imgBox">
+                  <img
+                    v-for="value in item.fileInfoList"
+                    :src="value.fileUrl"
+                    @click="previewsImg(item.fileInfoList)" />
+                </div>
+              </div>
+              <div class="formLabel z-cell z-cells" v-if="item.answerType == 'date'">
+                <van-cell>
+                  <template #title> {{ index + 1 }}.{{ item.collectionName }} </template>
+                </van-cell>
+                <div class="selesetText">
+                  <p class="mg0">{{ item.answerValue }}</p>
+                </div>
+                <p style="color: #444; font-size: 12px; margin: 0; text-align: right">
+                  <van-field
+                    class="mobile-input"
+                    v-model="item.collectionOptionList[0].collectionOption"
+                    autosize
+                    readonly
+                    type="textarea" />
+                </p>
+                <div v-if="item.fileInfoList" class="imgBox">
+                  <img
+                    v-for="value in item.fileInfoList"
+                    :src="value.fileUrl"
+                    @click="previewsImg(item.fileInfoList)" />
+                </div>
+              </div>
+              <div class="formLabel z-cell z-cells" v-if="item.answerType == 'sm'">
+                <van-cell>
+                  <template #title> {{ index + 1 }}.{{ item.collectionName }} </template>
+                </van-cell>
+                <div class="selesetText">
+                  <div style="font-size: 14px" v-if="item.collectionOptionList[0].answerValue">
+                    <div v-if="item.success" style="color: green">
+                      <p>系统资产编码:{{ item.equipmentCode1 }}</p>
+                      <p>&nbsp;&nbsp;&nbsp;&nbsp;条形码编码:{{ item.equipmentCode2 }}</p>
+                      <span style="float: right; margin-top: -48px"
+                        ><van-icon name="passed" size="16" />&nbsp;一致</span
+                      >
+                    </div>
+                    <div v-if="!item.success" style="color: red">
+                      <p>系统资产编码:{{ item.equipmentCode1 }}</p>
+                      <p>&nbsp;&nbsp;&nbsp;&nbsp;条形码编码:{{ item.equipmentCode2 }}</p>
+                      <span style="float: right; margin-top: -48px"
+                        ><van-icon name="close" size="16" />&nbsp;不一致</span
+                      >
+                    </div>
+                  </div>
+                </div>
+                <p
+                  style="color: #444; font-size: 12px; margin: 0; text-align: right"
+                  v-if="item.collectionOptionList[0].collectionOption">
+                  <van-field
+                    class="mobile-input"
+                    v-model="item.collectionOptionList[0].collectionOption"
+                    autosize
+                    readonly
+                    type="textarea" />
+                </p>
+                <div v-if="item.fileInfoList" class="imgBox">
+                  <img
+                    v-for="value in item.fileInfoList"
+                    :src="value.fileUrl"
+                    @click="previewsImg(item.fileInfoList)" />
+                </div>
+              </div>
+              <div class="formLabel z-cell z-cells" v-if="item.answerType == 'duox'">
+                <van-cell>
+                  <template #title> {{ index + 1 }}.{{ item.collectionName }} </template>
+                </van-cell>
+                <div class="selesetText">
+                  <p class="mg0" v-for="(item1, index1) in item.collectionOptionList" :key="index1">
+                    <span v-if="item1.isCheck == 1">{{ item1.collectionOption }}</span>
+                  </p>
+                </div>
+                <div v-if="item.fileInfoList" class="imgBox">
+                  <img
+                    v-for="value in item.fileInfoList"
+                    :src="value.fileUrl"
+                    @click="previewsImg(item.fileInfoList)" />
+                </div>
+              </div>
+              <div class="formLabel z-cell z-cells" v-if="item.answerType == 'dx'">
+                <van-cell>
+                  <template #title> {{ index + 1 }}.{{ item.collectionName }} </template>
+                </van-cell>
+                <div class="selesetText">
+                  <p class="mg0" v-for="(item2, index2) in item.collectionOptionList" :key="index2">
+                    <span v-if="item2.isCheck == 1">{{ item2.collectionOption }}</span>
+                  </p>
+                </div>
+                <div v-if="item.fileInfoList" class="imgBox">
+                  <img
+                    v-for="value in item.fileInfoList"
+                    :src="value.fileUrl"
+                    @click="previewsImg(item.fileInfoList)" />
+                </div>
+              </div>
+            </div>
+          </van-form>
+        </div>
+        <!-- <div class="shopSignImg">
+          <div class="text">店招照片</div>
+          <div class="imgBox">
+            <img
+              v-if="val && val.qualifiedState"
+              :src="val.fileUrl"
+              @click="previewsImg(val.fileUrl)" />
+          </div>
+        </div> -->
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import deleteUploadImg from '@/components/deleteUploadImg';
+import { getVisitsDetailPerfectStore } from '@/api/index';
+import { ImagePreview } from 'vant';
+export default {
+  name: 'perfectStoreTSJ',
+  components: { deleteUploadImg },
+  data() {
+    return {
+      visitsId: '',
+      detail: null,
+      tiaoSJArr: null,
+      //   collectionItemList: [],
+    };
+  },
+  activated() {
+    this.visitsId = this.$route.query.visitId || '';
+    this.detail = null;
+    this.getVisitsDetailFn();
+  },
+  methods: {
+    getVisitsDetailFn() {
+      this.toastLoading(0, '加载中...', true);
+      this.tiaoSJArr = null;
+      //   this.collectionItemList = [];
+      getVisitsDetailPerfectStore({ visitsId: this.visitsId })
+        .then((res) => {
+          this.toastLoading().clear();
+          if (res.code == 200) {
+            this.detail = res.data;
+            this.tiaoSJArr = this.detail.sfaTaskList.filter((val) => val.photoIdentifyType == '3');
+            console.log(this.tiaoSJArr);
+            for (let i = 0; i < this.tiaoSJArr.length; i++) {
+              this.filterCollectionItemLists(this.tiaoSJArr[i].collectionItemList);
+            }
+          } else {
+            this.$dialog.alert({
+              message: res.msg,
+            });
+          }
+        })
+        .catch((err) => {
+          this.$dialog.alert({
+            message: err.msg,
+          });
+        });
+    },
+    filterCollectionItemLists(item) {
+      for (let q = 0; q < item.length; q++) {
+        if (
+          item[q].answerType == 'sz' ||
+          item[q].answerType == 'wb' ||
+          item[q].answerType == 'tel' ||
+          item[q].answerType == 'date' ||
+          item[q].answerType == 'tel_send_code' ||
+          item[q].answerType == 'check_code' ||
+          item[q].answerType == 'nyr' ||
+          item[q].answerType == 'dhwb'
+        ) {
+          item[q].answerValue = item[q].collectionOptionList[0].answerValue;
+        }
+        if (item[q].answerType == 'sm') {
+          item[q].success = false;
+          if (
+            item[q].collectionOptionList[0].answerValue != null &&
+            item[q].collectionOptionList[0].answerValue != ''
+          ) {
+            item[q].equipmentCode2 = item[q].collectionOptionList[0].answerValue.split(',')[1];
+            if (item[q].collectionOptionList[0].answerValue.split(',')[0] != 'null') {
+              item[q].equipmentCode1 = item[q].collectionOptionList[0].answerValue.split(',')[0];
+            } else {
+              item[q].equipmentCode1 = '编码不存在';
+            }
+            if (
+              item[q].collectionOptionList[0].answerValue.split(',')[0] ==
+              item[q].collectionOptionList[0].answerValue.split(',')[1]
+            ) {
+              item[q].success = true;
+            }
+          }
+        }
+        if (item[q].answerType == 'duox' || item[q].answerType == 'dx') {
+          item[q].answerValue = [];
+          if (item[q].collectionOptionList.length) {
+            for (var qq = 0; qq < item[q].collectionOptionList.length; qq++) {
+              if (item[q].collectionOptionList[qq].isCheck == 1) {
+                item[q].answerValue.push(item[q].collectionOptionList[qq].collectionOptionId);
+                item[q].collectionOptionList[qq].code = item[q].collectionCode;
+                item[q].collectionOptionList[qq].answerType = item[q].answerType;
+              }
+            }
+            item[q].answerValue = item[q].answerValue.join();
+          }
+        }
+      }
+    },
+    previewsImg(fileInfoList) {
+      var arrimg = [];
+      for (var imgi = 0; imgi < fileInfoList.length; imgi++) {
+        arrimg.push(fileInfoList[imgi].fileUrl);
+      }
+      ImagePreview(arrimg);
+    },
+    onClickLeft() {
+      this.$router.go(-1);
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.perfectStoreTSJ {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  overflow: hidden;
+  .content {
+    flex: 1;
+    overflow-y: auto;
+    padding: 10px 15px;
+    .contentBox {
+      width: 100%;
+      margin-top: 10px;
+      .deviceCode {
+        font-size: 16px;
+        background-color: white;
+        border-radius: 5px;
+        position: relative;
+        overflow: hidden;
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-bottom: 10px;
+        // padding: 3px 0;
+      }
+      .vertical {
+        background-color: rgb(25, 137, 250);
+        height: 14px;
+        width: 8px;
+        border-radius: 40px;
+        margin-right: 10px;
+      }
+      .container {
+        background: #fff;
+      }
+    }
+
+    // ///////
+    .specialTask {
+      display: flex;
+      flex-direction: row;
+      padding: 10px;
+      font-size: 16px;
+      justify-content: space-between;
+      background: #e5faff;
+      .specialTaskLeft {
+        display: flex;
+        flex-direction: row;
+        width: 100%;
+      }
+      .SignText {
+        width: 80px;
+        font-weight: 600;
+      }
+      .signContent {
+        flex: 1;
+        display: flex;
+        flex-direction: row;
+        margin: 0 8px;
+        .icon {
+          padding-top: 2px;
+          margin-right: 5px;
+        }
+      }
+    }
+    .shopSignButton {
+      width: 56px;
+      button {
+        width: 55px;
+        height: 28px;
+        padding: 0;
+        font-size: 12px;
+      }
+    }
+    .shopSignImg {
+      .text {
+        font-size: 16px;
+        font-weight: 600;
+        padding: 15px 10px;
+      }
+    }
+  }
+  .imgBox {
+    width: 100%;
+    text-align: center;
+    img {
+      width: 60%;
+    }
+  }
+}
+</style>
+<style lang="scss">
+.perfectStoreTSJ {
+  .van-button--danger {
+    background-color: #ee0a24 !important;
+    border: 1px solid #ee0a24 !important;
+  }
+  .formLabel {
+    margin: 0 16px;
+    // padding-bottom: 16px;
+    border-bottom: 1px solid #f1f1f1;
+  }
+
+  .formLabel .van-cell {
+    padding: 5px 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;
+  }
+}
+</style>

+ 527 - 0
src/views/historicalVisit/perfectStoreTask.vue

@@ -0,0 +1,527 @@
+<template>
+  <div class="perfectStoreTask" v-if="formData">
+    <van-nav-bar class="navBar" left-arrow :title="formData.taskName" @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> -->
+                  <div class="headline">
+                    <span class="headlineIcon"></span>
+                    <span class="headlineTitle">任务相关照片</span>
+                  </div>
+                  <!-- 操作说明图片和电话 -->
+                  <taskTips
+                    v-if="item.contactPhone || item.examplePhoto"
+                    :contactPhone="item.contactPhone"
+                    :examplePhoto="item.examplePhoto">
+                  </taskTips>
+                </template>
+              </van-cell>
+              <template
+                v-if="
+                  formData.taskPhotoSkuImageUrlList && formData.taskPhotoSkuImageUrlList.length
+                ">
+                <div
+                  class="imgBox"
+                  v-for="(urls, index) in formData.taskPhotoSkuImageUrlList"
+                  :key="index">
+                  <img
+                    :src="urls.skuImageUrl"
+                    @click="previewsImg(formData.taskPhotoSkuImageUrlList, index)" />
+                </div>
+              </template>
+              <!-- <deleteUploadImg
+                :imgs="item.fileInfoList"
+                :storeGroupId="storeGroupId"
+                :taskIds="taskIds"
+                :visitsId="visitsId"
+                :collectionItemId="item.collectionId"
+                :putInCode="formData.putInCode"
+                :photoIdentifyType="formData.photoIdentifyType"
+                :pictureSource="item.pictureSource"
+                :continuousShoot="item.continuousShoot"
+                :insert="insert"
+                :objectType="objectType"
+                v-if="item.fileInfoList.length"></deleteUploadImg> -->
+              <span v-else>暂未识别到产品照片</span>
+            </div>
+          </div>
+        </van-form>
+      </div>
+      <div class="skuDeatil">
+        <div class="headline" style="margin-top: 10px">
+          <span class="headlineIcon"></span>
+          <span class="headlineTitle">SKU图像识别结果</span>
+        </div>
+        <el-table
+          :data="formData.taskPhotoRecognitionResult"
+          :span-method="taskObjectSpanMethod"
+          border
+          class="table-headermd1"
+          style="width: 100%">
+          <el-table-column label="序号" type="index" align="center" width="40"> </el-table-column>
+          <el-table-column
+            label="品类"
+            prop="skuProductType"
+            align="center"
+            width="60"></el-table-column>
+          <el-table-column label="SKU名称" prop="skuProductName" align="center">
+            <template slot-scope="scope">
+              <span class="tipTitle">{{ scope.row.skuProductName }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="排面数"
+            prop="identifyTheNumberOfCards"
+            align="center"
+            width="50"></el-table-column>
+          <el-table-column label="要求" prop="conditionIdentifyNum" align="center" width="60px">
+            <template slot-scope="scope">
+              <span :style="{ color: scope.row.meetTheStandard == 1 ? '#07c160' : 'red' }">
+                {{ scope.row.conditionIdentifyNum }}
+              </span>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <div class="dataList" v-if="dataList">
+        <div class="headline" style="margin-top: 10px">
+          <span class="headlineIcon"></span>
+          <span class="headlineTitle">陈列任务要求</span>
+        </div>
+        <div class="dataItem" v-for="(item, index) in dataList">
+          <div class="itemTop">
+            <div class="itemIndex">
+              <p>{{ index + 1 }}、</p>
+            </div>
+            <div class="itemHtml" v-html="item.displayInstructions"></div>
+          </div>
+          <div class="itemBottom" v-if="insert == '0'">
+            <van-button round type="primary" v-if="item.taskPhotoConditionPassed == 1"
+              >通过</van-button
+            >
+            <van-button round type="danger" v-else>不通过</van-button>
+            <!-- <img
+              @click="openDialog"
+              :src="
+                item.taskPhotoConditionPassed == 1
+                  ? require('@/assets/taskPhotoSu.png')
+                  : 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="formData.taskPhotoRecognitionResult"
+        style="padding: 0 10px">
+        <div class="resultContent">
+          <el-table
+            :data="formData.taskPhotoRecognitionResult"
+            :span-method="taskObjectSpanMethod"
+            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="identifyTheNumberOfCards"
+              width="70px"
+              align="center">
+            </el-table-column>
+            <el-table-column label="要求" prop="conditionIdentifyNum" align="center" width="60px">
+              <template slot-scope="scope">
+                <span :style="{ color: scope.row.meetTheStandard == 1 ? '#07c160' : 'red' }">
+                  {{ scope.row.conditionIdentifyNum }}
+                </span>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import { addCollectionAnswerBatch, getVisitsDetailPerfectStore } from '@/api/index';
+import taskTips from '@/views/deviceWithin/taskTips';
+import deleteUploadImg from '@/components/deleteUploadImgTaskPhoto';
+import { ImagePreview } from 'vant';
+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,
+      spanArr: [],
+    };
+  },
+  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;
+    this.formData = null;
+    this.getVisitsDetailFun();
+  },
+  methods: {
+    taskObjectSpanMethod({ row, column, rowIndex, columnIndex }) {
+      const cellValue = row[column.property];
+      if (cellValue && ['conditionIdentifyNum'].includes(column.property)) {
+        const _row = this.spanArr[rowIndex]; // 合并行数
+        const _col = this.spanArr[rowIndex] > 0 ? 1 : 0; // 合并的列数
+        return {
+          rowspan: _row,
+          colspan: _col,
+        };
+      }
+    },
+    getSpanArr(data) {
+      if (!data) return;
+      this.spanArr = []; // tip: 后台获取完成数据后,一定要重置spanArr=[],避免出现合并混乱!!!!!
+      for (let i = 0; i < data.length; i++) {
+        // 当为第一行时
+        if (i === 0) {
+          this.spanArr.push(1);
+          this.pos = 0;
+        } else {
+          // 判断当前值是否与上一行的【名称】相等,相等则进行合并
+          if (data[i].conditionDetailId === data[i - 1].conditionDetailId) {
+            this.spanArr[this.pos] += 1; // 合并单元格:合并的行数 +1
+            this.spanArr.push(0); // 0代表单元格是不需要显示, 已经被合并的单元格
+          } else {
+            this.spanArr.push(1); // 1代表当前这行的数据需要被显示
+            this.pos = i;
+          }
+        }
+      }
+    },
+    getVisitsDetailFun() {
+      this.toastLoading(0, '加载中...', true);
+      getVisitsDetailPerfectStore({ visitsId: this.visitsId }).then((res) => {
+        this.toastLoading().clear();
+        if (res.data.sfaTaskList) {
+          this.dataList = res.data.sfaTaskList.filter(
+            (val) => val.taskId == this.$route.query.taskId,
+          );
+          this.formData = this.dataList[0];
+          console.log(this.formData.taskPhotoRecognitionResult);
+          this.getSpanArr(this.formData.taskPhotoRecognitionResult);
+          console.log(this.formData);
+        } else {
+          this.formData = null;
+        }
+      });
+    },
+    openDialog(item) {
+      this.vanPopup = true;
+    },
+    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);
+        }
+      });
+    },
+    previewsImg(fileInfoList, index) {
+      var arrimg = [];
+      for (var imgi = 0; imgi < fileInfoList.length; imgi++) {
+        arrimg.push(fileInfoList[imgi].skuImageUrl);
+      }
+      ImagePreview({
+        images: arrimg,
+        startPosition: index,
+      });
+    },
+    onClickLeft() {
+      this.$router.go(-1);
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.perfectStoreTask {
+  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;
+      padding: 0 10px 10px 0px;
+    }
+    .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;
+    }
+    .headline {
+      font-weight: 600;
+      font-size: 16px;
+      position: relative;
+      display: flex;
+      align-items: center;
+      .headlineIcon {
+        display: inline-block;
+        position: absolute;
+        width: 3px;
+        height: 60%;
+        background: #3875c6;
+        border-radius: 5px;
+      }
+      .headlineTitle {
+        display: inline-block;
+        padding: 0px 20px;
+        background: #eef5ff;
+        border-radius: 0 18px 18px 0;
+        height: 36px;
+        line-height: 36px;
+      }
+    }
+  }
+  .dataList {
+    width: 100%;
+    margin-top: 10px;
+    // overflow-y: auto;
+    background: #fff;
+    .dataItem {
+      display: flex;
+      // border-radius: 6px;
+      flex-direction: row;
+      margin-bottom: 10px;
+      // padding: 10px;
+      font-size: 16px;
+      margin-left: 20px;
+      border-bottom: 1px solid #e2e1e1;
+      .itemIndex {
+      }
+      .itemTop {
+        flex: 1;
+        overflow: hidden;
+        padding-bottom: 10px;
+        .itemHtml {
+          overflow-x: auto;
+        }
+      }
+      .itemTop,
+      .itemBottom {
+        display: flex;
+        flex-direction: row;
+      }
+      .itemBottom {
+        align-items: center;
+        width: 60px;
+        margin-left: 5px;
+        img {
+          width: 100%;
+          height: 30px;
+        }
+        button {
+          width: 55px;
+          height: 25px;
+          padding: 0;
+          font-size: 12px;
+        }
+      }
+    }
+  }
+  .tableTitle {
+    padding: 10px 0;
+    font-size: 16px;
+    font-weight: bold;
+    background: #f5f5f5;
+    margin: 15px 0;
+  }
+  .imgBox {
+    width: 22%;
+    height: 80px;
+    position: relative;
+    display: inline-block;
+    border-radius: 6px;
+    overflow: hidden;
+    margin: 3px 1.5%;
+    img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+}
+</style>
+<style lang="scss">
+.perfectStoreTask {
+  .van-button--danger {
+    background-color: #ee0a24 !important;
+    border: 1px solid #ee0a24 !important;
+  }
+}
+.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;
+    }
+  }
+}
+.skuDeatil {
+  width: 100%;
+  margin-top: 10px;
+  background: #fff;
+  border-radius: 6px;
+  .table-headermd1 {
+    font-size: 14px;
+    text-align: center;
+    position: initial;
+    width: 98% !important;
+    margin: 0 auto;
+    border-right: 0;
+    border-radius: 8px;
+    margin-top: 10px;
+    th {
+      color: #000;
+      font-weight: bold;
+    }
+    td {
+      color: #000;
+    }
+    .el-table__cell {
+      padding: 6px 0 !important;
+      .cell {
+        padding: 0;
+      }
+    }
+  }
+  .table-headermd1 th.el-table__cell {
+    background-color: #f5f5f5;
+  }
+}
+.el-table::before {
+  height: 0;
+}
+</style>