Browse Source

feat: 投标决策分析

yangfeng 4 năm trước cách đây
mục cha
commit
cffd288c13

+ 52 - 0
src/api/modules/analysis.js

@@ -0,0 +1,52 @@
+import request from '@/api'
+import qs from 'qs'
+
+// 获取是否关注
+export function getFollowInfo (data) {
+  data = qs.stringify(data)
+  return request({
+    url: '/follow/project/check',
+    method: 'post',
+    data
+  })
+}
+
+// 关注项目
+export function addFollow (data) {
+  data = qs.stringify(data)
+  return request({
+    url: '/follow/project/add',
+    method: 'post',
+    data
+  })
+}
+
+// 取消关注
+export function cancelFollow (data) {
+  data = qs.stringify(data)
+  return request({
+    url: '/follow/project/cancel',
+    method: 'post',
+    data
+  })
+}
+
+// 获取项目基本信息(同跟筛选条件)
+export function getProjectInfo (data) {
+  data = qs.stringify(data)
+  return request({
+    url: '/analysis/projectInfo',
+    method: 'post',
+    data
+  })
+}
+
+// 获取投标决策分析结果
+export function getAnalysisResult (data) {
+  // data = qs.stringify(data)
+  return request({
+    url: '/decision/decInfo',
+    method: 'post',
+    data
+  })
+}

+ 1 - 0
src/api/modules/index.js

@@ -3,3 +3,4 @@ export * from './user'
 export * from './chart'
 export * from './report'
 export * from './forecast'
+export * from './analysis'

+ 12 - 12
src/components/chart/AgencyChart.vue → src/components/chart/BlueProgressChart.vue

@@ -3,15 +3,16 @@
     <div class="client-list">
       <div class="c-thead">
           <strong class="c-name"></strong>
-          <span class="c-count">项目数量</span>
-          <span class="c-time">最近合作日期</span>
+          <span class="c-count" v-if="from == 'unit'">项目数量</span>
+          <span class="c-time" v-if="from == 'unit'">最近合作日期</span>
+          <span class="c-time text-right" v-if="from == 'result'">参评项目数量(个)</span>
         </div>
         <div class="progress-bar-container">
           <div class="progress-bar-item" v-for="(item,index) in datas" :key="index">
             <div class="item-label">
-              <span class="ellipsis-2 item-name">{{item.agency_name}}</span>
-              <span class="item-count">{{item.project_count}}个</span>
-              <span class="item-time">{{item.last_with_time}}</span>
+              <span class="item-name">{{item.name}}</span>
+              <span class="item-count" :class="from == 'result'? 'text-right' : ''">{{item.count}}个</span>
+              <span class="item-time" v-if="from == 'unit'">{{item.time}}</span>
             </div>
             <div class="item-progress">
               <span class="item-progress-count active-progress" :style="{width: item.parent}"></span>
@@ -25,6 +26,7 @@
 export default {
   name: 'progess-chart',
   props: {
+    from: String,
     // 传入的数据
     datas: Array
   },
@@ -33,9 +35,7 @@ export default {
   },
   computed: {},
   watch: {},
-  mounted () {
-    console.log(this.datas)
-  },
+  mounted () {},
   methods: {}
 }
 </script>
@@ -53,9 +53,6 @@ export default {
     color: #1D1D1D;
     flex: 7;
   }
-  .item-name{
-    cursor: pointer;
-  }
   .c-count,.item-count,.c-time,.item-time{
     flex: 1;
     min-width: 100px;
@@ -84,7 +81,7 @@ export default {
     display: flex;
     flex-direction: column;
     justify-content: space-around;
-    margin-bottom: 14px;
+    padding: 8px 0 16px;
   }
   .item-label {
     display: flex;
@@ -128,5 +125,8 @@ export default {
   .active-progress{
     background: linear-gradient(270deg, #2ABED1 0.81%, #8DE0EB 100%);
   }
+  .text-right{
+    text-align: right;
+  }
 }
 </style>

+ 205 - 0
src/components/chart/ColumnBarChart.vue

@@ -0,0 +1,205 @@
+<template>
+  <ve-histogram
+    :height="options.height"
+    :colors="options.colors"
+    :data="datas"
+    :mark-point="barChartMarkPoint"
+    :settings="options.settings"
+    :after-config="options.config"
+    :extend="defaultOptions"
+    @ready="options.onReady"
+    >
+  </ve-histogram>
+</template>
+<script>
+export default {
+  name: 'chart',
+  props: {
+    datas: Object,
+    options: {
+      height: String,
+      colors: Array || Object,
+      settings: Object,
+      config: Function,
+      onReady: Function
+    }
+  },
+  data () {
+    return {
+      barChartMarkPoint: {
+        symbol: 'circle',
+        symbolOffset: [0, 0],
+        itemStyle: {
+          borderColor: '#fff',
+          color: '#FB483D'
+        },
+        symbolSize: 8,
+        label: {
+          show: true,
+          position: 'bottom',
+          fontSize: 12,
+          padding: [-6, 0],
+          offset: [0, 7],
+          formatter: (val) => {
+            return val.value + '天'
+          }
+        }
+      },
+      defaultOptions: {
+        color: ['#05A6F3'],
+        yAxis: {
+          axisLabel: {
+            fontSize: 12,
+            margin: 4
+          },
+          splitLine: {
+            lineStyle: {
+              type: 'dashed',
+              width: 0.5
+            }
+          },
+          nameGap: 20,
+          nameTextStyle: {
+            fontSize: 12,
+            align: 'left',
+            padding: [0, 0, 0, -20]
+          }
+        },
+        xAxis: {
+          min: 0,
+          axisLabel: {
+            showMinLabel: true,
+            showMaxLabel: true,
+            textStyle: {
+              color: '#626262',
+              fontSize: 12
+            },
+            formatter: (val, index) => {
+              if (val.indexOf('天') > -1) {
+                val = val.replace('天', '').split('-')[1]
+              }
+              return val
+            }
+          },
+          axisTick: {
+            interval: 0
+          },
+          nameGap: 20,
+          nameLocation: 'end',
+          nameTextStyle: {
+            fontSize: 10,
+            align: 'right',
+            padding: [80, 20, 0, 0],
+            color: '#9B9CA3'
+          }
+        },
+        series: [
+          {
+            type: 'bar',
+            name: '类似项目标书编制周期',
+            barWidth: 10,
+            barMaxWidth: 10,
+            itemStyle: {
+              color: '#05A6F3'
+            }
+          }
+        ],
+        graphic: [
+          {
+            type: 'group',
+            bottom: 10,
+            left: 32,
+            children: [{
+              type: 'circle',
+              z: 100,
+              top: 'middle',
+              style: {
+                fill: '#FB483D'
+              },
+              shape: {
+                cx: 0,
+                cy: 0,
+                r: 4
+              }
+            },
+            {
+              type: 'text',
+              z: 100,
+              top: 'middle',
+              style: {
+                fill: '#333',
+                text: '当前项目标书编制周期',
+                font: '12px Microsoft YaHei',
+                x: 8
+              }
+            }
+            ]
+          },
+          {
+            type: 'group',
+            bottom: 10,
+            right: 20,
+            children: [{
+              type: 'circle',
+              z: 100,
+              top: 'middle',
+              style: {
+                fill: '#3399FF'
+              },
+              shape: {
+                cx: 0,
+                cy: 0,
+                r: 4
+              }
+            },
+            {
+              type: 'text',
+              z: 100,
+              top: 'middle',
+              style: {
+                fill: '#333',
+                text: '类似项目标书编制周期',
+                font: '12px Microsoft YaHei',
+                x: 8
+              }
+            }
+            ]
+          }
+        ],
+        legend: {
+          show: false
+        },
+        tooltip: {
+          backgroundColor: '#fff',
+          confine: true,
+          textStyle: {
+            color: '#171826',
+            fontSize: 12
+          },
+          padding: [7, 12],
+          extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
+          borderWidth: 2,
+          borderColor: '#F5F6F7',
+          formatter: (params) => {
+            let tip = ''
+            for (var i = 0; i < params.length; i++) {
+              params[i].value === undefined ? params[i].value = 0 : params[i].value // eslint-disable-line
+              if (params[i].seriesName === '项目数量') {
+                tip = tip + '编制周期:' + params[i].name + '<br/>' + params[i].seriesName + ':' + params[i].value + '个' + '<br/>'
+              }
+            }
+            return tip
+          }
+        }
+      }
+    }
+  },
+  computed: {},
+  watch: {},
+  mounted () {},
+  methods: {},
+  beforeDestroy () {}
+}
+</script>
+<style lang="scss" scoped>
+</style>

+ 101 - 118
src/components/chart/HotChart.vue

@@ -1,22 +1,31 @@
 <template>
-  <div class="hot-chart" :style="{'height': height}"></div>
+  <div class="hot-chart" :style="{'height': heatHeight}"></div>
 </template>
 <script>
-// import { merge } from 'lodash'
-import { bSort, moneyUnit } from '@/utils/'
+import { bSort } from '@/utils/'
 export default {
   name: 'hot-chart',
   props: {
     datas: {
       type: Array,
       default: () => ({})
+    },
+    cycle: {
+      type: Number,
+      required: false,
+      default: 0
+    },
+    options: {
+      type: Object,
+      required: false,
+      default: () => ({})
     }
   },
   data () {
     return {
       myChart: null,
-      minusRows: 0,
-      height: null,
+      minusRows: null,
+      height: '500px',
       defaultOptions: {
         tooltip: {
           backgroundColor: '#fff',
@@ -174,31 +183,31 @@ export default {
           {
             type: 'group',
             bottom: 0,
-            right: 50
-            // children: [{
-            //   type: 'circle',
-            //   z: 100,
-            //   top: 'middle',
-            //   style: {
-            //     fill: '#2ABED1'
-            //   },
-            //   shape: {
-            //     cx: 0,
-            //     cy: 0,
-            //     r: 4
-            //   }
-            // },
-            // {
-            //   type: 'text',
-            //   z: 100,
-            //   top: 'middle',
-            //   style: {
-            //     fill: '#333',
-            //     text: '当前项目预算所在区间',
-            //     font: '12px Microsoft YaHei',
-            //     x: 12
-            //   }
-            // }]
+            right: 50,
+            children: [{
+              type: 'circle',
+              z: 100,
+              top: 'middle',
+              style: {
+                fill: '#2ABED1'
+              },
+              shape: {
+                cx: 0,
+                cy: 0,
+                r: 4
+              }
+            },
+            {
+              type: 'text',
+              z: 100,
+              top: 'middle',
+              style: {
+                fill: '#333',
+                text: '当前项目预算所在区间',
+                font: '12px Microsoft YaHei',
+                x: 12
+              }
+            }]
           }
         ],
         visualMap: [{
@@ -243,9 +252,7 @@ export default {
           zlevel: 2,
           tooltip: {
             confine: true,
-            formatter: (params) => {
-              return params
-            }
+            formatter: this.options.tooltip.formatter
           }
         }, {
           name: '当前项目预算所在区间',
@@ -271,6 +278,7 @@ export default {
           zlevel: 3,
           symbol: 'circle',
           symbolSize: 8,
+          data: [],
           tooltip: {
             confine: true,
             formatter: (params) => {
@@ -281,19 +289,23 @@ export default {
       }
     }
   },
-  computed: {},
+  computed: {
+    heatHeight () {
+      if (!this.minusRows) return
+      return 500 - 48 * this.minusRows + 'px'
+    }
+  },
   watch: {
     // 监听父组件传入数据, 有变化则重新渲染图表实例
     // datas: {
     //   handler (newVal, oldVal) {
-    //     console.log(newVal)
     //     this.updateChartView()
     //   },
     //   deep: true
     // },
     minusRows: {
       handler (newVal, oldVal) {
-        // this.height = 500 - 48 * newVal + 'px'
+        this.minusRows = newVal
         this.myChart.resize()
       },
       deep: true
@@ -301,19 +313,16 @@ export default {
   },
   created () {},
   mounted () {
-    this.formatHotChartData(this.datas)
     this.updateChartView()
   },
   methods: {
     updateChartView () {
       this.myChart = this.$echarts.init(this.$el)
       if (!this.myChart) return
-      this.myChart.getDom().style.height = this.height
-      this.formatHotChartData(this.datas)
       this.formatHotOptions()
       this.myChart.setOption(this.defaultOptions)
       window.addEventListener('resize', () => {
-        this.myChart.resize()
+        // this.myChart.resize()
       })
     },
     rectGroup (left, color) {
@@ -332,15 +341,39 @@ export default {
       }
     },
     formatHotOptions () {
+      const data = this.datas
       const options = this.defaultOptions
-      // const yAxis = options.yAxis
+      const yAxis = options.yAxis
       const series = options.series
       const visualMap = options.visualMap
       const graphic = options.graphic
+      let waitDelCount = 0
+      for (var i = 9; i > -1; i--) {
+        var nowArr = data.slice(i * 10, (i + 1) * 10)
+        var nowDelStatus = nowArr.filter((v) => { return v[3] > 0 })
+        if (nowDelStatus.length > 0) {
+          break
+        } else {
+          waitDelCount++
+          data.splice(i * 10, 10)
+          yAxis[0].data.splice(0, 1)
+          yAxis[1].data.splice(0, 1)
+        }
+      }
+      data.map(v => {
+        v[1] = v[1] - waitDelCount
+        return v
+      })
+      this.minusRows = waitDelCount
+      console.log(waitDelCount, '减掉几行')
+      this.myChart.getDom().style.height = 500 - 48 * waitDelCount + 'px'
+      series[0].data = data
+      series[1].data = this.cycle && this.cycle !== 0 ? [this.getCoordinateInfo(data, this.cycle)] : []
+      // console.log(series[1].data)
       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' },
@@ -350,43 +383,12 @@ export default {
         { min: pj * 3, max: pj * 4, color: '#F48A5D', symbol: 'rect' },
         { min: pj * 4, color: '#F06326', symbol: 'rect' }
       ]
-      series[0].tooltip.formatter = (params) => {
-        const data = params.value[4]
-        const newRange = data.split('-')
-        let sRange = moneyUnit(newRange[0])
-        let mRange = moneyUnit(newRange[1])
-        let totalRange
-        if (sRange === '10000元') {
-          sRange = '1万元'
-        }
-        if (mRange === '10000元') {
-          mRange = '1万元'
-        }
-        if (sRange === '10000万元') {
-          sRange = '1亿元'
-        }
-        if (mRange === '10000万元') {
-          mRange = '1亿元'
-        }
-        if (sRange === '100亿元') {
-          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
-      }
       series.pop()
       graphic.pop()
       let index
       const myChart = this.myChart
       this.$nextTick(() => {
         setTimeout(() => {
-          // 默认展示某一个tooltip
           myChart.dispatchAction({
             type: 'highlight',
             seriesIndex: 0,
@@ -415,40 +417,6 @@ export default {
         })
       })
     },
-    formatHotChartData (arr) {
-      if (!arr) return
-      const options = this.defaultOptions
-      const yAxis = options.yAxis
-      const series = options.series
-      let data = []
-      let waitDelCount = 0
-      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]
-      })
-      for (let i = 9; i > -1; i--) {
-        const nowArr = data.slice(i * 10, (i + 1) * 10)
-        const nowDelStatus = nowArr.filter((v) => { return v[3] > 0 })
-        if (nowDelStatus.length > 0) {
-          break
-        } else {
-          waitDelCount++
-          data.splice(i * 10, 10)
-          yAxis[0].data.splice(0, 1)
-          yAxis[1].data.splice(0, 1)
-        }
-      }
-      data.map(v => {
-        v[1] = v[1] - waitDelCount
-        return v
-      })
-      console.log(waitDelCount, '减掉几行')
-      this.minusRows = waitDelCount
-      this.height = 500 - 48 * waitDelCount + 'px'
-      series[0].data = data
-    },
     // 求最大项目数量
     getMaxProjectCount (analysisArr) {
       if (!analysisArr || !$.isArray(analysisArr)) return
@@ -464,19 +432,34 @@ export default {
       })
       return maxIndex
     },
-    // 一维数组转换为二维数组
-    arrTrans (num, arr) {
-      const newArr = []
-      arr.forEach((item, index) => {
-        // 计算该元素为第几个素组内
-        const page = Math.floor(index / num)
-        // 判断是否存在
-        if (!newArr[page]) {
-          newArr[page] = []
+    getCoordinateInfo (analysisArr, cMoney) {
+      if (!analysisArr || !$.isArray(analysisArr)) return
+      if (!cMoney) cMoney = 0
+      var arr = JSON.parse(JSON.stringify(analysisArr))
+      var itemKey = 4
+      var uM = cMoney / 10000
+      var cIndex = -1
+      arr.some((item, index) => {
+        // 获取区间信息
+        var minMaxString = item[itemKey]
+        var level = '万'
+        if (/亿/g.test(minMaxString)) {
+          level = '亿'
         }
-        newArr[page].push(item)
+        var minMaxArr = minMaxString.split('-').map((t) => {
+          if (level === '亿') {
+            return t.replace(/(万|亿|元)/g, '') * 10000
+          } else {
+            return t.replace(/(万|亿|元)/g, '') * 1
+          }
+        })
+        var gotIt = minMaxArr[0] <= uM && minMaxArr[1] > uM
+        if (gotIt) {
+          cIndex = index
+        }
+        return gotIt
       })
-      return newArr
+      return analysisArr[cIndex]
     }
   },
   beforeDestroy () {

+ 4 - 6
src/components/chart/MapChart.vue

@@ -92,7 +92,7 @@ export default {
         graphic: [
           {
             type: 'group',
-            bottom: 40,
+            bottom: 42,
             children: [
               {
                 type: 'text',
@@ -110,7 +110,7 @@ export default {
             type: 'rect',
             z: 101,
             left: 0,
-            bottom: 14,
+            bottom: 16,
             shape: {
               width: 150,
               height: 24
@@ -169,9 +169,7 @@ export default {
   },
   computed: {},
   watch: {},
-  mounted () {
-    console.log(this.datas)
-  },
+  mounted () {},
   methods: {
     extend (chart) {
       chart.setOption({
@@ -190,7 +188,7 @@ export default {
         type: 'rect',
         z: 90,
         left: left,
-        bottom: 14,
+        bottom: 16,
         shape: {
           width: 25,
           height: 24

+ 3 - 2
src/components/chart/PieChart.vue

@@ -12,6 +12,7 @@ export default {
     // 传入的配置
     options: {
       type: Object,
+      required: false,
       default: () => ({})
     }
   },
@@ -60,8 +61,8 @@ export default {
           padding: [7, 12],
           extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
           borderWidth: 2,
-          borderColor: '#F5F6F7'
-          // formatter: this.options.tooltip.formatter
+          borderColor: '#F5F6F7',
+          formatter: this.options.tooltip.formatter
         },
         series: {
           name: '半径模式',

+ 6 - 0
src/router.js

@@ -86,6 +86,12 @@ export default new Router({
       path: '/entportrayal',
       name: 'entportrayal',
       component: () => import('@/views/portrayal/EntPortrayal.vue')
+    },
+    // 投标决策分析结果页
+    {
+      path: '/analysis/result',
+      name: 'analysisResult',
+      component: () => import('@/views/bid-policy/AnalysisResult.vue')
     }
   ],
   scrollBehavior (to, from, savedPosition) {

+ 160 - 0
src/views/bid-policy/AnalysisResult.vue

@@ -0,0 +1,160 @@
+<template>
+  <div class="analysis-result">
+    <div class="filter">筛选条件部分</div>
+    <div class="digest">项目摘要部分</div>
+    <div class="result">
+      <el-tabs v-model="activeName" @tab-click="handleClick">
+        <el-tab-pane label="类似项目分析" name="1">
+          <div class="tab-item">
+            类似项目分析
+          </div>
+        </el-tab-pane>
+        <el-tab-pane label="类似项目明细" name="2">
+          <div class="tab-item">
+            <analysis-chart v-if="flag.charts" :active="activeName" :datas="propAnalysis" :info="baseInfo"></analysis-chart>
+          </div>
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+  </div>
+</template>
+<script>
+import AnalysisChart from '../portrayal/components/AnalysisChart'
+import { Tabs, TabPane } from 'element-ui'
+// 该页面需要调用的接口
+import { getFollowInfo, addFollow, cancelFollow, getProjectInfo, getAnalysisResult } from '@/api/modules/' // eslint-disable-line
+export default {
+  name: 'analysis-result',
+  components: {
+    [Tabs.name]: Tabs,
+    [TabPane.name]: TabPane,
+    AnalysisChart
+  },
+  data () {
+    return {
+      activeName: '1',
+      baseInfo: {}, // 项目摘要及类似项目分析基础数据(渲染页面及需传给子组件使用)
+      // 类似项目明细数据 传子组件的数据
+      propsDetails: [],
+      // 类似项目分析数据 传子组件的数据
+      propAnalysis: {},
+      // 开关 获取到数据再传给子组件,不加开关会将默认数据传给子组件
+      flag: {
+        charts: false,
+        details: false
+      }
+    }
+  },
+  computed: {},
+  created () {
+    this.getBaseInfo()
+    this.getResult()
+  },
+  mounted () {},
+  methods: {
+    handleClick () {
+      console.log(this.activeName)
+    },
+    // 获取项目基本信息
+    async getBaseInfo () {
+      const data = {
+        ptid: 'ABCY2FdcC4vIyM7NFV2dXJaJCQCTBFgV3NiKDg7LyEdfFZzcytUCiE%3D',
+        sourceinfoid: 'ABCY2EFYy4eAjg7JFphcHUJJzACHj1mZnB%2FKSg0PC9Fa3xwTwFUCVk%3D',
+        D: 'detail'
+      }
+      const res = await getProjectInfo(data)
+      if (res.error_code === 0 && res.data) {
+        if (res.data.s_subscopeclass) {
+          if (res.data.s_subscopeclass.indexOf('_') > -1) {
+            res.data.s_subscopeclass = res.data.s_subscopeclass.substring(0, res.data.s_subscopeclass.indexOf('_'))
+          }
+        }
+        this.baseInfo = res.data
+      } else {
+        console.log(res.error_code)
+      }
+    },
+    // 获取分析结果
+    async getResult () {
+      const data = {
+        appVersion: '',
+        area: {},
+        buyer: '河南省人民医院',
+        buyerClass: [],
+        buyerContent: [{ key: ['医药'], appendkey: [], notkey: [] }, { key: ['器械'], appendkey: [], notkey: [] }, { key: ['办公'], appendkey: [], notkey: [] }, { key: ['绿化'], appendkey: [], notkey: [] }, { key: ['器材'], appendkey: [], notkey: [] }, { key: ['设备'], appendkey: [], notkey: [] }],
+        industry: '',
+        maxPrice: '',
+        minPrice: '',
+        mobileModel: '',
+        pid: 'ABCY2FdcC4vIyM7NFV2dXJaJCQCTBFgV3NiKDg7LyEdfFZzcytUCiE%3D',
+        pname: '河南省人民医院',
+        sid: 'ABCY2EFYy4eAjg7JFphcHUJJzACHj1mZnB%2FKSg0PC9Fa3xwTwFUCVk%3D'
+      }
+      const res = await getAnalysisResult(data)
+      if (res.error_code === 0) {
+        if (res.data.status === -2) {
+          console.log('不展示')
+          this.showDetails = false
+          this.showChart = false
+        }
+        // 类似项目明细数据
+        if (res.data.PDeatils) {
+          this.propsDetails = res.data.PDeatils
+        } else {
+          this.showDetails = false
+        }
+        // 类似项目分析
+        if (res.data.PAnalysis && Object.keys(res.data.PAnalysis).length > 0) {
+          this.propAnalysis = res.data.PAnalysis
+          this.flag.charts = true
+        } else {
+          this.showChart = false
+        }
+      }
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.analysis-result{
+  width: 1200px;
+  margin: 32px auto;
+  .filter{
+    padding: 32px 40px;
+    background: #fff;
+  }
+  .digest{
+    margin-top: 8px;
+    padding: 24px 40px 32px;
+    background: #fff;
+  }
+  .result{
+    margin-top: 20px;
+    background: #fff;
+    ::v-deep.el-tabs__header{
+      margin: 0;
+    }
+    ::v-deep.el-tabs__item{
+      padding: 0 20px;
+      height: 48px;
+      line-height: 48px;
+    }
+    ::v-deep.el-tabs__item.is-active,::v-deep.el-tabs__item:hover{
+      color: #2CB7CA;
+    }
+    ::v-deep.el-tabs__active-bar{
+      background-color: #2CB7CA;
+    }
+    ::v-deep.el-tabs__nav-wrap::after{
+      height: 1px;
+      background-color: #ECECEC;
+    }
+    ::v-deep.el-tabs__content{
+      padding: 0 40px 32px;
+    }
+    .tab-item{
+      padding: 16px 0;
+    }
+  }
+}
+</style>

+ 0 - 24
src/views/portrayal/AnalysisChart.vue

@@ -1,24 +0,0 @@
-<template>
-  <div class="analysis-chart">
-    <!-- 年度项目统计 -->
-    <!-- 月度中标金额统计 -->
-    <!-- 市场区域分布 -->
-    <!-- 各类客户平均折扣率 -->
-    <!-- 客户类型分布 -->
-    <!-- 重点客户 -->
-  </div>
-</template>
-<script>
-export default {
-  name: 'analysis-chart',
-  components: {},
-  data () {
-    return {}
-  },
-  computed: {},
-  mounted () {},
-  methods: {}
-}
-</script>
-<style lang="scss" scoped>
-</style>

+ 5 - 1
src/views/portrayal/EntPortrayal.vue

@@ -6,7 +6,11 @@
     </div>
     <div class="ent-content">
       <el-tabs v-model="activeName" @tab-click="handleClick">
-        <el-tab-pane label="企业信息" name="1">用户管理</el-tab-pane>
+        <el-tab-pane label="企业信息" name="1">
+          <div style="padding-top:32px;">
+            企业信息
+          </div>
+        </el-tab-pane>
         <el-tab-pane label="中标信息" name="2">
           <ent-chart :active="activeName" v-on:entInfo="getEntInfo"></ent-chart>
         </el-tab-pane>

+ 422 - 0
src/views/portrayal/components/AnalysisChart.vue

@@ -0,0 +1,422 @@
+<template>
+  <div class="analysis-chart">
+    <!-- 类似项目标书编制周期分布 -->
+    <div v-if="bidCycle.show">
+      <div class="chart-title">类似项目标书编制周期分布</div>
+      <div class="chart-main">
+        <column-bar-chart :options="bidCycle.options" :datas="bidCycle.data" :onReady="bidCycle.onReady"></column-bar-chart>
+        <div class="chart-tips">注:标书编制周期是指招标文件发放之日至投标截止时间(开标)之间的时间间隔,标书编制周期越长,准备时间越充分。</div>
+      </div>
+    </div>
+    <!-- 类似项目预算分布 -->
+    <div v-if="budget.show">
+      <div class="chart-title">类似项目预算分布</div>
+      <div class="chart-main">
+        <hot-chart :datas="budget.data" :cycle="info.budget" :options="budget.options"></hot-chart>
+        <div class="chart-tips">注:少数缺失的项目预算,用中标金额补充;平均折扣率=(全部项目预算-全部中标金额)/全部项目预算,仅统计预算和中标金额同时存在的项目。</div>
+      </div>
+    </div>
+    <!-- 类似项目区域分布 -->
+    <div v-if="area.show">
+      <div class="chart-title">类似项目区域分布</div>
+      <div class="chart-main">
+        <map-chart :datas="area.data" :options="area.options"></map-chart>
+      </div>
+    </div>
+    <!-- 类似项目采购单位类型分布 -->
+    <div v-if="buyclass.show">
+      <div class="chart-title">类似项目采购单位类型分布</div>
+      <pie-chart :height="'328px'" :options="buyclass.options" :datas="buyclass.data"></pie-chart>
+      <div class="chart-tips">注:各采购单位类型占比以采购规模来计算,最多展示占比排名前十的采购单位类型。</div>
+    </div>
+    <!-- 类似项目热点中标企业 -->
+    <div v-if="hotWin.show">
+      <div class="chart-title">类似项目热点中标企业</div>
+      <hot-win-list v-if="hotWin.flag" :datas="hotWin.data"></hot-win-list>
+    </div>
+    <!-- 类似项目评标专家 -->
+    <div v-if="expert.show">
+      <div class="chart-title">类似项目评标专家</div>
+      <blue-progress-chart v-if="expert.flag" from="result" :datas="expert.data"></blue-progress-chart>
+    </div>
+  </div>
+</template>
+<script>
+import ColumnBarChart from '@/components/chart/ColumnBarChart'
+import HotChart from '@/components/chart/HotChart'
+import MapChart from '@/components/chart/MapChart'
+import PieChart from '@/components/chart/PieChart'
+import HotWinList from './AnalysisList'
+import BlueProgressChart from '@/components/chart/BlueProgressChart'
+import { moneyUnit } from '@/utils/'
+export default {
+  name: 'analysis-chart',
+  props: ['active', 'datas', 'info'],
+  components: {
+    ColumnBarChart,
+    HotChart,
+    MapChart,
+    PieChart,
+    HotWinList,
+    BlueProgressChart
+  },
+  data () {
+    return {
+      // 类似项目标书编制周期分布
+      bidCycle: {
+        show: false,
+        data: {
+          columns: ['编制周期', '项目数量'],
+          rows: []
+        },
+        options: {
+          height: '320px',
+          colors: ['#05A6F3'],
+          setting: {
+            xAxisName: ['标书编制周期'],
+            yAxisName: ['类似项目数量(个)']
+          },
+          config: this.bidCycleConfig,
+          onReady: this.onBarReady
+        }
+      },
+      // 类似项目预算分布
+      budget: {
+        show: false,
+        flag: false,
+        data: [],
+        options: {
+          tooltip: {
+            formatter: this.budgetConfig
+          }
+        }
+      },
+      // 类似项目区域分布
+      area: {
+        show: false,
+        data: {
+          columns: ['省份', '类似项目数量', '类似项目规模'],
+          rows: []
+        },
+        options: {
+          height: '570px',
+          colors: ['#05a6f3'],
+          config: this.areaConfig
+        }
+      },
+      // 类似项目采购单位类型
+      buyclass: {
+        show: false,
+        data: [],
+        options: {
+          tooltip: {
+            formatter: this.buyClassConfig
+          }
+        }
+      },
+      // 类似项目热点中标企业
+      hotWin: {
+        show: false,
+        flag: false,
+        data: []
+      },
+      // 类似项目评标专家
+      expert: {
+        show: false,
+        flag: false,
+        data: []
+      }
+    }
+  },
+  watch: {
+    active: {
+      handler (newVal) {
+        if (newVal === '2') {
+          this.initChartData()
+        }
+      },
+      deep: true
+    }
+  },
+  computed: {},
+  created () {},
+  mounted () {},
+  methods: {
+    // 处理图表数据
+    initChartData () {
+      this.formatBidCycleData(this.datas.bidcycle_ranges)
+      this.formatBudgetData(this.datas.budgetAnalysis)
+      this.formatAreaData(this.datas.group_area)
+      this.formatBuyClassData(this.datas.group_buyerclass)
+      this.formatHotWinData(this.datas.winnerAmount)
+      this.formatExpertData(this.datas.reviewExperts)
+    },
+    // 处理编制周期数据
+    formatBidCycleData (data) {
+      if (!data) return
+      const arr = []
+      data.forEach((item) => {
+        arr.push({
+          '编制周期': item.key, // eslint-disable-line
+          '项目数量': item.doc_count // eslint-disable-line
+        })
+      })
+      this.bidCycle.data.rows = arr
+      // 数据都为0 隐藏
+      var countArr = this.bidCycle.data.rows.map((v) => {
+        return v['项目数量']
+      })
+      const max = Math.max.apply(null, countArr)
+      if (max === 0) {
+        this.bidCycle.show = false
+      }
+      this.bidCycle.show = true
+    },
+    // 处理类似项目预算分布数据
+    formatBudgetData (arr) {
+      if (!arr) return
+      let data = []
+      data = arr.map((v, i) => {
+        v.avg = v.avg === null ? '0' : v.avg
+        const x = i % 10
+        const y = 10 - Math.ceil((i + 1) / 10)
+        return [x, y, v.avg, v.doc_count, v.key]
+      })
+      this.budget.data = data
+      this.budget.show = true
+      this.budget.flag = true
+    },
+    formatAreaData (data) {
+      if (!data) return
+      const rows = []
+      data.forEach((item) => {
+        rows.push({
+          /* eslint-disable */
+          '省份': item.key,
+          '类似项目数量': item.doc_count,
+          '类似项目规模': moneyUnit(item.bidamount_sum)
+          /* eslint-enable */
+        })
+      })
+      this.area.data.rows = rows
+      this.area.show = true
+    },
+    // 处理类似项目采购单位类型分布数据
+    formatBuyClassData (data) {
+      if (!data) return
+      const arr = []
+      // 降序排列
+      data.sort((a, b) => {
+        return b.doc_money - a.doc_money
+      })
+      data.forEach((item) => {
+        arr.push(item.key, item.doc_money, item.doc_count, item.avg, item.main)
+      })
+      const normal = ['行业', '类似项目规模', '类似项目数量', '平均折扣率', '是否当前项目']
+      const newArr = this.arrTrans(5, arr)
+      newArr.unshift(normal)
+      this.buyclass.data = newArr
+      this.buyclass.show = true
+    },
+    // 处理类似项目热点中标企业数据
+    formatHotWinData (data) {
+      if (!data) return
+      this.hotWin.show = true
+      this.hotWin.data = data
+      this.hotWin.flag = true
+    },
+    formatExpertData (data) {
+      if (!data) return
+      const arr = []
+      data.forEach((v) => {
+        v.parent = v.doc_count / data[0].doc_count * 100 + '%'
+        arr.push({
+          name: v.key,
+          count: v.doc_count,
+          parent: v.parent
+        })
+      })
+      this.expert.show = true
+      this.expert.data = arr
+      this.expert.flag = true
+    },
+    /* *********** 配置项部分 *********** */
+    // 类似项目标书编制周期分布配置
+    bidCycleConfig (options) {
+      // 处理一下当前项目编制周期>=60天时,不显示当前编制周期
+      // console.log(this.info.bidcycle, '传来的编制周期')
+      var curCycle = this.info.bidcycle >= 60 ? null : this.info.bidcycle
+      var data = this.bidCycle.data.rows
+      if (!data || data.length <= 0) return
+      const arr = []
+      for (var i = 0; i < data.length; i++) {
+        arr.push(data[i]['编制周期'].replace('天', '').split('-'))
+      }
+      const curIndex = this.getArrayIndex(arr, curCycle, 'cycle')
+      console.log('当前编制周期所在下标:', curIndex, curCycle)
+      options.yAxis[0].name = ''
+      options.series[0].markPoint.data = curCycle ? [{ name: '当前项目标书编制周期', coord: [curIndex, 0.5], value: arr[curIndex].join('-') }] : []
+      options.yAxis[0].minInterval = 1
+      options.tooltip.axisPointer = {
+        type: 'line',
+        lineStyle: {
+          color: '#FF9F40',
+          width: 2
+        }
+      }
+      return options
+    },
+    // 类似项目预算分布配置
+    budgetConfig (params) {
+      const data = params.value[4]
+      const newRange = data.split('-')
+      const sRange = newRange[0]
+      const mRange = 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
+    },
+    // 类似项目区域分布配置
+    areaConfig (options) {
+      const arr = this.area.data.rows
+      const maxNum = Math.max.apply(Math, arr.map((o) => { return o['类似项目数量'] }))
+      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.graphic[0].children[0].style.text = '项目数量(个)'
+      options.visualMap.min = 1
+      options.visualMap.max = maxNum < 100 ? 100 : maxNum
+      options.tooltip.formatter = (params) => {
+        const data = options.series
+        let scaleVal = ''
+        let counts = ''
+        for (let i = 0; i < data.length; i++) {
+          for (let j = 0; j < data[i].data.length; j++) {
+            if (data[i].name === '类似项目数量') {
+              if (params.name === data[i].data[j].name) {
+                counts = data[i].data[j].value
+              }
+            }
+            if (data[i].name === '类似项目规模') {
+              if (params.name === data[i].data[j].name) {
+                scaleVal = data[i].data[j].value
+              }
+            }
+          }
+        }
+        let tip = ''
+        const area = counts && counts !== '' ? params.name + '</br>' : ''
+        const count = counts && counts !== '' ? '<span>类似项目数量:' + counts + '个</span></br>' : ''
+        const scale = scaleVal && scaleVal !== '' ? '<span>类似项目规模:' + scaleVal + '</span></br>' : ''
+        tip = area + count + scale
+        return tip
+      }
+      return options
+    },
+    buyClassConfig (params) {
+      let tip = ''
+      const 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>'
+      const percent = '<span style="padding-left:13px;">采购规模占比:' + params.percent + '%</span></br>'
+      const scale = '<span style="padding-left:13px;">类似项目规模:' + (data[1] / 10000).fixed(2) + '万元</span></br>'
+      const count = '<span style="padding-left:13px;">类似项目数量:' + data[2] + '个</span></br>'
+      const rate = (typeof data[3] === 'number' && !isNaN(data[3])) ? '<span style="padding-left:13px;">平均折扣率:' + (data[3] * 100).fixed(2) + '%</span></br>' : ''
+      tip = params.marker + params.name + '<br/>' + percent + scale + count + rate
+      return tip
+    },
+    /* 公共函数 */
+    // 获取数组下标
+    getArrayIndex (arr, dst, type) {
+      let i = arr.length
+      switch (type) {
+        case 'cycle':
+          while (i--) {
+            if (dst >= arr[i][0] && dst < arr[i][1]) {
+              return i
+            }
+          }
+          break
+        case 'count':
+          while (i--) {
+            if (dst === arr[i]) {
+              return i
+            }
+          }
+          break
+        case 'pie':
+          while (i--) {
+            for (const key in arr[i]) {
+              if (dst === arr[i][key]) {
+                return i
+              }
+            }
+          }
+          break
+      }
+      return false
+    },
+    // 一维数组转换为二维数组
+    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
+    },
+    onBarReady ($event, name) {
+      const data = this.bidCycle.data.rows
+      if (!data || data.length <= 0) return
+      const arr = []
+      for (var i = 0; i < data.length; i++) {
+        arr.push(data[i]['项目数量'])
+      }
+      const maxNum = Math.max.apply(null, arr)
+      const curIndex = this.getArrayIndex(arr, maxNum, 'count')
+      console.log('最大值:' + maxNum + ',索引:' + curIndex)
+      setTimeout(() => {
+        $event.dispatchAction({
+          type: 'showTip',
+          seriesIndex: 0,
+          dataIndex: curIndex ? curIndex : 0 // eslint-disable-line
+        })
+      }, 20)
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.analysis-chart{
+  background: #fff;
+  .chart-title{
+    padding: 32px 0 16px;
+    font-size: 18px;
+    color: #1d1d1d;
+    line-height: 28px;
+  }
+  .chart-main{
+    width: 840px;
+    margin:  0 auto;
+  }
+  .chart-tips{
+    padding: 10px 0 32px;
+    font-size: 12px;
+    color: #999999;
+    line-height: 20px;
+    text-align: center;
+  }
+}
+</style>

+ 170 - 0
src/views/portrayal/components/AnalysisList.vue

@@ -0,0 +1,170 @@
+<template>
+  <div class="analysis-list">
+    <div class="d-content">
+      <div class="win-list" v-for="(hs, i) in list" :key="i">
+        <div class="win-name">
+          <span v-if="i === 0" class="index first-index">{{i + 1}}</span>
+          <span v-else-if="i === 1" class="index second-index">{{i + 1}}</span>
+          <span v-else-if="i === 2" class="index third-index">{{i + 1}}</span>
+          <span v-else class="index">{{i + 1}}</span>
+          <span class="title" @click="goEntImg(hs.entId)">{{hs.key}}</span>
+        </div>
+        <div class="company-info">
+          <span>项目数量:<em>{{hs.doc_count}}个</em> </span>
+          <span>项目金额:<em>{{formatterMoney(hs.total_project)}}</em></span>
+          <span>注册资本:<em>{{formatterMoney(hs.capital)}}</em></span>
+        </div>
+        <div class="same-history" v-if="hs.buyer_similar_list.doc_count > 0 || hs.buyer_similar_list.total_project > 0">
+          <div class="same-title">与{{hs.buyer_similar_list.buyer}}有类似项目合作历史</div>
+          <div class="same-info">
+            <span>项目数量:{{hs.buyer_similar_list.doc_count}}个</span>
+            <span>项目金额:{{formatterMoney(hs.buyer_similar_list.total_project)}}</span>
+            <span>最近中标时间:{{hs.buyer_similar_list.bid_winner_time || '--'}}</span>
+          </div>
+        </div>
+        <div class="other-history" v-if="hs.buyer_other_list.doc_count > 0 || hs.buyer_other_list.total_project > 0">
+          <div class="other-title">与{{hs.buyer_other_list.buyer}}有其他项目合作历史</div>
+          <div class="other-info">
+            <span>项目数量:{{hs.buyer_other_list.doc_count}}个</span>
+            <span>项目金额:{{formatterMoney(hs.buyer_other_list.total_project)}}</span>
+            <span>最近中标时间:{{hs.buyer_other_list.bid_winner_time || '--'}}</span>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import { moneyUnit } from '@/utils/'
+export default {
+  name: 'analysis-list',
+  components: {},
+  props: ['datas'],
+  data () {
+    return {
+      list: []
+    }
+  },
+  watch: {
+    datas: {
+      handler (newVal) {
+        console.log(newVal, 'new')
+        this.list = newVal
+      },
+      deep: true
+    }
+  },
+  computed: {},
+  created () {
+    this.list = this.datas
+  },
+  mounted () {},
+  methods: {
+    formatterMoney (data) {
+      return moneyUnit(data)
+    },
+    goEntImg (id) {
+      this.$router.push('/entportrayal?eId=' + encodeURIComponent(id))
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.analysis-list{
+  .win-list{
+    padding: 6px 8px;
+  }
+  .win-name{
+    display: flex;
+    align-items: center;
+  }
+  .index{
+    height: 20px;
+    margin-right: 16px;
+    padding: 0 4px;
+    line-height: 20px;
+    font-size: 12px;
+    color: #fff;
+    background-color: #C0C4CC;
+    box-sizing: border-box;
+    border-radius: 2px;
+  }
+  .first-index{
+    background: #FB483D;
+    color: #fff;
+    border-radius: 2px;
+  }
+  .second-index{
+    background: #FF9F40;
+    color: #fff;
+    border-radius: 2px;
+  }
+  .third-index{
+    background: #F1D090;
+    color: #fff;
+    border-radius: 2px;
+  }
+  .title{
+    font-size: 16px;
+    line-height: 24px;
+    color: #1D1D1D;
+    font-weight: bold;
+    cursor: pointer;
+  }
+  .company-info{
+    display: flex;
+    align-items: center;
+    margin-top: 12px;
+    color: #999;
+    font-size: 13px;
+    line-height: 20px;
+    span{
+      margin-right: 40px;
+    }
+    em{
+      color: #1D1D1D;
+    }
+  }
+  .same-history,.other-history{
+    margin-top: 12px;
+    padding: 6px 8px;
+    border-radius: 8px;
+  }
+  .same-history{
+    background: rgba(251, 72, 61, 0.06);
+  }
+  .other-history{
+    background: rgba(255, 159, 64, 0.06);
+  }
+  .same-title{
+    color: #FB483D;
+    font-size: 14px;
+    line-height: 24px;
+  }
+  .other-title{
+    color: #FF9F40;
+    font-size: 14px;
+    line-height: 24px;
+  }
+  .same-info,.other-info{
+    display: flex;
+    align-items: center;
+    margin-top: 2px;
+    font-size: 12px;
+  }
+  .same-info{
+    span{
+      margin-right: 12px;
+      color: #FB483D;
+      opacity: 0.8;
+    }
+  }
+  .other-info{
+    span{
+      margin-right: 12px;
+      color: #FF9F40;
+      opacity: 0.8;
+    }
+  }
+}
+</style>

+ 0 - 5
src/views/portrayal/components/EntChart.vue

@@ -399,7 +399,6 @@ export default {
       options.yAxis[1].axisLabel.formatter = (value, index) => {
         return value.toString().replace(/,/, '')
       }
-      // 以下代码为:处理左侧y轴与右侧y轴刻度保持在同一X轴水平线上
       const maxCountList = this.annual.data.rows.map((v) => {
         return v['项目数量']
       })
@@ -493,11 +492,7 @@ export default {
     },
     // 各类型客户折扣率配置
     rateFbConfig (options) {
-      // options.xAxis[0].axisLabel.margin = 12
       options.yAxis[0].axisLabel.formatter = '{value}%'
-      // options.legend.textStyle.padding = [0, 18, 0,0];
-      // options.legend.left = 16;
-      // options.legend.bottom = 10;
       options.tooltip.formatter = (params) => {
         let tip = ''
         for (let i = 0; i < params.length; i++) {

+ 67 - 46
src/views/portrayal/components/UnitChart.vue

@@ -14,7 +14,7 @@
     <!-- 采购规模分布 -->
     <div v-if="buyScaleFb.show">
       <div class="chart-title">采购规模分布</div>
-      <hot-chart v-if="buyScaleFb.flag" ref="hotChart" :datas="buyScaleFb.data"></hot-chart>
+      <hot-chart v-if="buyScaleFb.flag" :datas="buyScaleFb.data" :options="buyScaleFb.options"></hot-chart>
       <div class="chart-tips">注:平均节支率=(全部项目预算-全部中标金额)/全部项目预算,是指价格减让部分与原价的比率,仅统计预算和中标金额同时存在的项目。</div>
     </div>
     <!-- 各类招标方式占比 -->
@@ -55,7 +55,7 @@
     <!-- 重点合作代理机构 -->
     <div v-if="agency.show">
       <div class="chart-title">重点合作代理机构</div>
-      <agency-chart v-if="agency.flag" :datas="agency.data"></agency-chart>
+      <blue-progress-chart v-if="agency.flag" from="unit" :datas="agency.data"></blue-progress-chart>
     </div>
   </div>
 </template>
@@ -67,7 +67,7 @@ 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 AgencyChart from '@/components/chart/AgencyChart'
+import BlueProgressChart from '@/components/chart/BlueProgressChart'
 import { getUnitChart } from '@/api/modules/'
 import { getParam, bSort, moneyUnit } from '@/utils/'
 export default {
@@ -80,14 +80,14 @@ export default {
     PieChart,
     ProgressChart,
     MapChart,
-    AgencyChart
+    BlueProgressChart
   },
   data () {
     return {
       showChart: false,
       // 年度项目统计
       years: {
-        show: true,
+        show: false,
         data: {
           columns: [],
           rows: []
@@ -111,7 +111,7 @@ export default {
       },
       // 月度采购规模
       monthScale: {
-        show: true,
+        show: false,
         data: {
           columns: [],
           rows: []
@@ -124,9 +124,14 @@ export default {
       },
       // 采购规模分布
       buyScaleFb: {
-        show: true,
+        show: false,
         flag: false,
-        data: []
+        data: [],
+        options: {
+          tooltip: {
+            formatter: this.configBuyScaleFb
+          }
+        }
       },
       // 各类招标方式占比
       bidType: {
@@ -135,7 +140,7 @@ export default {
       },
       // 各行业项目平均节支率
       savingsRate: {
-        show: true,
+        show: false,
         flag: false,
         data: {
           columns: [],
@@ -149,7 +154,7 @@ export default {
       },
       // 各行业项目规模占比(饼图)
       projectScale: {
-        show: true,
+        show: false,
         flag: false,
         data: [],
         // 传入的配置
@@ -161,13 +166,13 @@ export default {
       },
       // 重点合作企业
       client: {
-        show: true,
+        show: false,
         flag: false,
         data: []
       },
       // 合作企业注册资本分布
       capital: {
-        show: true,
+        show: false,
         flag: false,
         data: {
           columns: [],
@@ -186,7 +191,7 @@ export default {
       },
       // 合作企业年龄分布
       age: {
-        show: true,
+        show: false,
         flag: false,
         data: {
           columns: ['企业年龄', '企业数量'],
@@ -220,8 +225,7 @@ export default {
         flag: false,
         data: []
       },
-      reqCount: 0,
-      timer: null
+      reqCount: 0
     }
   },
   computed: {},
@@ -255,14 +259,12 @@ export default {
           // 年度项目统计图表数据
           if (res.data.yearData && Object.keys(res.data.yearData).length > 0) {
             this.formatYearsData(res.data.yearData)
-          } else {
-            this.years.show = false
+            this.years.show = true
           }
           // 月度采购规模
           if (res.data.monthData && Object.keys(res.data.monthData).length > 0) {
             this.formatMonthScaleData(res.data.monthData)
-          } else {
-            this.monthScale.show = false
+            this.monthScale.show = true
           }
           // 采购规模分布
           if (res.data.moneyRange && res.data.moneyRange.length > 0) {
@@ -273,83 +275,72 @@ export default {
             if (max === 0) {
               this.buyScaleFb.show = false
             }
-            this.buyScaleFb.data = res.data.moneyRange
             this.buyScaleFb.flag = true
-            // this.formatHotChartData(res.data.moneyRange)
-          } else {
-            this.buyScaleFb.show = false
+            this.formatHotChartData(res.data.moneyRange)
+            this.buyScaleFb.show = true
           }
           // 各类招标方式占比
           if (res.data.bidtypeData && res.data.bidtypeData.length > 0) {
             this.bidType.data = this.formatterBarChart(res.data.bidtypeData)
-          } else {
-            this.bidType.show = false
+            this.bidType.show = true
           }
           // 各行业项目平均节支率
           if (res.data.rate && Object.keys(res.data.rate).length > 0) {
             this.formatSavingsRateData(res.data.rate)
             this.savingsRate.flag = true
-          } else {
-            this.savingsRate.show = false
+            this.savingsRate.show = true
           }
           // 各行业项目规模占比
           if (res.data.top12 && res.data.top12.length > 0) {
             this.formatProjectScaleData(res.data.top12)
             this.projectScale.flag = true
-          } else {
-            this.projectScale.show = false
+            this.projectScale.show = true
           }
           // 重点合作企业
           if (res.data.topShow && res.data.topShow.length > 0) {
             this.client.data = this.formatClientData(res.data.topShow)
             this.client.flag = true
             this.client.show = true
-          } else {
-            this.client.show = false
           }
           // 合作企业注册资本分布
           if (res.data.withCapitalData && res.data.withCapitalData.length > 0) {
             this.formatCapitalData(res.data.withCapitalData)
             this.capital.flag = true
-          } else {
-            this.capital.show = false
+            this.capital.show = true
           }
           // 合作企业年龄分布
           if (res.data.withEstablishData && res.data.withEstablishData) {
             this.formatAgeData(res.data.withEstablishData)
             this.age.flag = true
-          } else {
-            this.age.show = false
+            this.age.show = true
           }
           // 合作企业注册地分布
           if (res.data.withAreaData && res.data.withAreaData.length > 0) {
             this.formatAreaData(res.data.withAreaData)
             this.area.flag = true
             this.area.show = true
-          } else {
-            this.area.show = false
           }
           // 重点合作代理机构
           if (res.data.topAgencyData && res.data.topAgencyData.length > 0) {
             const data = res.data.topAgencyData
+            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 = data
+            this.agency.data = arr
             this.agency.flag = true
             this.agency.show = true
-          } else {
-            this.agency.show = false
           }
         } else {
           if (this.reqCount < 3) {
-            this.timer = setTimeout(() => {
-              this.getChartData()
-            })
-          } else {
-            console.log('请求了仍获取不到图表数据,不再请求')
-            clearTimeout(this.timer)
+            this.getChartData()
           }
         }
       } else {
@@ -585,6 +576,24 @@ export default {
       }
       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
+    },
     /* ********  数据格式化部分 ******* */
     // 格式化年度项目统计数据
     formatYearsData (data) {
@@ -647,6 +656,18 @@ export default {
       }
     },
     // 格式化采购规模分布(热力图)数据
+    formatHotChartData (arr) {
+      console.log(arr)
+      if (!arr) return
+      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.data = data
+    },
     // 格式化各类招标方式占比数据(双向柱图)
     formatterBarChart (data) {
       if (!data) return