首页统计tuxing

master
lion 1 year ago
parent 2776d895c6
commit bb46171f83

@ -1,11 +1,11 @@
<template> <template>
<div :class="className" :style="{height:height,width:width}" /> <div :class="className" :style="{ height: height, width: width }" ref="chartContainer" />
</template> </template>
<script> <script>
import * as echarts from 'echarts' import * as echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme
import resize from '@/mixins/resize' import resize from '@/mixins/resize'
export default { export default {
mixins: [resize], mixins: [resize],
props: { props: {
@ -15,159 +15,175 @@ export default {
}, },
height: { height: {
type: String, type: String,
default: '100px' default: '350px' //
}, },
width: { width: {
type: String, type: String,
default: '100px' default: '300px'
},
percent: {
type: [Number, String],
default: ''
}, },
chartData: { chartData: {
type: Array, type: Array,
default: () => [] required: true
}, },
title: { title: {
type: String, type: String,
default: '标题' default: '数据统计'
} }
}, },
data() { data() {
return { return {
flag: true, chart: null,
chart: null showRemaining: false,
usedAmount: 0,
totalAmount: 0,
remainingAmount: 0,
usedPercent: 0
} }
}, },
computed: { computed: {
options() { formattedUsedAmount() {
return { return this.usedAmount.toFixed(2)
legend: { },
show: true, formattedRemainingAmount() {
bottom: 0, return this.remainingAmount.toFixed(2)
left: 'center', },
orient: 'horizontal', formattedUsedPercent() {
itemWidth: 8, return this.usedPercent.toFixed(2)
itemHeight: 5 },
}, formattedRemainingPercent() {
color: ['#446df6', '#ccc', '#f2a93f', '#56b7f9'], return (100 - this.usedPercent).toFixed(2)
series: [
{
type: 'pie',
radius: ['50%', '70%'],
center: ['50%', '36%'],
padAngle: 4,
itemStyle: {
borderRadius: 10,
padding: 10
},
label: {
show: true,
position: 'center',
formatter: '{b}\n{d}%'
},
avoidLabelOverlap: true, //
emphasis: { //
scale: true // item
},
labelLine: {
show: false
},
data: (() => {
if (this.percent || this.percent === 0) {
return [
{ value: parseFloat(this.percent), name: `${this.title}` },
{ value: 100 - parseFloat(this.percent), name: `${this.title}` }
]
} else {
return this.chartData
}
})()
}
],
graphic: {
elements: []
}
}
}
},
watch: {
chartData() {
this.setOptions()
} }
}, },
mounted() { mounted() {
this.$nextTick(() => { this.$nextTick(() => {
this.initChart() this.initChart()
this.bindEvents()
}) })
}, },
beforeDestroy() {
if (this.chart) {
this.chart.dispose()
}
},
watch: {
chartData: {
handler() {
this.setOptions()
},
deep: true
}
},
methods: { methods: {
initChart() { initChart() {
this.chart = echarts.init(this.$el, 'macarons') this.chart = echarts.init(this.$refs.chartContainer)
this.setOptions() this.setOptions()
}, },
setOptions() { setOptions() {
this.chart?.setOption(this.options) // chartData
// this.setGraphics() const usedItem = this.chartData.find(item => item.name === '已用金额') || { value: 0 }
}, const totalItem = this.chartData.find(item => item.name === '合计金额') || { value: 0 }
setGraphics() {
const getPointOnCircle = (angle, radiusPercent) => {
const radian = (angle - 90 - 12) * Math.PI / 180
const radius = this.chart.getWidth() / 2 * radiusPercent / 100
const x = this.chart.getWidth() / 2 + Math.cos(radian) * radius
const y = this.chart.getHeight() / 2 + Math.sin(radian) * radius - this.chart.getHeight() * 0.1
return { x: x, y: y }
}
const graphicElements = []
let total = 0
if (!this.options?.series[0]?.data) return
this.options?.series[0]?.data.forEach(function(item) {
total += item.value
})
let startAngle = 0 this.usedAmount = parseFloat(usedItem.value) || 0
this.options?.series[0]?.data.forEach(function(item) { this.totalAmount = parseFloat(totalItem.value) || 0
const angle = (item.value / total) * 360 this.remainingAmount = Math.max(0, this.totalAmount - this.usedAmount)
const endAngle = startAngle + angle this.usedPercent = this.totalAmount > 0
const middleAngle = (startAngle + endAngle) / 2 ? (this.usedAmount / this.totalAmount) * 100
: 0
// const option = {
const pointStart = getPointOnCircle(middleAngle - angle / 2, 60) //
const pointEnd = getPointOnCircle(middleAngle + angle / 2, 60) legend: {
type: 'plain',
// orient: 'horizontal', //
graphicElements.push({ bottom: 0, //
type: 'circle', left: 'center', //
shape: { itemWidth: 12, //
cx: pointStart.x, itemHeight: 12, //
cy: pointStart.y, textStyle: {
r: 3 fontSize: 10,
color: '#333'
}, },
style: { data: [
fill: '#fff' { name: '已用金额', icon: 'circle' },
{ name: '剩余金额', icon: 'circle' }
]
},
series: [{
type: 'pie',
radius: ['50%', '70%'],
center: ['50%', '40%'], //
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 6,
borderColor: '#fff',
borderWidth: 2
}, },
z: 100 label: {
}) show: true,
graphicElements.push({ position: 'center',
type: 'circle', formatter: () => `已用\n{value|${this.formattedUsedAmount}}\n{percent|${this.formattedUsedPercent}%}`,
shape: { rich: {
cx: pointEnd.x, value: {
cy: pointEnd.y, fontSize: 14,
r: 3 fontWeight: 'bold',
lineHeight: 30
},
percent: {
fontSize: 12,
color: '#666'
}
}
}, },
style: { labelLine: {
fill: '#fff' show: false
}, },
z: 100 data: [
}) {
value: this.usedAmount,
name: '已用金额',
itemStyle: {
color: '#446df6' //
}
},
{
value: this.remainingAmount,
name: '剩余金额',
itemStyle: {
color: '#ddd' //
}
}
]
}]
}
startAngle += angle this.chart.setOption(option)
},
bindEvents() {
//
this.chart.on('mouseover', params => {
if (params.data.name === '剩余金额') {
this.showRemaining = true
this.chart.setOption({
series: [{
label: {
formatter: () => `剩余\n{value|${this.formattedRemainingAmount}}\n{percent|${this.formattedRemainingPercent}%}`
}
}]
})
}
}) })
this.chart.setOption({ //
graphic: { this.chart.on('mouseout', params => {
elements: graphicElements if (params.data.name === '剩余金额') {
this.showRemaining = false
this.chart.setOption({
series: [{
label: {
formatter: () => `已用\n{value|${this.formattedUsedAmount}}\n{percent|${this.formattedUsedPercent}%}`
}
}]
})
} }
}) })
} }
@ -175,5 +191,5 @@ export default {
} }
</script> </script>
<style scoped lang="scss"> <style scoped>
</style> </style>

@ -41,6 +41,9 @@ import { getProgress } from '@/api/budget/budget'
import { mergeTableRow } from '@/utils/mergeTableRow' import { mergeTableRow } from '@/utils/mergeTableRow'
export default { export default {
props: {
year: [Number,String]
},
data() { data() {
return { return {
type: [], type: [],
@ -48,7 +51,7 @@ export default {
select: { select: {
page_size: 10, page_size: 10,
page: 1, page: 1,
top_pid: 1 top_pid: 1,
}, },
total: 0, total: 0,
list: [], list: [],
@ -154,9 +157,11 @@ export default {
return row[span] return row[span]
} }
}, },
async getPlanProgress(val) {
async getPlanProgress() { const res = await getProgress({
const res = await getProgress(this.select) year:val,
...this.select
})
for (let m of res.list.data) { for (let m of res.list.data) {
m.pid_info_name = m.pid_info?.name m.pid_info_name = m.pid_info?.name
} }
@ -221,8 +226,16 @@ export default {
} }
}, },
computed: {}, computed: {},
watch: {
year: {
handler:function(val) {
this.getPlanProgress(val)
},
immediate: true
}
},
created() { created() {
this.getPlanProgress() // this.getPlanProgress()
} }
} }
</script> </script>

@ -304,7 +304,7 @@
</el-row> </el-row>
<detailContract ref="detailContract" /> <detailContract ref="detailContract" />
<budgetStatic ref="budgetStatic"></budgetStatic> <budgetStatic ref="budgetStatic" :year="select.year"></budgetStatic>
<carryStatic ref="carryStatic" :departments="statistic.departmentList" :year="select.year"></carryStatic> <carryStatic ref="carryStatic" :departments="statistic.departmentList" :year="select.year"></carryStatic>
</div> </div>

Loading…
Cancel
Save