Browse Source

Merge branch 'dev' of http://192.168.3.207:10080/jianyu/page_bigmember_pc into dev

TANGSHIZHE 4 years ago
parent
commit
9ee26f0968
36 changed files with 1349 additions and 1372 deletions
  1. 2 9
      src/components/chart/HotChart.vue
  2. 1 1
      src/components/chart/ProgressChart.vue
  3. 4 4
      src/components/forecast/ForLayout.vue
  4. 5 5
      src/components/forecast/ForeCast.vue
  5. 5 5
      src/components/push-list/PotentialList.vue
  6. 5 1
      src/components/push-list/PushList.vue
  7. 7 0
      src/components/selector/BusinessScopeSelector.vue
  8. 18 6
      src/router/router-interceptors.js
  9. 26 32
      src/router/routers.js
  10. 41 7
      src/store/user.js
  11. 49 0
      src/utils/bigmember/index.js
  12. 79 0
      src/utils/bigmember/powerMap.js
  13. 0 156
      src/utils/china.json
  14. 0 980
      src/utils/echarts_option.js
  15. 14 0
      src/utils/format.js
  16. 0 1
      src/utils/index.js
  17. 0 31
      src/views/EmptyDemo.vue
  18. 19 29
      src/views/Home.vue
  19. 29 17
      src/views/PotentialList.vue
  20. 1 1
      src/views/bid-forecast/BidForecastLimit.vue
  21. 1 1
      src/views/bid-policy/AnalysisResult.vue
  22. 1 1
      src/views/bid-policy/components/PolicyLimit.vue
  23. 1 1
      src/views/portrayal/components/AnalysisList.vue
  24. 5 1
      src/views/portrayal/components/UnitChart.vue
  25. 1 0
      src/views/portrayal/components/UnitList.vue
  26. 1 1
      src/views/potential-for/PotenSimilar.vue
  27. 3 3
      src/views/project/ProjectInfo.vue
  28. 9 9
      src/views/subscribe/Config.vue
  29. 77 38
      src/views/subscribe/Scope.vue
  30. 21 14
      src/views/subscribe/components/key/KeyConfig.vue
  31. 0 0
      src/views/subscribe/components/key/KeyEdit.vue
  32. 30 15
      src/views/subscribe/components/key/KeyList.vue
  33. 3 3
      src/views/subscribe/components/key/SubConfig.vue
  34. 313 0
      src/views/subscribe/components/scope/Add.vue
  35. 157 0
      src/views/subscribe/components/scope/Edit.vue
  36. 421 0
      src/views/subscribe/components/scope/List.vue

+ 2 - 9
src/components/chart/HotChart.vue

@@ -49,7 +49,7 @@ export default {
           }
         },
         grid: {
-          top: '10%',
+          top: '5%',
           left: 55,
           right: 55
         },
@@ -64,13 +64,6 @@ export default {
         },
         yAxis: [
           {
-            name: '单位(元)',
-            nameTextStyle: {
-              fontSize: 12,
-              color: '#9B9CA3',
-              padding: [0, 8, 0, -30]
-            },
-            nameGap: 10,
             type: 'category',
             data: ['0', '1万', '10万', '50万', '100万', '500万', '1000万', '5000万', '1亿', '10亿以上'].reverse(),
             splitArea: {
@@ -373,7 +366,7 @@ export default {
       const maxNum = Math.max.apply(Math, series[0].data.map((o) => { return o[3] }))
       visualMap.max = maxNum < 10 ? 10 : maxNum
       graphic[graphic.length - 2].children[0].style.text = maxNum > 10 ? maxNum.toString() : '10'
-      // graphic[0].children[0].style.text = '项目数量(个)'
+      graphic[0].children[0].style.text = '项目数量(个)'
       const pj = Math.floor((visualMap.max / 5) * 100) / 100
       visualMap[0].pieces = [
         { min: 0, max: 0, color: '#FFF4EB', symbol: 'rect' },

+ 1 - 1
src/components/chart/ProgressChart.vue

@@ -62,7 +62,7 @@ export default {
   mounted () {},
   methods: {
     goEntInfo (name) {
-      this.$router.push('/unitportrayal/' + encodeURIComponent(name))
+      this.$router.push('/unit_portrayal/' + encodeURIComponent(name))
     }
   }
 }

+ 4 - 4
src/components/forecast/ForLayout.vue

@@ -74,7 +74,7 @@ export default {
             // 企业情报
             if (data.events === 'select') {
               // 联想跳转
-              this.$router.push(`/entportrayal/${data.data.entId}`)
+              this.$router.push(`/ent_portrait/${data.data.entId}`)
             } else {
               this.$store.commit('forcast/setType', this.type)
               this.$store.commit('forcast/setEntFollowSearch', res.data)
@@ -94,7 +94,7 @@ export default {
                 const result = [data.data]
                 this.$store.commit('forcast/setHistoryList', result)
                 this.$router.push({
-                  path: '/bidforlimit',
+                  path: '/ai_add',
                   query: {
                     pid: data.data.s_id,
                     sid: data.data.sourceinfoid
@@ -121,13 +121,13 @@ export default {
               // 联想跳转
               const result = [data.data]
               this.$store.commit('forcast/setHistoryPolicyList', result)
-              this.$router.push(`/analysis/result/${data.data.s_id}/${data.data.sourceinfoid}`)
+              this.$router.push(`/analysis_result/${data.data.s_id}/${data.data.sourceinfoid}`)
             } else {
               // 点击搜索按钮
               // const result = []
               this.$store.commit('forcast/setType', this.type)
               this.$store.commit('forcast/setPolicyList', res.data)
-              // this.$router.push(`/bidforlimit/${result.data.s_id}/${data.data.sourceinfoid}`)
+              // this.$router.push(`/ai_add/${result.data.s_id}/${data.data.sourceinfoid}`)
             }
           }
         })

+ 5 - 5
src/components/forecast/ForeCast.vue

@@ -402,7 +402,7 @@ export default {
         const result = [data]
         this.$store.commit('forcast/setHistoryList', result)
         this.$router.push({
-          path: '/bidforlimit',
+          path: '/ai_add',
           query: {
             pid: data.s_id,
             sid: data.sourceinfoid
@@ -413,14 +413,14 @@ export default {
     goForcast (data) {
       const result = [data]
       this.$store.commit('forcast/setHistoryPolicyList', result)
-      this.$router.push(`/analysis/result/${data.s_id}/${data.sourceinfoid}`)
+      this.$router.push(`/analysis_result/${data.s_id}/${data.sourceinfoid}`)
     },
     goViewEnt (id) {
-      this.$router.push(`/entportrayal/${id}`)
+      this.$router.push(`/ent_portrait/${id}`)
     },
     goEntPor (id) {
       const routeUrl = this.$router.resolve({
-        path: `/entportrayal/${id}`
+        path: `/ent_portrait/${id}`
       })
       return window.open(routeUrl.href, '_blank')
     },
@@ -438,7 +438,7 @@ export default {
       })
       console.log(arr.toString())
       this.$router.push({
-        path: '/potensimilar',
+        path: '/analysis_filter',
         query: {
           id: id,
           keys: arr.toString()

+ 5 - 5
src/components/push-list/PotentialList.vue

@@ -34,7 +34,7 @@
               <i :class="'el-icon-jy-heart_' + (item.follow ? 'solid' : 'stroke')"></i>
               <span>{{item.follow ? '已' : ''}}关注</span>
             </div>
-            <span  @click.stop="changeRemove(item)">不是我的潜在竞争对手/合作伙伴</span>
+            <span  @click.stop="changeDelete(item)">不是我的潜在竞争对手/合作伙伴</span>
           </div>
         </div>
       </div>
@@ -129,14 +129,14 @@ export default {
   created () {},
   methods: {
     changeFollow (item) {
-      item.follow = true
+      this.$emit(item.follow ? 'remove' : 'follow', item)
+      item.follow = !item.follow
       this.$forceUpdate()
-      this.$emit('follow', item)
     },
-    changeRemove (item) {
+    changeDelete (item) {
       item.remove = true
       this.$forceUpdate()
-      this.$emit('remove', item)
+      this.$emit('delete', item)
     },
     goManage () {
       alert('订阅管理')

+ 5 - 1
src/components/push-list/PushList.vue

@@ -2,7 +2,7 @@
   <el-card class="info-list-card">
     <div slot="header" class="clearfix">
       <span class="card-title">订阅推送</span>
-      <el-button @click="goManage" class="sub-manager" type="plain" icon="el-icon-jy-edit">订阅管理</el-button>
+      <el-button v-if="subManager" @click="goManage" class="sub-manager" type="plain" icon="el-icon-jy-edit">订阅管理</el-button>
     </div>
     <div class="info-list" v-loading="listState.loading">
       <article-item
@@ -63,6 +63,10 @@ export default {
       type: Boolean,
       default: true
     },
+    subManager: {
+      type: Boolean,
+      default: false
+    },
     filters: {
       type: Object,
       default () {

+ 7 - 0
src/components/selector/BusinessScopeSelector.vue

@@ -41,6 +41,13 @@ export default {
   data () {
     return {}
   },
+  watch: {
+    initList () {
+      this.$nextTick(() => {
+        this.$refs.content.init()
+      })
+    }
+  },
   created () {},
   methods: {
     setState (data) {

+ 18 - 6
src/router/router-interceptors.js

@@ -1,15 +1,27 @@
 import router from '@/router/router'
 import store from '@/store/'
+import { powerCheck } from '@/utils/bigmember/'
+
+// 权限控制白名单-组件名
+const powerCheckWhiteList = ['404']
 
-// 从vue实例中获取store对象
-// const store = router.app.$store
 router.beforeEach(async (to, from, next) => {
-  const { power } = store.state.user
-  // 如果power为空,则请求power
-  if (Array.isArray(power) && power.length === 0) {
+  const { power, info } = store.state.user
+  if (!Object.keys(info).length) {
     await store.dispatch('user/getUserPower')
+  }
+  if (powerCheckWhiteList.includes(to.name)) {
     next()
   } else {
-    next()
+    let href = '/big/page/index'
+    const { pass, anchor } = powerCheck(info, power, to, from)
+    if (pass) {
+      next()
+    } else {
+      if (anchor) {
+        href = `${href}#${anchor}`
+      }
+      location.href = href
+    }
   }
 })

+ 26 - 32
src/router/routers.js

@@ -6,67 +6,61 @@ export default [
   },
   // 订阅推送
   {
-    path: '/sub-push',
-    name: 'sub-push',
+    path: '/big_subscribe',
+    name: 'big_subscribe',
     component: () => import('@/views/SubPush.vue')
   },
   // 潜在客户/对手
   {
-    path: '/potentialList/:type',
-    name: 'potentialList',
+    path: '/potential_cor_list/:type',
+    name: 'potential_cor_list',
     component: () => import('@/views/PotentialList.vue')
   },
-  // 周报详情
   {
-    path: '/empty-demo',
-    name: 'empty-demo',
-    component: () => import('@/views/EmptyDemo.vue')
-  },
-  {
-    path: '/report/week',
-    name: 'week',
+    path: '/bigvip_subreport_week',
+    name: 'bigvip_subreport_week',
     component: () => import('@/views/reportData/pageWeek.vue')
   },
   // 月报详情
   {
-    path: '/report/month',
-    name: 'month',
+    path: '/bigvip_subreport_month',
+    name: 'bigvip_subreport_month',
     component: () => import('@/views/reportData/pageMonth.vue')
   },
   // 中标企业预测
   {
-    path: '/bidforecast',
-    name: 'bidforecast',
+    path: '/ai_search',
+    name: 'ai_search',
     component: () => import('@/views/bid-forecast/BidForecast.vue')
   },
   // 中标企业预测-预测
   {
-    path: '/bidforlimit',
-    name: 'bidforlimit',
+    path: '/ai_add',
+    name: 'ai_add',
     component: () => import('@/views/bid-forecast/BidForecastLimit.vue')
   },
   // 投标决策分析
   {
-    path: '/bidpolicy',
-    name: 'bidpolicy',
+    path: '/analysis_search',
+    name: 'analysis_search',
     component: () => import('@/views/bid-policy/BidPolicy.vue')
   },
   // 企业情报监控
   {
-    path: '/entintel',
-    name: 'entintel',
+    path: '/ent_follow',
+    name: 'ent_follow',
     component: () => import('@/views/ent-intel/EntIntel.vue')
   },
   // 潜在项目预测
   {
-    path: '/potential',
-    name: 'potential',
+    path: '/forecast_list',
+    name: 'forecast_list',
     component: () => import('@/views/potential-for/PotenTial.vue')
   },
   // 潜在项目预测--相似项目
   {
-    path: '/potensimilar',
-    name: 'potensimilar',
+    path: '/analysis_filter',
+    name: 'analysis_filter',
     component: () => import('@/views/potential-for/PotenSimilar.vue')
   },
   {
@@ -76,14 +70,14 @@ export default [
   },
   // 采购单位画像
   {
-    path: '/unitportrayal/:entName',
-    name: 'unitportrayal',
+    path: '/unit_portrayal/:entName',
+    name: 'unit_portrayal',
     component: () => import('@/views/portrayal/UnitPortrayal.vue')
   },
   // 企业画像
   {
-    path: '/entportrayal/:eId',
-    name: 'entportrayal',
+    path: '/ent_portrait/:eId',
+    name: 'ent_portrait',
     component: () => import('@/views/portrayal/EntPortrayal.vue')
   },
   // 项目信息
@@ -94,8 +88,8 @@ export default [
   },
   // 投标决策分析结果页
   {
-    path: '/analysis/result/:ptid/:sourceinfoid',
-    name: 'analysisResult',
+    path: '/analysis_result/:ptid/:sourceinfoid',
+    name: 'analysis_result',
     component: () => import('@/views/bid-policy/AnalysisResult.vue')
   },
   // 业务范围

+ 41 - 7
src/store/user.js

@@ -1,26 +1,45 @@
 import { recoveryPageData, defaultLocalPageData } from '@/utils/'
 import {
-  getUserPower
+  getUserPower,
+  getBigMemberInfo
 } from '@/api/modules'
+import { formatKeywordsList } from '@/utils/format'
+
 export default {
   namespaced: true,
   state: () => ({
-    power: recoveryPageData('bigmember-power', []),
-    info: recoveryPageData('bigmember-info', {}),
-    scope: defaultLocalPageData('bigmember-scope', [])
+    power: recoveryPageData('bigmember-login-clear-power', []),
+    info: recoveryPageData('bigmember-login-clear-info', {}),
+    // 业务范围
+    scope: defaultLocalPageData('bigmember-login-clear-SCOPE', []),
+    // 采购内容设置
+    buyClass: defaultLocalPageData('bigmember-login-clear-BUY_CLASS', []),
+    // 大会员基本信息数据
+    bigKeywordsData: defaultLocalPageData('bigmember-login-clear-keywords', [])
   }),
   mutations: {
     setUserInfo (state, info) {
       state.info = info
-      // sessionStorage.setItem('bigmember-info', JSON.stringify(info))
+      sessionStorage.setItem('bigmember-login-clear-info', JSON.stringify(info))
     },
     setUserPower (state, power) {
       state.power = power
-      // sessionStorage.setItem('bigmember-power', JSON.stringify(power))
+      sessionStorage.setItem('bigmember-login-clear-power', JSON.stringify(power))
     },
+    // 设置的业务范围
     setScope (state, data) {
       state.scope = data
-      localStorage.setItem('bigmember-scope', JSON.stringify(data))
+      localStorage.setItem('bigmember-login-clear-SCOPE', JSON.stringify(data))
+    },
+    // 设置的采购内容
+    setBuyClass (state, data) {
+      state.buyClass = data
+      localStorage.setItem('bigmember-login-clear-BUY_CLASS', JSON.stringify(data))
+    },
+    // 大会员基本信息里所有数据
+    setBigKeywords (state, data) {
+      state.bigKeywordsData = data
+      localStorage.setItem('bigmember-login-clear-keywords', JSON.stringify(data))
     }
   },
   actions: {
@@ -35,6 +54,21 @@ export default {
         }
         return data
       } catch (error) {}
+    },
+    async getKeywordsList ({ commit, state }, payload) {
+      try {
+        const { data, error_code: code } = await getBigMemberInfo()
+        if (code === 0) {
+          // 如果传的有参数,提交的为采购内容,无参数则默认提交的为业务范围
+          if (payload) {
+            commit('setBuyClass', formatKeywordsList(data))
+          } else {
+            commit('setScope', formatKeywordsList(data))
+          }
+          commit('setBigKeywords', data)
+        }
+        return formatKeywordsList(data)
+      } catch (error) {}
     }
   },
   getters: {}

+ 49 - 0
src/utils/bigmember/index.js

@@ -0,0 +1,49 @@
+import { powerMap } from './powerMap'
+
+// 生成路由对应权限的map
+const createURL2Power = () => {
+  const URL2Power = new Map()
+  Object.keys(powerMap).forEach(v => {
+    const nowV = powerMap[v]
+    const tempUrls = nowV.url.split('&')
+    tempUrls.forEach(u => {
+      const oldPower = URL2Power.get(u) || []
+      URL2Power.set(u, Array.from(new Set(oldPower.concat(Number(v)))))
+    })
+  })
+  return URL2Power
+}
+
+// 路由权限控制判断
+export const powerCheck = (info, power, to, from) => {
+  const URL2Power = createURL2Power()
+  const passInfo = {
+    pass: true,
+    anchor: ''
+  }
+  if (info?.memberStatus > 0) {
+    // 开通了大会员
+    // 当前url对应的power列表
+    const urlPowerList = URL2Power.get(to.path) || URL2Power.get(to.name)
+    if (urlPowerList) {
+      // 当前页面需要权限
+      const intersectionPower = urlPowerList.filter(v => power.includes(v))
+      // 判断当前url是否有权限
+      if (intersectionPower.length) {
+        // 当前路由有权限
+        passInfo.pass = true
+      } else {
+        // 当前路由无权限
+        passInfo.anchor = powerMap[urlPowerList[0]].anchor
+        passInfo.pass = false
+      }
+    } else {
+      // 当前页面不需要权限
+    }
+    return passInfo
+  } else {
+    // 未开通大会员
+    passInfo.pass = false
+    return passInfo
+  }
+}

+ 79 - 0
src/utils/bigmember/powerMap.js

@@ -0,0 +1,79 @@
+export const powerMap = {
+  1: {
+    tip: '搜索+订阅',
+    url: 'big_subscribe&bigVip_detail&bigvip_viewpage',
+    anchor: 'zb'
+  },
+  2: {
+    tip: '子账号',
+    url: ''
+  },
+  3: {
+    tip: '附件下载',
+    url: ''
+  },
+  4: {
+    tip: '企业全景分析',
+    url: 'ent_portrait&ent_follow_search&ent_follow',
+    anchor: 'jc'
+  },
+  5: {
+    tip: '采购单位全景分析',
+    url: 'unit_portrayal',
+    anchor: 'jc'
+  },
+  6: {
+    tip: '投标决策分析',
+    url: 'analysis_search&analysis_filter&analysis_result&ai_unit',
+    anchor: 'jc'
+  },
+  7: {
+    tip: '挖掘潜在客户',
+    url: 'potential_cor_list&potential_cor',
+    anchor: 'qz'
+  },
+  8: {
+    tip: '挖掘潜在伙伴/竞争对手',
+    url: 'potential_cor_list&potential_cor',
+    anchor: 'qz'
+  },
+  9: {
+    tip: '挖掘潜在项目',
+    url: 'forecast_list&forecast_detail',
+    anchor: 'fx'
+  },
+  10: {
+    tip: '周报/月报',
+    url: 'bigvip_subreport_week&bigvip_subreport_month&report_detail_week&report_detail_month',
+    anchor: 'fx'
+  },
+  11: {
+    tip: '招标文件解读',
+    url: ''
+  },
+  12: {
+    tip: '企业情报监控',
+    url: 'ent_portrait&ent_portrait_change&ent_follow_search&ent_follow',
+    anchor: 'fx'
+  },
+  13: {
+    tip: '企业中标动态',
+    url: 'ent_follow&ent_portrait&ent_follow_search',
+    anchor: 'fx'
+  },
+  14: {
+    tip: '项目进度监控',
+    url: 'pro_follow_list&pro_follow_detail',
+    anchor: 'zb'
+  },
+  15: {
+    tip: '中标企业预测',
+    url: 'ai_search&ai_add&ai_result&ai_balance&voucher_center&ai_unit',
+    anchor: 'zb'
+  },
+  16: {
+    tip: '企业情报监控+企业中标动态',
+    url: '',
+    anchor: 'fx'
+  }
+}

File diff suppressed because it is too large
+ 0 - 156
src/utils/china.json


+ 0 - 980
src/utils/echarts_option.js

@@ -1,980 +0,0 @@
-// 中国地图配置项
-export var mapSettings = {
-  chartSettings: {
-    positionJsonLink: './china.json',
-    beforeRegisterMapOnce (map) {
-      return map
-    },
-    beforeRegisterMap (map) {
-      return map
-    },
-    label: {
-      show: true,
-      fontSize: 9
-    },
-    selectedMode: false, // 去掉省份小圆点
-    itemStyle: {
-      normal: {
-        borderColor: '#F06326',
-        areaColor: '#FFFFFF'
-      }
-    }
-    // zoom:0.95, // 缩放比例
-  },
-  chartExtend: {
-    tooltip: {
-      confine: true,
-      backgroundColor: '#fff',
-      axisPointer: { // 坐标轴指示器,坐标轴触发有效
-        type: 'shadow', // 默认为直线,可选为:'line' | 'shadow'
-        shadowStyle: {
-          color: 'rgba(5,166,243,0.1)'
-        },
-        z: 3
-      },
-      textStyle: {
-        color: '#171826',
-        fontSize: 12
-      },
-      padding: [8, 12],
-      extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
-      formatter: function (params, ticket, callback) {
-        if (params.data == null) {
-          return params.name + ':0'
-        } else {
-          return params.name + ':' + params.value
-        }
-      }
-    },
-    grid: {
-      height: '280px',
-      containLabel: true
-    },
-    legend: { // 隐藏图标上方小方块及文字
-      selectedMode: false,
-      textStyle: {
-        color: 'transparent'
-      },
-      itemWidth: 0,
-      itemHeight: 0
-    },
-    silent: false, // 禁用鼠标点击、滑过事件
-    series: {
-      showLegendSymbol: false,
-      selectedMode: false
-    },
-    graphic: [
-      {
-        type: 'group',
-        bottom: 54,
-        children: [
-          {
-            type: 'text',
-            z: 100,
-            left: 'left',
-            top: 'middle',
-            style: {
-              fill: '#333',
-              text: '市场分布数量',
-              font: '10px Microsoft YaHei'
-            }
-          }]
-      },
-      {
-        type: 'rect',
-        z: 101,
-        left: 0,
-        bottom: 34,
-        shape: {
-          width: 84,
-          height: 14
-        },
-        style: {
-          stroke: '#FB483D',
-          fill: 'transparent',
-          lineWidth: 0.5
-        }
-      },
-      rectGroup(0, '#F06326'),
-      rectGroup(14, '#F48A5D'),
-      rectGroup(28, '#FFB366'),
-      rectGroup(42, '#FFCF9F'),
-      rectGroup(56, '#FFE7CF'),
-      rectGroup(70, '#FFF4EB'),
-      {
-        type: 'group',
-        width: 84,
-        bottom: 20,
-        children: [
-          {
-            type: 'text',
-            z: 100,
-            left: 'left',
-            top: 'middle',
-            style: {
-              fill: '#333',
-              text: '100',
-              font: '10px Microsoft YaHei'
-            }
-          },
-          {
-            type: 'text',
-            z: 100,
-            left: 'right',
-            top: 'middle',
-            style: {
-              fill: '#333',
-              text: '0',
-              font: '10px Microsoft YaHei'
-            }
-          }]
-      }
-    ],
-    visualMap: {
-      show: false,
-      inRange: { // 定义 在选中范围中 的视觉元素
-        color: ['#FFF4EB', '#FFE7CF', '#FFCF9F', '#FFB366', '#F48A5D', '#F06326']
-      },
-      outOfRange: {
-        color: ['#F06326']
-      }
-    }
-  },
-  chart: null
-}
-// 月报本月项目规模分布
-export var mapSettings2 = {
-  chartSettings: {
-    positionJsonLink: './china.json',
-    beforeRegisterMapOnce (map) {
-      return map
-    },
-    beforeRegisterMap (map) {
-      return map
-    },
-    label: {
-      show: true,
-      fontSize: 9
-    },
-    selectedMode: false,
-    itemStyle: {
-      normal: {
-        borderColor: '#F06326',
-        areaColor: '#FFFFFF'
-      }
-    }
-  },
-  chartExtend: {
-    tooltip: {
-      confine: true,
-      backgroundColor: '#fff',
-      axisPointer: {
-        type: 'shadow', 
-        shadowStyle: {
-          color: 'rgba(5,166,243,0.1)'
-        },
-        z: 3
-      },
-      textStyle: {
-        color: '#171826',
-        fontSize: 12
-      },
-      padding: [8, 12],
-      extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
-      formatter: function (params, ticket, callback) {
-        if (params.data == null) {
-          return params.name + ':0'
-        } else {
-          return params.name + ':' + params.value
-        }
-      }
-    },
-    grid: {
-      height: '280px',
-      containLabel: true
-    },
-    legend: {
-      selectedMode: false,
-      textStyle: {
-        color: 'transparent'
-      },
-      itemWidth: 0,
-      itemHeight: 0
-    },
-    silent: false,
-    series: {
-      showLegendSymbol: false,
-      selectedMode: false
-    },
-    graphic: [
-      {
-        type: 'group',
-        bottom: 54,
-        children: [
-          {
-            type: 'text',
-            z: 100,
-            left: 'left',
-            top: 'middle',
-            style: {
-              fill: '#333',
-              text: '单位:万元',
-              font: '10px Microsoft YaHei'
-            }
-          }]
-      },
-      {
-        type: 'rect',
-        z: 101,
-        left: 0,
-        bottom: 34,
-        shape: {
-          width: 84,
-          height: 14
-        },
-        style: {
-          stroke: '#FB483D',
-          fill: 'transparent',
-          lineWidth: 0.5
-        }
-      },
-      rectGroup(0, '#F06326'),
-      rectGroup(14, '#F48A5D'),
-      rectGroup(28, '#FFB366'),
-      rectGroup(42, '#FFCF9F'),
-      rectGroup(56, '#FFE7CF'),
-      rectGroup(70, '#FFF4EB'),
-      {
-        type: 'group',
-        width: 84,
-        bottom: 20,
-        children: [
-          {
-            type: 'text',
-            z: 100,
-            left: 'left',
-            top: 'middle',
-            style: {
-              fill: '#333',
-              text: '100',
-              font: '10px Microsoft YaHei'
-            }
-          },
-          {
-            type: 'text',
-            z: 100,
-            left: 'right',
-            top: 'middle',
-            style: {
-              fill: '#333',
-              text: '0',
-              font: '10px Microsoft YaHei'
-            }
-          }]
-      }
-    ],
-    visualMap: {
-      show: false,
-      inRange: {
-        color: ['#FFF4EB', '#FFE7CF', '#FFCF9F', '#FFB366', '#F48A5D', '#F06326']
-      },
-      outOfRange: {
-        color: ['#F06326']
-      }
-    }
-  },
-  chart: null
-}
-// 月报本月中标企业注册地分布
-export var mapSettings3 = {
-  chartSettings: {
-    positionJsonLink: './china.json',
-    beforeRegisterMapOnce (map) {
-      return map
-    },
-    beforeRegisterMap (map) {
-      return map
-    },
-    label: {
-      show: true,
-      fontSize: 9
-    },
-    selectedMode: false,
-    itemStyle: {
-      normal: {
-        borderColor: '#F06326',
-        areaColor: '#FFFFFF'
-      }
-    }
-  },
-  chartExtend: {
-    tooltip: {
-      confine: true,
-      backgroundColor: '#fff',
-      axisPointer: {
-        type: 'shadow', 
-        shadowStyle: {
-          color: 'rgba(5,166,243,0.1)'
-        },
-        z: 3
-      },
-      textStyle: {
-        color: '#171826',
-        fontSize: 12
-      },
-      padding: [8, 12],
-      extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
-      formatter: function (params, ticket, callback) {
-        if (params.data == null) {
-          return params.name + ':0'
-        } else {
-          return params.name + ':' + params.value
-        }
-      }
-    },
-    grid: {
-      height: '280px',
-      containLabel: true
-    },
-    legend: {
-      selectedMode: false,
-      textStyle: {
-        color: 'transparent'
-      },
-      itemWidth: 0,
-      itemHeight: 0
-    },
-    silent: false,
-    series: {
-      showLegendSymbol: false,
-      selectedMode: false
-    },
-    graphic: [
-      {
-        type: 'group',
-        bottom: 54,
-        children: [
-          {
-            type: 'text',
-            z: 100,
-            left: 'left',
-            top: 'middle',
-            style: {
-              fill: '#333',
-              text: '单位:个',
-              font: '10px Microsoft YaHei'
-            }
-          }]
-      },
-      {
-        type: 'rect',
-        z: 101,
-        left: 0,
-        bottom: 34,
-        shape: {
-          width: 84,
-          height: 14
-        },
-        style: {
-          stroke: '#FB483D',
-          fill: 'transparent',
-          lineWidth: 0.5
-        }
-      },
-      rectGroup(0, '#F06326'),
-      rectGroup(14, '#F48A5D'),
-      rectGroup(28, '#FFB366'),
-      rectGroup(42, '#FFCF9F'),
-      rectGroup(56, '#FFE7CF'),
-      rectGroup(70, '#FFF4EB'),
-      {
-        type: 'group',
-        width: 84,
-        bottom: 20,
-        children: [
-          {
-            type: 'text',
-            z: 100,
-            left: 'left',
-            top: 'middle',
-            style: {
-              fill: '#333',
-              text: '100',
-              font: '10px Microsoft YaHei'
-            }
-          },
-          {
-            type: 'text',
-            z: 100,
-            left: 'right',
-            top: 'middle',
-            style: {
-              fill: '#333',
-              text: '0',
-              font: '10px Microsoft YaHei'
-            }
-          }]
-      }
-    ],
-    visualMap: {
-      show: false,
-      inRange: {
-        color: ['#FFF4EB', '#FFE7CF', '#FFCF9F', '#FFB366', '#F48A5D', '#F06326']
-      },
-      outOfRange: {
-        color: ['#F06326']
-      }
-    }
-  },
-  chart: null
-}
-// 中国地图例graphic配置函数
-export function rectGroup (left, color) {
-  return {
-    type: 'rect',
-    z: 100,
-    left: left,
-    bottom: 34,
-    shape: {
-      width: 14,
-      height: 14
-    },
-    style: {
-      fill: color
-    }
-  }
-}
-//  投标决策分析页面:预算分布、中标金额、折扣率分布三个图表配置项(只配置相同部分,不同部分在页面里单独配置)
-export var barChart = {
-  chartSettings: {},
-  chartExtend: {
-    grid: {
-      left: 4,
-      x: 0,
-      y: 20,
-      x2: 0,
-      bottom: 20
-    },
-    xAxis: {
-      axisLabel: {
-        interval: 0, // 强制显示x轴所有刻度
-        fontSize: 10
-      }
-    },
-    yAxis (item) {
-      item[0].splitLine = {
-        lineStyle: {
-          type: 'dashed', // y轴背景虚线
-          width: 0.5
-        }
-      }
-      item[0].axisLabel = {
-        margin: 2,
-        fontSize: 10
-      }
-      item[1].splitLine = {
-        show: false
-      }
-      item[1].axisLabel = {
-        show: false,
-        fontSize: 10
-      }
-      return item
-    },
-    tooltip: {
-      trigger: 'axis',
-      confine: true,
-      backgroundColor: '#fff',
-      axisPointer: {
-        type: 'shadow',
-        shadowStyle: {},
-        z: 3
-      },
-      textStyle: {
-        color: '#171826',
-        fontSize: 12
-      },
-      padding: [7, 12],
-      extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08);transform: translate3d(0,0,0)',
-      formatter: function (params) {
-        // 移除重复的数据
-        for (var i = 0; i < params.length; i++) {
-          for (var j = params.length - 1; j > i; j--) {
-            if (params[j].data == params[i].data) {
-              params.splice(j, 1)
-              break
-            }
-          }
-        }
-        var tip = ''
-        // eslint-disable-next-line no-redeclare
-        for (var i = 0; i < params.length; i++) {
-          if (i == 0) {
-            tip = params[i].value == 0 ? '' : tip + params[i].seriesName + ':' + params[i].value + '个' + '<br/>'
-          } else if (i == 1) {
-            if (params[i].value != 0 || params[i].value != '0.00') {
-              if (params[i].seriesName === '平均折扣率') {
-                tip = tip + params[i].seriesName + ':' + params[i].value + '%' + '<br/>'
-              } else {
-                tip = tip + params[i].seriesName + ':' + params[i].value + '万元' + '<br/>'
-              }
-            } else {
-              // eslint-disable-next-line no-self-assign
-              tip = tip
-            }
-          }
-        }
-        return tip
-      }
-    },
-    legend: {
-      show: false,
-      orient: 'horizontal',
-      icon: 'circle',
-      bottom: 20,
-      align: 'left',
-      itemWidth: 8,
-      itemHeight: 8,
-      itemGap: 20,
-      textStyle: {
-        fontSize: 11,
-        rich: {
-          a: {
-            fontSize: 16,
-            verticalAlign: 'top',
-            align: 'center',
-            padding: [0, 15, 28, 0]
-          },
-          b: {
-            fontSize: 14,
-            align: 'center',
-            padding: [0, 15, 0, 0],
-            lineHeight: 25
-          }
-        }
-      },
-      formatter: function (name) {
-        var wnYuan = ['金额', '项目金额', '项目规划', '项目总预算', '项目总规模']
-        var ge = ['数量', '项目数量']
-        if (wnYuan.indexOf(name) !== -1) {
-          name += '(万元)'
-        } else if (ge.indexOf(name) !== -1) {
-          name += '(个)'
-        }
-        return name
-      }
-    },
-    series: {
-      barWidth: 20,
-      smooth: false,
-      symbol: 'none',
-      lineStyle: {
-        width: 0,
-        color: 'rgba(0, 0, 0, 0)' // 线的颜色是透明的
-      }
-    }
-  }
-}
-
-// 平均折扣率配置
-export var multiBarChart = {
-  chartSettings: {
-    showLine: ['平均折扣率']
-  },
-  chartExtend: {
-    grid: {
-      x: 12,
-      y: 20,
-      x2: 12
-    },
-    yAxis: {
-      splitLine: {
-        show: true,
-        lineStyle: {
-          type: 'dashed', // y轴背景虚线
-          width: 0.5
-        }
-      },
-      axisLabel: {
-        fontSize: 10
-      }
-    },
-    xAxis: {
-      axisLabel: {
-        fontSize: 10
-      }
-    },
-    tooltip: {
-      trigger: 'axis',
-      confine: true,
-      backgroundColor: '#fff',
-      axisPointer: {
-        type: 'shadow',
-        shadowStyle: {
-          color: 'rgba(5,166,243,0.1)'
-        }
-      },
-      textStyle: {
-        color: '#171826',
-        fontSize: 12
-      },
-      padding: [8, 12],
-      extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
-      formatter: function (params) {
-        var tip = ''
-        for (var i = 0; i < params.length; i++) {
-          if (i < 4) {
-            tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '<br/>'
-          } else {
-            tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '%' + '<br/>'
-          }
-        }
-        tip += '<div style="padding-top:2px;text-align:center;color:#9B9CA3;">' + ' - ' + params[0].name.substring(0, params[0].name.lastIndexOf('年')) + ' - ' + '</div>'
-        return tip
-      }
-    },
-    legend: {
-      orient: 'horizontal',
-      bottom: 20,
-      icon: 'circle',
-      itemWidth: 8,
-      itemHeight: 8,
-      padding: [0, 6],
-      data: ['日期', '0~5%', '5~10%', '10~30%', '30~100%', '平均折扣率'],
-      textStyle: {
-        fontSize: 11
-      }
-    },
-    series: {
-      smooth: false
-    },
-    color: ['#05A6F3', '#0BD991', '#FF9F40', '#8E6DF2', '#F1D090']
-  }
-}
-
-export var mBarChart = {
-  dataEmpty: true,
-  chartSettings: {},
-  chartExtend: {
-    grid: {
-      x: 14,
-      y: 20,
-      x2: 14
-    },
-    tooltip: {
-      trigger: 'axis',
-      confine: true,
-      backgroundColor: '#fff',
-      axisPointer: {
-        type: 'shadow',
-        shadowStyle: {
-          color: 'rgba(5,166,243,0.1)'
-        }
-      },
-      textStyle: {
-        color: '#171826',
-        fontSize: 12
-      },
-      padding: [8, 12],
-      extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
-      z: 3
-    },
-    legend: {
-      orient: 'horizontal',
-      icon: 'circle',
-      bottom: 10,
-      left: 'center',
-      itemWidth: 8,
-      itemHeight: 8,
-      itemGap: 10,
-      textStyle: {
-        fontSize: 11
-      }
-    },
-    yAxis: {
-      splitLine: {
-        show: true,
-        lineStyle: {
-          type: 'dashed',
-          width: 0.5,
-          color: 'rgba(0, 0, 0, 0.08)'
-        }
-      },
-      axisLabel: {
-        fontSize: 10
-      }
-    },
-    xAxis: {
-      axisLabel: {
-        fontSize: 10
-      }
-    },
-    series: {
-      barWidth: 20,
-      type: 'bar'
-    },
-    color: ['#9C72F4', '#6B78E8', '#05A6F3', '#2ABED1', '#0BD991', '#C0C4CC', '#B8D4F9', '#444A7A', '#F1D090', '#B8D4F9', '#C09BFC', '#104EA3', '#21CED2', '#FFB901', '#7BBFE5', '#82E9D6', '#62B8FF', '#7E56EE', '#B3E3E7', '#8591FF', '#96C3D8', '#3774E8', '#CDCEFE', '#6BBEF4', '#6E55B4', '#2B82FE', '#FF9A01', '#01C290', '#BAE1A8', '#EB97D8']
-  }
-}
-
-// 月报 (本月项目规模)
-export var barChart2 = {
-  chartExtend: {
-    grid: {
-      left: 4,
-      x: 0,
-      y: 20,
-      x2: 12
-    },
-    xAxis: {
-      axisLabel: {
-        fontSize: 10
-      }
-    },
-    yAxis (item) {
-      var maxCountList = vNode.data.curMonthScaleData.rows.map(v => {
-        return v['项目规模']
-      })
-      var maxPriceList = vNode.data.curMonthScaleData.rows.map(v => {
-        return v['环比增长率(%)-右纵轴']
-      })
-      var maxCount = Math.ceil(Math.max.apply(null, maxCountList)).toString()
-      var maxPrice = Math.ceil(Math.max.apply(null, maxPriceList)).toString()
-      var minRight = Math.ceil(Math.min.apply(null, maxPriceList)).toString()
-      maxCount = Math.ceil(maxCount / (Math.pow(10, maxCount.length - 1))) * Math.pow(10, maxCount.length - 1)
-      maxPrice = Math.ceil(maxPrice / (Math.pow(10, maxPrice.length - 1))) * Math.pow(10, maxPrice.length - 1)
-      if (minRight.indexOf('-') > -1) {
-        minRight = '-' + Math.ceil(minRight.replace('-', '') / (Math.pow(10, minRight.replace('-', '').length - 1))) * Math.pow(10, minRight.replace('-', '').length - 1)
-      } else {
-        minRight = 0
-      }
-      item[0].min = 0
-      item[1].min = minRight
-      item[0].max = maxCount
-      item[0].interval = Math.ceil(maxCount / 5)
-      item[1].max = maxPrice
-      item[1].interval = Math.ceil((maxPrice - minRight) / 5)
-      item[0].splitLine = {
-        lineStyle: {
-          type: 'dashed',
-          width: 0.5
-        }
-      }
-      item[1].splitLine = {
-        show: false,
-        lineStyle: {
-          type: 'dashed',
-          width: 0.5
-        }
-      }
-      item[1].axisLabel = {
-        show: true,
-        fontSize: 10
-      }
-      item[0].axisLabel = {
-        margin: 2,
-        fontSize: 10,
-        formatter: function (value, index) {
-          return value.toString().replace(/,/, '')
-        }
-      }
-      return item
-    },
-    tooltip: {
-      trigger: 'axis',
-      confine: true,
-      backgroundColor: '#fff',
-      axisPointer: {
-        type: 'shadow',
-        shadowStyle: {
-          color: 'rgba(5,166,243,0.1)'
-        }
-      },
-      textStyle: {
-        color: '#171826',
-        fontSize: 12
-      },
-      padding: [7, 12],
-      extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
-      formatter: function (params) {
-        return formatterTip(params)
-      }
-    },
-    legend: {
-      show: true,
-      orient: 'horizontal',
-      icon: 'circle',
-      bottom: 20,
-      align: 'left',
-      itemWidth: 8,
-      itemHeight: 8,
-      itemGap: 20,
-      textStyle: {
-        fontSize: 11,
-        rich: {
-          a: {
-            fontSize: 16,
-            verticalAlign: 'top',
-            align: 'center',
-            padding: [0, 15, 28, 0]
-          },
-          b: {
-            fontSize: 14,
-            align: 'center',
-            padding: [0, 15, 0, 0],
-            lineHeight: 25
-          }
-        }
-      },
-      formatter: function (name) {
-        if (name == '项目规模') {
-          name = name + '(万元)'
-        }
-        return name
-      },
-      data: ['项目规模', '环比增长率(%)-右纵轴']
-    },
-    series: {
-      barWidth: 20,
-      smooth: false
-    },
-    color: ['#05A6F3', '#FF9F40']
-  }
-}
-// 月报 (本月中标企业中标项目数量分布)
-export var barChart3 = {
-  chartExtend: {
-    grid: {
-      x: 8,
-      y: 20,
-      x2: 12
-    },
-    xAxis: {
-      axisLabel: {
-        fontSize: 10,
-        formatter: function (val) {
-          return val + '个'
-        }
-      }
-    },
-    yAxis (item) {
-      var maxCountList = vNode.data.curWinEntCountData.rows.map(v => {
-        return v['企业数量']
-      })
-      var maxPriceList = vNode.data.curWinEntCountData.rows.map(v => {
-        return v['累计占比(%)-右纵轴']
-      })
-      var maxCount = Math.ceil(Math.max.apply(null, maxCountList)).toString()
-      var maxPrice = Math.ceil(Math.max.apply(null, maxPriceList)).toString()
-      maxCount = Math.ceil(maxCount / (Math.pow(10, maxCount.length - 1))) * Math.pow(10, maxCount.length - 1)
-      maxPrice = Math.ceil(maxPrice / (Math.pow(10, maxPrice.length - 1))) * Math.pow(10, maxPrice.length - 1)
-      item[0].min = 0
-      item[1].min = 0
-      item[0].max = maxCount
-      item[0].interval = Math.ceil(maxCount / 5)
-      item[1].max = maxPrice
-      item[1].interval = Math.ceil((maxPrice - 0) / 5)
-      item[0].splitLine = {
-        lineStyle: {
-          type: 'dashed',
-          width: 0.5
-        }
-      }
-      item[1].splitLine = {
-        show: false,
-        lineStyle: {
-          type: 'dashed',
-          width: 0.5
-        }
-      }
-      item[1].axisLabel = {
-        show: true,
-        fontSize: 10
-      }
-      item[0].axisLabel = {
-        margin: 2,
-        fontSize: 10,
-        formatter: function (value, index) {
-          return value.toString().replace(/,/, '')
-        }
-      }
-      return item
-    },
-    tooltip: {
-      trigger: 'axis',
-      confine: true,
-      backgroundColor: '#fff',
-      axisPointer: {
-        type: 'shadow',
-        shadowStyle: {
-          color: 'rgba(5,166,243,0.1)'
-        }
-      },
-      textStyle: {
-        color: '#171826',
-        fontSize: 12
-      },
-      padding: [7, 12],
-      extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
-      formatter: function (params) {
-        return formatterTip(params)
-      }
-    },
-    legend: {
-      show: true,
-      orient: 'horizontal',
-      icon: 'circle',
-      bottom: 20,
-      align: 'left',
-      itemWidth: 8,
-      itemHeight: 8,
-      itemGap: 20,
-      textStyle: {
-        fontSize: 11,
-        rich: {
-          a: {
-            fontSize: 16,
-            verticalAlign: 'top',
-            align: 'center',
-            padding: [0, 15, 28, 0]
-          },
-          b: {
-            fontSize: 14,
-            align: 'center',
-            padding: [0, 15, 0, 0],
-            lineHeight: 25
-          }
-        }
-      },
-      formatter: function (name) {
-        if (name == '企业数量') {
-          name = name + '(个)'
-        }
-        return name
-      },
-      data: ['企业数量', '累计占比(%)-右纵轴']
-    },
-    series: {
-      barWidth: 20,
-      smooth: false
-    },
-    color: ['#05A6F3', '#FF9F40']
-  }
-}
-// 修改tooltip展示效果函数
-export function formatterTip (params) {
-  var tip = ''
-  for (var i = 0; i < params.length; i++) { // 这里是自己定义样式, params[i].marker 表示是否显示左边的那个小圆圈
-    params[i].value == undefined ? params[i].value = 0 : params[i].value
-    params[i].marker = '<span style="display:inline-block;margin-right:5px;border-radius:8px;width:8px;height:8px;background-color:' + params[i].color + '"></span>'
-    if (params[i].seriesName === '项目数量' || params[i].seriesName === '企业数量') {
-      tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '个' + '<br/>'
-    } else if (params[i].seriesName === '环比增长率(%)-右纵轴' || params[i].seriesName === '累计占比(%)-右纵轴') {
-      tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '%' + '<br/>'
-    } else {
-      tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '万元' + '<br/>'
-    }
-  }
-  tip += '<div style="padding-top:2px;text-align:center;color:#9B9CA3;">' + ' - ' + params[0].name + ' - ' + '</div>'
-  return tip
-}

+ 14 - 0
src/utils/format.js

@@ -0,0 +1,14 @@
+// 处理关键词数据 转化成美元分类的关键词数组
+export function formatKeywordsList (res) {
+  if (!res || !res.member_jy.a_items) return
+  const data = res.member_jy.a_items
+  const newArr = []
+  data.forEach((v) => {
+    if (v.a_key) {
+      v.a_key.forEach((s) => {
+        newArr.push(s)
+      })
+    }
+  })
+  return newArr
+}

+ 0 - 1
src/utils/index.js

@@ -2,4 +2,3 @@ import './globalDirectives'
 import './globalFilters'
 
 export * from './globalFunctions'
-export * from './echarts_option'

+ 0 - 31
src/views/EmptyDemo.vue

@@ -1,31 +0,0 @@
-<template>
-  <div class="empty-demo">
-    <empty tip="订阅关键词,接收最新招投标信息"></empty>
-    <empty class="empty-body">
-      <span>订阅关键词,接收最新招投标信息</span>
-      <el-button class="empty-button" type="main" icon="el-icon-plus">订阅关键词</el-button>
-    </empty>
-  </div>
-</template>
-
-<script>
-import { Button } from 'element-ui'
-import empty from '@/components/common/Empty.vue'
-import { getUserPower } from '@/api/modules/'
-export default {
-  name: 'Home',
-  components: {
-    empty,
-    [Button.name]: Button
-  },
-  data () {
-    return {}
-  },
-  created () {
-    getUserPower()
-  }
-}
-</script>
-
-<style lang="scss">
-</style>

+ 19 - 29
src/views/Home.vue

@@ -10,8 +10,8 @@
             <div class="nav-item--text">{{item.text}}</div>
           </div>
         </div>
-        <push-list @getMore="$router.push('/sub-push')"></push-list>
-        <project-list class="m-40" @getMore="$router.push('/sub-push')"></project-list>
+        <push-list :subManager="getSubStatus" @getMore="$router.push('/big_subscribe')"></push-list>
+        <project-list class="m-40" @getMore="$router.push('/big_subscribe')"></project-list>
       </div>
     </forLayOut>
     <div class="flex-c-c float-side-group-for-right">
@@ -47,33 +47,23 @@ export default {
       navItem: [
         {
           text: '中标企业预测',
-          to: '/bidforecast',
-          anchor: 'zb',
-          id: 15
+          to: '/ai_search'
         },
         {
           text: '投标决策分析',
-          to: '/bidpolicy',
-          anchor: 'jc',
-          id: 6
+          to: '/analysis_search'
         },
         {
           text: '潜在项目预测',
-          to: '/potential',
-          anchor: 'fx',
-          id: 9
+          to: '/forecast_list'
         },
         {
           text: '潜在客户挖掘',
-          to: '/potentialList/c',
-          anchor: 'qz',
-          id: 7
+          to: '/potential_cor_list/c'
         },
         {
           text: '潜在竞争对手 合作伙伴挖掘',
-          to: '/potentialList/r',
-          anchor: 'qz',
-          id: 8
+          to: '/potential_cor_list/r'
         }
       ],
       floatSideList: [
@@ -123,8 +113,12 @@ export default {
   },
   computed: {
     ...mapState({
-      power: state => state.user.power
+      power: state => state.user.power,
+      info: state => state.user.info
     }),
+    getSubStatus () {
+      return !this.info?.isSubCount
+    },
     getFloatList () {
       return this.floatSideList.filter(v => this.checkAuthPower(v.id))
     }
@@ -222,15 +216,15 @@ export default {
       let link = ''
       switch (floatSide.title) {
         case '周报': {
-          link = '/report/week'
+          link = '/bigvip_subreport_week'
           break
         }
         case '月报': {
-          link = '/report/month'
+          link = '/bigvip_subreport_month'
           break
         }
         case '企业情报监控': {
-          link = '/entintel'
+          link = '/ent_follow'
           break
         }
       }
@@ -240,16 +234,16 @@ export default {
       let link = ''
       switch (floatSide.title) {
         case '周报': {
-          link = `/report/week?start=${item.start}&end=${item.end}`
+          link = `/bigvip_subreport_week?start=${item.start}&end=${item.end}`
           break
         }
         case '月报': {
-          link = `/report/month?start=${item.start}&end=${item.end}`
+          link = `/bigvip_subreport_month?start=${item.start}&end=${item.end}`
           break
         }
         case '企业情报监控': {
           const routeUrl = this.$router.resolve({
-            path: `/entportrayal/${item.id}`
+            path: `/ent_portrait/${item.id}`
           })
           return window.open(routeUrl.href, '_blank')
         }
@@ -271,11 +265,7 @@ export default {
       return result
     },
     goLink (item) {
-      if (this.checkAuthPower(item.id)) {
-        this.$router.push(item.to)
-      } else {
-        window.location.href = '/big/page/index#' + item.anchor
-      }
+      this.$router.push(item.to)
     },
     getSimpleFollowList (size = 5) {
       getSimpleFollowList({ size: size }).then(res => {

+ 29 - 17
src/views/PotentialList.vue

@@ -36,6 +36,7 @@
           <potential-list :key="filters.listKey" @goDetail="goDetail"
                           @follow="changeFollow"
                           @remove="changeRemove"
+                          @delete="changeDelete"
                           :title="getTopInfo.desc || getTopInfo.text" :filters="filters" ref="pushList" :showMore="false"></potential-list>
         </div>
       </div>
@@ -50,7 +51,8 @@ import IndustrySelector from '@/components/selector/IndustrySelector.vue'
 import BuyerclassSelector from '@/components/selector/BuyerclassSelector.vue'
 import BusinessScopeSelector from '@/components/selector/BusinessScopeSelector.vue'
 import forLayOut from '@/components/forecast/ForLayout.vue'
-import { setFollowEnt, setRemoveEnt } from '@/api/modules'
+import { setFollowEnt, setRemoveEnt, setCancelEnt } from '@/api/modules'
+import { mapState } from 'vuex'
 export default {
   name: 'Potential',
   components: {
@@ -97,6 +99,13 @@ export default {
       })
     },
     changeRemove (item) {
+      setCancelEnt({ entId: item.entId }).then(res => {
+        if (!(res && res.error_code === 0 && res.data === 'success')) {
+          this.$refs.pushList.doQuery(this.filters)
+        }
+      })
+    },
+    changeDelete (item) {
       setRemoveEnt({ entId: item.entId }).then(res => {
         if (!(res && res.error_code === 0 && res.data && res.data.success)) {
           this.$refs.pushList.doQuery(this.filters)
@@ -119,11 +128,11 @@ export default {
       let routeUrl = {}
       if (this.filters.pcor === 'C') {
         routeUrl = this.$router.resolve({
-          path: `/unitportrayal/${item.Buyer}`
+          path: `/unit_portrayal/${item.Buyer}`
         })
       } else {
         routeUrl = this.$router.resolve({
-          path: `/entportrayal/${item.entId}`
+          path: `/ent_portrait/${item.entId}`
         })
       }
       window.open(routeUrl.href, '_blank')
@@ -136,13 +145,13 @@ export default {
     },
     changeBusiness (item) {
       let tempArr = []
-      this.getScopeList.forEach(v => {
-        if (item.includes(v.key.join(','))) {
+      this.scope.forEach(v => {
+        if (item.includes(v.key.join(' '))) {
           tempArr.push(v)
         }
       })
       if (item.length === 0) {
-        tempArr = this.getScopeList
+        tempArr = this.scope
       }
       this.filters.business_scope = tempArr
     },
@@ -164,24 +173,23 @@ export default {
     }
   },
   computed: {
+    ...mapState({
+      scope: state => state.user.scope
+    }),
     getTopInfo () {
       return this.topInfo[this.$route.params.type || 'c']
     },
-    getScopeList () {
-      const scopeData = this.$store.state.user.scope
-      if (scopeData[0] && scopeData[0].a_key) {
-        return scopeData[0].a_key
-      }
-      return []
-    },
     getScopeKeyList () {
-      return this.getScopeList.map(v => {
-        return v.key.join(',')
+      return this.scope.map(v => {
+        return v.key.join(' ')
       })
     }
   },
-  created () {
-    this.filters.business_scope = this.getScopeList
+  async created () {
+    if (!this.scope.length) {
+      await this.$store.dispatch('user/getKeywordsList')
+    }
+    this.filters.business_scope = this.scope
   }
 }
 </script>
@@ -223,6 +231,10 @@ export default {
     .border-box {
       border: 1px solid #ececec;
       border-radius: 5px;
+      ::v-deep .selector-card .selector-card-content .j-button-item.active {
+        color: #fff;
+        background-color: #2cb7ca;
+      }
     }
     .content-list-box {
       margin-top: 16px;

+ 1 - 1
src/views/bid-forecast/BidForecastLimit.vue

@@ -211,7 +211,7 @@ export default {
     },
     goViewPur (name) {
       const routeUrl = this.$router.resolve({
-        path: '/unitportrayal/' + name
+        path: '/unit_portrayal/' + name
       })
       return window.open(routeUrl.href, '_blank')
     },

+ 1 - 1
src/views/bid-policy/AnalysisResult.vue

@@ -106,7 +106,7 @@ export default {
     },
     // 查看采购单位画像
     goViewPur (name) {
-      this.$router.push('/unitportrayal/' + name)
+      this.$router.push('/unit_portrayal/' + name)
     },
     // 获取项目基本信息
     async getBaseInfo () {

+ 1 - 1
src/views/bid-policy/components/PolicyLimit.vue

@@ -186,7 +186,7 @@ export default {
     // 中标企业预测跳转
     goBidForUrl () {
       this.$router.push({
-        path: '/bidforlimit',
+        path: '/ai_add',
         query: {
           pid: this.baseInfo.id,
           sid: this.baseInfo.infoid

+ 1 - 1
src/views/portrayal/components/AnalysisList.vue

@@ -64,7 +64,7 @@ export default {
       return moneyUnit(data)
     },
     goEntImg (id) {
-      this.$router.push('/entportrayal?eId=' + encodeURIComponent(id))
+      this.$router.push('/ent_portrait?eId=' + encodeURIComponent(id))
     }
   }
 }

+ 5 - 1
src/views/portrayal/components/UnitChart.vue

@@ -4,17 +4,20 @@
     <div v-if="years.show">
       <div class="chart-title">年度项目统计</div>
       <bar-chart id="years" :options="years.options" :datas="years.data"></bar-chart>
+      <div class="chart-tips text-center">注:项目金额指所有项目的中标金额之和,少数缺失的中标金额,用项目预算补充。</div>
     </div>
     <!-- 月度采购规模 -->
     <div v-if="monthScale.show">
       <div class="chart-title">月度采购规模统计</div>
+      <div style="padding: 0 12px 12px;font-size: 12px;color: #9B9CA3;">采购规模(万元)</div>
       <line-chart ref="monthScale" :options="monthScale.options" :datas="monthScale.data"></line-chart>
       <div class="chart-tips text-center">注:采购规模指中标金额,少数缺失的中标金额,用项目预算补充。</div>
     </div>
     <!-- 采购规模分布 -->
     <div v-if="buyScaleFb.show">
       <div class="chart-title">采购规模分布</div>
-      <hot-chart v-if="buyScaleFb.flag" :datas="buyScaleFb.data" :options="buyScaleFb.options"></hot-chart>
+      <div style="padding: 0 12px 12px;font-size: 12px;color: #9B9CA3;">单位(元)</div>
+      <hot-chart v-if="buyScaleFb.flag" ref="hotChart" :datas="buyScaleFb.data" :options="buyScaleFb.options"></hot-chart>
       <div class="chart-tips">注:平均节支率=(全部项目预算-全部中标金额)/全部项目预算,是指价格减让部分与原价的比率,仅统计预算和中标金额同时存在的项目。</div>
     </div>
     <!-- 各类招标方式占比 -->
@@ -664,6 +667,7 @@ export default {
         const y = 10 - Math.ceil((i + 1) / 10)
         return [x, y, v.bidamount_avg, v.project_count, v.range]
       })
+      // this.$refs.hotChart.defaultOptions.graphic[0].children[0].style.text = '项目数量(个)'
       this.buyScaleFb.data = data
     },
     // 格式化各类招标方式占比数据(双向柱图)

+ 1 - 0
src/views/portrayal/components/UnitList.vue

@@ -16,6 +16,7 @@
       <div class="pages">
         <el-pagination
           background
+          :page-size="5"
           @current-change="handleCurrentChange"
           layout="prev, pager, next"
           :total="dt.total">

+ 1 - 1
src/views/potential-for/PotenSimilar.vue

@@ -113,7 +113,7 @@ export default {
     },
     // 查看采购单位画像
     goViewPur () {
-      this.$router.push('/unitportrayal/' + this.dataInfo.buyer)
+      this.$router.push('/unit_portrayal/' + this.dataInfo.buyer)
     }
   }
 }

+ 3 - 3
src/views/project/ProjectInfo.vue

@@ -190,7 +190,7 @@ export default {
     toForecast () {
       const { sid, fid } = this
       this.$router.push({
-        path: '/bidforlimit',
+        path: '/ai_add',
         query: {
           pid: fid,
           sid: sid
@@ -199,12 +199,12 @@ export default {
     },
     toPolicy () {
       const { sid, fid } = this
-      this.$router.push(`/analysis/result/${fid}/${sid}`)
+      this.$router.push(`/analysis_result/${fid}/${sid}`)
     },
     toUnitportrayal () {
       const { buyer } = this.projectInfo
       const link = this.$router.resolve({
-        path: `/unitportrayal/${buyer}`
+        path: `/unit_portrayal/${buyer}`
       })
       window.open(link.href, '_blank')
     }

+ 9 - 9
src/views/subscribe/Config.vue

@@ -5,14 +5,14 @@
     <!-- 关键词设置 -->
     <key-config ref="keyConfigRef" :datas="setData" @updateKey="updateKeyWordsApi"></key-config>
     <!-- 关键词列表 -->
-    <key-list v-if="setData.keywordsList.length > 0" :total="setData.maxKeyCounts" :list="setData.keywordsList" @updateKey="updateKeyWordsApi"></key-list>
+    <key-list v-if="setData.keyList.length > 0" :datas="setData" @updateKey="updateKeyWordsApi"></key-list>
   </div>
 </template>
 
 <script>
-import SubConfig from './components/SubConfig'
-import KeyConfig from './components/KeyConfig'
-import KeyList from './components/KeyList'
+import SubConfig from './components/key/SubConfig'
+import KeyConfig from './components/key/KeyConfig'
+import KeyList from './components/key/KeyList'
 import { getBigMemberInfo, updateKey } from '@/api/modules'
 export default {
   name: 'config',
@@ -34,7 +34,6 @@ export default {
         projectmatch: null,
         buyclassmatch: null,
         mathway: null,
-        maxKeyCounts: 0,
         // 区域对象
         areaObj: {},
         // 采购单位行业数组
@@ -42,7 +41,8 @@ export default {
         // 信息类型数组
         infoTypeArr: [],
         // 关键词
-        keywordsList: []
+        keyList: [],
+        maxCount: 0
       },
       // 子账号业务范围
       scope: []
@@ -59,7 +59,7 @@ export default {
       const data = await getBigMemberInfo()
       const res = data.data
       if (res) {
-        this.setData.maxKeyCounts = res.key_max_length ? res.key_max_length : 0
+        this.setData.maxCount = res.key_max_length ? res.key_max_length : 0
         if (res.member_jy && Object.keys(res.member_jy).length === 0) {
           this.setdata.area = '全国'
           this.setdata.industry = '全部'
@@ -114,9 +114,9 @@ export default {
           }
           // 关键词
           if (res.member_jy.a_items && JSON.stringify(res.member_jy.a_items) !== '[]') {
-            this.setData.keywordsList = res.member_jy.a_items
+            this.setData.keyList = res.member_jy.a_items
           } else {
-            this.setData.keywordsList = []
+            this.setData.keyList = []
           }
         }
       } else {

+ 77 - 38
src/views/subscribe/Scope.vue

@@ -1,9 +1,9 @@
 <template>
   <div class="scope-config">
     <!-- 关键词设置 -->
-    <key-config ref="keyConfigRef" :datas="setData" @updateKey="updateKeyWordsApi"></key-config>
+    <ScopeAdd ref="keyConfigRef" :datas="setData" @updateKey="updateKeyWordsApi"></ScopeAdd>
     <!-- 关键词列表 -->
-    <key-list v-if="setData.keywordsList.length > 0" :total="setData.maxKeyCounts" :list="setData.keywordsList" @updateKey="updateKeyWordsApi"></key-list>
+    <ScopeList v-if="setData.keyList.length > 0" :datas="setData" @updateKey="updateKeyWordsApi"></ScopeList>
     <div>
       <div class="reset-tips">新增的关键词设置,将在登出时还原</div>
       <button type="button" class="save-btn" @click="saveSetting">保存设置</button>
@@ -12,75 +12,114 @@
 </template>
 
 <script>
-import KeyConfig from './components/KeyConfig'
-import KeyList from './components/KeyList'
-import { getBigMemberInfo } from '@/api/modules'
+import ScopeAdd from './components/scope/Add'
+import ScopeList from './components/scope/List'
+import { getParam } from '@/utils/'
+import { mapActions, mapState } from 'vuex'
 export default {
   name: 'scope',
   components: {
-    KeyList,
-    KeyConfig
+    ScopeAdd,
+    ScopeList
   },
   data () {
     return {
       setData: {
         title: '业务范围设置',
         // 关键词
-        keywordsList: [],
-        maxKeyCounts: 0
+        keyList: [],
+        maxCount: 0,
+        from: null
       }
     }
   },
   computed: {
-    // 是否是子账号
-    isSubCount () {
-      return this.$store.state.user.info.isSubCount
-    }
+    ...mapState({
+      scope: state => state.user.scope,
+      buyClass: state => state.user.buyClass,
+      bigKeywordsData: state => state.user.bigKeywordsData
+    })
   },
   created () {
+    const params = decodeURIComponent(getParam('title'))
+    if (params) {
+      this.setData.title = params
+      this.setData.from = 'buyClass'
+    }
     this.getBigInfo()
   },
   methods: {
+    ...mapActions('user', ['getKeywordsList']),
+    // 从接口中取数据 执行业务范围页面逻辑
     async getBigInfo () {
-      const data = await getBigMemberInfo()
-      const res = data.data
-      if (res) {
-        this.setData.maxKeyCounts = res.key_max_length ? res.key_max_length : 0
-        if (Object.keys(res.member_jy).length === 0) {
-          console.log('没有数据')
-        } else {
-          // 关键词
-          if (res.member_jy.a_items && JSON.stringify(res.member_jy.a_items) !== '[]') {
-            const scopeStorage = this.$store.state.user.scope
-            if (scopeStorage && scopeStorage.length > 0) {
-              this.setData.keywordsList = this.unique(res.member_jy.a_items.concat(scopeStorage))
-            } else {
-              this.setData.keywordsList = res.member_jy.a_items
-            }
-          } else {
-            this.setData.keywordsList = []
-          }
-        }
+      if (this.bigKeywordsData) {
+        this.setData.maxCount = this.bigKeywordsData.key_max_length
+      }
+      const state = this.setData.from ? this.buyClass : this.scope
+      if (state && state.length > 0) {
+        this.setData.keyList = state
       } else {
-        console.log('状态值为:' + res.status)
+        this.getKeywordsList(this.setData.from).then((res) => {
+          this.setData.keyList = res
+        })
       }
+      // const data = await getBigMemberInfo()
+      // const res = data.data
+      // const scopeStorage = this.setData.title === '采购内容设置' ? this.$store.state.user.buyClass : this.$store.state.user.scope
+      // if (res) {
+      //   this.setData.maxCount = res.key_max_length ? res.key_max_length : 0
+      //   if (res.member_jy && res.member_jy.a_items && res.member_jy.a_items.length > 0) {
+      //     const apiKey = this.formatKeyList(res.member_jy.a_items)
+      //     console.log('缓存里的数组长度:', scopeStorage.length, '接口里的数组长度:', apiKey.length)
+      //     if (scopeStorage && scopeStorage.length > 0) {
+      //       const newArr = apiKey.concat(scopeStorage)
+      //       this.setData.keyList = this.unique(newArr)
+      //     } else {
+      //       this.setData.keyList = this.formatKeyList(res.member_jy.a_items)
+      //     }
+      //   } else {
+      //     if (scopeStorage) {
+      //       this.setData.keyList = scopeStorage
+      //     }
+      //   }
+      // } else {
+      //   console.log('状态值为:' + res.status)
+      // }
+    },
+    formatKeyList (arr) {
+      if (!arr) return
+      const newArr = []
+      arr.forEach((v) => {
+        if (v.a_key) {
+          v.a_key.forEach((s) => {
+            newArr.push(s)
+          })
+        }
+      })
+      return newArr
     },
     // 子组件通知父组件更新关键词接口
     updateKeyWordsApi (data) {
-      // const isSubCount = this.$store.state.user.info.isSubCount
       console.log(data, '子组件传来的修改完缓存里的数据')
       this.$refs.keyConfigRef.clearInputData()
-      this.setData.keywordsList = data
+      this.setData.keyList = data
     },
     // 保存设置
     saveSetting () {
-      this.$store.commit('user/setScope', this.setData.keywordsList)
-      this.$router.back()
+      if (this.setData.from) {
+        this.$store.commit('user/setBuyClass', this.setData.keyList)
+        this.$router.back()
+      } else {
+        this.$store.commit('user/setScope', this.setData.keyList)
+        this.$router.back()
+      }
     },
     // 数组合并去重用于将新增的关键词组合并到本地缓存中
     unique (arr) {
       const res = new Map()
-      return arr.filter((item) => !res.has(item.s_item) && res.set(item.s_item, 1))
+      const newArr = arr.filter((item) => !res.has(item.key.toString()) && res.set(item.key.toString(), 1))
+      console.log(newArr)
+      return newArr
     }
   }
 

+ 21 - 14
src/views/subscribe/components/KeyConfig.vue → src/views/subscribe/components/key/KeyConfig.vue

@@ -2,7 +2,7 @@
   <div class="keywords">
     <div class="key-title">
       <span>{{datas.title}}</span>
-      <span style="font-size:14px;"><em style="color: #2cb7ca;"> {{keyCounts}}</em>/{{datas.maxKeyCounts}}</span>
+      <span style="font-size:14px;"><em style="color: #2cb7ca;"> {{keyCounts}}</em>/{{datas.maxCount}}</span>
     </div>
     <div class="key-content">
       <div class="item">
@@ -56,8 +56,8 @@ export default {
   props: {
     datas: {
       title: String,
-      keywordsList: Array,
-      maxKeyCounts: Number
+      keyList: Array,
+      maxCount: Number
     }
   },
   components: {
@@ -78,7 +78,7 @@ export default {
   computed: {
     keyCounts () {
       let count = 0
-      this.datas.keywordsList.forEach(v => {
+      this.datas.keyList.forEach(v => {
         if (v && v.a_key) {
           count += v.a_key.length
         }
@@ -93,7 +93,7 @@ export default {
   methods: {
     // 保存数据
     saveCurData () {
-      const data = this.datas.keywordsList
+      const data = this.datas.keyList
       const obj = {
         a_key: [
           {
@@ -109,11 +109,10 @@ export default {
     },
     // 提交关键词
     submitKeywords () {
-      console.log(this.addTotalCount(), '添加了几个')
       const totalCount = this.addTotalCount()
       const classArr = this.getClassArray()
       const keyArr = this.getKeyTotalArray()
-      if (totalCount >= this.datas.maxKeyCounts) {
+      if (totalCount >= this.datas.maxCount) {
         return this.$message({
           type: 'warning',
           message: '关键词超出最大限制'
@@ -180,7 +179,7 @@ export default {
     // 获取所有分类名 用于判断是否重复
     getClassArray () {
       const classArr = []
-      this.datas.keywordsList.forEach((v) => {
+      this.datas.keyList.forEach((v) => {
         if (v.s_item) {
           classArr.push(v.s_item)
         }
@@ -190,13 +189,11 @@ export default {
     // 获取所有关键词的key的属性,并返回一个数组(主要用于判断添加关键词是否重复)
     getKeyTotalArray () {
       const keysArr = []
-      this.datas.keywordsList.forEach((s) => {
+      this.datas.keyList.forEach((s) => {
         if (s && s.a_key && Array.isArray(s.a_key)) {
           s.a_key.forEach((v) => {
             if (Array.isArray(v.key)) {
-              v.key.forEach(x => {
-                keysArr.push(x)
-              })
+              keysArr.push(v.key.toString().replace(',', ' '))
             } else {
               keysArr.push(v.key)
             }
@@ -207,6 +204,7 @@ export default {
     },
     // 判断附加词、排除词是否重复
     getArrIsRepeat (arr) {
+      this.removeEmptyInput(arr)
       return (new Set(arr)).size !== arr.length
     },
     // 通过已有分类得到一个未分类名
@@ -220,7 +218,7 @@ export default {
         unclassifiedNum: [],
         sortedArr: []
       }
-      this.datas.keywordsList.forEach((item) => {
+      this.datas.keyList.forEach((item) => {
         if (item.s_item && conf.reg.test(item.s_item)) {
           let num = item.s_item.replace(new RegExp(conf.defaultT, 'g'), '')
           num = parseInt(num)
@@ -250,12 +248,21 @@ export default {
     },
     addTotalCount () {
       let count = 0
-      this.datas.keywordsList.forEach(v => {
+      this.datas.keyList.forEach(v => {
         if (v && v.a_key) {
           count += v.a_key.length
         }
       })
       return count
+    },
+    removeEmptyInput (arr) {
+      for (let i = 0; i < arr.length; i++) {
+        if (arr[i] === '' || arr[i] === null || typeof (arr[i]) === undefined) {
+          arr.splice(i, 1)
+          i = i - 1
+        }
+      }
+      return arr
     }
   }
 }

+ 0 - 0
src/views/subscribe/components/KeyEdit.vue → src/views/subscribe/components/key/KeyEdit.vue


+ 30 - 15
src/views/subscribe/components/KeyList.vue → src/views/subscribe/components/key/KeyList.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="classify">
-    <div class="classify-list" v-for="(item,index) in list" :key="'1' + index">
+    <div class="classify-list" v-for="(item,index) in datas.keyList" :key="'1' + index">
       <div class="classify-title">
         <span class="title-text">{{item.s_item}}</span>
         <span class="icon-edit" @click="editClassFn(item.s_item, index)"></span>
@@ -102,8 +102,10 @@ export default {
     KeyEdit
   },
   props: {
-    list: Array,
-    total: Number
+    datas: {
+      keyList: Array,
+      maxCount: Number
+    }
   },
   data () {
     return {
@@ -135,7 +137,7 @@ export default {
     },
     // 确认修改分类
     confirmEditClassFn () {
-      const data = this.list
+      const data = this.datas.keyList
       const classArr = this.getClassArray()
       if (classArr.indexOf(this.props.className) > -1) {
         return this.$message({
@@ -165,7 +167,7 @@ export default {
     },
     // 确认删除分类
     confirmDeleteClassFn () {
-      const data = this.list
+      const data = this.datas.keyList
       this.dialog.delClass = false
       // 删除整个分类的数据
       data.splice(this.props.classIndex, 1)
@@ -190,7 +192,7 @@ export default {
     // 删除单个关键词
     deleteKeyFn (index, i) {
       console.log(index, i)
-      const data = this.list
+      const data = this.datas.keyList
       if (!data) return
       data[index].a_key.splice(i, 1)
       this.$emit('updateKey', data)
@@ -219,7 +221,7 @@ export default {
     },
     // 修改关键词dialog 保存数据
     submitKeywords () {
-      const data = this.list
+      const data = this.datas.keyList
       const refs = this.$refs.keyEditRef.cur
       const keyArr = this.getKeyTotalArray()
       const type = this.props.ways
@@ -276,7 +278,7 @@ export default {
     },
     // 获取所有分类名
     getClassArray () {
-      const data = this.list
+      const data = this.datas.keyList
       const classArr = []
       data.forEach((v) => {
         if (v.s_item) {
@@ -287,7 +289,7 @@ export default {
     },
     // 获取所有关键词的key的属性,并返回一个数组(主要用于判断添加关键词是否重复)
     getKeyTotalArray () {
-      const data = this.list
+      const data = this.datas.keyList
       const keysArr = []
       data.forEach((s) => {
         if (s && s.a_key && Array.isArray(s.a_key)) {
@@ -306,16 +308,26 @@ export default {
     },
     // 判断附加词、排除词是否重复
     getArrIsRepeat (arr) {
+      this.removeEmptyInput(arr)
       return (new Set(arr)).size !== arr.length
     },
     // 判断是否超限
     getIsAdd () {
       const keyArr = this.getKeyTotalArray()
-      if (keyArr.length >= this.total) {
+      if (keyArr.length >= this.datas.maxCount) {
         return true
       } else {
         return false
       }
+    },
+    removeEmptyInput (arr) {
+      for (let i = 0; i < arr.length; i++) {
+        if (arr[i] === '' || arr[i] === null || typeof (arr[i]) === undefined) {
+          arr.splice(i, 1)
+          i = i - 1
+        }
+      }
+      return arr
     }
   }
 }
@@ -450,9 +462,11 @@ export default {
     display: flex;
     align-items: center;
     justify-content: flex-start;
+    flex-wrap: wrap;
     .list{
-      padding-top: 10px;
-      margin-right: 10px;
+      width: 160px;
+      height: 80px;
+      margin: 10px 10px 0 0;
       box-sizing: border-box;
       &:hover .list-edit{
         transform: scaleY(1);
@@ -463,11 +477,12 @@ export default {
         box-sizing: border-box;
       }
     }
+    :list:nth-child(6n) {
+      margin-right: 0;
+    }
     .list-box{
       position: relative;
       display: flex;
-      width: 162px;
-      height: 80px;
       padding: 10px 10px 10px 16px;
       border: 1px solid #ececec;
       border-radius: 9px;
@@ -524,7 +539,7 @@ export default {
       justify-content: center;
       font-size: 24px;
       border: 1px solid #ececec;
-      margin: 10px 10px 0 0;
+      margin: 10px 0 0 0;
       border-radius: 9px;
       color: #c4c4c4;
       cursor: pointer;

+ 3 - 3
src/views/subscribe/components/SubConfig.vue → src/views/subscribe/components/key/SubConfig.vue

@@ -66,7 +66,7 @@
               <el-radio name="matchway" :label="1">按标题匹配</el-radio>
             </div>
             <div>
-              <el-radio  name="matchway" :label="0">按全文匹配</el-radio>
+              <el-radio  name="matchway" :label="2">按全文匹配</el-radio>
             </div>
           </el-radio-group>
           <p class="math-tips">会产生无效信息,请根据需要选择</p>
@@ -101,7 +101,7 @@
         :initCate="datas.buyClassArr"
         @onCancel="dialog.buyClass = false"
         @onConfirm="saveBuyClassData">
-        <div slot="header">客户分类:</div>
+        <div slot="header">选择采购单位行业</div>
       </BuyClassSelect>
     </el-dialog>
     <!-- 信息类型dialog -->
@@ -117,7 +117,7 @@
         :initInfoType="datas.infoTypeArr"
         @onCancel="dialog.infoType = false"
         @onConfirm="saveInfoTypeData">
-        <div slot="header">信息类型</div>
+        <div slot="header">选择信息类型</div>
       </InfoTypeSelect>
     </el-dialog>
   </div>

+ 313 - 0
src/views/subscribe/components/scope/Add.vue

@@ -0,0 +1,313 @@
+<template>
+  <div class="keywords">
+    <div class="key-title">
+      <span>{{datas.title}}</span>
+      <span style="font-size:14px;"><em style="color: #2cb7ca;"> {{keyCounts}}</em>/{{datas.maxCount}}</span>
+    </div>
+    <div class="key-content">
+      <div class="item">
+        <div class="item-label item-label-required">关键词:</div>
+        <div class="item-value">
+          <el-input class="custom-long-input" v-model="cur.key" maxlength="20" placeholder="请输入关键词"></el-input>
+        </div>
+      </div>
+      <div class="item">
+        <div class="item-label"></div>
+        <div class="item-value item-keywords-value">
+          <div>
+            <div class="add-word-list" v-for="(add,index) in cur.appendkey" :key="'add' + index">
+              <el-input v-model.trim="cur.appendkey[index]" class="custom-short-input" maxlength="20" placeholder="请输入附加词"></el-input>
+            </div>
+            <div class="add-tag" @click="addAttachWordsFn">+添加附加词</div>
+          </div>
+          <div>
+            <div class="add-word-list" v-for="(not,index) in cur.notkey" :key="'0' + index">
+              <el-input v-model.trim="cur.notkey[index]" class="custom-short-input" maxlength="20" placeholder="请输入排除词"></el-input>
+            </div>
+            <div class="add-tag" @click="addExcludeWordsFn">+添加排除词</div>
+          </div>
+        </div>
+      </div>
+      <div class="item">
+        <div class="item-label"></div>
+        <div class="item-value">
+          <button type="button" :disabled="keyDisabled" class="save-btn" @click="submitKeywords">保存关键词</button>
+          <div class="keywords-help">
+            <p>例:某公司主管业务为软件系统开发 </p>
+            <p>关键词:目标信息钟的关键性词语,如“软件系统” </p>
+            <p>附加词:与关键词形成一体/组合,便于查找准确信息,如“开发”</p>
+            <p>排除词:与关键词互斥,可排除一部分非目标信息,如“运维”</p>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import { Input, Button } from 'element-ui'
+export default {
+  name: 'scope-add',
+  props: {
+    datas: {
+      title: String,
+      keyList: Array,
+      maxCount: Number
+    }
+  },
+  components: {
+    [Input.name]: Input,
+    [Button.name]: Button
+  },
+  data () {
+    return {
+      // 当前输入框的数据
+      cur: {
+        classify: '',
+        key: '',
+        appendkey: [],
+        notkey: []
+      }
+    }
+  },
+  computed: {
+    keyCounts () {
+      return this.datas.keyList.length
+    },
+    keyDisabled () {
+      return !this.cur.key
+    }
+  },
+  mounted () {},
+  methods: {
+    // 输入框为空移除
+    removeEmptyInput (arr) {
+      for (let i = 0; i < arr.length; i++) {
+        if (arr[i] === '' || arr[i] === null || typeof (arr[i]) === undefined) {
+          arr.splice(i, 1)
+          i = i - 1
+        }
+      }
+      return arr
+    },
+    // 保存数据
+    saveCurData () {
+      const data = this.datas.keyList
+      const obj = {
+        key: this.cur.key.split(' '),
+        notkey: this.cur.notkey,
+        appendkey: this.cur.appendkey
+      }
+      data.push(obj)
+      return data
+    },
+    // 提交关键词
+    submitKeywords () {
+      const totalCount = this.addTotalCount()
+      const keyArr = this.getKeyTotalArray()
+      if (totalCount >= this.datas.maxCount) {
+        return this.$message({
+          type: 'warning',
+          message: '关键词超出最大限制'
+        })
+      }
+      if (keyArr.indexOf(this.cur.key) > -1) {
+        return this.$message({
+          type: 'warning',
+          message: '关键词不能重复'
+        })
+      }
+      // 判断附加词是否重复
+      if (this.getArrIsRepeat(this.cur.appendkey)) {
+        return this.$message({
+          type: 'warning',
+          message: '设置的附加词重复,请调整后再添加'
+        })
+      }
+      // 判断排除词是否重复
+      if (this.getArrIsRepeat(this.cur.notkey)) {
+        return this.$message({
+          type: 'warning',
+          message: '设置的排除词重复,请调整后再添加'
+        })
+      }
+      const params = this.saveCurData()
+      // 通知父组件保存数据
+      this.$emit('updateKey', params)
+    },
+    // 添加附加词
+    addAttachWordsFn () {
+      const arr = this.cur.appendkey
+      if (this.inputIsEmpty(arr)) {
+        this.$message({
+          message: '请输入附加词',
+          type: 'warning'
+        })
+      } else {
+        this.cur.appendkey.push('')
+      }
+    },
+    // 添加排除词
+    addExcludeWordsFn () {
+      const arr = this.cur.notkey
+      if (this.inputIsEmpty(arr)) {
+        this.$message({
+          message: '请输入排除词',
+          type: 'warning'
+        })
+      } else {
+        this.cur.notkey.push('')
+      }
+    },
+    // 判断附加词排除词输入框是否有空
+    inputIsEmpty (arr) {
+      return arr.some((v) => !v)
+    },
+    // 获取所有关键词
+    getKeyTotalArray () {
+      const keysArr = []
+      this.datas.keyList.forEach((s) => {
+        if (s && s.key) {
+          // s.key.forEach((v) => {
+          //   keysArr.push(v)
+          // })
+          keysArr.push(s.key.toString().replace(',', ' '))
+        }
+      })
+      console.log(keysArr)
+      return keysArr
+    },
+    // 判断附加词、排除词是否重复
+    getArrIsRepeat (arr) {
+      this.removeEmptyInput(arr)
+      return (new Set(arr)).size !== arr.length
+    },
+    // 清空输入框 供父组件请求成功后刷新
+    clearInputData () {
+      this.cur.key = ''
+      this.cur.appendkey = []
+      this.cur.notkey = []
+    },
+    // 已添加的关键词数量
+    addTotalCount () {
+      let count = 0
+      this.datas.keyList.forEach(v => {
+        if (v && v.a_key) {
+          count += v.a_key.length
+        }
+      })
+      return count
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.keywords{
+  .key-title{
+    padding-bottom: 8px;
+    font-size: 18px;
+    color: #1d1d1d;
+    line-height: 28px;
+    border-bottom: 1px solid #ececec;
+  }
+  .key-content{
+    padding: 20px 0;
+    .item{
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      margin-bottom: 10px;
+    }
+    .item-label{
+      margin-right: 8px;
+      min-width: 120px;
+      height: 40px;
+      color: #1d1d1d;
+      font-size: 14px;
+      line-height: 40px;
+      text-align: right;
+    }
+    .item-label-required:before{
+      content: "*";
+      color: #f56c6c;
+      margin-right: 2px;
+    }
+    .item-value{
+      width: 352px;
+    }
+    .custom-long-input{
+      width: 352px;
+    }
+    .custom-short-input{
+      width: 170px;
+    }
+    .item-other{
+      display: flex;
+      justify-content: center;
+      margin-bottom: 10px;
+    }
+    .item-other-value{
+      margin-top: 8px;
+    }
+    .math-tips{
+      margin-top: 4px;
+      font-size: 12px;
+      color: #999999;
+      line-height: 20px;
+    }
+    .radio-item{
+      margin-bottom: 10px;
+    }
+    .item-keywords-value{
+      display: flex;
+      justify-content: space-between;
+    }
+    .add-tag{
+      width: 170px;
+      height: 40px;
+      line-height: 40px;
+      color: #2cb7ca;
+      border-radius: 6px;
+      text-align: center;
+      cursor: pointer;
+      color: #2cb7ca;
+      border: 1px dashed #2cb7ca;
+    }
+    .add-word-list{
+      margin-bottom: 6px;
+    }
+    .save-btn{
+      width: 352px;
+      height: 46px;
+      line-height: 46px;
+      font-size: 16px;
+      background: #2cb7ca;
+      border-radius: 6px;
+      color: #fff;
+      &:disabled{
+        opacity: 0.5;
+        cursor: not-allowed;
+      }
+    }
+    .keywords-help{
+      width: 412px;
+      margin-top: 20px;
+      font-size: 12px;
+      color: #999999;
+      line-height: 20px;
+      text-align: justify;
+    }
+  }
+  // element-ui样式修改
+  ::v-deep.el-input__inner{
+    font-size: 14px;
+    color: #1D1D1D;
+    border-color: #ececec;
+  }
+  ::v-deep.el-input__inner:hover{
+    border-color: #ececec;
+  }
+  ::v-deep.el-input__inner:focus{
+    border-color: #2cb7ca;
+  }
+}
+</style>

+ 157 - 0
src/views/subscribe/components/scope/Edit.vue

@@ -0,0 +1,157 @@
+<template>
+  <div class="keywords-edit">
+    <div class="item">
+      <div class="item-label item-label-required">关键词:</div>
+      <div class="item-value">
+        <el-input class="custom-long-input" v-model="cur.key" maxlength="20" placeholder="请输入关键词"></el-input>
+      </div>
+    </div>
+    <div class="item">
+      <div class="item-label"></div>
+      <div class="item-value item-keywords-value">
+        <div>
+          <div class="add-word-list" v-for="(add,index) in cur.appendkey" :key="'add' + index">
+            <el-input v-model.trim="cur.appendkey[index]" class="custom-short-input" maxlength="20" placeholder="请输入附加词"></el-input>
+          </div>
+          <div class="add-tag" @click="addAppendKey">+添加附加词</div>
+        </div>
+        <div>
+          <div class="add-word-list" v-for="(not,index) in cur.notkey" :key="'0' + index">
+            <el-input v-model.trim="cur.notkey[index]" class="custom-short-input" maxlength="20" placeholder="请输入排除词"></el-input>
+          </div>
+          <div class="add-tag" @click="addNotKey">+添加排除词</div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import { Input } from 'element-ui'
+export default {
+  name: 'keywords-edit',
+  components: {
+    [Input.name]: Input
+  },
+  props: {
+    datas: {
+      key: Array,
+      notkey: Array,
+      appendkey: Array
+    }
+  },
+  data () {
+    return {
+      cur: {
+        key: '',
+        appendkey: [],
+        notkey: []
+      }
+    }
+  },
+  watch: {},
+  computed: {},
+  created () {
+    this.getParentData()
+  },
+  mounted () {},
+  methods: {
+    // 获取父组件keyList传来的数据 并进行格式转化渲染到输入框
+    getParentData () {
+      this.cur.key = this.datas.key.join(' ')
+      this.cur.notkey = this.datas.notkey
+      this.cur.appendkey = this.datas.appendkey
+    },
+    addAppendKey () {
+      const arr = this.cur.appendkey
+      if (this.inputIsEmpty(arr)) {
+        this.$message({
+          message: '请输入附加词',
+          type: 'warning'
+        })
+      } else {
+        this.cur.appendkey.push('')
+      }
+    },
+    addNotKey () {
+      const arr = this.cur.notkey
+      if (this.inputIsEmpty(arr)) {
+        this.$message({
+          message: '请输入排除词',
+          type: 'warning'
+        })
+      } else {
+        this.cur.notkey.push('')
+      }
+    },
+    inputIsEmpty (arr) {
+      return arr.some((v) => !v)
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.keywords-edit{
+  .item{
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-bottom: 10px;
+  }
+  .item-label{
+    margin-right: 8px;
+    min-width: 120px;
+    height: 40px;
+    color: #1d1d1d;
+    font-size: 14px;
+    line-height: 40px;
+    text-align: right;
+  }
+  .item-label-required:before{
+    content: "*";
+    color: #f56c6c;
+    margin-right: 2px;
+  }
+  .item-value{
+    width: 352px;
+  }
+  .custom-long-input{
+    width: 352px;
+  }
+  .custom-short-input{
+    width: 170px;
+  }
+  .item-keywords-value{
+    display: flex;
+    justify-content: space-between;
+  }
+  .add-tag{
+    width: 170px;
+    height: 40px;
+    line-height: 40px;
+    color: #2cb7ca;
+    border-radius: 6px;
+    text-align: center;
+    cursor: pointer;
+    color: #2cb7ca;
+    border: 1px dashed #2cb7ca;
+  }
+  .add-word-list{
+    margin-bottom: 6px;
+  }
+  // element-ui样式修改
+  ::v-deep.el-input__inner{
+    font-size: 14px;
+    color: #1D1D1D;
+    border-color: #ececec;
+    padding-left: 16px!important;
+    border-radius: 6px!important;
+    background: #fff!important;
+  }
+  ::v-deep.el-input__inner:hover{
+    border-color: #ececec;
+  }
+  ::v-deep.el-input__inner:focus{
+    border-color: #2cb7ca;
+  }
+}
+</style>

+ 421 - 0
src/views/subscribe/components/scope/List.vue

@@ -0,0 +1,421 @@
+<template>
+  <div class="classify">
+    <div class="classify-list">
+      <div class="classify-content">
+        <div class="list" v-for="(v, i) in datas.keyList" :key="'0' + i">
+          <div class="list-box">
+            <div class="list-value">
+              <p>关键词: {{v.key.join(' ') || '--'}}</p>
+              <p>附加词: {{v.appendkey.join('、') || '--'}}</p>
+              <p>排除词: {{v.notkey.join('、') || '--'}}</p>
+            </div>
+            <div class="list-icon" @click="deleteKeyFn(i)"></div>
+            <div class="list-edit" @click="editKeyFn(v, i)">
+              编辑
+              <i class="tri-down"></i>
+            </div>
+          </div>
+        </div>
+        <div class="words-add" @click="addKeyFn()">
+          <i class="el-icon-plus"></i>
+        </div>
+      </div>
+    </div>
+    <!-- 关键词dialog -->
+    <el-dialog
+      custom-class="sub-dialog"
+      :visible.sync="dialog.editKey"
+      :close-on-click-modal="false"
+      :show-close="false"
+      center
+      width="800px"
+      v-if="dialog.editKey"
+    >
+      <KeyCard @onCancel="dialog.editKey = false" @onConfirm="submitKeywords">
+        <div slot="header">修改关键词</div>
+        <div class="key-edit-content">
+          <ScopeEdit ref="keyEditRef" :datas="props"></ScopeEdit>
+        </div>
+      </KeyCard>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import { Tooltip, Dialog, Input, Button } from 'element-ui'
+import KeyCard from '@/components/selector/SelectorCard'
+import ScopeEdit from './Edit'
+export default {
+  name: 'scope-list',
+  components: {
+    [Tooltip.name]: Tooltip,
+    [Dialog.name]: Dialog,
+    [Input.name]: Input,
+    [Button.name]: Button,
+    KeyCard,
+    ScopeEdit
+  },
+  props: {
+    datas: {
+      keyList: Array,
+      maxCount: Number
+    }
+  },
+  data () {
+    return {
+      dialog: {
+        editKey: false // 修改关键词弹框
+      },
+      // 传给dialog子组件的数据
+      props: {
+        ways: '', // 编辑还是新增
+        keyIndex: null, // 关键词下标
+        key: [], // 关键词
+        notkey: [], // 排除词
+        appendkey: [] // 附加词
+      }
+    }
+  },
+  computed: {},
+  mounted () {},
+  methods: {
+    // 添加关键词
+    addKeyFn () {
+      const isCan = this.getIsAdd()
+      if (isCan) {
+        return this.$message({
+          type: 'warning',
+          message: '关键词超出最大限制'
+        })
+      }
+      this.dialog.editKey = true
+      this.props.ways = 'add'
+      this.props.key = []
+      this.props.notkey = []
+      this.props.appendkey = []
+    },
+    // 删除单个关键词
+    deleteKeyFn (i) {
+      const data = this.datas.keyList
+      if (!data) return
+      data.splice(i, 1)
+      this.$emit('updateKey', data)
+    },
+    // 编辑单个关键词
+    editKeyFn (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
+    },
+    // 清空传值
+    clearPropsData () {
+      this.props.key = []
+      this.props.notkey = []
+      this.props.appendkey = []
+    },
+    // 修改关键词dialog 保存数据
+    submitKeywords () {
+      const data = this.datas.keyList
+      const refs = this.$refs.keyEditRef.cur
+      const keyArr = this.getKeyTotalArray()
+      const type = this.props.ways
+      const obj = {
+        key: refs.key.split(' '),
+        notkey: refs.notkey,
+        appendkey: refs.appendkey
+      }
+      if (refs.key === '') {
+        return this.$message({
+          type: 'warning',
+          message: '关键词不能为空'
+        })
+      }
+      // 判断附加词是否重复
+      if (this.getArrIsRepeat(refs.appendkey)) {
+        return this.$message({
+          type: 'warning',
+          message: '设置的附加词重复,请调整后再添加'
+        })
+      }
+      // 判断排除词是否重复
+      if (this.getArrIsRepeat(refs.notkey)) {
+        return this.$message({
+          type: 'warning',
+          message: '设置的排除词重复,请调整后再添加'
+        })
+      }
+      if (type === 'add') {
+        if (keyArr.indexOf(refs.key) > -1) {
+          return this.$message({
+            type: 'warning',
+            message: '关键词不能重复'
+          })
+        }
+        data.push(obj)
+      } else if (type === 'edit') {
+        // 如果当前编辑的关键词和修改框里的关键词不相同 需校验是否重复
+        if (data[this.props.keyIndex].key.toString() !== refs.key) {
+          if (keyArr.indexOf(refs.key) > -1) {
+            return this.$message({
+              type: 'warning',
+              message: '关键词不能重复'
+            })
+          }
+        }
+        data[this.props.keyIndex].key = refs.key.split(' ')
+        data[this.props.keyIndex].notkey = refs.notkey
+        data[this.props.keyIndex].appendkey = refs.appendkey
+      }
+      // 通知父组件发请求修改并更新
+      this.$emit('updateKey', data)
+      this.dialog.editKey = false
+    },
+    // 获取所有关键词的key的属性,并返回一个数组(主要用于判断添加关键词是否重复)
+    getKeyTotalArray () {
+      const data = this.datas.keyList
+      const keysArr = []
+      data.forEach((s) => {
+        if (s && s.key && Array.isArray(s.key)) {
+          s.key.forEach((v) => {
+            keysArr.push(v)
+          })
+        }
+      })
+      console.log(keysArr, 'keysArr')
+      return keysArr
+    },
+    // 判断附加词、排除词是否重复
+    getArrIsRepeat (arr) {
+      this.removeEmptyInput(arr)
+      return (new Set(arr)).size !== arr.length
+    },
+    // 判断是否超限
+    getIsAdd () {
+      const keyArr = this.getKeyTotalArray()
+      if (keyArr.length >= this.datas.maxCount) {
+        return true
+      } else {
+        return false
+      }
+    },
+    // 输入框为空移除
+    removeEmptyInput (arr) {
+      for (let i = 0; i < arr.length; i++) {
+        if (arr[i] === '' || arr[i] === null || typeof (arr[i]) === undefined) {
+          arr.splice(i, 1)
+          i = i - 1
+        }
+      }
+      return arr
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+// dialog 自定义class样式
+.sub-dialog{
+  border-radius: 8px;
+  .selector-card{
+    width: 800px;
+    height: auto;
+  }
+  .key-edit-content,.class-edit-content{
+    width: 740px;
+    padding: 30px 0;
+    height: auto;
+    max-height: 340px;
+    margin: 0 auto;
+    border: 1px solid #ececec;
+    overflow-y: scroll;
+    box-sizing: border-box;
+  }
+  .item{
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-bottom: 10px;
+  }
+  .item-label{
+    margin-right: 8px;
+    min-width: 120px;
+    height: 40px;
+    color: #1d1d1d;
+    font-size: 14px;
+    line-height: 40px;
+    text-align: right;
+  }
+  .item-label-required:before{
+    content: "*";
+    color: #f56c6c;
+    margin-right: 2px;
+  }
+  .item-value{
+    width: 352px;
+  }
+  .custom-long-input{
+    width: 352px;
+  }
+  .custom-short-input{
+    width: 170px;
+  }
+  .delete-class{
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    padding: 32px 32px 42px;
+    background: #FFFFFF;
+    border-radius: 6px;
+    .delete-class-header{
+      font-size: 18px;
+      line-height: 28px;
+      color: #1D1D1D;
+    }
+    .delete-class-content{
+      padding: 20px 0 42px;
+      color: #686868;
+      font-size: 14px;
+      line-height: 22px;
+    }
+    .delete-class-footer{
+      display: flex;
+      align-items: center;
+      .confirm,
+      .cancel {
+        padding: 10px 50px;
+        margin: 0 20px;
+      }
+      ::v-deep {
+        .el-button--primary {
+          color: #2cb7ca;
+          background: none;
+          border-color: #2cb7ca;
+          &:hover {
+            color: #fff;
+            background-color: #2cb7ca;
+          }
+        }
+        .el-button--default {
+          &:hover,
+          &:active {
+            color: #2cb7ca;
+            border-color: #2cb7ca;
+            background: #eaf8fa;
+          }
+        }
+      }
+    }
+  }
+}
+.classify-list{
+  margin-bottom: 30px;
+  .icon-edit,.icon-delete{
+    display: inline-block;
+    width: 16px;
+    height: 16px;
+    background-repeat: no-repeat;
+    background-position: center center;
+    cursor: pointer;
+  }
+  .icon-edit{
+    margin: 0 10px;
+    background-image: url('~@/assets/images/icon-edit.png');
+    background-size: contain;
+  }
+  .icon-delete{
+    background-image: url('~@/assets/images/icon-delete.png');
+    background-size: contain;
+  }
+  .classify-content{
+    display: flex;
+    align-items: center;
+    justify-content: flex-start;
+    flex-wrap: wrap;
+    .list{
+      padding-top: 10px;
+      margin-right: 10px;
+      margin-bottom: 10px;
+      width: 160px;
+      height: 80px;
+      box-sizing: border-box;
+      &:hover .list-edit{
+        transform: scaleY(1);
+        transition: transform .1s;
+      }
+      &:hover .list-box{
+        border: 1px solid #2cb7ca;
+        box-sizing: border-box;
+      }
+    }
+    .list:nth-child(6n) {
+      margin-right: 0;
+    }
+    .list-box{
+      position: relative;
+      display: flex;
+      padding: 10px 10px 10px 16px;
+      border: 1px solid #ececec;
+      border-radius: 9px;
+      box-sizing: border-box;
+      cursor: pointer;
+    }
+    .list-edit{
+      transform: scaleY(0);
+      transition: transform .1s;
+      position: absolute;
+      top: -40px;
+      left: 50%;
+      margin-left: -22px;
+      padding: 10px;
+      color: #fff;
+      background: #1d1d1d;
+      border-radius: 4px;
+      font-size: 12px;
+      cursor: pointer;
+      .tri-down{
+        position: absolute;
+        bottom: -6px;
+        left: 50%;
+        margin-left: -5px;
+        width: 0;
+        height: 0;
+        border-left: 6px solid transparent;
+        border-right: 6px solid transparent;
+        border-top: 6px solid #1d1d1d;
+      }
+    }
+    .list-value{
+      width: 124px;
+      font-size: 12px;
+      line-height: 20px;
+      color: #000;
+      text-overflow: ellipsis;
+      overflow: hidden;
+      white-space: nowrap;
+      p{
+        @extend .list-value
+      }
+    }
+    .list-icon{
+      @extend .icon-delete;
+      width: 12px;
+      height: 12px;
+    }
+    .words-add{
+      width: 162px;
+      height: 80px;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      font-size: 24px;
+      border: 1px solid #ececec;
+      margin: 10px 0 0 0;
+      border-radius: 9px;
+      color: #c4c4c4;
+      cursor: pointer;
+    }
+  }
+}
+</style>

Some files were not shown because too many files changed in this diff