123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909 |
- <template>
- <div class="unit-chart">
- <!-- 年度项目统计 -->
- <div v-if="years.show">
- <div class="chart-title">年度项目统计</div>
- <bar-chart id="years" :options="years.options" :datas="years.data"></bar-chart>
- </div>
- <!-- 月度采购规模 -->
- <div v-if="monthScale.show">
- <div class="chart-title">月度采购规模统计</div>
- <line-chart ref="monthScale" :options="monthScale.options" :datas="monthScale.data"></line-chart>
- <div class="chart-tips text-center">注:采购规模指中标金额,少数缺失的中标金额,用项目预算补充。</div>
- </div>
- <!-- 采购规模分布 -->
- <div v-if="buyScaleFb.show">
- <div class="chart-title">采购规模分布</div>
- <hot-chart v-if="buyScaleFb.flag" ref="hotChart" :datas="buyScaleFb.data"></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="projectScale.show">
- <div class="chart-title">各行业项目规模占比</div>
- <pie-chart v-if="projectScale.flag" :height="'326px'" :options="projectScale.options" :datas="projectScale.data"></pie-chart>
- </div>
- <!-- 重点合作企业 -->
- <div v-if="client.data.length > 0">
- <div class="chart-title">重点合作企业</div>
- <progress-chart ref="clientChart" :datas="client.data"></progress-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="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="agency.show">
- <div class="chart-title">重点合作代理机构</div>
- <agency-chart v-if="agency.flag" :datas="agency.data"></agency-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 AgencyChart from '@/components/chart/AgencyChart'
- import { getUnitChart } from '@/api/modules/'
- import { getParam, bSort, moneyUnit } from '@/utils/'
- export default {
- name: 'unit-chart',
- components: {
- BarChart,
- HotChart,
- LineChart,
- DoubleBarChart,
- pieChart,
- ProgressChart,
- MapChart,
- AgencyChart
- },
- data () {
- return {
- // 年度项目统计
- years: {
- show: true,
- 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: true,
- data: {
- columns: [],
- rows: []
- },
- options: {
- height: '326px',
- colors: ['#05A6F3', '#0BD991', '#FF9F40'],
- config: this.configMonthScle
- }
- },
- // 采购规模分布
- buyScaleFb: {
- show: true,
- flag: false,
- data: []
- },
- // 各类招标方式占比
- bidType: {
- show: true,
- data: []
- },
- // 各行业项目平均节支率
- savingsRate: {
- show: true,
- flag: false,
- data: {
- columns: [],
- rows: []
- },
- options: {
- height: '326px',
- colors: ['#FB483D', '#05A6F3', '#0BD991', '#FF9F40', '#8E6DF2', '#C0C4CC'],
- config: this.configSavingsRate
- }
- },
- // 各行业项目规模占比(饼图)
- projectScale: {
- show: true,
- flag: false,
- data: [],
- // 传入的配置
- options: {
- tooltip: {
- formatter: event
- }
- }
- },
- // 重点合作企业
- client: {
- show: true,
- flag: false,
- data: []
- },
- // 合作企业注册资本分布
- capital: {
- show: true,
- flag: false,
- data: {
- columns: [],
- rows: [],
- customData: []
- },
- options: {
- height: '320px',
- colors: ['#05a6f3', '#FF9F40'],
- config: this.configCapital,
- settings: {
- showLine: ['累计采购规模'],
- axisSite: { right: ['累计采购规模'] }
- }
- }
- },
- // 合作企业年龄分布
- age: {
- show: true,
- 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,
- timer: null
- }
- },
- computed: {},
- mounted () {
- this.getChartData()
- },
- methods: {
- // 画像数据
- async getChartData () {
- const res = await getUnitChart({
- buyer: decodeURIComponent(getParam('entName'))
- })
- if (res.error_code === 0) {
- this.reqCount++
- if (res.data && Object.keys(res.data).length > 0) {
- const info = {}
- info.province = res.data.province ? res.data.province.replace(/省|市|自治区|特别行政区|壮族|回族|维吾尔/g, '') : '--'
- info.city = res.data.city
- info.buyerClass = res.data.buyerclass ? res.data.buyerclass : '--'
- info.start = new Date(Number(res.data.timeRange.start + '000')).pattern('yyyy/MM/dd')
- info.end = new Date(Number(res.data.timeRange.end + '000')).pattern('yyyy/MM/dd')
- info.buyerCount = res.data.project_count ? res.data.project_count + '个' : '--'
- info.winnerCount = res.data.winner_count ? res.data.winner_count + '个' : '--'
- info.otherWinner = res.data.otherProvincesWinnerCount ? res.data.otherProvincesWinnerCount + '个' : '--'
- info.buyerScale = res.data.bidamount_count ? moneyUnit(res.data.bidamount_count) : '--'
- info.fail_count = res.data.fail_count ? res.data.fail_count + '条' : '--'
- console.log(info, 'info')
- this.$emit('base-info', info)
- // 年度项目统计图表数据
- if (res.data.yearData && Object.keys(res.data.yearData).length > 0) {
- this.formatYearsData(res.data.yearData)
- } else {
- this.years.show = false
- }
- // 月度采购规模
- if (res.data.monthData && Object.keys(res.data.monthData).length > 0) {
- this.formatMonthScaleData(res.data.monthData)
- } else {
- this.monthScale.show = false
- }
- // 采购规模分布
- if (res.data.moneyRange && res.data.moneyRange.length > 0) {
- const countArr = res.data.moneyRange.map((v) => {
- return v.project_count
- })
- const max = Math.max.apply(null, countArr)
- 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
- }
- // 各类招标方式占比
- if (res.data.bidtypeData && res.data.bidtypeData.length > 0) {
- this.bidType.data = this.formatterBarChart(res.data.bidtypeData)
- } else {
- this.bidType.show = false
- }
- // 各行业项目平均节支率
- 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
- }
- // 各行业项目规模占比
- if (res.data.top12 && res.data.top12.length > 0) {
- this.formatProjectScaleData(res.data.top12)
- this.projectScale.flag = true
- } else {
- this.projectScale.show = false
- }
- // 重点合作企业
- 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
- }
- // 合作企业年龄分布
- if (res.data.withEstablishData && res.data.withEstablishData) {
- this.formatAgeData(res.data.withEstablishData)
- this.age.flag = true
- } else {
- this.age.show = false
- }
- // 合作企业注册地分布
- 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
- 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 + '%'
- })
- this.agency.data = data
- 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)
- }
- }
- }
- },
- /* ******** 配置项部分 ******* */
- configYears (options) {
- options.yAxis[1].axisLabel.formatter = (value, index) => {
- return value.toString().replace(/,/, '')
- }
- 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
- },
- /* ******** 数据格式化部分 ******* */
- // 格式化年度项目统计数据
- formatYearsData (data) {
- if (!data) return
- 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
- } else {
- this.years.show = false
- }
- },
- // 格式化月度采购规模数据
- formatMonthScaleData (data) {
- if (!data) return
- const rows = []
- const columns = ['月份']
- let count = 0
- const years = []
- for (var key in data) {
- years.push(parseInt(key))
- }
- 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)
- }
- if (count > 0) {
- this.monthScale.data.columns = columns
- this.monthScale.data.rows = rows
- } else {
- this.monthScale.show = false
- }
- },
- // 格式化采购规模分布(热力图)数据
- // 格式化各类招标方式占比数据(双向柱图)
- formatterBarChart (data) {
- if (!data) return
- 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)
- })
- return newData
- },
- // 格式化平均节支率数据
- formatSavingsRateData (data) {
- if (!data) return
- 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
- } else {
- this.savingsRate.show = false
- }
- },
- // 格式化各行业项目规模占比数据
- formatProjectScaleData (data) {
- if (!data) return
- const arr = []
- // 降序排列
- data.sort((a, b) => {
- return b.bidamount_share - a.bidamount_share
- })
- data.forEach((item) => {
- 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.data = newArr
- 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] * 100).fixed(2) + '%</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 = (typeof data[4] === 'number' && !isNaN(data[4])) ? '<span style="padding-left:13px;">平均节支率:' + (data[4] * 100).fixed(2) + '%</span></br>' : ''
- tip = params.marker + params.name + '<br/>' + percent + scale + count + rate
- return tip
- }
- },
- // 格式化注册资本数据
- formatCapitalData (data) {
- if (!data) return
- 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
- },
- // 格式化企业年龄分布数据
- formatAgeData (data) {
- if (!data) return
- 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
- },
- // 格式化企业注册地分布数据
- formatAreaData (data) {
- if (!data) return
- 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
- },
- // 格式化重点合作企业数据
- formatClientData (data) {
- if (!data) return
- 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')
- s.countMoney = s.countMoney ? moneyUnit(s.countMoney) : ''
- })
- })
- 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
- })
- return newData
- },
- /* ******** 公共函数部分 ******* */
- // 求最大项目数量
- 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{
- width: 1200px;
- 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>
|