浏览代码

feat:广东移动搜索及画像

yangfeng 3 年之前
父节点
当前提交
44ff2f9f16

二进制
src/assets/images/custom-bg.png


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

@@ -67,7 +67,7 @@ export default {
         series: {
           name: '半径模式',
           type: 'pie',
-          bottom: 20,
+          bottom: 40,
           avoidLabelOverlap: true,
           stillShowZeroSum: false,
           radius: [2, '90%'],

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

@@ -131,7 +131,7 @@ import Empty from '@/components/common/Empty.vue'
 import ArticleItem from '@/components/article-item/ArticleItem.vue'
 import { getPushList, getExportPushList } from '@/api/modules/'
 import { moneyUnit, dateFromNow, replaceKeyword } from '@/utils/'
-
+/* eslint-disable */
 export default {
   name: 'push-list',
   components: {
@@ -897,6 +897,7 @@ export default {
     }
   }
 }
+/* eslint-enable */
 </script>
 <style>
 .info-list-card .custom-checkbox {

+ 12 - 0
src/router/routers.js

@@ -133,5 +133,17 @@ export default [
     path: '/free/project_progress',
     name: 'project_progress',
     component: () => import('@/views/ProjectProgress.vue')
+  },
+  // 广东客户-搜索列表
+  {
+    path: '/free/custom_search',
+    name: 'custom_search',
+    component: () => import('@/views/customer/EntSearch.vue')
+  },
+  // 广东客户-采购单位画像
+  {
+    path: '/free/custom_unit_portrayal/:entName',
+    name: 'custom_unit_portrayal',
+    component: () => import('@/views/customer/Buyer.vue')
   }
 ]

+ 874 - 0
src/views/customer/Buyer.vue

@@ -0,0 +1,874 @@
+<template>
+  <Layout class="unit-portrayal">
+    <div class="unit-portrayal-content" v-loading="loading" background="#fff">
+      <div class="unit-type">
+        <div class="u-top-container">
+          <div class="u-name">{{ info.buyerName }}</div>
+          <!-- <div class="u-follow" @click="setFollow" v-if="conf7">
+            <span :class="{ icon_heart_red: follow.followed, icon_heart_gray: !follow.followed }"></span>
+            <span class="follow-text">{{ follow.followed ? '已关注' : '关注' }}</span>
+          </div> -->
+        </div>
+        <div class="u-type">
+          <div class="u-t-item">
+            <span class="area-icon"></span>
+            <span>所在地:{{ info.province }} {{ info.city }}</span>
+          </div>
+          <div class="u-t-item">
+            <span class="type-icon"></span>
+            <span>采购单位类型:{{ info.buyerClass }}</span>
+          </div>
+        </div>
+      </div>
+      <!-- 超级订阅用户、免费用户显示 -->
+      <!-- <div>
+        <div class="free-bg" v-if="userInfo.isFree && userInfo.freeBuyerPort === 0">
+          <span class="give-tip">赠送</span>
+          <div class="free-text">免费赠送1次【采购单位全景分析】权益体验机会!</div>
+          <div class="unlock-btn" @click="goUnlock">去解锁>></div>
+        </div>
+        <div class="supervip-bg" v-if="vipStatusNoMember">
+          <div class="vip-balance">当月采购单位画像余额:<em class="highlight-text">{{usageInfo.surplus}}</em></div>
+          <div class="update-btn" @click.stop="goUpdate">{{vipStatusBtn}}</div>
+        </div>
+      </div> -->
+      <!-- 采购单位通讯录 -->
+      <!-- <ContactList name="buyer" titlename="采购单位通讯录" style="padding:32px 40px 32px;" v-if="!noBuyerAuth"></ContactList>
+      <div class="mask-bg-group" v-else>
+        <MaskCard @click="openBigPage('采购单位通讯录', getEntContactMap)" k="采购单位通讯录 " :key="'采购单位通讯录' + getEntContactMap.button + getEntContactMap.title" :item="getEntContactMap"></MaskCard>
+      </div> -->
+      <div class="unit-info">
+        <div class="bidcomp">
+          <BidInfoActive whichPor="unitpor" @onPageChange="onLimitChange" :canselect="canSelect" title="采购单位分析"></BidInfoActive>
+        </div>
+        <div class="u-i-box" v-if="baseShow">
+          <div class="b-item">
+            <span>{{ info.buyerCount }}</span>
+            <span>采购项目数量</span>
+          </div>
+          <div class="b-item">
+            <span>{{ info.buyerScale }}</span>
+            <span>采购规模</span>
+          </div>
+          <div class="b-item">
+            <span>{{ info.winnerCount }}</span>
+            <span>中标企业数量</span>
+          </div>
+          <div class="b-item">
+            <span>{{ info.otherWinner }}</span>
+            <span>外省中标企业</span>
+          </div>
+          <div class="b-item">
+            <span>{{ info.fail_count }}</span>
+            <span>流标记录数</span>
+          </div>
+        </div>
+        <div class="u-i-tip" v-if="baseShow">数据统计范围:{{ info.start }}-{{ info.end }}</div>
+      </div>
+      <unit-chart @isTrial="getIsTrail" @baseInfoBool="baseInfoBool" @showEmpty="showEmpty" :params="bidInfoParams" v-on:baseInfo="getBaseInfo"></unit-chart>
+      <!-- 招标动态 -->
+      <unit-list :noauth="noBuyerAuth" :usage="usageInfo" :bidparams="bidInfoParams" v-if="unitlistshow" @list="getList" @click="openCheckPop" @onClickUnlock="goEmitClick"></unit-list>
+      <!-- <div class="unit-big-upgrade-group" v-if="noBuyerAuth && !emptyShow">
+        <MaskCard @click="openBigPage(k, item)" v-for="(item, k) in getBigUpgradeMap" :key="k + item.button + item.title"
+                  :k="k" :item="item"></MaskCard>
+      </div> -->
+      <Empty v-show="emptyShow" :images="require('@/assets/images/empty/jy-chagrin.png')">
+        <div slot="default" style="text-align:center">
+          <span>对不起,没有匹配到相关信息,</span><br/>
+          <span>修改时间范围或换个搜索词试试吧</span>
+        </div>
+      </Empty>
+    </div>
+    <el-dialog
+      class="unit-dialog-group"
+      title="联系客服"
+      :visible.sync="isDialogShow"
+    >
+      <div class="unit-dialog-content">如有疑问,请联系客服:400-108-6670</div>
+    </el-dialog>
+    <!-- <CollectInfo ref="collectRef"></CollectInfo> -->
+  </Layout>
+</template>
+<script>
+import Layout from '@/components/common/ContentLayout'
+import UnitChart from './components/BuyerChart'
+import UnitList from '../portrayal/components/UnitList'
+import BidInfoActive from '../portrayal/components/BidInfoActive'
+import ContactList from '@/components/contact-info/ContactInfo'
+import MaskCard from '@/components/mask-card/MaskCard.vue'
+import Empty from '@/components/common/Empty'
+import { Dialog } from 'element-ui'
+import { setLogs, getStatusCustomer, setStatusCustomer, getBuyerSelect, getVipBuyerSelect, getUsage } from '@/api/modules'
+import { mapState } from 'vuex'
+
+function getImgForBigUpgrade (name, bg = false, suffix = '.png') {
+  const temp = (bg ? 'bg/' : '') + name + suffix
+  return require('@/assets/images/big/' + temp)
+}
+/* eslint-disable */
+export default {
+  name: 'unit-portrayal',
+  components: {
+    Layout,
+    UnitChart,
+    UnitList,
+    ContactList,
+    MaskCard,
+    BidInfoActive,
+    [Dialog.name]: Dialog,
+    Empty
+  },
+  data () {
+    return {
+      isDialogShow: false,
+      loading: true,
+      info: {
+        buyerName: '',
+        province: '',
+        city: '',
+        buyerClass: '',
+        buyerCount: '',
+        buyerScale: '',
+        winnerCount: '',
+        otherWinner: '',
+        fail_count: '',
+        start: '',
+        end: ''
+      },
+      follow: {
+        followed: false,
+        loading: false
+      },
+      listData: [],
+      unitData: {
+        id: ''
+      },
+      entContactTip: {
+        title: '开通大会员',
+        subtitle: '获取采购单位类似项目联系人、联系方式等,一键拨打!',
+        button: '免费体验',
+        source: 'buyer_portrait_contacts_freeuser',
+        img: getImgForBigUpgrade('1-big'),
+        bg: getImgForBigUpgrade('1-bg', true)
+      },
+      bigUpgradeMap: {
+        年度项目统计: {
+          title: '开通大会员',
+          subtitle: '采购单位年度项目规模、增长趋势一目了然,快速分析市场!',
+          img: getImgForBigUpgrade('2-big'),
+          bg: getImgForBigUpgrade('2-bg', true),
+          source: 'buyer_portrait_yearData_freeuser'
+        },
+        月度采购规模统计: {
+          title: '开通大会员',
+          subtitle: '通过纵向对比近3年月度中标金额,快速分析行业月度采购趋势!',
+          img: getImgForBigUpgrade('3-big'),
+          bg: getImgForBigUpgrade('3-bg', true),
+          source: 'buyer_portrait_monthData_freeuser'
+        },
+        采购规模分布: {
+          title: '开通大会员',
+          subtitle: '全面了解采购单位的年度采购规划、项目预算,帮助投标人制定投标策略!',
+          img: getImgForBigUpgrade('4-big'),
+          bg: getImgForBigUpgrade('4-bg', true),
+          source: 'buyer_portrait_moneyRange_freeuser'
+        },
+        各类招标方式占比: {
+          title: '开通大会员',
+          subtitle: '洞察采购单位招标方式、数量、金额占比,综合了解采购单位,帮企业决策是否投标!',
+          img: getImgForBigUpgrade('5-big'),
+          bg: getImgForBigUpgrade('5-bg', true),
+          source: 'buyer_portrait_bidtypeData_freeuser'
+        },
+        各行业项目平均节支率: {
+          title: '开通大会员',
+          subtitle: '分析行业项目的预算、中标价格差额比率,帮助企业核算采购项目的利润率!',
+          img: getImgForBigUpgrade('6-big'),
+          bg: getImgForBigUpgrade('6-bg', true),
+          source: 'buyer_portrait_rate_freeuser'
+        },
+        重点合作代理机构: {
+          title: '开通大会员',
+          subtitle: '通过提供合作代理机构的名录、数量,全面洞察采购单位合作环境,辅助投标决策!',
+          img: getImgForBigUpgrade('12-big'),
+          bg: getImgForBigUpgrade('12-bg', true),
+          source: 'buyer_portrait_topAgencyData_freeuser'
+        },
+        重点合作企业: {
+          title: '开通大会员',
+          subtitle: '通过挖掘重点合作企业,直观了解采购单位与企业关系远近,辅助投标决策!',
+          img: getImgForBigUpgrade('8-big'),
+          bg: getImgForBigUpgrade('8-bg', true),
+          source: 'buyer_portrait_topShow_freeuser'
+        },
+        各行业项目规模占比: {
+          title: '开通大会员',
+          subtitle: '通过行业采购项目的规模、数量、利润率,洞悉采购单位的采购状况!',
+          img: getImgForBigUpgrade('7-big'),
+          bg: getImgForBigUpgrade('7-bg', true),
+          source: 'buyer_portrait_top12_freeuser'
+        }
+      },
+      bidInfoParams: {},
+      canSelect: {},
+      baseShow: true,
+      chartShowArr: [],
+      emptyShow: false,
+      unitlistshow: true,
+      usageInfo: {
+        total: 0,
+        usage: 0,
+        provin: 0,
+        visited: false,
+        surplus: 0
+      }, // 画像访问量
+      freeTrial: false,
+      entInfo: {}
+    }
+  },
+  watch: {
+    chartShowArr (newval) {
+      if (newval.indexOf(true) !== -1) {
+        this.emptyShow = false
+      } else {
+        if (this.noBuyerAuth) {
+          this.emptyShow = false
+        } else {
+          this.emptyShow = true
+        }
+      }
+    },
+    'usageInfo.provin' (newVal) {
+      this.usageInfo.provin = newVal
+    }
+  },
+  computed: {
+    ...mapState({
+      userInfo: state => state.user.info
+    }),
+    conf7 () {
+      const power = this.userInfo.power
+      if (power) {
+        // 7.挖掘潜在客户
+        return power.indexOf(7) !== -1
+      } else {
+        return false
+      }
+    },
+    canShowHistoryContact () {
+      const info = this.userInfo
+      const usage = this.usageInfo
+      // 大会员用户有采购单位全景分析权限
+      const bigMember = info.memberStatus > 0 && info.power.indexOf(5) !== -1
+      // 新超级订阅用户 有采购单位画像余额
+      const svip = info.vipStatus > 0 && info.viper && usage.surplus > 0
+      // 新超级订阅用户 次数用完 浏览过
+      const svipTrial = info.vipStatus > 0 && info.viper && usage.surplus <= 0 && usage.visited
+      // 免费用户 留过资 免费体验一次
+      const freePort = info.isFree && info.freeBuyerPort > 0
+      // 免费用户 体验过期 浏览过
+      const freeTail = info.isFree && info.freeBuyerPort < 0
+      return bigMember || svip  || svipTrial || freePort || freeTail
+    },
+    // 可以查看画像权限,显示遮罩
+    noBuyerAuth () {
+      const info = this.userInfo
+      const usage = this.usageInfo
+      const isFreeAuth = info.isFree && info.freeBuyerPort > 0
+      const isVipAuth = info.vipStatus > 0 && info.viper && usage.surplus > 0
+      const isMember = info.power.indexOf(5)  !== -1
+      // 超级订阅用户是否访问过该画像
+      const vipTrial = info.vipStatus > 0 && info.viper && usage.surplus === 0 && usage.visited
+      // 免费用户是否查看过该画像
+      const freeTrial = info.isFree && info.freeBuyerPort < 0 && this.freeTrial
+      // 免费用户无体验次数的、超级订阅用户无剩余次数的、没有大会员浏览权限的 显示遮罩
+      return !isFreeAuth && !isVipAuth && !isMember && !freeTrial && !vipTrial
+    },
+    getEntContactMap () {
+      const tempMap = this.entContactTip
+      const canShow = this.userInfo.memberStatus > 0
+      let tempTitle = '大会员'
+      // let tempButton = '联系客服'
+      if (!canShow) {
+        tempTitle = '开通大会员'
+        // tempButton = '免费体验'
+      }
+      tempMap.title = tempTitle
+      tempMap.button = this.shadeBottomBtnText
+      return tempMap
+    },
+    // 纯超级订阅用户
+    vipStatusNoMember () {
+      return this.userInfo.vipStatus > 0 && this.userInfo.viper && this.userInfo.memberStatus <= 0
+    },
+    // 超级订阅余额提醒 对应文案
+    vipStatusBtn () {
+      let text = ''
+      if (this.usageInfo.provin === -1) {
+        text = '联系客服'
+      } else {
+        text = '前往升级'
+      }
+      return text
+    },
+    getBigUpgradeMap () {
+      for (const v in this.bigUpgradeMap) {
+        // let tempTitle = '大会员'
+        // let tempButton = '联系客服'
+        // if (!tempPowerInfo.isMember) {
+        //   tempTitle = '开通大会员'
+        //   tempButton = '免费体验'
+        // }
+        // this.bigUpgradeMap[v].title = tempTitle
+        console.log(this.shadeBottomBtnText)
+        this.bigUpgradeMap[v].button = this.shadeBottomBtnText
+      }
+      return  this.bigUpgradeMap
+    },
+    // 遮罩按钮对应文案
+    shadeBottomBtnText () {
+      let btnText = ''
+      const info = this.userInfo
+      const usage = this.usageInfo
+      // 【立即解锁】:未体验过采购单位画像的免费用户,点击进行“欢迎体验采购单位全景分析”留资
+      // 【去开通】:已体验过1次采购单位画像的免费用户,点击进入超级订阅购买页
+      // 【前往升级】:超级订阅老版用户+购买了非全国采购单位画像余额为0的超级订阅新版用户,点击进入超级订阅升级页
+      // 【联系客服】:购买了全国采购单位画像余额为0的超级订阅新版用户+无采购单位画像权限的大会员客户;点击调起智齿在线客服
+      if (info.isFree) {
+        if (info.freeBuyerPort === 0) {
+          btnText = '立即解锁'
+        } else {
+          btnText = '去开通'
+        }
+      } else {
+        btnText = ''
+        // 老超级订阅用户
+        const oldVip = info.vipStatus > 0 && !info.viper
+        // 新超级订阅用户
+        const newVip = info.vipStatus > 0 && info.viper
+        // 大会员用户
+        const member = info.memberStatus > 0
+        // 新超级订阅用户买的非全国 余额为0
+        const noAllProvinNoCounts = newVip && usage.provin !== -1 && usage.surplus <= 0
+        // 超级订阅新用户 购买的全国 余额为0
+        const allProvinNoCounts = newVip && usage.provin === -1 && usage.surplus <= 0
+        // 无权限的大会员用户
+        const noAuthMember = info.memberStatus > 0 && info.power.indexOf(5) === -1
+        // 纯商机管理用户
+        const entniche = info.entniche && !oldVip && !newVip && !member
+        if (oldVip || noAllProvinNoCounts) {
+          btnText = '前往升级'
+        } else if (allProvinNoCounts || noAuthMember || entniche) {
+          btnText = '联系客服'
+        }
+      }
+      return btnText
+    }
+  },
+  created () {
+    if (this.$route.query.info) {
+      this.entInfo = JSON.parse(this.$route.query.info)
+    }
+    this.$store.dispatch('user/getUserPower')
+  },
+  mounted () {
+    this.info.buyerName = decodeURIComponent(this.$route.params.entName)
+    // this.getBigUpgradeMap()
+    this.getFollowState()
+    this.getSelect()
+    this.getBuyerUsage()
+    $.ajax({
+      url: '/publicapply/bidcoll/power',
+      type: 'POST',
+      success: (res) => {
+        // 如果是商机管理、大会员、超级订阅会员有筛选权限
+        let tempType = ''
+        if (res.data.vip > 0) {
+          tempType = '1'
+        }
+        if (res.data.member) {
+          if (tempType !== '') {
+            tempType += ','
+          }
+          tempType += '2'
+        }
+        if (res.data.entniche) {
+          if (tempType !== '') {
+            tempType += ','
+          }
+          tempType += '3'
+        }
+        if (tempType === '') {
+          tempType = '0'
+        }
+        setLogs({
+          platform: 'P',
+          userType: tempType
+        }).then(res => {
+          if (res.error_msg === '' && res.data) {
+            this.unitData = res.data
+          }
+        })
+      }
+    })
+  },
+  methods: {
+    // 获取免费用户是否体验过该采购单位
+    getIsTrail (data) {
+      console.log(data, 'dadadada')
+      this.freeTrial = data ? data : false
+    },
+    // 采购单位画像访问量查询
+    getBuyerUsage () {
+      const info = this.userInfo
+      const isNewVip = info.vipStatus > 0 && info.viper && info.power.indexOf(5) === -1
+      if (!isNewVip) return
+      getUsage({
+        buyer: decodeURIComponent(this.$route.params.entName),
+        p_type: '1'
+      }).then(res => {
+        if (res.error_code === 0 && res.data) {
+          if (res.data.usage > res.data.total) {
+            res.data.usage = res.data.total
+          }
+          res.data.surplus = res.data.total - res.data.usage
+          this.usageInfo = res.data
+        }
+      })
+    },
+    goExp () {
+      this.$refs.collectRef.noCallApiFn('buyer_portrait_exp_freeuser', true)
+    },
+    // 采购单位-筛选项
+    onLimitChange (data) {
+      this.unitlistshow = true
+      this.loading = true
+      this.bidInfoParams = JSON.parse(data)
+    },
+    showEmpty (data) {
+      this.chartShowArr = data
+    },
+    baseInfoBool (data) {
+      this.baseShow = data
+    },
+    async getSelect () {
+      const params = { buyer: this.$route.params.entName }
+      const info = this.usageInfo
+      const isMember = info.memberStatus > 0 && info.power.indexOf(5) > -1
+      const res = isMember ? await getBuyerSelect(params) : await getVipBuyerSelect(params)
+      if (res.error_code === 0) {
+        this.canSelect = res.data
+      }
+    },
+    openCheckPop () {
+      this.openBigPage('', {
+        source: 'buyer_portrait_getNewMsg_freeuser',
+        button: this.shadeBottomBtnText
+      })
+    },
+    
+    openBigPage (k, item) {
+      try {
+        // eslint-disable-next-line no-undef
+        _hmt.push(['_trackEvent', '采购单位画像-pc', 'click', k + '-' + item.button])
+      } catch (e) {
+        console.log('未初始化百度统计')
+      }
+      if (item.button === '立即解锁') {
+        this.$refs.collectRef.noCallApiFn(item.source, true)
+      } else if (item.button === '去开通') {
+        this.$router.push('/free/svip/buy')
+      } else if (item.button === '前往升级') {
+        this.$router.push('/free/svip/buy?type=upgrade')
+      } else if (item.button === '联系客服') {
+        // this.isDialogShow = true
+        $('.help-slide-zx.open-customer').trigger('click')
+      }
+    },
+    getList (data) {
+      if (!data) {
+        this.chartShowArr.push(false)
+        if (this.emptyShow) {
+          this.unitlistshow = false
+        } else {
+          this.unitlistshow = true
+        }
+      } else {
+        this.chartShowArr.push(true)
+      }
+      this.loading = false
+    },
+    getBaseInfo (data) {
+      // 子组件传来的值
+      if (!data) return
+      this.info = data
+      this.loading = false
+    },
+    getFollowState () {
+      // 查询当前企业是否在 关注的客户 列表中
+      getStatusCustomer({ name: this.info.buyerName }).then(res => {
+        if (res && res.error_code === 0 && res.data) {
+          this.follow.followed = res.data
+        }
+      })
+    },
+    setFollow () {
+      if (this.follow.loading) return
+      const data = {
+        name: this.info.buyerName,
+        province: this.info.province,
+        city: this.info.city,
+        b: this.follow.followed
+      }
+      this.follow.loading = true
+      // 潜在客户挖掘/我的客户-关注
+      setStatusCustomer(data).then(res => {
+        if (res && res.error_code === 0 && res.data) {
+          if (this.follow.followed) {
+            // 取消关注操作返回
+            this.$toast('取消关注成功')
+            this.follow.followed = false
+          } else {
+            // 关注操作返回
+            this.follow.followed = true
+            this.$toast(res.error_msg || '关注成功,可前往“我关注的客户”中查看')
+          }
+        } else {
+          this.$toast(res.error_msg)
+        }
+      }).finally(() => {
+        this.follow.loading = false
+      })
+    },
+    // 去解锁
+    goUnlock () {
+      this.$refs.collectRef.noCallApiFn('buyer_portrait_freeuser', true)
+    },
+    goEmitClick (data) {
+      this.$refs.collectRef.noCallApiFn(data, true)
+    },
+    goUpdate () {
+      if (this.usageInfo.provin === -1) {
+        try {
+          $('.help-slide-zx.open-customer').unbind('click').trigger('click')
+        } catch (e) {
+          console.log(e)
+        }
+      } else {
+        this.$router.push('/free/svip/buy?type=upgrade')
+      }
+    }
+  }
+}
+/* eslint-enable */
+</script>
+<style lang="scss" scoped>
+::v-deep{
+  .release_main{
+    position:relative;
+    .el-input__inner{
+      background: #fff;
+      cursor: pointer;
+      color: #1D1D1D;
+      font-size: 14px;
+    }
+  }
+}
+.icon_heart_gray,
+.icon_heart_red {
+  margin-right: 4px;
+  display: flex;
+  width: 18px;
+  height: 18px;
+}
+.icon_heart_gray{
+  background: url('~@/assets/images/icon/icon-heart.png') no-repeat;
+  background-size: contain;
+}
+.icon_heart_red{
+  background: url('~@/assets/images/icon/icon-favorite.png') no-repeat;
+  background-size: contain;
+}
+
+.unit-portrayal {
+  .empty-container.mtb60 {
+    background: #fff;
+    margin: 0 auto;
+    padding: 0 0 60px 0;
+  }
+  // width: 1200px;
+  .mask-bg-group {
+    margin-top: 16px;
+    background: #fff;
+    padding-top: 20px;
+  }
+  .unit-big-upgrade-group {
+    padding-top: 32px;
+    background: #fff;
+  }
+
+  .unit-dialog-group {
+    ::v-deep {
+      .el-dialog {
+        width: 380px;
+        background: #ffffff;
+        border-radius: 8px;
+      }
+      .el-dialog__header {
+        text-align: center;
+        padding: 32px;
+        padding-bottom: 20px;
+      }
+      .el-dialog__body {
+        padding: 32px;
+        padding-top: 0;
+        font-size: 14px;
+        font-family: Microsoft YaHei, Microsoft YaHei-Regular;
+        font-weight: 400;
+        text-align: CENTER;
+        color: #686868;
+        line-height: 22px;
+      }
+      .el-dialog__title {
+        font-size: 18px;
+        font-family: Microsoft YaHei, Microsoft YaHei-Regular;
+        font-weight: 400;
+        color: #1d1d1d;
+        line-height: 28px;
+      }
+      .el-dialog__footer {
+        padding: 0;
+      }
+    }
+    .unit-dialog-footer {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      justify-content: space-between;
+      padding: 32px;
+      padding-top: 0;
+      ::v-deep {
+        .el-button--default {
+          border: 1px solid #e0e0e0;
+          color: #686868;
+          background: #fff;
+        }
+        .el-button {
+          width: 132px;
+          height: 36px;
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+          justify-content: center;
+          font-size: 16px;
+          font-family: Microsoft YaHei, Microsoft YaHei-Regular;
+          font-weight: 400;
+          text-align: CENTER;
+          border-radius: 6px;
+
+        }
+        .el-button--primary {
+          background: #2cb7ca;
+          color: #ffffff;
+          border-color: #2CB7CA;
+        }
+      }
+    }
+  }
+
+  .unit-type {
+    padding: 32px 40px;
+    background: #fff;
+
+    .u-top-container {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+    }
+
+    .u-name {
+      flex: 1;
+      font-size: 24px;
+      line-height: 36px;
+      color: #171826;
+    }
+
+    .u-follow {
+      margin-left: 6px;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      cursor: pointer;
+      .follow-text {
+        margin-left: 2px;
+        font-size: 14px;
+        color: #686868;
+        line-height: 22px;
+      }
+    }
+
+    .u-type {
+      display: flex;
+      align-items: center;
+      margin-top: 8px;
+      font-size: 14px;
+      line-height: 22px;
+      color: #686868;
+    }
+
+    .area-icon {
+      display: inline-block;
+      width: 18px;
+      height: 18px;
+      margin-right: 4px;
+      background: url('~@/assets/images/icon/icon-location.png') no-repeat center center;
+      background-size: contain;
+    }
+
+    .type-icon {
+      display: inline-block;
+      width: 18px;
+      height: 18px;
+      margin-right: 4px;
+      background: url('~@/assets/images/icon/icon-type.png') no-repeat center center;
+      background-size: contain;
+    }
+
+    .u-t-item {
+      display: flex;
+      align-items: center;
+      margin-right: 32px;
+    }
+  }
+
+  .unit-info {
+    margin-top: 16px;
+    padding: 32px;
+    background: #fff;
+  }
+
+  .u-i-box {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    margin-top: 32px;
+
+    .b-item {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      flex: 1;
+      border-right: 1px solid #ECECEC;
+    }
+
+    .b-item:last-child {
+      border-right: none;
+    }
+
+    & span:nth-child(1) {
+      font-size: 20px;
+      line-height: 32px;
+      color: #2CB7CA;
+    }
+
+    & span:nth-child(2) {
+      font-size: 14px;
+      line-height: 22px;
+      color: #686868;
+    }
+  }
+
+  .u-i-tip {
+    margin-top: 12px;
+    font-size: 12px;
+    line-height: 20px;
+    color: #999999;
+    text-align: center;
+  }
+  ::v-deep {
+    .collect-dialog{
+      position: fixed;
+      top: 50%;
+      left: 50%;
+      margin-top: 0;
+      transform: translate(-50%, -50%);
+    }
+    .el-dialog{
+      border-radius: 8px;
+    }
+    .el-dialog__header{
+      padding: 0;
+    }
+    .el-dialog__body{
+      padding: 0;
+    }
+  }
+  .free-bg{
+    position: relative;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 100%;
+    height: 48px;
+    margin-top: 16px;
+    background: url('~@/assets/images/free-bg.png') no-repeat center center;
+    background-size: 100% 100%;
+    border-radius: 8px;
+    .give-tip{
+      position: absolute;
+      top: 0;
+      left: 0;
+      width: 48px;
+      height: 22px;
+      line-height: 22px;
+      background: linear-gradient(104deg, #D69C06 0%, #B16C05 100%);
+      border-radius: 8px 0 16px 0;
+      font-size: 14px;
+      color: #fff;
+      text-align: center;
+    }
+    .free-text{
+      margin-right: 32px;
+      font-size: 18px;
+      color: #663600;
+    }
+    .unlock-btn{
+      width: 110px;
+      height: 30px;
+      line-height: 30px;
+      text-align: center;
+      background: linear-gradient(104deg, #D69C06 0%, #B16C05 100%);
+      border-radius: 20px;
+      color:#fff;
+      cursor: pointer;
+    }
+  }
+  .supervip-bg{
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    width: 100%;
+    height: 48px;
+    padding: 0 40px;
+    margin-top: 16px;
+    background: url('~@/assets/images/vip-bg.png') no-repeat center center;
+    background-size: 100% 100%;
+    border-radius: 8px;
+    .vip-balance{
+      font-size: 14px;
+      color: #686868;
+    }
+    .update-btn{
+      width: 90px;
+      height: 30px;
+      line-height: 30px;
+      text-align: center;
+      background: #2CB7CA;
+      border-radius: 4px;
+      color:#fff;
+      font-size: 14px;
+      cursor: pointer;
+    }
+  }
+}
+</style>

+ 87 - 0
src/views/customer/EntSearch.vue

@@ -0,0 +1,87 @@
+<template>
+  <div class="ent-search">
+    <div class="ent-header">
+      <div class="w1200">
+        <div class="ent-header-title">专属私域企业数据</div>
+        <div class="ent-header-input">
+          <EntInput placeholder="输入企业名称"></EntInput>
+        </div>
+      </div>
+    </div>
+    <div class="ent-main">
+      <div class="w1200">
+        <SearchList></SearchList>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import EntInput from '@/components/input/SearchInput.vue'
+import SearchList from './components/SearchList.vue'
+import { mapState } from 'vuex'
+export default {
+  name: 'ent-search',
+  components: {
+    EntInput,
+    SearchList
+  },
+  data () {
+    return {
+      myDataObj: {
+        list: [],
+        total: 0
+      },
+      tiptext: ''
+    }
+  },
+  computed: {
+    ...mapState({
+      forcastSer: state => state.forcast.entSearchList,
+      type: state => state.forcast.type
+    })
+  },
+  created () {
+    this.getSearchList()
+  },
+  mounted () {},
+  methods: {
+    // 企业查询默认列表
+    getSearchList () {}
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.ent-search{
+  width: 100%;
+  .w1200{
+    width: 1200px;
+    margin: 0 auto;
+  }
+  .ent-header{
+    width: 100%;
+    height: 186px;
+    background: url('~@/assets/images/custom-bg.png') no-repeat center center;
+    background-size: cover;
+    .ent-header-title{
+      padding-top: 40px;
+      text-align: center;
+      font-size: 28px;
+      color: #1D1D1D;
+    }
+    .ent-header-input{
+      margin-top: 20px;
+    }
+  }
+  .icon_ent{
+    display: flex;
+    align-items: center;
+    margin-right: 6px;
+    width: 36px;
+    height: 36px;
+    background: url('~@/assets/images/icon/book.png') no-repeat;
+    background-size: contain;
+  }
+}
+</style>

+ 1108 - 0
src/views/customer/components/BuyerChart.vue

@@ -0,0 +1,1108 @@
+<template>
+  <div class="unit-chart" v-if="showChart">
+    <!-- 年度项目统计 -->
+    <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>
+      <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>
+    <!-- 各类招标方式占比 -->
+    <div v-if="bidType.show">
+      <div class="chart-title">各类招标方式占比</div>
+      <double-bar-chart :datas="bidType.data"></double-bar-chart>
+    </div>
+    <!-- 各行业项目平均节支率 -->
+    <div v-if="savingsRate.show">
+      <div class="chart-title">各行业项目平均节支率</div>
+      <line-chart v-if="savingsRate.flag" :options="savingsRate.options" :datas="savingsRate.data"></line-chart>
+    </div>
+    <!-- 合作企业注册地分布 -->
+    <div v-if="area.show">
+      <div class="chart-title">合作企业注册地分布</div>
+      <map-chart v-if="area.flag" id="area" :options="area.options" :datas="area.data"></map-chart>
+    </div>
+    <!-- 各行业项目规模占比 -->
+    <div v-if="projectScale.show">
+      <div class="chart-title">各行业项目规模占比</div>
+      <pie-chart v-if="projectScale.flag" :height="'380px'" :options="projectScale.options" :datas="projectScale.data"></pie-chart>
+    </div>
+    <!-- 合作企业注册资本分布 -->
+    <!-- <div v-if="capital.show">
+      <div class="chart-title">合作企业注册资本分布</div>
+      <bar-chart v-if="capital.flag" id="capital" :options="capital.options" :datas="capital.data"></bar-chart>
+    </div> -->
+    <!-- 合作企业年龄分布 -->
+    <!-- <div v-if="age.show">
+      <div class="chart-title">合作企业年龄分布</div>
+      <bar-chart v-if="age.flag" id="age" :options="age.options" :datas="age.data"></bar-chart>
+    </div> -->
+    <!-- 重点合作代理机构 -->
+    <div v-if="agency.show">
+      <div class="chart-title">重点合作代理机构</div>
+      <blue-progress-chart v-if="agency.flag" from="unit" :datas="agency.data"></blue-progress-chart>
+    </div>
+    <!-- 重点合作企业 -->
+    <div v-if="client.data.length > 0">
+      <div class="chart-title">重点合作企业</div>
+      <progress-chart type="unit"  :datas="client.data"></progress-chart>
+    </div>
+  </div>
+</template>
+<script>
+import BarChart from '@/components/chart/BarLineChart'
+import HotChart from '@/components/chart/HotChart'
+import LineChart from '@/components/chart/LineChart'
+import DoubleBarChart from '@/components/chart/DoubleBarChart'
+import PieChart from '@/components/chart/PieChart'
+import ProgressChart from '@/components/chart/ProgressChart'
+import MapChart from '@/components/chart/MapChart'
+import BlueProgressChart from '@/components/chart/BlueProgressChart'
+import { getUnitChart, getVipUnitChart } from '@/api/modules/'
+import { bSort, moneyUnit } from '@/utils/'
+export default {
+  name: 'unit-chart',
+  components: {
+    BarChart,
+    HotChart,
+    LineChart,
+    DoubleBarChart,
+    PieChart,
+    ProgressChart,
+    MapChart,
+    BlueProgressChart
+  },
+  props: {
+    params: {
+      type: Object,
+      default () {
+        return {}
+      }
+    }
+  },
+  data () {
+    return {
+      allBool: [],
+      showChart: false,
+      // 年度项目统计
+      years: {
+        show: false,
+        data: {
+          columns: [],
+          rows: []
+        },
+        options: {
+          height: '326px',
+          colors: [new this.$echarts.graphic.LinearGradient(
+            0, 1, 0, 0,
+            [
+              { offset: 1, color: '#2ABED1' },
+              { offset: 0.5, color: '#2ABED1' },
+              { offset: 0, color: '#8DE0EB' }
+            ], false
+          ), '#FF9F40'],
+          config: this.configYears,
+          settings: {
+            showLine: ['项目金额'],
+            axisSite: { right: ['项目金额'] }
+          }
+        }
+      },
+      // 月度采购规模
+      monthScale: {
+        show: false,
+        data: {
+          columns: [],
+          rows: []
+        },
+        options: {
+          height: '326px',
+          colors: ['#05A6F3', '#0BD991', '#FF9F40'],
+          config: this.configMonthScle
+        }
+      },
+      // 采购规模分布
+      buyScaleFb: {
+        show: false,
+        flag: false,
+        data: [],
+        options: {
+          tooltip: {
+            formatter: this.configBuyScaleFb
+          }
+        }
+      },
+      // 各类招标方式占比
+      bidType: {
+        show: false,
+        data: []
+      },
+      // 各行业项目平均节支率
+      savingsRate: {
+        show: false,
+        flag: false,
+        data: {
+          columns: [],
+          rows: []
+        },
+        options: {
+          height: '326px',
+          colors: ['#FB483D', '#05A6F3', '#0BD991', '#FF9F40', '#8E6DF2', '#C0C4CC'],
+          config: this.configSavingsRate
+        }
+      },
+      // 各行业项目规模占比(饼图)
+      projectScale: {
+        show: false,
+        flag: false,
+        data: [],
+        // 传入的配置
+        options: {
+          tooltip: {
+            formatter: event
+          }
+        }
+      },
+      // 重点合作企业
+      client: {
+        show: false,
+        flag: false,
+        data: []
+      },
+      // 合作企业注册资本分布
+      capital: {
+        show: false,
+        flag: false,
+        data: {
+          columns: [],
+          rows: [],
+          customData: []
+        },
+        options: {
+          height: '320px',
+          colors: ['#05a6f3', '#FF9F40'],
+          config: this.configCapital,
+          settings: {
+            showLine: ['累计采购规模'],
+            axisSite: { right: ['累计采购规模'] }
+          }
+        }
+      },
+      // 合作企业年龄分布
+      age: {
+        show: false,
+        flag: false,
+        data: {
+          columns: ['企业年龄', '企业数量'],
+          rows: [],
+          customData: []
+        },
+        options: {
+          height: '320px',
+          colors: ['#05a6f3'],
+          config: this.configAge
+        }
+      },
+      // 合作企业年龄分布
+      area: {
+        show: false,
+        flag: false,
+        data: {
+          columns: ['企业注册地', '企业数量', '累计采购规模', '采购项目数量', '平均节支率'],
+          rows: [],
+          customData: []
+        },
+        options: {
+          height: '570px',
+          colors: ['#05a6f3'],
+          config: this.configArea
+        }
+      },
+      // 重点合作代理机构
+      agency: {
+        show: false,
+        flag: false,
+        data: []
+      },
+      reqCount: 0,
+      initParams: {
+        buyer: this.$route.params.entName,
+        match: '', // 关键词
+        exactMatch: 0, // 模糊、精准搜索
+        matchRange: '', // 搜索范围
+        area: {}, // 地区
+        scopeClass: '', // 行业
+        timeRange: ''
+      }
+    }
+  },
+  watch: {
+    params (newval) {
+      this.getChartData(newval)
+    },
+    allBool: {
+      handler (newval) {
+        this.$emit('showEmpty', newval)
+      },
+      deep: true
+    }
+  },
+  mounted () {
+    this.getChartData(this.initParams)
+  },
+  methods: {
+    initData (flag, res) {
+      // a段数据 timeRange、city、province、buyerclass、bidamount_count、fail_count、project_count、winner_count、otherProvincesWinnerCount、yearData、monthData、moneyRange、bidtypeData、rate、top12、topAgencyData
+      // b段数据 topShow
+      // c段数据 withCapitalData、withAreaData、withEstablishData
+      if (flag === 'a') {
+        // 基本信息
+        this.formatBaseInfo(res)
+        // 年度项目统计图表数据
+        this.formatYearsData(res.yearData)
+        // 月度采购规模
+        this.formatMonthScaleData(res.monthData)
+        // 采购规模分布
+        this.formatHotChartData(res.moneyRange)
+        // 各类招标方式占比
+        this.formatterBarChart(res.bidtypeData)
+        // 各行业项目平均节支率
+        this.formatSavingsRateData(res.rate)
+        // 各行业项目规模占比
+        this.formatProjectScaleData(res.top12)
+        // 重点合作代理机构
+        this.formatAgencyData(res.topAgencyData)
+      } else if (flag === 'b') {
+        // 重点合作企业
+        this.formatClientData(res.topShow)
+      } else if (flag === 'c') {
+        // 合作企业注册资本分布
+        this.formatCapitalData(res.withCapitalData)
+        // 合作企业年龄分布
+        this.formatAgeData(res.withEstablishData)
+        // 合作企业注册地分布
+        this.formatAreaData(res.withAreaData)
+      } else {
+        // 基本信息
+        this.formatBaseInfo(res)
+        // 年度项目统计图表数据
+        this.formatYearsData(res.yearData)
+        // 月度采购规模
+        this.formatMonthScaleData(res.monthData)
+        // 采购规模分布
+        this.formatHotChartData(res.moneyRange)
+        // 各类招标方式占比
+        this.formatterBarChart(res.bidtypeData)
+        // 各行业项目平均节支率
+        this.formatSavingsRateData(res.rate)
+        // 各行业项目规模占比
+        this.formatProjectScaleData(res.top12)
+        // 重点合作企业
+        this.formatClientData(res.topShow)
+        // 合作企业注册资本分布
+        this.formatCapitalData(res.withCapitalData)
+        // 合作企业年龄分布
+        this.formatAgeData(res.withEstablishData)
+        // 合作企业注册地分布
+        this.formatAreaData(res.withAreaData)
+        // 重点合作代理机构
+        this.formatAgencyData(res.topAgencyData)
+      }
+    },
+    // 画像数据
+    async getChartData (newval) {
+      this.allBool = []
+      const info = this.$store.state.user.info
+      const isMember = info.memberStatus > 0 && info.power.indexOf(5) > -1
+      const res = isMember ? await getUnitChart(newval) : await getVipUnitChart(newval)
+      if (res.error_code === 0) {
+        if (res.data && Object.keys(res.data).length > 0) {
+          this.showChart = true
+          if (res.data.onTrial) {
+            this.$emit('isTrial', res.data.onTrial)
+          }
+          this.initData('', res.data)
+        } else {
+          this.getSectionChartData('a', newval)
+        }
+      } else {
+        this.showChart = false
+      }
+    },
+    getSectionChartData (type, newval) {
+      const flagAjaxParams = {
+        buyer: decodeURIComponent(this.$route.params.entName)
+      }
+      Object.assign(flagAjaxParams, newval)
+      getUnitChart(flagAjaxParams).then((res) => {
+        if (res.error_code === 0) {
+          this.reqCount++
+          if (res.data && Object.keys(res.data).length > 0) {
+            this.showChart = true
+            this.initData('', res.data)
+            if (type === 'a') {
+              this.reqCount = 0
+              this.getSectionChartData('b', newval)
+            } else if (type === 'b') {
+              this.reqCount = 0
+              this.getSectionChartData('c', newval)
+            }
+          } else {
+            if (this.reqCount < 5) {
+              this.getSectionChartData(type, newval)
+            } else {
+              this.showChart = false
+            }
+          }
+        }
+      })
+    },
+    /* ******** 配置项部分 ******* */
+    configYears (options) {
+      options.legend.show = true
+      options.yAxis[1].axisLabel.show = true // 显示右侧y轴刻度
+      var maxCountList = this.years.data.rows.map((v) => {
+        return v['项目数量']
+      })
+      var maxPriceList = this.years.data.rows.map((v) => {
+        return v['项目金额']
+      })
+      let maxCount = Math.ceil(Math.max.apply(null, maxCountList)).toString()
+      let maxPrice = Math.ceil(Math.max.apply(null, maxPriceList)).toString()
+      maxPrice = Math.ceil(maxPrice / (Math.pow(10, maxPrice.length - 1))) * Math.pow(10, maxPrice.length - 1)
+      maxCount = Math.ceil(maxCount / (Math.pow(10, maxCount.length - 1))) * Math.pow(10, maxCount.length - 1)
+      const item = options.yAxis
+      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)
+      options.tooltip.formatter = (params) => {
+        let tip = ''
+        for (let i = 0; i < params.length; i++) {
+          // 因柱状图颜色为渐变色,此处获取到的柱状图颜色,css不能识别,需单独设置小圆点的颜色
+          params[0].marker = '<span style="display:inline-block;margin-right:5px;border-radius:8px;width:8px;height:8px;background-color:#2ABED1"></span>'
+          if (i === 0) {
+            tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '个' + '<br/>'
+          } else if (i === 1) {
+            tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '万元' + '<br/>'
+          } else {}
+        }
+        tip += '<div style="padding-top:2px;text-align:center;color:#9B9CA3;">' + ' - ' + params[0].name + ' - ' + '</div>'
+        return tip
+      }
+      options.legend.formatter = (name) => {
+        if (name === '项目金额') {
+          name = name + '(万元)-右轴'
+        }
+        if (name === '项目数量') {
+          name = name + '(个)'
+        }
+        return name
+      }
+      return options
+    },
+    // 月度采购规模数据及修改配置
+    configMonthScle (options) {
+      options.tooltip.formatter = (params) => {
+        let tip = ''
+        for (let i = 0; i < params.length; i++) {
+          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].value[1] && params[i].value[1] !== 0) {
+            tip = tip + ''
+          } else {
+            tip = tip + params[i].marker + params[i].seriesName + params[i].name + '采购规模:' + params[i].value[1].toString().replace(/,/, '') + '万元' + '<br/>'
+          }
+        }
+        tip += '<div style="padding-top:2px;text-align:center;color:#9B9CA3;">' + ' - ' + params[0].name + ' - ' + '</div>'
+        return tip
+      }
+      return options
+    },
+    configSavingsRate (options) {
+      const data = this.savingsRate.data.rows
+      const arr = []
+      for (let i = 0; i < data.length; i++) {
+        var obj = data[i]
+        for (var key in obj) {
+          if (key !== '日期' && obj[key]) {
+            arr.push(obj[key])
+          }
+        }
+      }
+      let maxRate = Math.ceil(Math.max.apply(null, arr)).toString()
+      maxRate = Math.ceil(maxRate / (Math.pow(10, maxRate.length - 1))) * Math.pow(10, maxRate.length - 1)
+      options.xAxis[0].axisLabel.margin = 12
+      options.yAxis[0].axisLabel.formatter = '{value}%'
+      options.yAxis[0].min = 0
+      options.yAxis[0].max = maxRate
+      options.yAxis[0].interval = Math.ceil(maxRate / 5)
+      options.grid = {
+        top: 20,
+        right: 16,
+        bottom: 70,
+        left: 10
+      }
+      options.legend.textStyle.padding = [0, 18, 0, 0]
+      options.legend.bottom = 10
+      options.tooltip.formatter = (params) => {
+        let tip = ''
+        for (let i = 0; i < params.length; i++) {
+          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].value[1] === undefined || params[i].value[1] === null || isNaN(params[i].value[1])) {
+            tip = tip + params[i].marker + params[i].seriesName + ':--<br/>'
+          } else {
+            tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value[1] + '%<br/>'
+          }
+        }
+        tip += '<div style="padding-top:2px;text-align:center;color:#9B9CA3;">' + ' - ' + params[0].name + ' - ' + '</div>'
+        return tip
+      }
+      return options
+    },
+    configCapital (options) {
+      const customData = this.capital.data.customData
+      var maxCountList = this.capital.data.rows.map((v) => {
+        return v['企业数量']
+      })
+      var maxPriceList = this.capital.data.rows.map((v) => {
+        return v['累计采购规模']
+      })
+      var maxLeft = Math.max.apply(null, maxCountList)
+      var maxRight = Math.max.apply(null, maxPriceList)
+      maxLeft = Math.ceil(maxLeft).toString()
+      maxRight = Math.ceil(maxRight).toString()
+      var l = Math.ceil(maxLeft / (Math.pow(10, maxLeft.length - 1))) * Math.pow(10, maxLeft.length - 1)
+      var r = Math.ceil(maxRight / (Math.pow(10, maxRight.length - 1))) * Math.pow(10, maxRight.length - 1)
+      var item = options.yAxis
+      item[0].min = 0
+      item[1].min = 0
+      item[0].max = l
+      item[0].interval = Math.ceil(l / 5)
+      item[1].max = Math.ceil(r)
+      item[1].interval = Math.ceil((r - 0) / 5)
+      item[0].minInterval = 1
+      options.tooltip.axisPointer.shadowStyle.color = 'rgba(5, 166, 243,0.1)'
+      options.tooltip.formatter = (params) => {
+        const obj = {}
+        let tip = ''
+        customData.forEach((v) => {
+          if (v['注册资本'] === params[0].name) {
+            for (const key in v) {
+              obj[key] = v[key]
+            }
+          }
+        })
+        const regMoney = '<span>注册资本:' + obj['注册资本'] + '</span></br>'
+        const count = '<span>企业数量:' + obj['企业数量'] + '个</span></br>'
+        const scale = '<span>累计采购规模:' + obj['累计采购规模'] + '万元</span></br>'
+        const pCount = '<span>采购项目数量:' + obj['采购项目数量'] + '个</span></br>'
+        const rate = (typeof obj['平均节支率'] === 'number' && !isNaN(obj['平均节支率'])) ? '<span>平均节支率:' + (obj['平均节支率'] * 100).fixed(2) + '%</span></br>' : ''
+        tip = regMoney + count + scale + pCount + rate
+        return tip
+      }
+      options.series.forEach((item) => {
+        if (item.name === '累计采购规模') {
+          item.type = 'line'
+        } else {
+          item.type = 'bar'
+          item.barWidth = 12
+        }
+      })
+      options.legend.formatter = (name) => {
+        if (name === '累计采购规模') {
+          name = '累计采购规模(万元)-右轴'
+        }
+        if (name === '企业数量') {
+          name = '企业数量(个)'
+        }
+        return name
+      }
+      return options
+    },
+    configAge (options) {
+      for (let i = 0; i < options.series.length; i++) {
+        options.series[i].barWidth = 20
+        options.series[i].stack = '企业年龄分布'
+      }
+      const arr = this.age.data.customData
+      options.yAxis[0].minInterval = 1
+      options.xAxis[0].name = '企业年龄(年)'
+      options.xAxis[0].axisLabel.interval = 0
+      options.tooltip.axisPointer.shadowStyle.color = 'rgba(5, 166, 243,0.1)'
+      options.tooltip.formatter = (params) => {
+        const obj = {}
+        let tip = ''
+        arr.forEach((v) => {
+          if (v['企业年龄'] === params[0].name) {
+            for (const key in v) {
+              obj[key] = v[key]
+            }
+          }
+        })
+        const regMoney = '<span>企业年龄:' + obj['企业年龄'] + '</span></br>'
+        const count = '<span>企业数量:' + obj['企业数量'] + '个</span></br>'
+        const scale = '<span>累计采购规模:' + obj['累计采购规模'] + '万元</span></br>'
+        const pCount = '<span>采购项目数量:' + obj['采购项目数量'] + '个</span></br>'
+        const rate = (typeof obj['平均节支率'] === 'number' && !isNaN(obj['平均节支率'])) ? '<span>平均节支率:' + (obj['平均节支率'] * 100).fixed(2) + '%</span></br>' : ''
+        tip = regMoney + count + scale + pCount + rate
+        return tip
+      }
+      return options
+    },
+    configArea (options) {
+      const arr = this.area.data.customData
+      const maxNum = Math.max.apply(Math, arr.map((o) => { return o['企业数量'] }))
+      options.visualMap.min = 1
+      options.visualMap.max = maxNum < 100 ? 100 : maxNum
+      options.graphic[0].children[0].style.text = '企业数量(个)'
+      options.graphic[options.graphic.length - 1].children[0].style.text = maxNum > 100 ? maxNum : 100
+      options.graphic[options.graphic.length - 1].children[1].style.text = 1
+      options.tooltip.formatter = (params) => {
+        const obj = {}
+        let tip = ''
+        arr.forEach((v) => {
+          if (v['企业注册地'] === params.name) {
+            for (const key in v) {
+              obj[key] = v[key]
+            }
+          }
+        })
+        if (Object.keys(obj).length > 0) {
+          const regArea = '<span>企业注册地:' + obj['企业注册地'] + '</span></br>'
+          const count = '<span>企业数量:' + obj['企业数量'] + '个</span></br>'
+          const scale = '<span>累计采购规模:' + obj['累计采购规模'] + '万元</span></br>'
+          const pCount = '<span>采购项目数量:' + obj['采购项目数量'] + '个</span></br>'
+          const rate = (typeof obj['平均节支率'] === 'number' && !isNaN(obj['平均节支率'])) ? '<span>平均节支率:' + (obj['平均节支率'] * 100).fixed(2) + '%</span></br>' : ''
+          tip = regArea + count + scale + pCount + rate
+        } else {
+          tip = ''
+        }
+        return tip
+      }
+      return options
+    },
+    configBuyScaleFb (params) {
+      const data = params.value[4]
+      const newRange = data.split('-')
+      const sRange = moneyUnit(newRange[0])
+      const mRange = moneyUnit(newRange[1])
+      let totalRange
+      if (sRange === '100.0亿元以上') {
+        totalRange = sRange
+      } else {
+        totalRange = sRange + '-' + mRange
+      }
+      let tip = ''
+      const count = '<span>项目数量:' + params.value[3] + '个</span></br>'
+      const rate = (typeof params.value[2] === 'number' && !isNaN(params.value[2])) ? '<span>平均节支率:' + (params.value[2] * 100).fixed(2) + '%</span></br>' : ''
+      const budget = '<span>采购规模:' + totalRange + '</span></br>'
+      tip = budget + count + rate
+      return tip
+    },
+    /* ********  数据格式化部分 ******* */
+    formatBaseInfo (res) {
+      if (res) {
+        const info = {}
+        info.buyerName = decodeURIComponent(this.$route.params.entName)
+        info.province = res.province ? res.province.replace(/省|市|自治区|特别行政区|壮族|回族|维吾尔/g, '') : '--'
+        info.city = res.city === res.province ? '' : res.city
+        info.buyerClass = res.buyerclass ? res.buyerclass : '--'
+        if (res.timeRange) {
+          info.start = new Date(Number(res.timeRange.start + '000')).pattern('yyyy/MM/dd')
+          info.end = new Date(Number(res.timeRange.end + '000')).pattern('yyyy/MM/dd')
+        }
+        info.buyerCount = res.project_count ? res.project_count + '个' : '--'
+        info.winnerCount = res.winner_count ? res.winner_count + '个' : '--'
+        info.otherWinner = res.otherProvincesWinnerCount ? res.otherProvincesWinnerCount + '个' : '--'
+        info.buyerScale = res.bidamount_count ? moneyUnit(res.bidamount_count) : '--'
+        info.fail_count = res.fail_count ? res.fail_count + '条' : '--'
+        this.$emit('baseInfo', info)
+        if (!res.project_count && !res.winner_count && !res.otherProvincesWinnerCount && !res.bidamount_count && !res.fail_count) {
+          this.$emit('baseInfoBool', false)
+          this.allBool.push(false)
+        } else {
+          this.$emit('baseInfoBool', true)
+          this.allBool.push(true)
+        }
+      } else {
+        this.$emit('baseInfoBool', false)
+        this.allBool.push(false)
+      }
+    },
+    // 格式化年度项目统计数据
+    formatYearsData (data) {
+      if (data && Object.keys(data).length) {
+        const rows = []
+        let count = 0
+        /* eslint-disable */
+        for (const key in data) {
+          rows.push({
+            '年份': key,
+            '项目数量': data[key].Count,
+            '项目金额': (data[key].Money / 10000).fixed(0)
+          })
+          count += data[key].Count
+        }
+        /* eslint-enable */
+        if (count !== 0) {
+          this.years.data.columns = ['年份', '项目数量', '项目金额']
+          this.years.data.rows = rows
+          this.years.show = true
+          this.allBool.push(true)
+        } else {
+          this.allBool.push(false)
+          this.years.show = false
+        }
+      } else {
+        this.years.show = false
+        this.allBool.push(false)
+      }
+    },
+    // 格式化月度采购规模数据
+    formatMonthScaleData (data) {
+      if (data && Object.keys(data).length > 0) {
+        const rows = []
+        const columns = ['月份']
+        let count = 0
+        const allNum = []
+        const years = []
+        for (var key in data) {
+          years.push(parseInt(key))
+          for (const n in data[key]) {
+            allNum.push(data[key][n])
+          }
+        }
+        years.sort((a, b) => { return a - b })
+        years.forEach(function (item) {
+          columns.push(item + '年')
+        })
+        for (let i = 1; i <= 12; i++) {
+          const columnsItem = {}
+          columns.forEach((item) => {
+            let value = ''
+            if (item === '月份') {
+              value = i + '月'
+            } else if (/年/g.test(item)) {
+              if (data[item.slice(0, -1)]) {
+                value = data[item.slice(0, -1)][i]
+                value = (value / 10000).fixed(2)
+                count += value
+              }
+            }
+            columnsItem[item] = value
+          })
+          rows.push(columnsItem)
+        }
+        const maxNum = Math.max.apply(Math, allNum.map((o) => { return o }))
+        // console.log('数据最大值为:', maxNum)
+        if (count !== 0 && maxNum !== 0) {
+          this.monthScale.data.columns = columns
+          this.monthScale.data.rows = rows
+          this.monthScale.show = true
+          this.allBool.push(true)
+        } else {
+          this.monthScale.show = false
+          this.allBool.push(false)
+        }
+      } else {
+        this.monthScale.show = false
+        this.allBool.push(false)
+      }
+    },
+    // 格式化采购规模分布(热力图)数据
+    formatHotChartData (arr) {
+      if (arr && arr.length > 0) {
+        const countArr = arr.map((v) => {
+          return v.project_count
+        })
+        const max = Math.max.apply(null, countArr)
+        if (max === 0) {
+          this.buyScaleFb.show = false
+        }
+        let data = []
+        data = arr.map((v, i) => {
+          v.bidamount_avg = v.bidamount_avg === null ? '0' : v.bidamount_avg
+          const x = i % 10
+          const y = 10 - Math.ceil((i + 1) / 10)
+          return [x, y, v.bidamount_avg, v.project_count, v.range]
+        })
+        this.buyScaleFb.flag = true
+        this.buyScaleFb.data = data
+        this.buyScaleFb.show = true
+        this.allBool.push(true)
+      } else {
+        this.allBool.push(false)
+        this.buyScaleFb.flag = false
+        this.buyScaleFb.data = []
+        this.buyScaleFb.show = false
+      }
+    },
+    // 格式化各类招标方式占比数据(双向柱图)
+    formatterBarChart (data) {
+      if (data && data.length > 0) {
+        data.forEach((item) => {
+          item.money = (item.money / 10000).fixed(2)
+          item.moneyShare = (item.moneyShare * 100).fixed(2)
+          item.numShare = (item.numShare * 100).fixed(2)
+          switch (item.type) {
+            case '招标':
+              item.type = '公开招标'
+              break
+            case '邀标':
+              item.type = '邀请招标'
+              break
+            case '询价':
+              item.type = '询价采购'
+              break
+            case '单一':
+              item.type = '单一来源采购'
+              break
+            case '竞价':
+              item.type = '竞价采购'
+              break
+            case '竞谈':
+              item.type = '竞争性谈判'
+              break
+          }
+        })
+        const newData = data
+        const maxLeftNum = Math.max.apply(Math, data.map((o) => { return o.numShare }))
+        const maxRightNum = Math.max.apply(Math, data.map((o) => { return o.moneyShare }))
+        newData.forEach((v) => {
+          v.lPercent = (v.numShare / maxLeftNum * 100).fixed(2)
+          v.rPercent = (v.moneyShare / maxRightNum * 100).fixed(2)
+        })
+        this.bidType.data = newData
+        this.bidType.show = true
+        this.allBool.push(true)
+      } else {
+        this.allBool.push(false)
+        this.bidType.data = []
+        this.bidType.show = false
+      }
+    },
+    // 格式化平均节支率数据
+    formatSavingsRateData (data) {
+      if (data && Object.keys(data).length > 0) {
+        const rows = []
+        const columns = ['日期', '全部行业']
+        let count = 0
+        for (const key in data) {
+          if (key !== '全部行业') {
+            columns.push(key)
+          }
+        }
+        const industryArr = []
+        for (const key in data['全部行业']) {
+          industryArr.push(key)
+        }
+        industryArr.sort((a, b) => { return a - b })
+        industryArr.forEach((item) => {
+          const rowsItem = {
+            '日期': item + '年' // eslint-disable-line
+          }
+          for (const k in data) {
+            count += (data[k][item] * 100)
+            rowsItem[k] = data[k][item] == null ? null : (data[k][item] * 100).fixed(2)
+          }
+          rows.push(rowsItem)
+        })
+        if (count !== 0) {
+          this.savingsRate.data.columns = columns
+          this.savingsRate.data.rows = rows
+          this.savingsRate.show = true
+          this.savingsRate.flag = true
+          this.allBool.push(true)
+        } else {
+          this.savingsRate.show = false
+          this.allBool.push(false)
+        }
+      } else {
+        this.savingsRate.show = false
+        this.allBool.push(false)
+      }
+    },
+    // 格式化各行业项目规模占比数据
+    formatProjectScaleData (data) {
+      if (data && data.length > 0) {
+        const arr = []
+        // 降序排列
+        data.sort((a, b) => {
+          return b.bidamount_share - a.bidamount_share
+        })
+        data.forEach((item) => {
+          item.bidamount_share = item.bidamount_share !== null && !isNaN(item.bidamount_share) ? (item.bidamount_share * 100).fixed(2) + '%' : '--'
+          item.rate_avg = item.rate_avg !== null && !isNaN(item.rate_avg) ? (item.rate_avg * 100).fixed(2) + '%' : '--'
+          arr.push(item.scopeclassName, item.bidamount_share, item.bidamount_count, item.project_count, item.rate_avg)
+        })
+        const normal = ['行业', '采购规模占比', '采购规模', '采购项目数量', '平均节支率']
+        var newArr = this.arrTrans(5, arr)
+        newArr.unshift(normal)
+        this.projectScale.options.tooltip.formatter = (params) => {
+          var tip = ''
+          var data = params.data
+          params.marker = '<span style="display:inline-block;margin-right:5px;border-radius:8px;width:8px;height:8px;background-color:' + params.color + '"></span>'
+          var percent = '<span style="padding-left:13px;">采购规模占比:' + data[1] + '</span></br>'
+          var scale = '<span style="padding-left:13px;">采购规模:' + moneyUnit(data[2].fixed(2)) + '</span></br>'
+          var count = '<span style="padding-left:13px;">采购项目数量:' + data[3] + '个</span></br>'
+          var rate = data[4] === '--' ? '' : '<span style="padding-left:13px;">平均节支率:' + data[4] + '</span></br>'
+          tip = params.marker + params.name + '<br/>' + percent + scale + count + rate
+          return tip
+        }
+        this.projectScale.flag = true
+        this.projectScale.data = newArr
+        this.projectScale.show = true
+        this.allBool.push(true)
+      } else {
+        this.allBool.push(false)
+        this.projectScale.flag = false
+        this.projectScale.data = []
+        this.projectScale.show = false
+      }
+    },
+    // 格式化注册资本数据
+    formatCapitalData (data) {
+      if (data && data.length > 0) {
+        const columns = ['注册资本', '企业数量', '累计采购规模']
+        const rows = []
+        const capData = []
+        data.forEach((item) => {
+          /* eslint-disable */
+          rows.push({
+            '注册资本': this.formatMoneyRange(item.key),
+            '企业数量': item.ent_count,
+            '累计采购规模': (item.money_count /10000).fixed(2)
+          })
+          capData.push({
+            '注册资本': this.formatMoneyRange(item.key),
+            '企业数量': item.ent_count,
+            '累计采购规模': (item.money_count /10000).fixed(2),
+            '采购项目数量': item.project_count,
+            '平均节支率': item.rate_avg
+          })
+          /* eslint-enable */
+        })
+        this.capital.data.columns = columns
+        this.capital.data.rows = rows
+        this.capital.data.customData = capData
+        this.capital.show = true
+        this.capital.flag = true
+        this.allBool.push(true)
+      } else {
+        this.allBool.push(false)
+        this.capital.data.columns = []
+        this.capital.data.rows = []
+        this.capital.data.customData = []
+        this.capital.show = false
+        this.capital.flag = false
+      }
+    },
+    // 格式化企业年龄分布数据
+    formatAgeData (data) {
+      if (data && data.length > 0) {
+        const ageRows = []
+        const customRows = []
+        data.forEach((item) => {
+          if (item.key === '0_1') {
+            item.key = '<1'
+          }
+          if (item.key === '40') {
+            item.key = '≥40'
+          }
+          /* eslint-disable */
+          ageRows.push({
+            '企业年龄': item.key.replace('_', '-'),
+            '企业数量': item.ent_count
+          })
+          customRows.push({
+            '企业年龄': item.key.replace('_', '-'),
+            '企业数量': item.ent_count,
+            '累计采购规模': (item.money_count /10000).fixed(2),
+            '采购项目数量': item.project_count,
+            '平均节支率': item.rate_avg
+          })
+          /* eslint-enable */
+        })
+        this.age.data.rows = ageRows
+        this.age.data.customData = customRows
+        this.age.show = true
+        this.age.flag = true
+        this.allBool.push(true)
+      } else {
+        this.allBool.push(false)
+        this.age.data.rows = []
+        this.age.data.customData = []
+        this.age.show = false
+        this.age.flag = false
+      }
+    },
+    // 格式化企业注册地分布数据
+    formatAreaData (data) {
+      if (data && data.length > 0) {
+        const rows = []
+        const custom = []
+        data.forEach((item) => {
+          /* eslint-disable */
+          rows.push({
+            '企业注册地': item.area_name,
+            '企业数量': item.ent_count
+          })
+          custom.push({
+            '企业注册地': item.area_name,
+            '企业数量': item.ent_count,
+            '累计采购规模': (item.money_count / 10000).fixed(2),
+            '采购项目数量': item.project_count,
+            '平均节支率': item.rate_avg
+          })
+          /* eslint-enable */
+        })
+        this.area.data.rows = rows
+        this.area.data.customData = custom
+        this.area.show = true
+        this.area.flag = true
+        this.allBool.push(true)
+      } else {
+        this.allBool.push(false)
+        this.area.data.rows = []
+        this.area.data.customData = []
+        this.area.show = false
+        this.area.flag = false
+      }
+    },
+    // 格式化重点合作企业数据
+    formatClientData (data) {
+      if (data && data.length > 0) {
+        data.forEach((v, i) => {
+          v.topData.forEach((s, j) => {
+            s.parent = s.countMoney / v.topData[0].countMoney * 100 + '%'
+            s.lastTime = new Date(Number(s.lastTime + '000')).pattern('yyyy/MM/dd')
+          })
+        })
+        const newData = data.map((v) => {
+          v.topData = v.topData.filter((s) => {
+            return s.winnerName && s.winnerName.trim().length
+          })
+          return v
+        }).filter(function (v, i) {
+          return v.topData.length
+        })
+        this.client.data = newData
+        this.client.flag = true
+        this.client.show = true
+        this.allBool.push(true)
+      } else {
+        this.allBool.push(false)
+        this.client.data = []
+        this.client.flag = false
+        this.client.show = false
+      }
+    },
+    // 格式化重点合作代理机构数据
+    formatAgencyData (data) {
+      if (data && data.length > 0) {
+        const arr = []
+        data.forEach((v, i) => {
+          v.last_with_time = new Date(Number(v.last_with_time + '000')).pattern('yyyy/MM/dd')
+          v.parent = v.project_count / data[0].project_count * 100 + '%'
+          arr.push({
+            name: v.agency_name,
+            count: v.project_count,
+            time: v.last_with_time,
+            parent: v.parent
+          })
+        })
+        this.agency.data = arr
+        this.agency.flag = true
+        this.agency.show = true
+        this.allBool.push(true)
+      } else {
+        this.allBool.push(false)
+        this.agency.data = []
+        this.agency.flag = false
+        this.agency.show = false
+      }
+    },
+    /* ******** 公共函数部分 ******* */
+    // 求最大项目数量
+    getMaxProjectCount (analysisArr) {
+      if (!analysisArr || !$.isArray(analysisArr)) return
+      const itemMaxKey = 3 // 每一项中要比较大小的索引
+      const arr = JSON.parse(JSON.stringify(analysisArr))
+      bSort(arr, itemMaxKey)
+      const maxCount = arr[arr.length - 1][itemMaxKey]
+      let maxIndex = -1
+      analysisArr.some((item, index) => {
+        const gotIt = item[itemMaxKey] === maxCount
+        if (gotIt) maxIndex = index
+        return gotIt
+      })
+      return maxIndex
+    },
+    // 一维数组转换为二维数组
+    arrTrans (num, arr) {
+      const newArr = []
+      arr.forEach((item, index) => {
+        // 计算该元素为第几个素组内
+        const page = Math.floor(index / num)
+        // 判断是否存在
+        if (!newArr[page]) {
+          newArr[page] = []
+        }
+        newArr[page].push(item)
+      })
+      return newArr
+    },
+    // 处理金额区间转换
+    formatMoneyRange (key) {
+      if (!key) return
+      if (key.indexOf('_')) {
+        key = key.split('_')
+      } else {
+        key = key.split('-')
+      }
+      if (!key[1]) return '>' + (key[0] / 100000000).fixed(2) + '亿'
+      key[0] = key[0] >= 100000000 ? (key[0] / 100000000).fixed(2) : (key[0] / 10000).fixed(2)
+      key[1] = key[1] >= 100000000 ? (key[1] / 100000000).fixed(2) + '亿' : (key[1] / 10000).fixed(2) + '万'
+      return key[0] + '-' + key[1]
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.unit-chart{
+  padding: 32px 40px;
+  margin: 0 auto;
+  background: #fff;
+  .chart-title{
+    padding: 32px 0 16px;
+    font-size: 18px;
+    color: #1d1d1d;
+    line-height: 28px;
+    font-family: 'Microsoft YaHei, Microsoft YaHei-Regular';
+  }
+  .chart-tips{
+    padding: 0 0 32px 46px;
+    font-size: 12px;
+    color: #999999;
+    line-height: 20px;
+  }
+  .text-center{
+    text-align: center;
+  }
+}
+</style>

+ 474 - 0
src/views/customer/components/SearchList.vue

@@ -0,0 +1,474 @@
+<template>
+  <div class="ent-list">
+    <el-tabs v-model="activeName" @tab-click="handleClick">
+      <el-tab-pane label="采购单位" name="first">
+        <div class="search-result-container">
+          <div class="ent-info-list" v-loading="listState.loading">
+            <div
+              class="ent-info-item"
+              :class="{ hover: !item.showMask }"
+              v-for="item in listState.list"
+              @click="toDetail(item)"
+              :key="item.id"
+            >
+              <div class="ei-i-left">
+                <div class="ei-i-l-container" :class="item.randomBgc">
+                  {{ item.company_shortname ? item.company_shortname.slice(0,4)
+                  : item.company_name.slice(0,4) }}
+                </div>
+              </div>
+              <div class="ei-i-right">
+                <div class="ei-r-title-container flex">
+                  <div class="ei-r-title">{{ item.company_name }}</div>
+                  <div
+                    class="ei-r-tag"
+                    :class="getEntStatus(item.company_status)"
+                    v-if="item.company_status"
+                  >
+                    {{ item.company_status }}
+                  </div>
+                </div>
+                <div class="ei-r-info-container">
+                  <div class="ei-r-info-item">
+                    <div class="i-label">法定代表人:</div>
+                    <div class="i-text">
+                      {{ item.legal_person ? item.legal_person : '-' }}
+                    </div>
+                  </div>
+                  <div class="ei-r-info-item">
+                    <div class="i-label">注册资本:</div>
+                    <div class="i-text">
+                      {{ calcListItemForCap(item.capital) }}
+                    </div>
+                  </div>
+                  <div class="ei-r-info-item">
+                    <div class="i-label">成立日期:</div>
+                    <div class="i-text">
+                      {{ item.establishStamp ? new Date(item.establishStamp *
+                      1000).pattern('yyyy-MM-dd') : '-' }}
+                    </div>
+                  </div>
+                  <div class="ei-r-info-item">
+                    <div class="i-label">联系方式:</div>
+                    <div class="i-text">
+                      {{ item.company_phone ? item.company_phone : '-' }}
+                    </div>
+                  </div>
+                </div>
+                <div class="ei-r-info-container">
+                  <div class="ei-r-info-item">
+                    <div class="i-label">地址:</div>
+                    <div class="i-text">
+                      {{ item.company_address ? item.company_address : '-' }}
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+            <div class="_u4m8od8j3s"></div>
+            <!-- <no-data
+              style="display: none"
+              v-show="listState.list.length === 0 && listState.loaded"
+              tip-text="没有找到符合条件的企业"
+            ></no-data> -->
+          </div>
+        </div>
+        <div class="el-pagination-container">
+          <el-pagination
+            background
+            layout="prev, pager, next, ->"
+            :hide-on-single-page="true"
+            :current-page="listState.pageNum"
+            :page-size="listState.pageSize"
+            :total="listState.total"
+            @current-change="onPageChange"
+          ></el-pagination>
+        </div>
+      </el-tab-pane>
+      <el-tab-pane label="中标单位" name="second" disabled></el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+
+<script>
+import { Tabs, TabPane, Pagination } from 'element-ui'
+import { mapState } from 'vuex'
+import chinaMapJSON from '@/assets/js/china_area.js'
+export default {
+  name: 'ent-list',
+  props: {
+    list: {
+      type: Object,
+      default () {
+        return {}
+      }
+    }
+  },
+  components: {
+    [Tabs.name]: Tabs,
+    [TabPane.name]: TabPane,
+    [Pagination.name]: Pagination
+  },
+  data () {
+    return {
+      activeName: 'first',
+      listState: {
+        loaded: false, // 是否已经搜索过
+        loading: false,
+        pageNum: 1, // 当前页, 从0开始
+        pageSize: 5, // 每页多少条数据
+        total: 0, // 一共多少条数据
+        list: [] // 查询请求返回的数据
+      }
+    }
+  },
+  computed: {
+    ...mapState({})
+  },
+  created () {
+    this.getList()
+  },
+  mounted () {},
+  methods: {
+    getEntStatus (status) {
+      if (status === '吊销') {
+        return 'tag-danger'
+      } else if (status === '注销') {
+        return 'tag-danger'
+      } else if (status === '撤销') {
+        return 'tag-disabled'
+      } else {
+        return ''
+      }
+    },
+    calcListItemForCap (p) {
+      if (p) {
+        return p + '万元'
+      } else {
+        return '-'
+      }
+    },
+    // 随机颜色
+    randomBgc () {
+      var arr = ['default', 'blue', 'orange', 'green']
+      var randomIndex = this.getRandomNumber(0, arr.length - 1)
+      return 'bgc-' + arr[randomIndex]
+    },
+    getRandomNumber (min, max) {
+      return Math.floor(Math.random() * (max - min + 1) + min)
+    },
+    getShortName (comName) {
+      var areaMap = chinaMapJSON || []
+      var shortname = comName
+      // 1. 循环省份城市进行替换
+      areaMap.forEach(function (item) {
+        var p = item.name.replace(/[省市]/, '')
+        if (shortname.indexOf(p) !== -1) {
+          shortname = shortname.replace(item.name, '').replace(p, '')
+        }
+        item.city.forEach(function (iitem) {
+          var c = iitem.name.replace(/[省市]/, '')
+          if (shortname.indexOf(c) !== -1) {
+            shortname = shortname.replace(iitem.name, '').replace(c, '')
+          }
+          iitem.area.forEach(function (iiitem) {
+            if (shortname.indexOf(iiitem) !== -1) {
+              shortname = shortname.replace(iiitem, '')
+            }
+          })
+        })
+      })
+      var matchRes = shortname.match(/[\u4e00-\u9fa5]{4}/gm)
+      let shortName = matchRes ? matchRes[0] : shortname.slice(0, 4)
+      if (shortName.length < 4) {
+        shortName = shortName.slice(0, 4)
+      }
+      return shortName
+    },
+    getList () {
+      // this.listState.loading = true
+      // this.listState.loaded = false
+      const res = {
+        data: {
+          total: 2,
+          list: [
+            /* eslint-disable */
+            {
+              "capital": 19399093,
+              "company_address": "郑州市陇海中路106号",
+              "company_name": "中国铁路郑州局集团有限公司",
+              "company_shortname": "",
+              "company_status": "存续",
+              "establishStamp": 830102400,
+              "id": "ABCZnZaYikvNDY4EmRmcFwJJTACDjF3XFJ0KAUjKjogd3xndS8oNwkjJGBxXnEkDlxTDHQ%3D",
+              "legal_person": "孙景"
+            },
+            {
+              "capital": 878300,
+              "company_address": "郑州航空港区护航路16号兴港大厦",
+              "company_name": "郑州航空港区国有资产经营管理有限公司",
+              "company_shortname": "",
+              "company_status": "存续",
+              "establishStamp": 1368374400,
+              "id": "ABCY1xGYDIOOyw7Amd1c2JbDzIvCSFjdmNlPB4gNj0eZFZwYls4NAkrIndhXnAhOFxTDPI%3D",
+              "legal_person": "许永喜"
+            },
+            {
+              "capital": 620809.56,
+              "company_address": "河南省郑州市二七区建设东路50号",
+              "company_name": "郑州大学第一附属医院",
+              "company_shortname": "",
+              "company_status": "存续",
+              "establishStamp": 1585497600,
+              "id": "ABCY3FCYi4%2FLyk4EnN5c18sPiQZDSRjYWh%2BKSgsPyFFaGdnXCw%2BICgoMWMBVnEmDlxTDJQ%3D",
+              "legal_person": "刘章锁"
+            },
+            {
+              "capital": 600000,
+              "company_address": "郑州市中牟县商都大街399号",
+              "company_name": "郑州牟中发展投资有限公司",
+              "company_shortname": "",
+              "company_status": "存续",
+              "establishStamp": 1274803200,
+              "id": "ABCdGZJczIFKD8vRHRoZ1wwMyc4IDR0V0FgK1gvKC4gcFVzdTAxND8vJ3dhBX8vDlxTDQ8%3D",
+              "legal_person": "张伍发"
+            },
+            {
+              "capital": 377926,
+              "company_address": "郑州航空港区护航路16号兴港大厦",
+              "company_name": "郑州航空港区航程置业有限公司",
+              "company_shortname": "",
+              "company_status": "存续",
+              "establishStamp": 1323964800,
+              "id": "ABCYHYAfT1YUT07NGd6ZHIoPicCASFmdnRyKCgZIyEgY3lwYiQxND80MndXQnAhOFxTDUA%3D",
+              "legal_person": "许永喜"
+            },
+            {
+              "capital": 310000,
+              "company_address": "郑州市郑东新区龙子湖智慧岛尚贤街6号",
+              "company_name": "郑州一建集团有限公司",
+              "company_shortname": "",
+              "company_status": "存续",
+              "establishStamp": 1088524800,
+              "id": "ABCdAEBYTIFMyg4I395ZE8%2FJScCDSJmYXdlKD8nKj0wXlVkdSsqNBkaMWZhWnAsDlxTC%2BY%3D",
+              "legal_person": "段利民"
+            },
+            {
+              "capital": 266632.1,
+              "company_address": "河南省郑州市高新技术产业开发区科学大道136号",
+              "company_name": "郑州轻工业大学",
+              "company_shortname": "",
+              "company_status": "存续",
+              "establishStamp": 1596988800,
+              "id": "ABCdEdCYjxYLD84JHt4Z1wnJDNfSCNjV1J%2BKS8wODoeY35nZSMlIBkVIHRHRnIbDlxTDQg%3D",
+              "legal_person": "黄荣杰"
+            },
+            {
+              "capital": 193000,
+              "company_address": "郑州市郑东新区平安大道189号正商环湖国际17层",
+              "company_name": "郑州市建设投资集团有限公司",
+              "company_shortname": "",
+              "company_status": "存续",
+              "establishStamp": 1301414400,
+              "id": "ABCYAEBZCkvND0vAn94ZwcjIyRfDRZgYWdhKDgjKC4nZFRnTzw4NwI0MWNHQnAyKFxTC38%3D",
+              "legal_person": "秦广远"
+            },
+            {
+              "capital": 173247.137,
+              "company_address": "郑州市经济技术开发区第九大街167号",
+              "company_name": "郑州煤矿机械集团股份有限公司",
+              "company_shortname": "",
+              "company_status": "存续",
+              "establishStamp": 1036512000,
+              "id": "ABCYAFaYj0eID87Antxc1w4PjNfCjF0XFJ%2BPC8nID0eUXlkciMtNwI3J3RXAXFeHlxTDK4%3D",
+              "legal_person": "焦承尧"
+            },
+            {
+              "capital": 138325,
+              "company_address": "河南省郑州市郑东新区鹏程大道56号",
+              "company_name": "郑州铁路职业技术学院",
+              "company_shortname": "",
+              "company_status": "存续",
+              "establishStamp": 1519833600,
+              "id": "ABCYFxoYjIFAjYvNHxlcE8gMycoDRZmYVViKB4zKC8ecFFzciMtNDg4MHQBBXAbHlxTC8U%3D",
+              "legal_person": "马玉霞"
+            }
+            /* eslint-enable */
+          ]
+        }
+      }
+      this.setList(res)
+      // this.listState.loading = false
+      // this.listState.loaded = true
+    },
+    setList (res) {
+      if (res.data) {
+        if (res.data.total) {
+          this.listState.total = res.data.total
+        }
+        if (res.data.list) {
+          res.data.list.forEach((d) => {
+            d.company_shortname = this.getShortName(d.company_name)
+            d.randomBgc = this.randomBgc()
+          })
+          this.listState.list = res.data.list || []
+        }
+      } else {
+        this.listState.total = 0
+        this.listState.list = []
+      }
+    },
+    toDetail (item) {
+      console.log(item)
+      const data = JSON.stringify(item)
+      const routeUrl = this.$router.resolve({
+        path: `/free/custom_unit_portrayal/${item.company_name}`,
+        query: {
+          info: data
+        }
+      })
+      return window.open(routeUrl.href, '_blank')
+    },
+    handleClick (tab, event) {
+      console.log(tab, event)
+    },
+    onPageChange (p) {
+      this.listState.pageNum = p
+      this.getList()
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.ent-list {
+  padding: 40px 0 80px;
+  .ent-info-list {
+    min-height: 400px;
+    .flex{
+      display: flex;
+      align-items: center;
+    }
+    .ent-info-item {
+      position: relative;
+      padding: 18px 16px;
+      display: flex;
+      border-bottom: 1px solid rgba(0, 0, 0, 0.05);
+      cursor: pointer;
+    }
+    .ent-info-item.hover:hover {
+      background-color: #f5f6f7;
+      box-shadow: inset 0 -1px 0 0 rgb(0, 0, 0, 0.05);
+    }
+    .ent-info-item{
+      .ei-i-l-container {
+        padding: 8px 12px;
+        height: 60px;
+        width: 60px;
+        color: #fff;
+        font-size: 18px;
+        line-height: 22px;
+        overflow: hidden;
+        border-radius: 5px;
+      }
+      .ei-i-l-container.bgc-default {
+        background-color: #2cb7ca;
+      }
+      .ei-i-l-container.bgc-blue {
+        background-color: #f5af5c;
+      }
+      .ei-i-l-container.bgc-orange {
+        background-color: #58a1e7;
+      }
+      .ei-i-l-container.bgc-green {
+        background-color: #51cea2;
+      }
+      .ei-i-l-container > img {
+        display: block;
+        width: 100%;
+        height: 100%;
+      }
+      .ei-i-right {
+        margin-left: 32px;
+      }
+      .ei-r-info-container {
+        margin-top: 12px;
+        display: flex;
+        align-items: center;
+        font-size: 14px;
+        line-height: 22px;
+      }
+      .ei-r-info-item {
+        display: flex;
+        .i-label {
+          color: #a0a0a0;
+        }
+        .i-text {
+          color: #7d7d7d;
+        }
+      }
+      .ei-r-info-item:not(:last-of-type) {
+        margin-right: 32px;
+      }
+      .ei-r-title {
+        margin-right: 12px;
+        color: #1d1d1d;
+        font-size: 18px;
+      }
+      .ei-r-tag {
+        padding: 4px 8px;
+        color: #2cb7ca;
+        font-size: 12px;
+        text-align: center;
+        border: 1px solid #2cb7ca;
+        background-color: rgba(44, 183, 202, 0.08);
+        border-radius: 5px;
+      }
+      .ei-r-tag.tag-danger {
+        color: #ff3a20;
+        border: 1px solid #ff3a20;
+        background-color: rgba(255, 58, 32, 0.08);
+      }
+      .ei-r-tag.tag-warning {
+        color: #ff9f40;
+        border: 1px solid #ff9f40;
+        background: rgba(255, 159, 64, 0.08);
+        background-color: transparent;
+      }
+      .ei-r-tag.tag-disabled {
+        color: #aaa;
+        border: 1px solid #aaa;
+      }
+    }
+  }
+  ::v-deep {
+    .el-tabs__nav-wrap::after {
+      height: 0;
+    }
+    .el-tabs__nav-scroll {
+      border: 1px solid #ebebeb;
+    }
+    .el-tabs__item {
+      padding: 0 16px !important;
+    }
+    .el-tabs__item:hover {
+      color: #2cb7ca;
+    }
+    .el-tabs__item.is-active {
+      color: #2cb7ca;
+    }
+    .el-tabs__active-bar {
+      background-color: #2cb7ca;
+    }
+    .el-tabs__item.is-disabled {
+      color: #c0c4cc;
+      cursor: default;
+    }
+    .el-tabs__header {
+      margin: 0;
+    }
+    .el-tabs__content {
+    }
+  }
+}
+</style>

+ 1 - 2
src/views/portrayal/EntSearchPortrayal.vue

@@ -85,8 +85,7 @@ import Empty from '@/components/common/Empty'
 import { mapState } from 'vuex'
 import { Tabs, TabPane } from 'element-ui'
 import { moneyUnit, dateFormatter } from '@/utils'
-import { getEntSearchPower, getSvipNewMsg, getUsage, getNewMsg, getsubVipPortraitSelect, getUserPower, getSvipMsgSelects } from '@/api/modules'
-import { getSubVipEntChart } from '../../api/modules'
+import { getEntSearchPower, getSvipNewMsg, getUsage, getNewMsg, getsubVipPortraitSelect, getUserPower, getSvipMsgSelects, getSubVipEntChart } from '@/api/modules'
 
 function getImgForVipUpgrade (name, bg = false, suffix = '.png') {
   return require('@/assets/images/vip/' + (bg ? 'bg/mask/' : '') + name + suffix)

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

@@ -250,7 +250,7 @@ export default {
       })
     },
     toPolicy () {
-      const { sid, fid } = this
+      const { sid } = this
       this.$router.push(`/analysis_result?sid=${sid}`)
     },
     toUnitportrayal () {

+ 2 - 1
src/views/public/Buy.vue

@@ -81,7 +81,7 @@ import {
   getUserAccountInfo,
   getUserPower
 } from '@/api/modules/'
-
+/* eslint-disable */
 export default {
   name: 'vip-subscribe-buy',
   components: {
@@ -441,6 +441,7 @@ export default {
     }
   }
 }
+/* eslint-enable */
 </script>
 
 <style lang="scss" scoped>

+ 1 - 1
src/views/subscribe/components/key/SubConfig.vue

@@ -162,7 +162,7 @@ export default {
     },
     'datas.buyClassArr' (newVal) {
       this.buyerData = newVal
-    },
+    }
   },
   mounted () {},
   methods: {