Files
td_official/src/views/enterpriseLarge/digitalizationScreen/components/rightPage.vue
2025-09-10 10:02:04 +08:00

393 lines
10 KiB
Vue

<template>
<div class="leftPage">
<div class="topPage">
<Title title="项目进度分析" style="font-size: 22px" />
<div class="progress">
<div class="progress_item">
<div class="progress_imgBox">
<div class="progress_img">
<img src="@/assets/large/capacity.png" style="width: 100%; height: 100%" />
</div>
</div>
<div class="progress_text">
<div class="progress_text_title">
<div>{{ capacityData.gridConnectedCapacity ?? '0' }}</div>
<div>MW</div>
</div>
<div class="content_text">井网总容量</div>
</div>
</div>
<div class="progress_item">
<div class="progress_imgBox">
<div class="progress_img">
<img src="@/assets/large/plan.png" style="width: 100%; height: 100%" />
</div>
</div>
<div class="progress_text">
<div class="progress_text_title">
<div>{{ capacityData.plannedCapacity ?? '0' }}</div>
<div>MW</div>
</div>
<div class="content_text">计划总容量</div>
</div>
</div>
<div class="progress_item">
<div class="progress_imgBox">
<div class="progress_img">
<img src="@/assets/large/delay.png" style="width: 100%; height: 100%" />
</div>
</div>
<div class="progress_text">
<div class="progress_text_title">
<div>{{ capacityData.delayedProjectCount ?? '0' }}</div>
<div></div>
</div>
<div class="content_text">延期项目</div>
</div>
</div>
</div>
</div>
<div class="projectItem">
<div class="chart_container">
<div ref="pieChartRef" class="echart" />
</div>
</div>
<div class="output">
<Title title="实际产值与预期产值对比" style="font-size: 22px" />
<div class="chart_container">
<div ref="lineChartRef" class="echart" />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import Title from './title.vue';
import * as echarts from 'echarts';
import { pieOption, barOption } from './optionList';
import { projectProgress, outpuProgress } from '@/api/outputApi';
const capacityData: any = ref({});
const props = defineProps({
projectId: {
type: String,
default: 0
}
});
const generalize = ref();
// 饼图相关
const pieChartRef = ref<HTMLDivElement | null>(null);
let pieChart: any = null;
const totalPercent = ref(0);
// 折线图相关
const lineChartRef = ref<HTMLDivElement | null>(null);
let lineChart: any = null;
// 土地数据 折线图
const designAreaData = ref([]);
const transferAreaData = ref([]);
const barNames = ref([]);
// // 饼图数据
// const pieData = [
// { label: 'areaPercentage', name: '厂区', value: 0 },
// { label: 'roadPercentage', name: '道路', value: 0 },
// { label: 'collectorLinePercentage', name: '集电线路', value: 0 },
// { label: 'exportLinePercentage', name: '送出线路', value: 0 },
// { label: 'substationPercentage', name: '升压站', value: 0 },
// { label: 'boxTransformerPercentage', name: '箱变', value: 0 }
// ];
// 响应窗口大小变化
const handleResize = () => {
if (pieChart) pieChart.resize();
if (lineChart) lineChart.resize();
};
const processedDataList = ref([]);
//获取数据
const getData = async () => {
const res = await projectProgress();
if (res.code == 200) {
capacityData.value = res.data;
// processedDataList.value = res.data.projectProgressDetailList;
let totalCapacity = 0;
const processedData = res.data.projectProgressDetailList.map((item) => {
const capacity = parseInt(item.projectCapacity) || 0;
totalCapacity += capacity;
return {
name: item.projectName,
value: capacity,
completionRate: item.completionRate
};
});
// 计算每个项目的百分比
processedData.forEach((item) => {
item.percentage = totalCapacity > 0 ? ((item.value / totalCapacity) * 100).toFixed(2) : '0%';
});
processedDataList.value = processedData;
initPieChart();
}
};
// 初始化饼图
const initPieChart = () => {
if (!pieChartRef.value) {
console.error('未找到饼图容器元素');
return;
}
const data = processedDataList.value.map((item: any) => {
return {
name: item.name,
value: item.percentage,
completionRate: item.value
};
});
pieOption.series.data = data;
// pieOption.graphic[0].style.text = totalPercent.value + '%';
pieChart = echarts.init(pieChartRef.value, null, {
renderer: 'canvas',
useDirtyRect: false
});
pieChart.setOption(pieOption);
};
//获取产值数据
const getOutputData = async () => {
const res = await outpuProgress();
if (res.code == 200) {
designAreaData.value = res.data.map((item: any) => Number(item.planValue));
transferAreaData.value = res.data.map((item: any) => Number(item.actualValue));
barNames.value = res.data.map((item: any) => item.projectName);
initLineChart();
}
};
// 初始化柱状图图
const initLineChart = () => {
if (!lineChartRef.value) {
console.error('未找到柱状图容器元素');
return;
}
console.log(barOption);
barOption.xAxis.data = barNames.value;
barOption.series[0].data = designAreaData.value;
barOption.series[1].data = transferAreaData.value;
lineChart = echarts.init(lineChartRef.value, null, {
renderer: 'canvas',
useDirtyRect: false
});
lineChart.setOption(barOption);
};
// /**
// * 获取项目土地统计数据
// */
// const getScreenLandData = async () => {
// const res = await getScreenLand(props.projectId);
// const { data, code } = res;
// if (code === 200) {
// designAreaData.value = data.map((item: any) => Number(item.designArea));
// transferAreaData.value = data.map((item: any) => Number(item.transferArea));
// // initLineChart();
// }
// };
// /**
// * 获取项目形象进度数据
// */
// const getScreenImgProcessData = async () => {
// const res = await getScreenImgProcess(props.projectId);
// const { data, code } = res;
// if (code === 200) {
// totalPercent.value = data.totalPercentage;
// pieData.forEach((item: any) => {
// item.value = data[item.label];
// });
// initPieChart();
// }
// };
// /**
// * 获取项目概况数据
// */
// const getScreenGeneralizeData = async () => {
// const res = await getScreenGeneralize(props.projectId);
// const { data, code } = res;
// if (code === 200) {
// generalize.value = data;
// }
// };
// 组件挂载时初始化图表
onMounted(() => {
// getScreenLandData();
// getScreenImgProcessData();
// getScreenGeneralizeData();
getData();
getOutputData();
nextTick(() => {
initPieChart();
window.addEventListener('resize', handleResize);
});
});
// 组件卸载时清理
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
if (pieChart) {
pieChart.dispose();
pieChart = null;
}
if (lineChart) {
lineChart.dispose();
lineChart = null;
}
});
</script>
<style scoped lang="scss">
.leftPage {
display: flex;
flex-direction: column;
height: 100%;
.topPage {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
padding: 15px 0 0 0;
border: 1px solid rgba(29, 214, 255, 0.1);
box-sizing: border-box;
height: 20%;
}
}
// .content {
// height: 100px;
// margin: 0 15px;
// padding: 0 10px;
// margin-top: 15px;
// box-sizing: border-box;
// overflow-y: auto;
// &::-webkit-scrollbar-track {
// background: rgba(204, 204, 204, 0.1);
// border-radius: 10px;
// }
// &::-webkit-scrollbar-thumb {
// background: rgba(29, 214, 255, 0.78);
// border-radius: 10px;
// }
// .content_item {
// font-size: 14px;
// font-weight: 400;
// color: rgba(230, 247, 255, 1);
// margin-bottom: 10px;
// &:last-child {
// margin-bottom: 0;
// }
// }
// }
.progress {
width: 100%;
height: 100%;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 10px;
.progress_item {
width: 100%;
height: 100%;
// background: rgba(29, 214, 255, 1);
display: flex;
flex-direction: column;
position: relative;
.progress_imgBox {
width: 100%;
height: 35%;
position: relative;
.progress_img {
width: 84px;
height: 48px;
position: absolute;
left: 50%;
top: 80%;
transform: translate(-50%, -50%);
}
}
.progress_text {
width: 100%;
height: 65%;
background: rgba(29, 214, 255, 0.1);
display: flex;
flex-direction: column;
align-items: flex-end;
padding: 15px 5px 5px 5px;
.progress_text_title {
width: 100%;
// height: 100%;
display: flex;
justify-content: space-between;
align-items: center;
& > div:first-child {
// 第一个子元素的样式
width: 50%;
font-size: 24px;
// font-weight: bold;
font-family: 'AlimamaShuHeiTi', sans-serif;
text-align: center;
}
& > div:last-child {
// 最后一个子元素的样式
width: 50%;
font-size: 12px;
color: #999;
text-align: center;
}
}
.content_text {
width: 100%;
font-size: 14px;
color: #c6d1db;
text-align: center;
}
}
}
}
.projectItem {
width: 100%;
height: 40%;
// background: rgba(29, 214, 255, 1);
padding: 10px 10px 10px 0;
// border: 1px solid rgba(29, 214, 255, 0.1);
.chart_container {
width: 100%;
height: 100%;
.echart {
height: 100%;
width: 100%;
}
}
}
.output {
width: 100%;
height: 40%;
// background: rgba(29, 214, 255, 0.5);
padding: 10px 10px 10px 0;
border: 1px solid rgba(29, 214, 255, 0.1);
.chart_container {
width: 100%;
height: 100%;
.echart {
height: 90%;
width: 100%;
}
}
}
</style>