WholeProcessPlatform/frontend/src/components/developStatusChart/index.vue

280 lines
8.2 KiB
Vue
Raw Normal View History

<!-- developStatusChart/index.vue -->
<template>
<div class="basic_body">
<div ref="chartContainer" class="chart-container"></div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, onUnmounted, watch } from 'vue';
import * as echarts from 'echarts';
import { getVmsstbprptKendoList } from '@/api/home';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
defineOptions({
name: 'developStatusChart'
});
const emit = defineEmits<{
(e: 'chart-click', params: any): void;
}>();
const JidiSelectEventStore = useJidiSelectEventStore();
const baseid = ref('');
const chartContainer = ref<HTMLDivElement | null>(null);
let chartInstance: echarts.ECharts | null = null;
const dataLoading = ref(false);
onUnmounted(() => {
if (chartInstance) {
chartInstance.dispose();
chartInstance = null;
}
});
const transUnit = (value: number) => {
return value * 0.1;
};
const getData = async () => {
if (!baseid.value) return;
const baseFilters: any[] = [
{ field: 'sttpCode', operator: 'eq', dataType: 'string', value: 'ENG' },
{ field: 'prsc', operator: 'in', dataType: 'string', value: ['1', '2', '3'] }
];
if (baseid.value !== 'all') {
baseFilters.unshift({ field: 'baseId', operator: 'eq', dataType: 'string', value: baseid.value });
}
const params1 = {
filter: {
logic: 'and',
filters: [
...baseFilters,
{ field: 'ttpwr', operator: 'isnotnull' }
]
},
group: [{ dir: 'desc', field: 'bldsttCcode', aggregates: [{ field: 'ttpwr', aggregate: 'sum' }] }]
};
const params2 = {
filter: {
logic: 'and',
filters: [...baseFilters]
},
group: [{ dir: 'desc', field: 'bldsttCcode' }]
};
try {
dataLoading.value = true;
const [res1, res2] = await Promise.all([
getVmsstbprptKendoList(params1),
getVmsstbprptKendoList(params2)
]);
const res1Data = res1?.data?.data || [];
const res2Data = res2?.data?.data || [];
// debugger
if (res1Data.length > 0 || res2Data.length > 0) {
const ttpwrlist = res1Data.map((item: any) => ({
key: item.key,
ttpwr: transUnit(item.items[0].SUM_TTPWR)
}));
const engTotalList = res2Data.map((item: any) => ({
key: item.key,
engTotal: item.count
}));
const result: any = Object.values(
[...engTotalList, ...ttpwrlist].reduce((result: any, item: any) => {
const { key, engTotal = 0, ttpwr = 0 } = item;
const existingItem = result[key] || { key, engTotal: 0, ttpwr: 0 };
existingItem.bldstt = item.key == 0 ? '未建' : item.key == 1 ? '在建' : '已建';
existingItem.engTotal += engTotal;
existingItem.ttpwr += ttpwr;
return { ...result, [key]: existingItem };
}, {})
);
result.sort((a: any, b: any) => {
if (a.bldstt === '已建' && b.bldstt !== '已建') return -1;
else if (a.bldstt !== '已建' && b.bldstt === '已建') return 1;
else if (a.bldstt === '在建' && b.bldstt === '未建') return -1;
else if (a.bldstt === '未建' && b.bldstt === '在建') return 1;
else return 0;
});
const legendData: string[] = [];
const capData: { name: string; value: number }[] = [];
const countData: { name: string; value: number }[] = [];
result.forEach((item: any) => {
const name = item.bldstt;
if (name !== '未建') {
legendData.push(name);
countData.push({ name, value: Number(item.engTotal) });
capData.push({ name, value: Number(item.ttpwr).toFixed(2) });
}
});
const colors = ['#78c300', '#2196F3'];
const option = {
tooltip: {
trigger: 'item',
formatter: '{b}电站{a}: {c}',
position: 'right'
},
legend: {
data: legendData,
left: '60%',
orient: 'vertical',
top: 'center',
itemWidth: 20,
itemHeight: 12
},
color: colors,
series: [
{
name: '数量(座)',
type: 'pie',
radius: [0, '55%'],
label: { show: false },
labelLine: { show: false },
data: countData,
center: ['30%', '50%'],
itemStyle: {
borderRadius: 2,
borderColor: '#fff',
borderWidth: 2
}
},
{
name: '装机容量(万kW)',
type: 'pie',
radius: ['70%', '90%'],
labelLine: { length: 30 },
label: { show: false },
data: capData,
center: ['30%', '50%'],
itemStyle: {
borderRadius: 2,
borderColor: '#fff',
borderWidth: 2
}
}
]
};
if (chartInstance) {
chartInstance.setOption(option, true);
}
}
} catch (error) {
console.error('DevelopStatusChart getData error:', error);
} finally {
dataLoading.value = false;
}
};
const initChart = () => {
if (!chartContainer.value) return;
chartInstance = echarts.init(chartContainer.value);
const option = {
tooltip: {
trigger: 'item',
formatter: '{a} {b}: {c} ({d}%)',
position: 'right'
},
legend: {
data: ['已建', '在建'],
left: '60%',
orient: 'vertical',
top: 'center',
itemWidth: 20,
itemHeight: 12
},
color: ['#78c300', '#2196F3'],
series: [
{
name: '装机容量(万kW)',
type: 'pie',
radius: ['70%', '90%'],
center: ['30%', '50%'],
itemStyle: {
borderRadius: 2,
borderColor: '#fff',
borderWidth: 2
},
label: { show: false },
labelLine: { show: false },
data: []
},
{
2026-04-03 16:08:05 +08:00
name: '数量(座)',
type: 'pie',
radius: ['0%', '50%'],
center: ['30%', '50%'],
itemStyle: {
borderRadius: 2,
borderColor: '#fff',
borderWidth: 2
},
label: { show: false },
labelLine: { show: false },
data: []
}
]
};
chartInstance.setOption(option);
// 添加点击事件
chartInstance.on('click', (params: any) => {
emit('chart-click', {
seriesName: params.seriesName,
name: params.name,
dataIndex: params.dataIndex
});
});
2026-05-15 08:51:17 +08:00
window.addEventListener('resize', () => {
chartInstance?.resize();
2026-05-15 08:51:17 +08:00
});
};
onMounted(() => {
if (chartContainer.value) {
initChart();
}
});
2026-05-15 08:51:17 +08:00
watch(
() => JidiSelectEventStore.selectedItem,
newVal => {
if (newVal && newVal.wbsCode) {
baseid.value = newVal.wbsCode;
getData();
}
},
{ deep: true, immediate: true }
);
</script>
2026-04-03 16:08:05 +08:00
<style lang="scss" scoped>
.basic_body {
width: 100%;
height: 100%;
.chart-container {
width: 203px;
height: 100px;
2026-05-15 08:51:17 +08:00
}
}
</style>