大屏提交

This commit is contained in:
ljx
2025-09-09 22:07:43 +08:00
parent d01a56d9dc
commit 0afefe44ca
8 changed files with 751 additions and 421 deletions

View File

@ -1,13 +1,60 @@
<template>
<div class="leftPage">
<div class="topPage">
<Title title="项目概况" />
<div class="content" v-html="generalize"></div>
<Title title="项目进度分析" />
<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="endPage">
<Title title="形象进度" />
<div class="projectItem">
<div class="chart_container">
<div ref="pieChartRef" class="echart" />
</div>
</div>
<div class="output">
<Title title="实际产值与预期产值对比" />
<div class="chart_container">
<div ref="lineChartRef" class="echart" />
</div>
</div>
@ -15,69 +62,40 @@
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted, nextTick } from "vue"
import Title from './title.vue'
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import Title from './title.vue';
import * as echarts from 'echarts';
import { pieOption, barOption } from './optionList';
import { getScreenLand, getScreenImgProcess, getScreenGeneralize } from '@/api/projectScreen';
import { projectProgress, outpuProgress } from '@/api/outputApi';
const capacityData: any = ref({});
const props = defineProps({
projectId: {
type: String,
default: 0
}
})
});
const generalize = ref()
const generalize = ref();
// 饼图相关
const pieChartRef = ref<HTMLDivElement | null>(null);
let pieChart: any = null;
const totalPercent = ref(0)
const totalPercent = ref(0);
// 折线图相关
const lineChartRef = ref<HTMLDivElement | null>(null);
let lineChart: any = null;
// 土地数据 折线图
const designAreaData = ref([])
const transferAreaData = 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 initPieChart = () => {
if (!pieChartRef.value) {
console.error('未找到饼图容器元素');
return;
}
pieOption.series.data = pieData
pieOption.graphic[0].style.text = totalPercent.value + '%'
pieChart = echarts.init(pieChartRef.value, null, {
renderer: 'canvas',
useDirtyRect: false
});
pieChart.setOption(pieOption);
}
// 初始化折线图
const initLineChart = () => {
if (!lineChartRef.value) {
console.error('未找到折线图容器元素');
return;
}
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 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 = () => {
@ -85,50 +103,126 @@ const handleResize = () => {
if (lineChart) lineChart.resize();
};
/**
* 获取项目土地统计数据
*/
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))
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 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 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 getScreenGeneralizeData = async () => {
const res = await getScreenGeneralize(props.projectId);
const { data, code } = res
if (code === 200) {
generalize.value = data
}
}
// /**
// * 获取项目形象进度数据
// */
// 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()
// getScreenLandData();
// getScreenImgProcessData();
// getScreenGeneralizeData();
getData();
getOutputData();
nextTick(() => {
initPieChart();
window.addEventListener('resize', handleResize);
@ -155,67 +249,144 @@ onUnmounted(() => {
flex-direction: column;
height: 100%;
.topPage,
.endPage {
.topPage {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
padding: 15px 0;
padding: 15px 0 0 0;
border: 1px solid rgba(29, 214, 255, 0.1);
box-sizing: border-box;
height: 20%;
}
}
.endPage {
flex: 1;
margin-top: 23px;
// .content {
// height: 100px;
// margin: 0 15px;
// padding: 0 10px;
// margin-top: 15px;
// box-sizing: border-box;
// overflow-y: auto;
.chart_container {
// &::-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;
gap: 5px;
width: 100%;
height: 100%;
}
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: 48%;
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);
.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;
.chart_container {
width: 100%;
height: 100%;
.echart {
height: 90%;
width: 100%;
}
}
}
.subfont {
color: rgba(138, 149, 165, 1);
}
</style>