首页统计tuxing

master
lion 4 months ago
parent 2776d895c6
commit bb46171f83

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

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

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

Loading…
Cancel
Save