Эх сурвалжийг харах

feat: 企业情报监控、分组弹框组件

yangfeng 3 жил өмнө
parent
commit
1e51093382

+ 10 - 0
src/api/modules/forecast.js

@@ -160,3 +160,13 @@ export function getSvipMsgSelects (data) {
     data: data
   })
 }
+
+// 更改关注企业分组
+export function changeEntGroup (data) {
+  data = qs.stringify(data)
+  return request({
+    url: '/follow/ent/changeGroup',
+    method: 'post',
+    data: data
+  })
+}

BIN
src/assets/images/icon/help.png


BIN
src/assets/images/icon/icon-checked.png


+ 1 - 0
src/components/common/Empty.vue

@@ -4,6 +4,7 @@
       <el-image :src="require('@/assets/images/empty.png')"></el-image>
       <div class="empty-main">
         <slot name="default">{{ tip }}</slot>
+        <slot name="button"></slot>
       </div>
     </div>
   </div>

+ 72 - 0
src/components/common/TabHeader.vue

@@ -0,0 +1,72 @@
+<template>
+  <div class="bid-tab-header">
+    <div class="tab-header-container">
+      <div class="tab-content">
+        <router-link class="tab-link" :class="actived === 'ent' ? 'active' : ''" to="/ent_follow" replace>企业情报监控</router-link>
+        <router-link class="tab-link" :class="actived === 'rival' ? 'active' : ''" to="/potential_rival_list/r" replace>潜在竞争对手/合作伙伴挖掘</router-link>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'bid-tab-header',
+  props: {
+    actived: {
+      type: String
+    }
+  },
+  computed: {},
+  components: {},
+  data () {
+    return {}
+  },
+  methods: {}
+}
+</script>
+
+<style lang="scss">
+.bid-tab-header{
+  position: absolute;
+  top: 100px;
+  width: 100%;
+  .tab-header-container{
+    width: 1200px;
+    margin: 0 auto;
+  }
+  .tab-content{
+    display: flex;
+    align-items: center;
+    .tab-link{
+      margin-right: 48px;
+      font-size: 18px;
+      line-height: 28px;
+      color: rgba(255, 255, 255, 0.8);
+      text-decoration: none;
+      &.active{
+        position: relative;
+        font-size: 24px;
+        line-height: 36px;
+        text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.15);
+        color: #fff;
+        font-weight: bold;
+        &::after{
+          content: "";
+          position: absolute;
+          bottom: -8px;
+          left: 50%;
+          width: 48px;
+          height: 3px;
+          border-radius: 3px;
+          background-color: #fff;
+          transition: transform 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), -webkit-transform 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
+          list-style: none;
+          z-index: 1;
+          transform: translateX(-50%);
+        }
+      }
+    }
+  }
+}
+</style>

+ 72 - 0
src/components/forecast/ForFilter.vue

@@ -0,0 +1,72 @@
+<template>
+  <div class="ent-filter">
+    <div class="filter-title">筛选条件</div>
+    <div class="filter-item">
+      <span class="item-label">分组:</span>
+      <div>
+        <GroupTag selectorType="line"></GroupTag>
+      </div>
+    </div>
+    <div class="filter-item">
+      <span class="item-label">企业名称:</span>
+      <div>
+        <el-input class="ent-input" v-model="entVal" placeholder="请输入已关注企业名称"></el-input>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { Input, FormItem } from 'element-ui'
+import GroupTag from '@/components/selector/GroupSelectorContent.vue'
+export default {
+  name: 'ent-filter',
+  props: {},
+  computed: {},
+  components: {
+    [Input.name]: Input,
+    [FormItem.name]: FormItem,
+    GroupTag
+  },
+  data () {
+    return {
+      entVal: ''
+    }
+  },
+  methods: {}
+}
+</script>
+
+<style lang="scss" scoped>
+.ent-filter{
+  margin-bottom:16px;
+  padding: 42px 40px;
+  background: #fff;
+  .filter-title{
+    margin-bottom: 14px;
+    font-weight: bold;
+    font-size: 18px;
+    color: #1d1d1d;
+  }
+  .filter-item{
+    display: flex;
+    align-items: center;
+    padding: 12px 0;
+    .item-label{
+      font-size: 14px;
+      min-width: 80px;
+      text-align: right;
+    }
+    .ent-input{
+      ::v-deep{
+        .el-input__inner{
+          width: 432px;
+          height: 30px;
+          line-height: 30px;
+          font-size: 14px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 2 - 1
src/components/forecast/ForLayout.vue

@@ -7,10 +7,11 @@
           <slot name="proname"></slot>
         </div>
         <div class="bidfor_search" v-if="search">
-           <SearchInput :placeholder="placeholder.text" @submit="getRecovery" :onlySelect="searchConfig.select" :ajaxType="searchConfig.type"></SearchInput>
+          <SearchInput :placeholder="placeholder.text" @submit="getRecovery" :onlySelect="searchConfig.select" :ajaxType="searchConfig.type"></SearchInput>
         </div>
         <slot name="bidfre"></slot>
         <slot name="bidImg"></slot>
+        <slot name="bidtab"></slot>
       </div>
     </div>
     <div class="for_main">

+ 220 - 29
src/components/forecast/ForeCast.vue

@@ -1,6 +1,10 @@
 <template>
   <div class="listData">
-    <div class="listData_title">{{ title }}</div>
+    <div class="listData_title"  v-if="type=='entintel'">
+      <strong style="font-weight:bold;font-size: 18px;color: #1d1d1d">企业列表</strong>
+      <span style="font-size:14px;color:#686868;">(可关注 {{myDataObj.maxCount}} 个企业,已关注 <em style="color:#2CB7CA;">{{myDataObj.total}}</em> 个)</span>
+    </div>
+    <div class="listData_title" v-else>{{ title }}</div>
     <!-- 中标企业预测-->
     <ul class="listData_ul" v-if="type=='bidfor'">
       <li class="list_li" v-for="(item, index) in listState.list.slice((listState.pageNum - 1) * listState.pageSize, listState.pageNum * listState.pageSize)" :key="index" @click="goBidForcast(item)">
@@ -62,29 +66,58 @@
       </li>
     </ul>
     <!-- 企业情报 -->
-    <ul class="listData_ul" v-if="type=='entintel'">
-      <li class="list_li" v-for="(item, index) in getMyData.listState.list" :key="index" @click="goViewEnt(item.s_entId)">
-        <div class="list_name ent_li_name">{{item.s_entname}}<span class="red_point" v-if="item.i_apppushunread!==0&&item.i_apppushunread"></span></div>
-        <div class="list_unit">
-          <div class="pur_unit">
-            <span class="unit_label">成立日期:</span>
-            <span class="unit_name entname">{{item.l_establishdate?dateFormatter(item.l_establishdate*1000, 'yyyy-MM-dd'):'--'}}</span>
+    <div v-if="type=='entintel'" style="padding:0 40px;">
+      <div class="entintel-thead">
+        <span style="width:830px;">企业</span>
+        <span style="width:100px;" class="thead-flex">
+          <em>项目<br>更新时间</em>
+          <el-tooltip class="item" effect="dark" placement="top">
+            <div slot="content" style="text-align:center;font-size:13px;line-height:20px;">
+              初始值为关注企业的时间,<br> 关注后,企业下项目动态如有更新, <br>则为项目更新时间
+            </div>
+            <i class="icon-quesion"></i>
+          </el-tooltip>
+        </span>
+        <span style="width:100px;">分组</span>
+        <span style="width:100px;">操作</span>
+      </div>
+      <ul class="listData_ul">
+        <li class="list_li" style="padding:24px 0 26px;display:flex;align-items: center;cursor: default;" v-for="(item, index) in getMyData.listState.list" :key="index">
+          <div style="padding: 0 12px;width:830px;cursor: pointer" @click="goViewEnt(item.s_entId)">
+            <div class="list_name ent_li_name">{{item.s_entname}}<span class="red_point" v-if="item.i_apppushunread!==0&&item.i_apppushunread"></span>
+            </div>
+            <div class="list_unit">
+              <div class="pur_unit">
+                <span class="unit_label">成立日期:</span>
+                <span class="unit_name entname">{{item.l_establishdate?dateFormatter(item.l_establishdate*1000, 'yyyy-MM-dd'):'--'}}</span>
+              </div>
+              <div class="pur_unit">
+                <span class="unit_label">注册资本:</span>
+                <span class="unit_name entname">{{item.f_capital?moneyUnit(item.f_capital*10000):'--'}}</span>
+              </div>
+              <div class="pur_unit">
+                <span class="unit_label">企业地址:</span>
+                <span class="unit_name entname">{{item.s_area?item.s_area:'--'}}{{item.s_city?item.s_city:''}}</span>
+              </div>
+              <div class="pur_unit">
+                <span class="unit_label">企业联系方式:</span>
+                <span class="unit_name entname">{{item.s_phone?item.s_phone:'--'}}</span>
+              </div>
+            </div>
           </div>
-          <div class="pur_unit">
-            <span class="unit_label">注册资本:</span>
-            <span class="unit_name entname">{{item.f_capital?moneyUnit(item.f_capital*10000):'--'}}</span>
+          <div class="list_li_item">
+            {{item.l_lastpushtime ? dateFormatter(item.l_lastpushtime*1000, 'yyyy-MM-dd') : '--'}}
           </div>
-          <div class="pur_unit">
-            <span class="unit_label">企业地址:</span>
-            <span class="unit_name entname">{{item.s_area?item.s_area:'--'}}{{item.s_city?item.s_city:''}}</span>
+          <div class="list_li_item item-flex-column">
+            <span v-for="(s,j) in formatGroup(item.s_group)" :key="'00' + j">{{s}}</span>
           </div>
-          <div class="pur_unit">
-            <span class="unit_label">企业联系方式:</span>
-            <span class="unit_name entname">{{item.s_phone?item.s_phone:'--'}}</span>
+          <div class="list_li_item entintel-handle">
+            <span @click="editGroup(item)">编辑分组</span>
+            <span @click="cancelFollow(item)">取消关注</span>
           </div>
-        </div>
-      </li>
-    </ul>
+        </li>
+      </ul>
+    </div>
     <!-- 企业情报搜索结果组件 -->
     <ul class="listData_ul" v-if="type=='entintelRes'">
       <li class="list_li res_li" v-for="(item, index) in listState.list" :key="index">
@@ -179,7 +212,17 @@
         </div>
       </li>
     </ul>
-    <Empty v-if="showEmpty&&potenCode!=1" :tip="getTipText"></Empty>
+    <Empty v-if="showEmpty&&potenCode!=1" :tip="getTipText">
+      <el-button
+        v-if="tips === '暂无企业情报信息,前往企业搜索关注企业'"
+        class="add-btn"
+        type="primary"
+        slot="button"
+        @click="goSearchEnt"
+      >
+        添加关注企业
+      </el-button>
+    </Empty>
     <Empty v-else-if="showEmpty&&potenCode==1">
       <div name="default">
         <div class="poten_tip">暂未设置订阅关键词,无法进行预测</div>
@@ -200,16 +243,36 @@
       >
       </el-pagination>
     </div>
+    <!-- 分组dialog -->
+    <el-dialog
+      custom-class="sub-dialog"
+      :visible.sync="dialog.group"
+      :close-on-click-modal="false"
+      :show-close="false"
+      :destroy-on-close="true"
+      :lock-scroll="false"
+      center
+      width="460px"
+    >
+      <GroupCard
+        :initGroupInfo="this.cur.group"
+        @onCancel="dialog.group = false"
+        @onConfirm="saveGroupData"
+      >
+        <div slot="header">编辑分组</div>
+      </GroupCard>
+    </el-dialog>
   </div>
 </template>
 
 <script>
-import { Pagination, Progress, Message } from 'element-ui'
+import { Pagination, Progress, Message, Tooltip, Dialog, Button } from 'element-ui'
 import { mapState } from 'vuex'
 // import { getPushList } from '@/api/modules/'
 import Empty from '@/components/common/Empty.vue'
+import GroupCard from '@/components/selector/GroupSelector.vue'
 import { moneyUnit, dateFormatter } from '@/utils'
-import { setFollowEnt, setCancelEnt } from '@/api/modules'
+import { setFollowEnt, setCancelEnt, changeEntGroup } from '@/api/modules'
 export default {
   props: ['type', 'title', 'mydata', 'myDataObj', 'resData', 'myPolicydata', 'potenObj', 'potenResult', 'entSearch', 'entSearchRes'],
   name: 'listData',
@@ -217,7 +280,11 @@ export default {
     [Pagination.name]: Pagination,
     [Progress.name]: Progress,
     [Message.name]: Message,
-    Empty
+    [Tooltip.name]: Tooltip,
+    [Dialog.name]: Dialog,
+    [Button.name]: Button,
+    Empty,
+    GroupCard
   },
   data () {
     return {
@@ -225,13 +292,20 @@ export default {
         loaded: true, // 是否已经搜索过
         loading: false,
         pageNum: 1, // 当前页
-        pageSize: 10, // 每页多少条数据
+        pageSize: this.type === 'entintel' ? 25 : 10, // 每页多少条数据
         total: 0, // 一共多少条数据
         list: [] // 查询请求返回的数据
       },
       isFollow: '1',
       potenCode: 0,
-      tips: '' // 空状态提示
+      tips: '', // 空状态提示
+      dialog: {
+        group: false
+      },
+      cur: {
+        group: '', // 当前点击编辑的分组信息
+        fid: ''
+      }
     }
   },
   created () {
@@ -306,7 +380,7 @@ export default {
     },
     getMyData () {
       // eslint-disable-next-line vue/no-side-effects-in-computed-properties
-      this.tips = '您还没有关注企业'
+      this.tips = '暂无企业情报信息,前往企业搜索关注企业'
       return this
     },
     activeColor () {
@@ -421,7 +495,7 @@ export default {
       } else {
         this.listState.list = []
         this.listState.total = 0
-        this.tips = '您还没有关注企业'
+        this.tips = '暂无企业情报信息,前往企业搜索关注企业'
       }
     },
     // 企业查询
@@ -546,6 +620,71 @@ export default {
     onPageChange (p) {
       this.listState.pageNum = p
       this.$emit('onPageChange', p)
+    },
+    // 处理显示分组
+    formatGroup (data) {
+      if (!data) return
+      let val
+      switch (data) {
+        case 'A':
+          val = '默认分组'
+          break
+        case 'B':
+          val = '竞争对手'
+          break
+        case 'C':
+          val = '合作伙伴'
+          break
+        case 'B,C' || 'C,B':
+          val = '竞争对手,合作伙伴'
+          break
+        default:
+          val = '默认分组'
+          break
+      }
+      const arr = val.split(',')
+      return arr
+    },
+    // 企业情报监控 编辑分组
+    editGroup (item) {
+      this.dialog.group = true
+      this.cur.group = item.s_group ? item.s_group : 'A'
+      this.cur.fid = item.fid
+    },
+    // 企业情报监控 取消关注
+    cancelFollow (item) {
+      setCancelEnt({
+        entId: item.s_entId,
+        fid: item.fid
+      }).then(res => {
+        if (res.data === 'success') {
+          this.$toast('取消关注成功')
+          this.$emit('onPageChange', this.listState.pageNum)
+        } else {
+          this.$toast(res.error_msg)
+        }
+      })
+    },
+    saveGroupData (data) {
+      console.log(data, '保存分组')
+      const params = {
+        fid: this.cur.fid,
+        group: data
+      }
+      const defaultParams = {
+        fid: this.cur.fid
+      }
+      changeEntGroup(data === 'A' ? defaultParams : params).then(res => {
+        if (res.data === 'success') {
+          this.dialog.group = false
+          this.$emit('onPageChange', this.listState.pageNum)
+        } else {
+          this.$toast(res.error_msg)
+        }
+      })
+    },
+    goSearchEnt () {
+      location.href = '/jylab/entSearch/index.html'
     }
   }
 }
@@ -566,6 +705,58 @@ export default {
     color: #1d1d1d;
     line-height: 28px;
   }
+  .entintel-thead{
+    display: flex;
+    align-items: center;
+    margin-top: 26px;
+    height:48px;
+    background:#f7f9fc;
+    color: #1D1D1D;
+    text-align: center;
+    font-size: 14px;
+    .thead-flex{
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+    .icon-quesion{
+      display: inline-block;
+      width: 18px;
+      height: 18px;
+      margin-left: 2px;
+      background: url('~@/assets/images/icon/help.png') no-repeat center center;
+      background-size: contain;
+      cursor: pointer;
+    }
+  }
+  .list_li_item{
+    width: 100px;
+    text-align: center;
+    font-size: 14px;
+    &.item-flex-column{
+      display:flex;
+      flex-direction: column;
+      align-items: center;
+    }
+  }
+  .add-btn{
+    margin: 16px 0;
+    background: #2cb7ca;
+    border-radius: 6px;
+    border: 0;
+  }
+  .entintel-handle{
+    width:100px;
+    display:flex;
+    flex-direction: column;
+    align-items: center;
+    font-size: 14px;
+    color: #2CB7CA;
+    line-height: 22px;
+    span{
+      cursor: pointer
+    }
+  }
   .listData_ul{
     content: '';
     overflow: hidden;
@@ -598,7 +789,7 @@ export default {
         display: flex;
         margin-top: 12px;
         .pur_unit{
-          margin-right: 40px;
+          margin-right: 28px;
           font-size: 14px;
           color: #2CB7CA;
           font-weight: 400;

+ 64 - 0
src/components/selector/GroupSelector.vue

@@ -0,0 +1,64 @@
+<template>
+  <selector-card
+    style="height:auto;"
+    class="group-selector"
+    :cardType="selectorType"
+    @onConfirm="onConfirm"
+    @onCancel="onCancel">
+    <div slot="header">
+      <slot name="header">选择分组</slot>
+    </div>
+    <GroupSelectorContent
+      ref="content"
+      :initGroupInfo="initGroupInfo"
+      :selectorType="selectorType"
+      @onChange="onChange"
+    />
+  </selector-card>
+</template>
+
+<script>
+import SelectorCard from '@/components/selector/SelectorCard.vue'
+import GroupSelectorContent from '@/components/selector/GroupSelectorContent.vue'
+export default {
+  name: 'group-selector',
+  components: {
+    SelectorCard,
+    GroupSelectorContent
+  },
+  props: {
+    selectorType: {
+      type: String,
+      default: 'card' // card/line
+    },
+    initGroupInfo: {
+      type: String,
+      default: ''
+    }
+  },
+  watch: {},
+  created () {},
+  methods: {
+    getSelectGroup () {
+      return this.$refs.content.getSelected()
+    },
+    setSelectGroup () {
+      return this.$refs.content.setGroupSelected()
+    },
+    onCancel () {
+      this.$emit('onCancel')
+    },
+    onConfirm () {
+      const selectedGroup = this.getSelectGroup()
+      this.$emit('onConfirm', selectedGroup)
+    },
+    onChange (selected) {
+      this.$emit('onChange', selected)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 305 - 0
src/components/selector/GroupSelectorContent.vue

@@ -0,0 +1,305 @@
+<template>
+  <div class="selector-content" v-if="selectorType === 'card'" key="s-content">
+    <div class="" ref="selectList">
+      <div class="select-group">
+        <div v-for="(item, key) in groupList" :key="key" class="select-group-container">
+          <div class="tab-name-container" @click="changeGroupState(item)">
+            <div v-if="item.name === '默认分组'" class="j-radio" :class="item.checked ? 'r-checked' : ''"></div>
+            <div v-else class="j-checkbox" :class="item.checked ? 'checked' : ''"></div>
+            <span class="tab-name">{{ item.name }}</span>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+  <div class="selector-content" v-else-if="selectorType === 'line'" key="s-content">
+    <div class="selected-list">
+      <el-tag
+        type="plain"
+        v-for="tag in selectedTagList"
+        :key="tag.name"
+        @close="tagClose(tag)"
+      >{{ tag.name }}</el-tag>
+    </div>
+  </div>
+</template>
+
+<script>
+import { Icon, Tag } from 'element-ui'
+export default {
+  name: 'group-selector-content',
+  components: {
+    [Icon.name]: Icon,
+    [Tag.name]: Tag
+  },
+  props: {
+    selectorType: {
+      type: String,
+      default: 'card' // card/line
+    },
+    initGroupInfo: {
+      type: String,
+      default: 'A'
+    }
+  },
+  data () {
+    return {
+      groupList: [
+        {
+          index: 'A',
+          name: '默认分组',
+          checked: false
+        }, {
+          index: 'B',
+          name: '竞争对手',
+          checked: false
+        }, {
+          index: 'C',
+          name: '合作伙伴',
+          checked: false
+        }
+      ],
+      selectedTagList: [
+        {
+          name: '全部'
+        },
+        {
+          name: '默认分组'
+        },
+        {
+          name: '竞争对手'
+        },
+        {
+          name: '合作伙伴'
+        }
+      ]
+    }
+  },
+  computed: {
+
+  },
+  watch: {
+    initGroupInfo (newVal, oldVal) {
+      console.log(newVal, 'newVal')
+      this.setGroupSelected(newVal)
+    }
+  },
+  created () {
+    this.setGroupSelected(this.initGroupInfo)
+  },
+  methods: {
+    changeGroupState (item) {
+      const list = this.groupList.slice(1, 3)
+      if (item.name === '默认分组') {
+        item.checked = true
+        list.forEach(v => {
+          v.checked = false
+        })
+      } else {
+        item.checked = !item.checked
+        const allChecked = list.some(s => {
+          return s.checked
+        })
+        if (allChecked) {
+          this.groupList[0].checked = false
+        } else {
+          this.groupList[0].checked = true
+        }
+      }
+      const selected = this.getSelected()
+      this.$emit('onChange', selected)
+    },
+    // 获取选中的分组
+    getSelected () {
+      const data = []
+      const lists = this.groupList
+      lists.forEach(v => {
+        if (v.checked) {
+          data.push(v.index)
+        }
+      })
+      return data.toString()
+    },
+    // 设置选中的分组
+    setGroupSelected (data) {
+      if (!data) return
+      const list = this.groupList
+      const newData = data.split(',')
+      list.forEach(v => {
+        v.checked = false
+        newData.forEach(s => {
+          if (s === v.index) {
+            v.checked = true
+          }
+        })
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+  .s-card {
+    .j-radio{
+      width: 18px;
+      height: 18px;
+      border-radius: 50%;
+      border: 1px solid #e0e0e0;
+      cursor: pointer;
+      &.r-checked {
+        border: 0;
+        background: url('~@/assets/images/icon/checked.png') no-repeat center center;
+        background-size: 20px;
+      }
+    }
+    .j-checkbox {
+      width: 15px;
+      height: 15px;
+      border-radius: 4px;
+      border: 1px solid #e0e0e0;
+      cursor: pointer;
+      &.checked {
+        border: 0;
+        background: url('~@/assets/images/icon/icon-checked.png') no-repeat center center;
+        background-size: 16px;
+        &[disabled] {
+          background: url('~@/assets/images/icon/icon-checked.png') no-repeat;
+          background-size: 18px;
+        }
+      }
+    }
+
+    .select-group {
+      font-size: 14px;
+      &.global {
+        padding: 0 18px;
+      }
+      .tab {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        padding: 0 18px;
+        height: 40px;
+        border-bottom: 1px solid rgba(0,0,0,.05);
+        cursor: pointer;
+      }
+      .select-group-container{
+        display: flex;
+        align-items: center;
+        padding: 10px 22px;
+        border-bottom: 1px solid #eee;
+        &:last-child {
+          border: none;
+        }
+      }
+      .tab-name-container {
+        display: flex;
+        align-items: center;
+        cursor: pointer;
+        .tab-name {
+          margin-left: 10px;
+          font-weight: bold;
+          font-size: 14px;
+          line-height: 22px;
+        }
+      }
+    }
+  }
+
+  .s-line {
+    .el-tag--plain {
+      color: $color-text--highlight;
+      border-color: $color-text--highlight;
+      .el-tag__close {
+        color: $color-text--highlight;
+        &:hover {
+          color: #fff;
+          background-color: $color-text--highlight;
+        }
+      }
+    }
+    .s-header {
+      line-height: 30px;
+    }
+    .el-tag {
+      margin: 4px 6px;
+      height: 30px;
+    }
+    .selector-content {
+      .select-list {
+        position: relative;
+        display: flex;
+        flex-wrap: wrap;
+        overflow: hidden;
+        .index-item {
+          .index-bar {
+            margin-left: 10px;
+            margin-right: 5px;
+            color: #999;
+          }
+        }
+        .j-button-item {
+          display: inline-block;
+          &:hover {
+            color: $color-text--highlight;
+          }
+          &.active {
+            color: #fff;
+            background-color: $color-text--highlight;
+          }
+          &.expand {
+            background-color: #f5f5fb;
+            border: 1px solid #e0e0e0;
+            border-bottom-color: transparent;
+            border-bottom-left-radius: 0;
+            border-bottom-right-radius: 0;
+            position: relative;
+            z-index: 2;
+            // transform: translateZ(0px);
+          }
+        }
+      }
+      .city-list {
+        margin-top: -7px;
+        padding: 12px 20px;
+        width: 100%;
+        background-color: #f5f5fb;
+        border-radius: 4px;
+        border: 1px solid #E0E0E0;
+        .city-item {
+          display: inline-block;
+          margin: 0 4px 4px;
+          padding: 4px 8px;
+          border-radius: 4px;
+          cursor: pointer;
+          &.active {
+            color: #fff;
+            background-color: $color-text--highlight;
+          }
+        }
+        .city-list-footer {
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          margin-top: 12px;
+          button {
+            padding: 4px 16px;
+            font-size: 14px;
+            line-height: 18px;
+            color: #1D1D1D;
+            background-color: #fff;
+            cursor: pointer;
+            border-radius: 4px;
+            border: 1px solid #E0E0E0;
+            &.confirm {
+              margin-right: 15px;
+              color: #fff;
+              background-color: #2CB7CA;
+              border-color: #2CB7CA;
+            }
+          }
+        }
+      }
+    }
+  }
+</style>

+ 1 - 0
src/components/toast/Toast.vue

@@ -13,6 +13,7 @@
     transform: translate(-50%,-50%);
     color:#fff;
     font-size: 16px;
+    z-index: 9999;
   }
   .fadein {
     animation: animate_in 0.25s;

+ 5 - 3
src/views/PotentialList.vue

@@ -1,10 +1,11 @@
 <template>
   <div class="page--potential">
     <forLayOut :search="false">
-      <div class="flex-r-c center" slot="proname">
+      <!-- <div class="flex-r-c center" slot="proname">
         <i :class="'el-icon-jy-' + getTopInfo.icon"></i>
         <span class="bidfor_text" >{{getTopInfo.text}}</span>
-      </div>
+      </div> -->
+      <TabHeader slot="bidtab" actived="rival"></TabHeader>
       <img class="bidfor_img" :src="getTopInfo.img" :alt="getTopInfo.text" slot="bidImg">
       <div slot="main">
         <div class="border-box">
@@ -61,7 +62,8 @@ export default {
     IndustrySelector,
     BuyerclassSelector,
     BusinessScopeSelector,
-    forLayOut
+    forLayOut,
+    TabHeader
   },
   data () {
     return {

+ 32 - 10
src/views/ent-intel/EntIntel.vue

@@ -1,11 +1,21 @@
 <template>
   <div class="ent-intel">
-    <forLayOut :placeholder="{ text:'输入企业名称'}" :searchConfig="{ type: 'follow'}">
-      <span class="icon_ent" slot="icon"></span>
+    <forLayOut :placeholder="{ text:'输入企业名称'}" :searchConfig="{ type: 'follow'}" :search="false">
+      <!-- <span class="icon_ent" slot="icon"></span>
       <span class="bidfor_text" slot="proname">企业情报</span>
-      <img class="bidfor_img" src="@/assets/images/item_2.png" alt="" slot="bidImg">
+      <img class="bidfor_img" src="@/assets/images/item_2.png" alt="" slot="bidImg"> -->
+      <TabHeader slot="bidtab" actived="ent"></TabHeader>
+      <img class="bidfor_img" src="@/assets/images/item_1.png" slot="bidImg">
       <template v-slot:main>
-        <ForeCast key="entintel" @onPageChange="getMyFollowList" ref="myList" type="entintel" v-if="type==0"  title="我关注的企业" slot="main" :myDataObj="myDataObj"></ForeCast>
+        <ForFilter v-if="type==0" ></ForFilter>
+        <ForeCast
+          key="entintel"
+          @onPageChange="getMyFollowList"
+          ref="myList" type="entintel"
+          v-if="type==0"
+          slot="main"
+          :myDataObj="myDataObj"
+        ></ForeCast>
         <ForeCast key="entintelRes" type="entintelRes" v-if="type==1" title="近似企业" slot="main" :entSearch="forcastSer"></ForeCast>
       </template>
     </forLayOut>
@@ -15,17 +25,22 @@
 <script>
 import forLayOut from '@/components/forecast/ForLayout.vue'
 import ForeCast from '@/components/forecast/ForeCast.vue'
+import TabHeader from '@/components/common/TabHeader.vue'
+import ForFilter from '@/components/forecast/ForFilter.vue'
 import { mapState } from 'vuex'
 import { getFollowtList } from '@/api/modules'
 export default {
   name: 'ent-intel',
   components: {
     ForeCast,
-    forLayOut
+    forLayOut,
+    TabHeader,
+    ForFilter
   },
   data () {
     return {
       myDataObj: {
+        maxCount: 0,
         list: [],
         total: 0
       },
@@ -51,11 +66,11 @@ export default {
       if (p > 0) {
         p--
       }
-      getFollowtList({ pageNum: p, pageSize: 10 }).then(res => {
-        console.log(res)
+      getFollowtList({ pageNum: p, pageSize: 25 }).then(res => {
         if (res.error_code === 0 && res.data && res.data.list && res.data.list.length > 0) {
-          this.myDataObj.list = res.data.list
-          this.myDataObj.total = res.data.total
+          this.myDataObj.list = []
+          this.myDataObj.maxCount = res.data.followMax
+          this.myDataObj.total = 0
           this.$refs.myList.entInitData(this.myDataObj)
           this.$refs.myList.$forceUpdate()
           // this.$store.commit('forcast/setEntFollowList', res.data)
@@ -70,7 +85,14 @@ export default {
 .ent-intel{
   width: 100%;
   ::v-deep .for_main{
-    background: #fff;
+    // background: #fff;
+    margin-top: -130px;
+  }
+  ::v-deep .sub-dialog{
+    .el-dialog__header,
+    .el-dialog__body{
+      padding: 0;
+    }
   }
   .icon_ent{
     display: flex;

+ 11 - 1
src/views/subscribe/Scope.vue

@@ -142,7 +142,8 @@ export default {
     background: rgb(255, 159, 64, 0.1);
     text-align: center;
   }
-  .save-btn{
+  .save-btn,
+  .cancle-btn{
     display: block;
     width: 180px;
     height: 46px;
@@ -159,6 +160,15 @@ export default {
       cursor: not-allowed;
     }
   }
+  .confirm-btn{
+    margin: 20px 0;
+  }
+  .cancle-btn{
+    margin: 20px;
+    background: #fff;
+    border: 1px solid #2cb7ca;
+    color: #2CB7CA;
+  }
 }
 .small-dialog{
   border-radius: 8px;

+ 14 - 3
src/views/subscribe/components/scope/Edit.vue

@@ -62,8 +62,9 @@
           <div class="add-words-btn" @click="showNotWay = true">+添加排除词(不希望接收,与关键词互斥)</div>
         </div>
       </div>
-      <div>
-        <button type="button" :disabled="keyDisabled" class="save-btn" @click="submitKeywords">保存</button>
+      <div class="btn-groups">
+        <button type="button" :disabled="keyDisabled" class="save-btn confirm-btn" @click="submitKeywords">保存</button>
+        <button type="button" class="cancle-btn" @click="cancelEdit">取消</button>
       </div>
     </div>
     <!-- 关键词重复提示 -->
@@ -300,9 +301,14 @@ export default {
         const cNotKey = JSON.stringify(obj.notkey) === JSON.stringify(notKeyArr)
         const cWay = obj.matchway === matchWay
         const notChange = cKey && cAppend && cNotKey && cWay
-        console.log(cKey, cAppend, cNotKey, cWay, JSON.stringify(obj.appendkey), JSON.stringify(appendArr), JSON.stringify(obj.notkey), JSON.stringify(notKeyArr), obj.matchway, matchWay)
+        // console.log(cKey, cAppend, cNotKey, cWay, JSON.stringify(obj.appendkey), JSON.stringify(appendArr), JSON.stringify(obj.notkey), JSON.stringify(notKeyArr), obj.matchway, matchWay)
         return notChange
       }
+    },
+    cancelEdit () {
+      this.$emit('closeForm', {
+        index: this.keyIndex
+      })
     }
   }
 }
@@ -462,6 +468,11 @@ export default {
     line-height: 20px;
     text-align: justify;
   }
+  .btn-groups{
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
 }
 // element-ui样式修改
 ::v-deep {

+ 14 - 9
src/views/subscribe/components/scope/List.vue

@@ -166,15 +166,20 @@ export default {
     },
     // 编辑单个关键词
     editKeyFn (v, i) {
-      console.log(v, i)
-      this.props.ways = 'edit'
-      // this.dialog.editKey = true
-      // 把当前关键词传到dialog key,notkey,appendKey都为数组
-      this.props.key = v.key
-      this.props.notkey = v.notkey
-      this.props.appendkey = v.appendkey
-      this.props.keyIndex = i
-      v.showForm = true
+      const data = this.newWordsList
+      const t = data.some(s => {
+        return s.showForm
+      })
+      if (t) {
+        return this.$toast('请先保存或取消正在操作的关键词组')
+      } else {
+        this.props.ways = 'edit'
+        this.props.key = v.key
+        this.props.notkey = v.notkey
+        this.props.appendkey = v.appendkey
+        this.props.keyIndex = i
+        v.showForm = true
+      }
     },
     // 清空传值
     clearPropsData () {