ソースを参照

Merge remote-tracking branch 'origin/mergeBranch' into mergeBranch

qymljy 2 年 前
コミット
56bdcb9273

+ 15 - 1
src/App.vue

@@ -4,10 +4,16 @@
   </div>
 </template>
 <script>
+  import {mapGetters} from 'vuex'
   export default{
     data () {
       return {}
     },
+    computed:{
+    ...mapGetters({
+      searchValue:'searchValue',
+    })
+  },
     methods:{
     },
     created () {
@@ -25,7 +31,7 @@
             })
             sessionStorage.setItem('active_modules',JSON.stringify(val.meta.modules))
             
-            this.$store.dispatch('setActiveApp',{app:app[0],val:''})
+            this.$store.dispatch('setActiveApp',{app:app[0],val:this.searchValue})
 
             let system = JSON.parse(sessionStorage.getItem('module_info'))
             
@@ -54,4 +60,12 @@ body{
   background: rgba(255,255,255,.5);
   box-shadow: 0 2px 5px rgb(0 0 0 / 10%);
 }
+.el-drawer__header{
+  padding: 10px !important;
+  margin-bottom: 0 !important;
+  font-size: 16px  !important;
+  font-family: PingFang SC-Bold, PingFang SC;
+  font-weight: bold  !important;
+  color: #333333  !important;
+}
 </style>

+ 1 - 7
src/HManagement/clueManage/clue_public/modules/add.vue

@@ -15,7 +15,7 @@
             <el-input v-model="param.content.phonenumber" size="small"></el-input>
           </el-form-item>
           <el-form-item label="省市县" prop="province">
-            <el-cascader size="small" class="width-240" v-model="param.content.province" :options="_arealist"
+            <el-cascader size="small" class="width-240" v-model="param.content.province" :options="basicData.data().areaData"
               @change="cascaderChange" ref="cascader">
             </el-cascader>
           </el-form-item>
@@ -81,12 +81,6 @@ export default {
       type:Function
     }
   },
-  inject:['arealist'],
-  computed:{
-    _arealist() {
-      return this.arealist()
-    }
-  },
   methods: {
     onShow () {
       this.drawer = true

+ 16 - 3
src/HManagement/clueManage/clue_public/modules/detail.vue

@@ -46,8 +46,16 @@
         <div class="item" v-for="(item,index) in recordlist" :key="index">
           <p>{{index + 1}}.{{item.createdate}},由经销商端<span style="font-weight:bold;margin:0 6px;font-size:13px">{{item.createby}}</span>开始跟进,跟进方式:<span style="font-weight:bold;margin:0 5px">{{item.followupmode}}</span>,{{handleTxt[item.logtype]}}</p>
           <div class="content">
-            <p v-if="item.competitor">已购买品牌:{{item.competitor}}</p>
-            {{item.content}}
+            <div style="margin-bottom:10px">
+              <p v-if="item.competitor">已购买品牌:{{item.competitor}}</p>
+              {{item.content}}
+            </div>
+            <file-item 
+              :rowCount="5"
+              :isDownLoad="true" 
+              :fileData="item.attinfo"
+              @deleteSuccess="deleteFile">
+            </file-item>
           </div>
         </div>
       </div>
@@ -56,6 +64,7 @@
 </template>
 
 <script>
+import FileItem from '@/SManagement/orderclue/components/file/index2'
 import BaseInfo from '@/HDrpManagement/projectChange/modules/modules/baseInfo/baseInfo'
 import recall from './recall.vue'
 export default {
@@ -81,7 +90,8 @@ export default {
     }
   },
   components:{
-    BaseInfo,recall
+    BaseInfo,recall,
+    FileItem
   },
   methods:{
     async followRecord () {
@@ -95,6 +105,9 @@ export default {
         }
       })
       this.recordlist = res.data
+      this.recordlist.forEach(item => {
+        item.attinfo = this.fileType.fileList(item.attinfo)
+      })
     },
     dateChange (val) {
       if (!val) {val = []}

+ 2 - 0
src/SManagement/notice/notice_detail/NoticeDetail.vue

@@ -118,6 +118,8 @@ export default {
       this.param.content.sat_noticeid = this.$route.query.id
       let res = await this.$api.requested(this.param)
       this.detailData = res.data
+      console.log(this.detailData.attinfos);
+      
       this.detailData.attinfos = this.fileType.fileList(this.detailData.attinfos)
       this.detailData.content != '<p><br></p>' ? this.compileFWB() : ''
     },

+ 1 - 1
src/SManagement/orderclue/components/edit.vue

@@ -114,7 +114,7 @@ export default {
   methods: {
     isHandleFun () {
       let is 
-      if(JSON.parse(window.sessionStorage.getItem('userInfo')).userid == this.data.leader[0].userid) {
+      if(this.data.leader && JSON.parse(window.sessionStorage.getItem('userInfo')).userid == this.data.leader[0].userid) {
         is = true
         if(this.data.status == '待跟进' || this.data.status == '跟进中') {
           is = true

+ 55 - 0
src/SManagement/orderclue/components/file-block/components/SeeFile.vue

@@ -0,0 +1,55 @@
+<template>
+  <el-dialog
+    append-to-body
+    title="预览"
+    :visible.sync="dialogVisible"
+    :before-close="handleClose"
+    v-if="fileData">
+    <video :src="fileData.url" controls v-if="fileData.fileType == 'video'"></video>
+    <el-image 
+      :src="fileData.url" 
+      v-if="fileData.fileType == 'image'">
+    </el-image>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  name: '',
+  data() {
+    return {
+      dialogVisible:false
+    };
+  },
+  props:['fileData'],
+  computed:{
+  },
+  watch:{
+  },
+  created() {
+
+  },
+  methods: {
+    handleClose() {
+      this.dialogVisible = false
+    }
+  },
+};
+</script>
+
+<style scoped>
+  video {
+    width: 100%;
+  }
+  img {
+    width: 100%;
+  }
+  /deep/.el-dialog__body {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+  }
+  /deep/.el-dialog {
+    z-index: 9999;
+  }
+</style>

+ 198 - 0
src/SManagement/orderclue/components/file-block/index2.vue

@@ -0,0 +1,198 @@
+<template>
+
+  <div class="file-box">
+    <div 
+      class="item-file" 
+      v-for="(item,index) in fileData" 
+      :key="index"
+      :style="[
+        {'width': itemWidth + 'px'},
+        {'margin-right':marginRight + 'px'}
+      ]"
+    >
+      <div class="left">
+        <div class="image">
+          <el-image :src="item.cover" fit="cover" alt  />
+        </div>
+        <div class="text">
+          <el-tooltip v-if="item.document" class="item" effect="dark" :content="item.document" placement="top-start">
+            <p @click="downLoad(item)" style="font-size:14px" class="file-title">{{item.document}}</p>
+          </el-tooltip>
+          <el-tooltip v-if="item.createdate" class="item" effect="dark" :content="item.createdate" placement="bottom-start">
+            <p class="create-date" style="font-size:12px">{{item.createdate}}</p>
+          </el-tooltip>
+        </div>
+      </div>
+      <div class="right">
+        <i class="el-icon-zoom-in" @click="seeClick(item)"></i>
+        <i class="el-icon-delete" style="font-size:16px" @click="deleteFile(item,index)" v-if="isDelete"></i>
+      </div>
+    </div>
+    <see-File ref="seeFile" :fileData="seeFile"></see-File>
+  </div>
+</template>
+
+<script>
+import SeeFile from '@/components/file-block/components/SeeFile'
+
+import removeFile from '@/utils/removeFile'
+import { log } from '@antv/g2plot/lib/utils';
+export default {
+  name: 'index',
+  data () {
+    return {
+      seeFile: '',
+      isSeeFileShow:false,
+      fileBoxEl: '',
+      itemWidth:0
+    };
+  },
+  props: {
+    isDownLoad: Boolean,
+    isDelete:Boolean,
+    fileData: {
+      default() {
+        return []
+      }
+    },
+    /* 一行展示几个 */
+    rowCount: {
+      type: Number,
+      default () {
+        return 1
+      }
+    },
+    /* 块margin-right */
+    marginRight: {
+      type:Number,
+      default () {
+        return 20
+      }
+    },
+  },
+  components: {
+    SeeFile,
+  },
+  computed: {
+  },
+  watch: {
+  },
+  created() {
+    
+  },
+  mounted () {
+    let el = document.querySelector('.file-box')
+    this.itemWidth = el.clientWidth / this.rowCount - this.marginRight > 200 ? el.clientWidth / this.rowCount - this.marginRight : 200
+  },
+  methods: {
+    debouned () {
+
+    },
+    deleteFile(item,index) {
+      let temp = item
+      removeFile.removeFileList([item]).then(res => {
+        this.tool.showMessage(res,() => {
+          this.$emit('deleteSuccess',temp)
+        })
+      })
+      this.$emit('deleteFile',index)
+    },
+    //预览
+    seeClick(item) {
+      if(item.fileType == 'image' || item.fileType == 'video') {
+        this.seeFile = item
+        this.$refs.seeFile.dialogVisible = true
+      } else {
+        this.$notify({
+          title:'提示',
+          message:'该文件暂不支持',
+          type:'warning'
+        })
+      }
+    },
+    downLoad(item) {
+      this.$emit('updateDownLoadRecord',item)
+      window.open(item.url,'_self')
+    }
+  },
+};
+</script>
+
+<style scoped>
+*{
+  box-sizing: border-box;
+}
+.file-box {
+  width: 100%;
+  display: flex;
+  flex-wrap: wrap;
+}
+.item-file {
+  display: flex;
+  padding: 10px;
+  display: flex;
+  align-items: center;
+  cursor: pointer;
+  transition: .2s linear;
+  cursor: pointer;
+  border-radius: 5px;
+  margin-bottom: 20px;
+  background: #ffffff;
+}
+.item-file:hover {
+  box-shadow: 0 5px 10px rgb(0 0 0 / 10%);
+}
+.file-box .left {
+  width: 90%;
+  height: 100%;
+  display: flex;
+  align-items: center;
+}
+.file-box .left .image {
+  width: 50%;
+  margin-right: 10px;
+}
+.file-box .left .image .el-image{
+  width: 100%;
+}
+.file-box .left .text {
+  width: 50%;
+  font-size: 14px;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-evenly;
+  height: 100%;
+  padding-right: 10px;
+}
+.file-box .left .text .file-title {
+  color: #3874f6;
+  font-size: 16px;
+  text-decoration: underline;
+
+  text-overflow: ellipsis;
+  overflow: hidden;
+  white-space: nowrap;
+}
+.file-box .left .text .create-date {
+  text-overflow: ellipsis;
+  overflow: hidden;
+  white-space: nowrap;
+}
+
+.file-box .right {
+  width: 10%;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: space-evenly;
+  height: 100%;
+}
+.file-box .right .see{}
+.el-empty {
+  height: 150px;
+  transform: scale(70%);
+}
+/deep/.el-dialog__wrapper {
+  z-index: 9999;
+}
+</style>

+ 55 - 0
src/SManagement/orderclue/components/file/components/SeeFile.vue

@@ -0,0 +1,55 @@
+<template>
+  <el-dialog
+    append-to-body
+    title="预览"
+    :visible.sync="dialogVisible"
+    :before-close="handleClose"
+    v-if="fileData">
+    <video :src="fileData.url" controls v-if="fileData.fileType == 'video'"></video>
+    <el-image 
+      :src="fileData.url" 
+      v-if="fileData.fileType == 'image'">
+    </el-image>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  name: '',
+  data() {
+    return {
+      dialogVisible:false
+    };
+  },
+  props:['fileData'],
+  computed:{
+  },
+  watch:{
+  },
+  created() {
+
+  },
+  methods: {
+    handleClose() {
+      this.dialogVisible = false
+    }
+  },
+};
+</script>
+
+<style scoped>
+  video {
+    width: 100%;
+  }
+  img {
+    width: 100%;
+  }
+  /deep/.el-dialog__body {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+  }
+  /deep/.el-dialog {
+    z-index: 9999;
+  }
+</style>

+ 197 - 0
src/SManagement/orderclue/components/file/index2.vue

@@ -0,0 +1,197 @@
+<template>
+
+  <div class="file-box">
+    <div 
+      class="item-file" 
+      v-for="(item,index) in fileData" 
+      :key="index"
+      :style="[
+        {'width': auto ? '100%' : '300px'},
+        {'margin-right':marginRight + 'px'}
+      ]"
+    >
+      <div class="left">
+        <div class="image">
+          <el-image :src="item.cover" fit="cover" alt  />
+        </div>
+        <div class="text">
+          <!-- <el-tooltip v-if="item.document" class="item" effect="dark" :content="item.document" placement="top-start"> -->
+            <p @click="downLoad(item)" style="font-size:14px" class="file-title">{{item.document}}</p>
+          <!-- </el-tooltip> -->
+          <p class="create-date" style="font-size:12px">{{item.createdate}}</p>
+        </div>
+      </div>
+      <div class="right">
+        <i class="el-icon-zoom-in" @click="seeClick(item)"></i>
+        <i class="el-icon-delete" style="font-size:16px" @click="deleteFile(item,index)" v-if="isDelete"></i>
+      </div>
+    </div>
+    <see-File ref="seeFile" :fileData="seeFile"></see-File>
+  </div>
+</template>
+
+<script>
+import SeeFile from '@/components/file-block/components/SeeFile'
+
+import removeFile from '@/utils/removeFile'
+import { log } from '@antv/g2plot/lib/utils';
+export default {
+  name: 'index',
+  data () {
+    return {
+      seeFile: '',
+      isSeeFileShow:false,
+      fileBoxEl: '',
+      itemWidth:0
+    };
+  },
+  props: {
+    auto: Boolean,
+    isDownLoad: Boolean,
+    isDelete:Boolean,
+    fileData: {
+      default() {
+        return []
+      }
+    },
+    /* 一行展示几个 */
+    rowCount: {
+      type: Number,
+      default () {
+        return 1
+      }
+    },
+    /* 块margin-right */
+    marginRight: {
+      type:Number,
+      default () {
+        return 0
+      }
+    },
+  },
+  components: {
+    SeeFile,
+  },
+  computed: {
+  },
+  watch: {
+  },
+  created() {
+    
+  },
+  mounted () {
+    let el = document.querySelector('.file-box')
+    this.itemWidth = el.clientWidth / this.rowCount - this.marginRight > 200 ? el.clientWidth / this.rowCount - this.marginRight : 200
+  },
+  methods: {
+    debouned () {
+
+    },
+    deleteFile(item,index) {
+      let temp = item
+      removeFile.removeFileList([item]).then(res => {
+        this.tool.showMessage(res,() => {
+          this.$emit('deleteSuccess',temp)
+        })
+      })
+      this.$emit('deleteFile',index)
+    },
+    //预览
+    seeClick(item) {
+      if(item.fileType == 'image' || item.fileType == 'video') {
+        this.seeFile = item
+        this.$refs.seeFile.dialogVisible = true
+      } else {
+        this.$notify({
+          title:'提示',
+          message:'该文件暂不支持',
+          type:'warning'
+        })
+      }
+    },
+    downLoad(item) {
+      this.$emit('updateDownLoadRecord',item)
+      window.open(item.url,'_self')
+    }
+  },
+};
+</script>
+
+<style scoped>
+*{
+  box-sizing: border-box;
+}
+.file-box {
+  width: 100%;
+  display: flex;
+  flex-wrap: wrap;
+}
+.item-file {
+  display: flex;
+  padding: 10px;
+  display: flex;
+  align-items: center;
+  cursor: pointer;
+  transition: .2s linear;
+  cursor: pointer;
+  border-radius: 5px;
+  margin-bottom: 20px;
+  background: #ffffff;
+  height: 80px;
+}
+.item-file:hover {
+  box-shadow: 0 5px 10px rgb(0 0 0 / 10%);
+}
+.file-box .left {
+  width: 90%;
+  height: 100%;
+  display: flex;
+  align-items: center;
+}
+.file-box .left .image {
+  margin-right: 10px;
+}
+.file-box .left .image .el-image{
+  width: 50px;
+}
+.file-box .left .text {
+  width: calc(100% - 50px);
+  font-size: 14px;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-evenly;
+  height: 100%;
+  padding-right: 10px;
+}
+.file-box .left .text .file-title {
+  color: #3874f6;
+  font-size: 16px;
+  text-decoration: underline;
+
+  text-overflow: ellipsis;
+  overflow: hidden;
+  white-space: nowrap;
+}
+.file-box .left .text .create-date {
+  text-overflow: ellipsis;
+  overflow: hidden;
+  white-space: nowrap;
+}
+
+.file-box .right {
+  width: 10%;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: space-evenly;
+  height: 100%;
+}
+.file-box .right .see{}
+.el-empty {
+  height: 150px;
+  transform: scale(70%);
+}
+/deep/.el-dialog__wrapper {
+  z-index: 9999;
+}
+</style>

+ 101 - 118
src/SManagement/orderclue/components/follow.vue

@@ -1,110 +1,95 @@
 <template>
   <div class="follow" style="margin-right:10px">
-    <el-button 
-      size="mini" 
-      @click="followBtn"
-      :disabled="disabled"
-    >跟进</el-button>
-    <el-dialog title="线索跟进" append-to-body :visible.sync="dialogVisible" width="900" :before-close="handleClose">
-      <el-form :model="param" :rules="rules" ref="ruleForm" label-width="80px" class="demo-ruleForm"
-        label-position="right">
-        <el-row :gutter="10">
-          <el-col :span="12">
-            <el-form-item label="跟进时间" label-position="right" label-width="100px">
-              <!-- <el-input :value="getNowDate()" size="small" disabled></el-input> -->
-              <el-date-picker
-                v-model="timer"
-                type="date"
-                format="yyyy-MM-dd HH:mm:ss"
-                disabled
-                size="small">
-              </el-date-picker>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="本次跟进方式" label-width="130px" label-position="right" prop="followupmode">
+    <el-button size="mini" @click="followBtn" :disabled="disabled">跟进</el-button>
+    <el-drawer title="线索跟进" append-to-body :visible.sync="dialogVisible" size="30%" :before-close="handleClose">
+      <div class="drawer__panel">
+        <el-form :model="param" :rules="rules" ref="ruleForm" label-width="110px" class="demo-ruleForm"
+          label-position="right">
+          <el-form-item label="跟进时间">
+            <el-date-picker v-model="timer" type="date" format="yyyy-MM-dd HH:mm:ss" disabled size="small">
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="本次跟进方式" prop="followupmode">
             <el-select v-model="param.followupmode" placeholder="请选择方式" size="small">
-              <el-option label="当面拜访" value="当面拜访"></el-option>
-              <el-option label="电话沟通" value="电话沟通"></el-option>
+              <el-option v-for="(item,index) in followTypeList" :key="index" :label="item.value" :value="item.value">
+              </el-option>
             </el-select>
           </el-form-item>
-          </el-col>
-          <el-col :span="24">
-            <el-form-item label="本次跟进结果" label-width="110px" label-position="right" prop="logtype">
-              <el-radio-group v-model="param.logtype">
-                <el-radio label="跟进">跟进</el-radio>
-              </el-radio-group>
-            </el-form-item>
-          </el-col>
-          <el-col :span="24" v-if="param.logtype == '丢单'">
-            <el-form-item label="已购买商品" prop="competitor" label-width="200px">
-              <el-input v-model="param.competitor" size="small"></el-input>
-            </el-form-item>
-          </el-col>
-          <el-col :span="24">
-            <el-form-item label="跟进内容" prop="content" v-if="param.logtype == '跟进'">
-              <el-input type="textarea" v-model="param.content" size="small"></el-input>
-            </el-form-item>
-            <el-form-item label="丢单原因" prop="content" v-if="param.logtype == '丢单'">
-              <el-input type="textarea" v-model="param.content" size="small"></el-input>
-            </el-form-item>
-            <el-form-item label="添加备注" prop="content" v-if="param.logtype == '成交'">
-              <el-input type="textarea" v-model="param.content" size="small"></el-input>
-            </el-form-item>
-            <el-form-item label="无效原因" prop="content" v-if="param.logtype == '无效'">
-              <el-input type="textarea" v-model="param.content" size="small"></el-input>
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-      <span slot="footer" class="dialog-footer">
-        <el-button @click="dialogVisible = false" size="small">取 消</el-button>
-        <el-button type="primary" @click="followAction" size="small">确 定</el-button>
-      </span>
-    </el-dialog>
+          <!-- <el-form-item label="本次跟进结果" prop="logtype">
+            <el-radio-group v-model="param.logtype">
+              <el-radio label="跟进">跟进</el-radio>
+            </el-radio-group>
+          </el-form-item> -->
+          <el-form-item label="跟进内容" prop="content" v-if="param.logtype == '跟进'">
+            <el-input type="textarea" v-model="param.content" size="small"></el-input>
+          </el-form-item>
+          <upload
+            ref="upload"
+            :folderid="folderid"
+            @onSuccess="onSuccess"
+            :bindData="bindData"
+            type="button">
+          </upload>
+        </el-form>
+        
+      </div>
+      <div class="fixed__btn__panel">
+        <el-button size="small" @click="dialogVisible = false" class="normal-btn-width">取 消</el-button>
+        <el-button size="small" type="primary" @click="followAction" class="normal-btn-width" :loading="loading">确 定</el-button>
+      </div>
+    </el-drawer>
   </div>
 </template>
 
 <script>
-import { log } from '@antv/g2plot/lib/utils';
+import upload from './upload'
 export default {
+  components:{upload},
   name: '',
   data () {
     return {
+      loading:false,
+      bindData:{},
+      folderid:JSON.parse(sessionStorage.getItem('folderid')).appfolderid,
       param: {
-        "sat_orderclueid":0,
+        "sat_orderclueid": 4,
         "content": "",
         "followupmode": "", //当面拜访、电话沟通
-        "logtype": '跟进', //跟进、成交、丢单、无效
-        "competitor": ""
+        "logtype": "跟进", //跟进、成交、丢单、无效
+        "competitor": "",
+         "latitude":"",//经度,可选
+        "longitude":"",//纬度,可选
+        "address":"",//解析地址,
+        "sat_ordercluefollowuplogid":0//传0新增
       },
-      timer:new Date(),
+      timer: new Date(),
       rules: {
-        content:[
-          {required:true,message:'内容不能为空',trigger:'blur'},
+        content: [
+          { required: true, message: '内容不能为空', trigger: 'blur' },
         ],
-        followupmode:[
-          {required:true,message:'内容不能为空',trigger:'blur'},
+        followupmode: [
+          { required: true, message: '内容不能为空', trigger: 'blur' },
         ],
-        logtype:[
-          {required:true,message:'内容不能为空',trigger:'blur'},
+        logtype: [
+          { required: true, message: '内容不能为空', trigger: 'blur' },
         ],
-        competitor:[
-          {required:true,message:'内容不能为空',trigger:'blur'},
+        competitor: [
+          { required: true, message: '内容不能为空', trigger: 'blur' },
         ],
       },
-      time:'',
+      time: '',
       dialogVisible: false,
+      followTypeList: []
     }
   },
   props: {
     detailInfo: {
-      default() {
+      default () {
         return []
       }
     },
     position: {
-      type:String
+      type: String
     },
     updataList: {
       type: Function
@@ -114,70 +99,68 @@ export default {
     },
     disabled: Boolean
   },
+  watch: {
+    dialogVisible(val) {
+      if (!val) {
+        this.$refs['ruleForm'].resetFields()
+        this.$refs.upload.fileLinkList = []
+        this.$refs.upload.fileList = []
+
+      }
+    }
+  },
   computed: {
   },
   created () {
+    this.getFollowType()
   },
   methods: {
+    async getFollowType () {
+      let res = await this.$store.dispatch('optiontypeselect', 'followupmode')
+      this.followTypeList = res.data
+    },
     followBtn () {
       this.dialogVisible = true
-      this.param = Object.assign({},this.param,this.detailInfo)
-      console.log(this.param);
     },
-    handleClose() {
+    handleClose () {
       this.dialogVisible = false
     },
-    followAction() {
-      this.$refs.ruleForm.validate( async val => {
-        if(!val) return this.$notify({
-          title:'提示',
-          message:'请按照要求填写信息',
-          type:'warning'
-        })
+    followAction () {
+      this.$refs.ruleForm.validate(async val => {
+        if (!val) return
         this.param.sat_orderclueid = this.detailInfo.sat_orderclueid
         let res = await this.$api.requested({
-          "classname": "saletool.orderclue.web.orderclue",
-          "method": "addFollowUpLog",
+          "id":20221208100602,
           "content": this.param
         })
-        this.tool.showMessage(res,() => {
+        this.bindData = {
+          "ownertable": 'sat_ordercluefollowuplog',
+          "ownerid": res.data.sat_ordercluefollowuplogid,
+          "usetype": 'default',
+        }
+        this.loading = true
+        this.$refs['upload'].toUpload(() => {
+          this.loading = false
+          this.$emit('onSuccess')
           this.dialogVisible = false
-          this.$emit('updataList')
-          this.$refs.ruleForm.resetFields()
+          console.log('上传完成');
+          
         })
       })
     },
+    onSuccess () {
+
+    }
   },
 };
 </script>
 
 <style scoped>
-  /deep/.el-form-item__content{
-    margin-left: 0 !important;
-  }
-  
-  .follow {
-    display: inline-block;
-  }
-  /deep/.el-dialog__body {
-    padding-bottom: 0;
-  }
-  /deep/.el-dialog__footer {
-    display: flex;
-    justify-content: space-around;
-    padding-top: 0;
-  }
-  /deep/.el-form-item {
-    display: flex;
-    flex-direction: column;
-  }
-  /deep/.el-select {
-    width: 100%;
-  }
-  /deep/.el-form-item {
-    margin-bottom: 5px;
-  }
- /deep/.dialog-footer span {
-   text-align: center;
- } 
+
+.follow {
+  display: inline-block;
+}
+/deep/.el-input,.el-select {
+  width: 100%;
+}
 </style>

+ 191 - 0
src/SManagement/orderclue/components/upload.vue

@@ -0,0 +1,191 @@
+<template>
+  <div class="file">
+    <!-- <div class="flex-align-center flex-between pionter" v-for="(img,index) in fileLinkList" :key="img.index">
+      <div class="flex-align-center">
+        <img width="30" :src="img.type.split('/')[0] === 'image'?img.url:require('@/assets/file_icons/file.svg')" class="inline-16" alt="">
+        <div class="file__link inline-16">
+          <p>{{img.name}}</p>
+        </div>
+      </div>
+      <i style="color:red;" class="el-icon-delete" @click="handleRemove(index)"></i>
+    </div> -->
+    <file-item 
+        :auto="true"
+        :isDownLoad="true" 
+        :isDelete='true'
+        :fileData="fileLinkList"
+        @deleteFile="handleRemove">
+    </file-item>
+    <el-upload
+      action="#"
+      :on-change="onChange"
+      :show-file-list="false"
+      :auto-upload="false"
+      multiple>
+      <el-button size="small" type="text" icon="el-icon-paperclip">点击上传</el-button>
+    </el-upload>
+  </div>
+</template>
+
+<script>
+import FileItem from './file/index2'
+export default {
+  components: {FileItem},
+  props:['folderid','bindData','type','accept'],
+  name: '',
+  data() {
+    return {
+      imageUrl:'',
+      fileList:[],
+      fileLinkList:[],
+      params: {
+        "classname": "system.attachment.huawei.OBS",
+        "method": "getFileName",
+        "content": {
+          "filename": '',
+          "filetype": '',
+          "parentid": ""//归属文件夹ID
+        }
+      },
+      fileLength:0
+    };
+  },
+  computed:{
+  },
+  watch:{
+  },
+  methods: {
+    onChange (file,filelist) {
+      this.fileList.push(file)
+      console.log(this.fileList);
+      
+      this.beforeUpload(file.raw)
+    },
+    beforeUpload (file) {
+      var that = this
+
+      var fileReader = new FileReader();
+
+      fileReader.readAsDataURL(file);
+
+      fileReader.onload = function(e) {
+        
+        var result = e.target.result;
+
+        let postfix = file.name.substr(file.name.lastIndexOf('.') + 1)
+        
+        that.fileLinkList.push(that.fileType.fileList([{document:file.name,url:result,type:file.type,name:file.name,postfix:postfix}])[0])
+        console.log(that.fileLinkList);
+        
+      }
+    },
+    handleRemove (index) {
+      this.fileList = this.fileList.filter((e,idx)=>{
+        if (idx !== index) {
+          return e
+        }
+      })
+      console.log(this.fileList);
+      
+      this.fileLinkList = this.fileLinkList.filter((e,idx)=>{
+        if (idx !== index) {
+          return e
+        }
+      })
+    },
+    toUpload (callback) {
+      this.fileList.forEach(file=>{
+        let index = file.name.lastIndexOf(".");
+        let ext = file.name.substr(index + 1);
+        this.params.content.filename = file.name
+        this.params.content.filetype = ext
+        this.getUploadUrl(file, ext,callback)
+      })
+     
+    },
+
+    // 获取华为云上传地址
+    async getUploadUrl (file, ext,callback) {
+      this.params.content.parentid = this.folderid
+      const res = await this.$api.requested(this.params)
+      let url = res.data.uploadurl
+      let obsfilename = res.data.serialfilename
+
+      this.upoladFileToServer(url, file, ext, obsfilename,callback)
+    },
+
+    // 上传到华为云
+    async upoladFileToServer (url, file, ext, obsfilename,callback) {      
+      let THIS = this
+      let config = {
+        headers: ext === 'pdf' ? { 'Content-Type': 'application/pdf' } : ext === 'svg'?{ 'Content-Type': 'image/svg+xml' } : { 'Content-Type': 'application/octet-stream' },
+      }
+      let res = await this.$upload.hw_upload(url, file.raw, config)
+      this.createFileRecord(obsfilename,callback)
+      
+    },
+
+    // 上传成功以后生成附件记录
+    async createFileRecord (obsfilename,callback) {
+      let obj = {
+        "serialfilename": obsfilename
+      }
+      obj = Object.assign({},obj,this.bindData)
+      let param = {
+        "classname": "system.attachment.huawei.OBS",
+        "method": "uploadSuccess",
+        "content":obj
+      }
+      const res = await this.$api.requested(param)
+      if (res.code ===  1) {
+        callback()
+        this.$emit('onSuccess',res)
+        this.fileList = []
+        this.fileLinkList = []
+      }
+    },
+  },
+};
+</script>
+
+<style scoped>
+.upload_image__panel{
+  position: relative;
+  height:148px;
+  width: 148px;
+  border-radius: 6px;
+  margin-right: 10px;
+  margin-bottom:10px;
+  border: 1px solid #c0ccda;
+  overflow: hidden;
+}
+.upload_image__panel img{
+  width: 100%;
+  height: 100%;
+}
+.upload_image__panel_mod{
+  position: absolute;
+  top:0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  color:#fff;
+  background: rgba(0,0,0,.8);
+  opacity: 0;
+  transition: .3s linear;
+  cursor: pointer;
+}
+.upload_image__panel:hover .upload_image__panel_mod{
+  opacity: 1;
+}
+.pionter{
+  margin:6px 0;
+  padding: 20px 10px;
+  transition: .2s linear;
+  cursor: pointer;
+  border-radius: 5px;
+}
+.pionter:hover{
+  box-shadow: 0 5px 10px rgb(0 0 0 / 10%);
+}
+</style>

+ 64 - 17
src/SManagement/orderclue_detail/components/followDetail.vue

@@ -1,36 +1,49 @@
 <template>
-  <div class="normal-card">
+  <div class="normal-card" style="padding-right:0">
     <p class="title">跟进记录<i class="el-icon-sort" @click="sortFun"></i></p>
     <div class="select">
       <span class="demonstration">日期范围:</span>
       <time-select @clearSelect="clearSelect" @timeChange="timeChange"></time-select>
     </div>
-    <div class="detail" v-if="follow">
+    <div class="detail" v-if="follow.length > 0">
       <div class="item" v-for="(item,index) in follow" :key="index">
         <p>{{index + 1}}.{{item.createdate}},由经销商端<span style="font-weight:bold;margin:0 6px;font-size:13px">{{item.createby}}</span>开始跟进,跟进方式:<span style="font-weight:bold;margin:0 5px">{{item.followupmode}}</span>,{{handleTxt[item.logtype]}}</p>
         <div class="content">
-          <p v-if="item.competitor">已购买品牌:{{item.competitor}}</p>
-          {{item.content}}
+          <div style="margin-bottom:10px">
+            <p v-if="item.competitor">已购买品牌:{{item.competitor}}</p>
+            {{item.content}}
+          </div>
+          <file-item 
+            :marginRight="20"
+            :rowCount="5"
+            :isDownLoad="true" 
+            :fileData="item.attinfo"
+            @deleteSuccess="deleteFile">
+          </file-item>
         </div>
       </div>
     </div>
-    <div style="margin-top: 16px; text-align: right">
-      <!-- <el-pagination
-        background
-        small
-        @current-change="handleCurrentChange"
-        :current-page="param.content.pageNumber"
-        :page-size="param.content.pageSize"
-        layout="total, prev, pager, next, jumper"
-        :total="total"
-      >
-      </el-pagination> -->
+    <el-empty title="暂无数据" v-else></el-empty>
+    <div style="margin-top:16px;text-align:right">
+      <el-pagination
+      background
+      small
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+      :current-page="param.content.pageNumber"
+      :page-size="param.content.pageSize"
+      layout="total, prev, pager, next"
+      :total="total">
+      </el-pagination>
     </div>
   </div>
 </template>
 
 <script>
+import FileItem from '../../orderclue/components/file/index2'
+
 import TimeSelect from '@/SManagement/submitedit_one/components/TimeSelect'
+import { log } from '@antv/g2plot/lib/utils';
 export default {
   name: 'followDetail',
   data() {
@@ -41,6 +54,8 @@ export default {
         "content": {
             "sat_orderclueid": this.$route.query.id,
             "isdesc": 1,
+            "pageNumber":1,
+            "pageSize":20,
             "where": {
                 "start": "",
                 "end": ""
@@ -58,7 +73,7 @@ export default {
       total:0
     };
   },
-  components:{ TimeSelect },
+  components:{ TimeSelect , FileItem},
   computed:{
   },
   watch:{
@@ -71,6 +86,11 @@ export default {
       let res = await this.$api.requested(this.param)
       this.follow = res.data
       this.total = res.total
+      this.follow.forEach(item => {
+        item.attinfo = this.fileType.fileList(item.attinfo)
+      })
+      console.log(this.follow);
+      
     },
     handleCurrentChange(n) {
       this.param.content.pageNumber = n
@@ -79,17 +99,41 @@ export default {
     clearSelect() {
       this.param.content.where.start = ''      
       this.param.content.where.end = ''
+      this.param.content.pageNumber = 1
       this.getFollowDetail()  
     },
     timeChange(result) {
       this.param.content.where.start = result[0]      
       this.param.content.where.end = result[1]    
+      this.param.content.pageNumber = 1
       this.getFollowDetail()  
     },
     sortFun() {
       this.param.content.isdesc = this.param.content.isdesc == 1 ? this.param.content.isdesc = 0 : this.param.content.isdesc = 1
       this.getFollowDetail()
-    }
+    },
+    deleteFile (data) {
+      this.follow.forEach(item => {
+        item.attinfo.forEach((item2,index) => {
+          if(item2.linksid == data.linksid) {
+            console.log(item2,data);
+            
+            item.attinfo.splice(index,1)
+          }
+        })
+      })
+      
+    },
+    handleSizeChange(val) {
+      // console.log(`每页 ${val} 条`);
+      this.param.content.pageSize = val
+      this.getFollowDetail()
+    },
+    handleCurrentChange(val) {
+      // console.log(`当前页: ${val}`);
+      this.param.content.pageNumber = val
+      this.getFollowDetail()
+    },
   },
 };
 </script>
@@ -114,6 +158,9 @@ export default {
   }
   .normal-card .detail {
     font-size: 14px;
+    overflow-y: scroll;
+    height: calc(100vh - 400px);
+    padding-right: 10px;
   }
   .normal-card .detail .content {
     margin: 10px 0 16px 0;

+ 26 - 7
src/SManagement/orderclue_detail/index.vue

@@ -12,25 +12,26 @@
         turnPageId="20221101094502"
         idname="sat_orderclueid"
         tags=""
-        :tabs="['详细信息','跟进记录']"
+        :tabs="['跟进记录','详细信息']"
         @pageChange="pageChange"
         @onEditSuccess="queryMainData($route.query.id)"
         @detailCreate="detailCreate">
       <div slot="customOperation">
         <follow :detailInfo="mainData" 
-          @updataList="queryMainData" :disabled="!isHandle"></follow>
+          @updataList="queryMainData();$refs.followDetail.getFollowDetail()" @onSuccess="$refs.followDetail.getFollowDetail()" :disabled="!isHandle"></follow>
         <!-- <move :data="mainData" 
           @updataList="queryMainData" 
           :teamList="teamList()"  
           v-if="userInfo.isAuth == 1 ? mainData.status == '待跟进' || mainData.status == '跟进中' : ''"></move> -->
         <changeData :data="mainData" :disabled="!isHandle" class="inline-16"/>
         <noNull class="inline-16" :disabled="!isHandle" @onSuccess="$store.dispatch('changeDetailDrawer',false);$router.replace('/orderclue')" :id="mainData.sat_orderclueid"/>
+        <el-button :disabled="!isHandle" class="inline-16" size="mini" @click="goBack">退 回</el-button>
         <Del class="inline-16" :disabled="!isHandle" :idName="20221123193702" @onSuccess="$store.dispatch('changeDetailDrawer',false);$router.replace('/orderclue')" :id="mainData.sat_orderclueid" idKey="sat_orderclueids"/>
       </div>
-      <div slot="slot0" class="container normal-panel">
+      <div slot="slot1" class="container normal-panel">
         <BaseInfo :detailInfo="detailInfo"/>
       </div>
-      <div slot="slot1">
+      <div slot="slot0">
         <followDetail ref="followDetail"/>
       </div>
     </basicDetails>
@@ -97,8 +98,6 @@ export default {
             "sat_orderclueid": this.$route.query.id
         }
       })
-      this.$nextTick(() => {
-      })
       this.mainData = res.data
       console.log(this.mainData);
       
@@ -106,8 +105,12 @@ export default {
     },
     changeDataStructure() {
       this.mainAreaData = [
-          {
+        {
           label:'客户名称',
+          value:this.mainData.enterprisename_customer
+        },
+        {
+          label:'联系人',
           value:this.mainData.name
         },
         {
@@ -195,6 +198,22 @@ export default {
         ]
       }
     },
+    goBack () {
+      this.$confirm('退回该线索后无法撤销,是否继续','提示',{
+        "confirmButtonText":'确定',
+        "cancelButtonText":'取消'
+      }).then(async confirm => {
+        let res = await this.$api.requested({
+          "id":20221207160802,
+          "content": {
+            sat_orderclueid: this.mainData.sat_orderclueid
+          }
+        })
+        this.tool.showMessage(res , () => {
+          this.queryMainData()
+        })
+      })
+    },
     // 监听切换数据,上一页,下一页
     pageChange (id,rowindex) {
       this.flag = false

+ 1 - 0
src/components/file-block/index2.vue

@@ -60,6 +60,7 @@ export default {
           this.$emit('deleteSuccess',temp)
         })
       })
+      this.$emit('deleteFile',item)
     },
     //预览
     seeClick(item) {

+ 11 - 4
src/components/normal-basic-layout/details/index.vue

@@ -35,14 +35,17 @@
           </tabTemp>
           <slot name="custom"></slot>
         </el-col>
-        <el-col style="width:400px;" :span="6">
+        <el-col v-if="collapse" style="width:400px;" :span="6">
           <group v-if="activeApp.isdatateam" ref="group" style="margin-bottom:10px" :ownertable="ownertable?ownertable:idname.slice(0, this.idname.length - 2)" @onSuccess="onSuccess">
-            <el-button slot="collapse" type="text" icon="el-icon-s-unfold" class="inline-16"></el-button>
+            <el-button slot="collapse" type="text" icon="el-icon-s-unfold" class="inline-16" @click="onCollapse"></el-button>
           </group>
           <follow-up v-if="activeApp.isdatafollowup" ref="follow" :ownertable="ownertable?ownertable:idname.slice(0, this.idname.length - 2)">
-            <el-button slot="collapse" type="text" icon="el-icon-s-unfold" class="inline-16"></el-button>
+            <el-button slot="collapse" type="text" icon="el-icon-s-unfold" class="inline-16" @click="onCollapse"></el-button>
           </follow-up>
         </el-col>
+        <div v-else style="text-align-center" class="container normal-panel">
+          <el-button slot="collapse" type="text" icon="el-icon-s-fold" @click="onCollapse"></el-button>
+        </div>
         
       </el-row>
     </div>
@@ -75,7 +78,8 @@ export default {
             "condition": ""
           }
         }
-      }
+      },
+      collapse:true
     }
   },
   computed:{
@@ -157,6 +161,9 @@ export default {
     },
     onTabClick () {
       this.$emit('onTabClick')
+    },
+    onCollapse () {
+      this.collapse?this.collapse = false:this.collapse = true
     }
   },
   mounted () {

+ 5 - 8
src/components/normal-basic-layout/index.vue

@@ -32,7 +32,7 @@
         </div>
         <div class="flex-align-stretch" style="min-width:800px">
           <slot name="custom"></slot>
-          <el-input style="width:200px;" placeholder="搜索" suffix-icon="el-icon-search" @input="searchChange" v-model="param.content.where.condition" @keyup.native.enter="listData(param.content.pageNumber = 1)" @clear="listData(param.content.pageNumber = 1)" size="small" class="input-with-select inline-16 layout_search__panel" clearable>
+          <el-input style="width:200px;" placeholder="搜索" suffix-icon="el-icon-search" v-model="param.content.where.condition" @keyup.native.enter="listData(param.content.pageNumber = 1)" @clear="clearSearch" size="small" class="input-with-select inline-16 layout_search__panel" clearable>
           </el-input>
         </div>
       </div>
@@ -126,11 +126,12 @@ export default {
     }
   },
   methods:{
-    searchChange (val) {
-      val == '' && this.listData()
+    clearSearch () {
+      this.$store.state.searchValue = ''
+      this.listData(this.param.content.pageNumber = 1)
     },
     async listData () {
-      // console.log(this.activeApp)
+      this.param.content.where.condition = this.searchValue
       this.param.id = this.apiId.query
       const res = await this.$api.requested(this.param)
       this.list = res.data
@@ -232,16 +233,12 @@ export default {
     }
   },
   watch:{
-    $route () {
-      
-    }
   },
   mounted () {
     this.autoQuery === false?'':this.listData()
   },
   created () {
     this.routerName = this.$route.meta.title
-    this.param.content.where.condition = this.searchValue
     this.layout = this.tool.tabelCol(this.$route.name)[this.tableName].tablecols
     this.tableLayout = this.layout
     this.$emit('listCreate',this.param)

+ 6 - 2
src/store/index.js

@@ -76,11 +76,15 @@ export default new Vuex.Store({
     },
     
     setActiveApp (state,data) {
+      console.log(data)
+      //头部区域搜索所传入的数值
+      state.searchValue = data.val
+
+      
       data.app?sessionStorage.setItem('activeApp',JSON.stringify(data.app)):''
       state.appname = data.name
       state.activeApp = JSON.parse(sessionStorage.getItem('activeApp'))
-        //头部区域搜索所传入的数值
-      state.searchValue = data.val
+      
     },
     systemModules (state,data) {
       state.sys_modules = data

+ 1 - 9
src/style/style.css

@@ -179,15 +179,7 @@ ul{
 .el-drawer__wrapper{
   right:60px !important;
 }
-.el-drawer__header{
-  /* margin-bottom: 20px !important; */
-  padding: 10px !important;
-  margin-bottom: 0 !important;
-  font-size: 16px  !important;
-  font-family: PingFang SC-Bold, PingFang SC;
-  font-weight: bold  !important;
-  color: #333333  !important;
-}
+
 .fixed__btn__panel{
   position: absolute;
   display: flex;

+ 3 - 0
src/views/login/login.vue

@@ -93,6 +93,9 @@ export default {
       count:0
     }
   },
+  created () {
+    this.$store.dispatch('DrawerShowChange',false)
+  },
   mounted () {
     if (localStorage.getItem('phonenumber')) {
       this.loginForm.phonenumber = localStorage.getItem('phonenumber')