Bladeren bron

feature_20260203_完美门店

zhujindu 1 week geleden
bovenliggende
commit
8ddc613c00
3 gewijzigde bestanden met toevoegingen van 690 en 1 verwijderingen
  1. 5 0
      src/router/index.js
  2. 21 1
      src/views/deviceOutside/index.vue
  3. 664 0
      src/views/historicalVisit/PerfectStore.vue

+ 5 - 0
src/router/index.js

@@ -273,6 +273,11 @@ const router = new VueRouter({
           name: 'historicalDetails',
           component: () => import('@/views/historicalVisit/historicalDetails.vue'),
         },
+        {
+          path: '/PerfectStore',
+          name: 'PerfectStore',
+          component: () => import('@/views/historicalVisit/PerfectStore.vue'),
+        },
         {
           path: '/historiStoreVisit',
           name: 'historiStoreVisit',

+ 21 - 1
src/views/deviceOutside/index.vue

@@ -368,7 +368,16 @@
               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 == '已拜访'">
+              <div
+                class="statstext"
+                style="background-color: #ed5c68"
+                v-if="true"
+                @click="openPerfectStore(item)">
+                jinpaidian
+              </div>
+              <div class="statstext" v-else>已拜访</div>
+            </template>
             <div class="btnbox">
               <van-row>
                 <van-col
@@ -2346,6 +2355,17 @@ export default {
         });
       }
     },
+    // 完美门店
+    openPerfectStore(val) {
+      this.$router.push({
+        path: '/PerfectStore',
+        query: {
+          visitId: val.visitId,
+          storeId: val.storeId,
+          storeCode: val.storeCode,
+        },
+      });
+    },
   },
 };
 </script>

+ 664 - 0
src/views/historicalVisit/PerfectStore.vue

@@ -0,0 +1,664 @@
+<template>
+  <div class="PerfectStore">
+    <!--        顶部条-->
+    <van-nav-bar class="navBar" title="完美门店报告" 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>
+      <template v-if="list.isSku == '是'">
+        <div style="padding: 10px 16px; font-size: 16px; font-weight: bold">SKU图像识别结果</div>
+        <div class="card">
+          <div
+            class="info"
+            @click="toSkuRecognize"
+            style="
+              display: flex;
+              align-items: center;
+              justify-content: space-between;
+              padding: 3px;
+            ">
+            <p
+              style="flex: 1; margin: 0; line-height: 24px; padding: 10px 0; display: inline-block">
+              拍摄的所有产品陈列照识别结果:<span v-if="list.skuTotal" style="color: red"
+                >{{ list.skuTotal }}个</span
+              >
+            </p>
+            <p class="arrowdetils1">
+              <van-icon name="arrow" />
+            </p>
+          </div>
+        </div>
+      </template>
+      <!-- 特殊任务展示 -->
+      <!-- 店招 -->
+      <div class="shopSign specialTask" v-if="shopSignDetail">
+        <div class="SignText">店招</div>
+        <div class="signContent">
+          <div class="icon">
+            <van-icon name="checked" color="#07c160" v-if="shopSignDetail.status == '1'" />
+            <van-icon name="warning" color="#ee0a24" v-else />
+          </div>
+          <div
+            class="content"
+            :style="{ color: shopSignDetail.status == '1' ? '#07c160' : '#ee0a24' }">
+            {{ shopSignDetail.status == '1' ? '已通过' : '未通过' }}
+          </div>
+        </div>
+        <div class="shopSignImg">
+          <img :src="shopSignDetail.fileUrl" @click="previewsImg(shopSignDetail.fileUrl)" />
+        </div>
+      </div>
+      <!-- 调色机 -->
+      <div class="TSJBox specialTask" v-if="tiaoSJDetail">
+        <div class="SignText">调色机</div>
+        <div class="signContent">
+          <div class="icon">
+            <van-icon name="checked" color="#07c160" v-if="tiaoSJDetail.status == '1'" />
+            <van-icon name="warning" color="#ee0a24" v-else />
+          </div>
+          <div
+            class="content"
+            :style="{ color: tiaoSJDetail.status == '1' ? '#07c160' : '#ee0a24' }">
+            {{ tiaoSJDetail.status == '1' ? '已通过' : '未通过' }}
+          </div>
+        </div>
+        <div class="shopSignImg">
+          <img :src="tiaoSJDetail.fileUrl" @click="previewsImg(tiaoSJDetail.fileUrl)" />
+        </div>
+      </div>
+
+      <div style="padding: 10px 16px; font-size: 16px; font-weight: bold">任务</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"
+          @click="historiStoreVisit(item, index)">
+          <template v-if="item.photoIdentifyType != '1' && item.photoIdentifyType != '3'">
+            <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>
+          </template>
+        </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 {
+  getVisitsDetail,
+  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,
+    };
+  },
+  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() {
+      getVisitsDetail({ visitsId: this.$route.query.visitId }).then((res) => {
+        this.toastLoading().clear();
+        if (res.code == 200) {
+          this.list = res.data;
+          this.list.sfaTaskList = this.filterSfaTaskList(this.list.sfaTaskList);
+          this.list.sfaTaskList.forEach((val) => {
+            if (val.photoIdentifyType == '1') {
+              this.shopSignDetail = val;
+            }
+            if (val.photoIdentifyType == '3') {
+              this.tiaoSJDetail = val;
+            }
+          });
+          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) {
+      let taskTypeArr = list.filter((val) => val.taskType !== '5');
+      let taskType5Index = list.findIndex((val) => val.taskType == '5');
+      if (taskType5Index != -1) {
+        let taskType5Arr = list.filter((val) => val.taskType == '5');
+        let taskIds = [];
+        taskType5Arr.forEach((val) => {
+          taskIds.push(val.taskId);
+        });
+        let taskType5 = {
+          ...list[taskType5Index],
+          taskIds: taskIds,
+          taskPhotoConditionPassed: null,
+        };
+        taskType5.taskName = '生动化陈列';
+        taskTypeArr.splice(taskType5Index, 0, taskType5);
+      }
+      console.log(taskTypeArr);
+      return taskTypeArr;
+    },
+    historiStoreVisit(val, index) {
+      if (val.taskType == '5') {
+        this.$router.push({
+          path: '/taskPhotoTaking',
+          query: {
+            storeCode: this.$route.query.storeCode || this.list.storeCode,
+            visitsId: this.visitsId,
+            taskIds: val.taskIds.join(','),
+            storeGroupId: this.list.storeGroupId,
+            insert: 0,
+            source: 'historicalDetails',
+          },
+        });
+      } else {
+        this.$router.push({
+          path: '/historiStoreVisit',
+          query: { visitId: this.visitsId, ids: index, taskType: val.taskType, taskId: val.taskId },
+        });
+      }
+      sessionStorage.setItem('collectionItemList', JSON.stringify(val.collectionItemList));
+    },
+    toSkuRecognize() {
+      this.$router.push({
+        path: '/skuRecognize',
+        query: { visitId: this.visitsId },
+      });
+    },
+    onClickLeft() {
+      if (this.$route.query.token) {
+        this.$router.push({
+          path: '/historicalVisit',
+        });
+      } else {
+        this.$router.go(-1);
+      }
+    },
+    previewsImg(url) {
+      ImagePreview([url]);
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.PerfectStore {
+  .specialTask {
+    display: flex;
+    flex-direction: row;
+    margin: 5px 10px;
+    border-radius: 10px;
+  }
+  .shopSign {
+    background: #e5faff;
+  }
+  .TSJBox {
+    background: #fff4e4;
+    margin-top: 20px;
+  }
+}
+.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;
+    }
+  }
+}
+.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>