Files
yudao-dev/src/views/home/costComponents/operatingLineBar.vue
‘937886381’ 51e66cf6e1 修改
2026-01-06 17:09:52 +08:00

279 lines
7.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div ref="cockpitEffChip" id="coreLineChart" style="width: 100%; height: 400px;"></div>
</template>
<script>
import * as echarts from 'echarts';
export default {
name: 'operatingLineBar',
props: {
echartData: {
type: Object,
// 确保默认值中 flag 是数组,避免 undefined
default: () => ({
locations: [],
target: [],
value: [],
proportion: [],
flag: [] // 强制初始化为空数组
})
}
},
data() {
return {
myChart: null
};
},
watch: {
echartData: {
handler() {
this.initData();
},
deep: true,
immediate: true // 首次绑定就执行 handler
}
},
mounted() {
this.$nextTick(() => {
this.initData();
});
},
methods: {
initData() {
const chartDom = this.$refs.cockpitEffChip;
if (!chartDom) {
console.error('图表容器未找到!');
return;
}
if (!this.myChart) {
this.myChart = echarts.init(chartDom);
}
// 解构时给 flag 加默认值,防止 undefined
const {
locations = [],
target = [],
value = [],
proportion = [],
flag = []
} = this.echartData;
console.log('this.echartData', this.echartData);
// 确保 flag 数组长度与 value 一致(补全缺失的 flag 值为 0
const safeFlag = [...flag];
while (safeFlag.length < value.length) {
safeFlag.push(0); // 缺失的 flag 默认为 0达标
}
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
},
formatter: (params) => {
if (!params.length) return '';
const currentIndex = params[0].dataIndex;
// 使用处理后的 safeFlag避免越界
const currentFlag = safeFlag[currentIndex] || 0;
// const statusText = currentFlag === 0 ? '达标' : '不达标';
let html = `${params[0].axisValue}<br/>`;
params.forEach(item => {
const unit = item.seriesName === '完成率' ? '%' : '万元';
html += `${item.marker} ${item.seriesName}: ${item.value}${unit}<br/>`;
});
return html;
}
},
grid: {
top: 30,
bottom: 30,
right: 20,
left: 60,
},
xAxis: [
{
type: 'category',
boundaryGap: true,
axisTick: { show: false },
axisLine: {
show: true,
lineStyle: { color: 'rgba(0, 0, 0, 0.15)' }
},
axisLabel: {
color: 'rgba(0, 0, 0, 0.45)',
fontSize: 12,
interval: 0,
padding: [5, 0, 0, 0]
},
data: locations
}
],
yAxis: [
{
type: 'value',
name: '万元',
nameTextStyle: {
color: 'rgba(0, 0, 0, 0.45)',
fontSize: 12,
align: 'right'
},
min: 0,
max: (val) => val.max > 0 ? Math.ceil(val.max * 1.1) : 10,
scale: false,
axisTick: { show: false },
axisLabel: {
color: 'rgba(0, 0, 0, 0.45)',
fontSize: 12,
formatter: '{value}'
},
splitLine: { lineStyle: { color: 'rgba(0, 0, 0, 0.15)' } },
axisLine: { lineStyle: { color: 'rgba(0, 0, 0, 0.15)' } },
splitNumber: 4
},
{
type: 'value',
nameTextStyle: {
color: 'rgba(0, 0, 0, 0.45)',
fontSize: 12,
align: 'left'
},
// min: 0,
// max: 100,
axisTick: { show: false },
axisLabel: {
color: 'rgba(0, 0, 0, 0.45)',
fontSize: 12,
formatter: '{value}%'
},
splitLine: { show: false },
axisLine: { lineStyle: { color: 'rgba(0, 0, 0, 0.15)' } },
splitNumber: 4
}
],
series: [
{
name: '完成率',
type: 'line',
yAxisIndex: 1,
lineStyle: {
color: 'rgba(40, 138, 255, .5)',
width: 2
},
itemStyle: {
color: 'rgba(40, 138, 255, 1)',
borderColor: 'rgba(40, 138, 255, 1)',
borderWidth: 2,
radius: 4
},
areaStyle: {
opacity: 0.2,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(40, 138, 255, .9)' },
{ offset: 1, color: 'rgba(40, 138, 255, 0)' }
])
},
data: proportion,
symbol: 'circle',
symbolSize: 6
},
{
name: '预算',
type: 'bar',
yAxisIndex: 0,
barWidth: 14,
itemStyle: {
// 移除多余的 normal 层级,直接配置 color 渐变
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(130, 204, 255, 1)' },
{ offset: 1, color: 'rgba(75, 157, 255, 1)' }
]
},
borderRadius: [4, 4, 0, 0],
borderWidth: 0
},
// itemStyle: {
// color: 'rgba(40, 137, 255, 1)',
// borderRadius: [4, 4, 0, 0],
// borderWidth: 0
// },
data: target
},
{
name: '实际',
type: 'bar',
yAxisIndex: 0,
barWidth: 14,
itemStyle: {
// 根据 safeFlag 动态返回不同的渐变色
color: (params) => {
const dataIndex = params.dataIndex;
const currentFlag = safeFlag[dataIndex] || 0; // 默认为0不达标
// 达标时的渐变(绿色系)
if (currentFlag === 1) {
return {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(174, 239, 224, 1)' }, // 浅绿
{ offset: 1, color: 'rgba(118, 218, 190, 1)' } // 深绿
]
};
}
// 不达标时的渐变(橙色系)
else {
return {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(253, 209, 129, 1)' }, // 浅橙
{ offset: 1, color: 'rgba(249, 164, 74, 1)' } // 深橙
]
};
}
},
borderRadius: [4, 4, 0, 0],
borderWidth: 0
},
data: value
}
]
};
this.myChart.setOption(option);
// 窗口缩放适配
window.addEventListener('resize', () => {
this.myChart && this.myChart.resize();
});
// 组件销毁清理
this.$once('hook:destroyed', () => {
window.removeEventListener('resize', () => {
this.myChart && this.myChart.resize();
});
this.myChart && this.myChart.dispose();
});
}
},
};
</script>