|
|
|
|
@ -1,195 +1,167 @@
|
|
|
|
|
<template>
|
|
|
|
|
<div :class="className" :style="{ height: height, width: width }" ref="chartContainer" />
|
|
|
|
|
</template>
|
|
|
|
|
<div :class="className" :style="{ height: height, width: width }" ref="chartContainer" />
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
import * as echarts from 'echarts'
|
|
|
|
|
import resize from '@/mixins/resize'
|
|
|
|
|
<script>
|
|
|
|
|
import * as echarts from 'echarts'
|
|
|
|
|
import resize from '@/mixins/resize'
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
mixins: [resize],
|
|
|
|
|
props: {
|
|
|
|
|
className: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: ''
|
|
|
|
|
},
|
|
|
|
|
height: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: '350px' // 增加高度以容纳图例
|
|
|
|
|
export default {
|
|
|
|
|
mixins: [resize],
|
|
|
|
|
props: {
|
|
|
|
|
className: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: ''
|
|
|
|
|
},
|
|
|
|
|
height: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: '350px' // 增加高度以容纳图例
|
|
|
|
|
},
|
|
|
|
|
width: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: '300px'
|
|
|
|
|
},
|
|
|
|
|
chartData: {
|
|
|
|
|
type: Array,
|
|
|
|
|
required: true
|
|
|
|
|
},
|
|
|
|
|
title: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: '数据统计'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
width: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: '300px'
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
chart: null,
|
|
|
|
|
showRemaining: false,
|
|
|
|
|
usedAmount: 0,
|
|
|
|
|
totalAmount: 0,
|
|
|
|
|
remainingAmount: 0,
|
|
|
|
|
usedPercent: 0
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
chartData: {
|
|
|
|
|
type: Array,
|
|
|
|
|
required: true
|
|
|
|
|
computed: {
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
title: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: '数据统计'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
chart: null,
|
|
|
|
|
showRemaining: false,
|
|
|
|
|
usedAmount: 0,
|
|
|
|
|
totalAmount: 0,
|
|
|
|
|
remainingAmount: 0,
|
|
|
|
|
usedPercent: 0
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
computed: {
|
|
|
|
|
formattedUsedAmount() {
|
|
|
|
|
return this.usedAmount.toFixed(2)
|
|
|
|
|
mounted() {
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
this.initChart()
|
|
|
|
|
// this.bindEvents()
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
formattedRemainingAmount() {
|
|
|
|
|
return this.remainingAmount.toFixed(2)
|
|
|
|
|
beforeDestroy() {
|
|
|
|
|
if (this.chart) {
|
|
|
|
|
this.chart.dispose()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
formattedUsedPercent() {
|
|
|
|
|
return this.usedPercent.toFixed(2)
|
|
|
|
|
watch: {
|
|
|
|
|
chartData: {
|
|
|
|
|
handler() {
|
|
|
|
|
this.setOptions()
|
|
|
|
|
},
|
|
|
|
|
deep: true
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
formattedRemainingPercent() {
|
|
|
|
|
return (100 - this.usedPercent).toFixed(2)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
mounted() {
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
this.initChart()
|
|
|
|
|
this.bindEvents()
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
beforeDestroy() {
|
|
|
|
|
if (this.chart) {
|
|
|
|
|
this.chart.dispose()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
watch: {
|
|
|
|
|
chartData: {
|
|
|
|
|
handler() {
|
|
|
|
|
methods: {
|
|
|
|
|
initChart() {
|
|
|
|
|
this.chart = echarts.init(this.$refs.chartContainer)
|
|
|
|
|
this.setOptions()
|
|
|
|
|
},
|
|
|
|
|
deep: true
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
initChart() {
|
|
|
|
|
this.chart = echarts.init(this.$refs.chartContainer)
|
|
|
|
|
this.setOptions()
|
|
|
|
|
},
|
|
|
|
|
setOptions() {
|
|
|
|
|
// 从chartData中提取已用金额和合计金额
|
|
|
|
|
const usedItem = this.chartData.find(item => item.name === '已用金额') || { value: 0 }
|
|
|
|
|
const totalItem = this.chartData.find(item => item.name === '合计金额') || { value: 0 }
|
|
|
|
|
setOptions() {
|
|
|
|
|
// 从chartData中提取已用金额和合计金额
|
|
|
|
|
const usedItem = this.chartData.find(item => item.name === '已用金额') || { value: 0 }
|
|
|
|
|
const totalItem = this.chartData.find(item => item.name === '合计金额') || { value: 0 }
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
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 option = {
|
|
|
|
|
// 添加图例配置
|
|
|
|
|
legend: {
|
|
|
|
|
type: 'plain',
|
|
|
|
|
orient: 'horizontal', // 水平排列
|
|
|
|
|
bottom: 0, // 位于底部
|
|
|
|
|
left: 'center', // 居中对齐
|
|
|
|
|
itemWidth: 12, // 图例标记宽度
|
|
|
|
|
itemHeight: 12, // 图例标记高度
|
|
|
|
|
textStyle: {
|
|
|
|
|
fontSize: 10,
|
|
|
|
|
color: '#333'
|
|
|
|
|
},
|
|
|
|
|
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
|
|
|
|
|
},
|
|
|
|
|
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'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
labelLine: {
|
|
|
|
|
show: false
|
|
|
|
|
const option = {
|
|
|
|
|
// 添加图例配置
|
|
|
|
|
legend: {
|
|
|
|
|
type: 'plain',
|
|
|
|
|
orient: 'horizontal', // 水平排列
|
|
|
|
|
bottom: 0, // 位于底部
|
|
|
|
|
left: 'center', // 居中对齐
|
|
|
|
|
itemWidth: 12, // 图例标记宽度
|
|
|
|
|
itemHeight: 12, // 图例标记高度
|
|
|
|
|
textStyle: {
|
|
|
|
|
fontSize: 10,
|
|
|
|
|
color: '#333'
|
|
|
|
|
},
|
|
|
|
|
data: [
|
|
|
|
|
{ name: '已用金额', icon: 'circle' },
|
|
|
|
|
{ name: '剩余金额', icon: 'circle' }
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
data: [
|
|
|
|
|
{
|
|
|
|
|
value: this.usedAmount,
|
|
|
|
|
name: '已用金额',
|
|
|
|
|
itemStyle: {
|
|
|
|
|
color: '#446df6' // 已用金额颜色
|
|
|
|
|
}
|
|
|
|
|
series: [{
|
|
|
|
|
type: 'pie',
|
|
|
|
|
radius: ['40%', '65%'],
|
|
|
|
|
center: ['50%', '45%'],
|
|
|
|
|
avoidLabelOverlap: false,
|
|
|
|
|
minShowLabelAngle: 10,
|
|
|
|
|
itemStyle: {
|
|
|
|
|
borderRadius: 6,
|
|
|
|
|
borderColor: '#fff',
|
|
|
|
|
borderWidth: 2
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
value: this.remainingAmount,
|
|
|
|
|
name: '剩余金额',
|
|
|
|
|
itemStyle: {
|
|
|
|
|
color: '#ddd' // 剩余金额颜色
|
|
|
|
|
label: {
|
|
|
|
|
show: true,
|
|
|
|
|
position: 'outside',
|
|
|
|
|
fontSize: 12,
|
|
|
|
|
color: '#333',
|
|
|
|
|
formatter: params => {
|
|
|
|
|
// 只显示有数值的部分
|
|
|
|
|
if (params.value === 0) return '';
|
|
|
|
|
const percent = this.totalAmount > 0 ? ((params.value / this.totalAmount) * 100).toFixed(2) : '0.00';
|
|
|
|
|
return `${params.name}\n${percent}%`;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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}%}`
|
|
|
|
|
},
|
|
|
|
|
labelLine: {
|
|
|
|
|
show: true,
|
|
|
|
|
length: 8,
|
|
|
|
|
length2: 5,
|
|
|
|
|
smooth: true
|
|
|
|
|
},
|
|
|
|
|
data: [
|
|
|
|
|
{
|
|
|
|
|
value: this.usedAmount,
|
|
|
|
|
name: '已用金额',
|
|
|
|
|
itemStyle: {
|
|
|
|
|
color: '#446df6' // 已用金额颜色
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
value: this.remainingAmount,
|
|
|
|
|
name: '剩余金额',
|
|
|
|
|
itemStyle: {
|
|
|
|
|
color: '#ddd' // 剩余金额颜色
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}]
|
|
|
|
|
})
|
|
|
|
|
]
|
|
|
|
|
}]
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 鼠标移出时恢复显示已用金额
|
|
|
|
|
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}%}`
|
|
|
|
|
}
|
|
|
|
|
}]
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
this.chart.setOption(option)
|
|
|
|
|
},
|
|
|
|
|
// 移除bindEvents方法和相关调用
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
</style>
|
|
|
|
|
<style scoped>
|
|
|
|
|
</style>
|
|
|
|
|
|