<template>
|
<div class="app-container">
|
<!-- 搜索区域 -->
|
<div class="search_form">
|
<el-form :model="searchForm"
|
:inline="true">
|
<el-form-item label="时间维度:">
|
<el-select v-model="searchForm.timeDimension"
|
placeholder="请选择时间维度"
|
style="width: 120px;"
|
@change="handleQuery">
|
<el-option label="年度"
|
value="year" />
|
<el-option label="月度"
|
value="month" />
|
</el-select>
|
</el-form-item>
|
<el-form-item label="年份:">
|
<el-select v-model="searchForm.year"
|
placeholder="请选择年份"
|
style="width: 120px;"
|
@change="handleQuery">
|
<el-option v-for="year in years"
|
:key="year"
|
:label="year + '年'"
|
:value="year" />
|
</el-select>
|
</el-form-item>
|
<el-form-item label="月份:"
|
v-if="searchForm.timeDimension === 'month'">
|
<el-select v-model="searchForm.month"
|
placeholder="请选择月份"
|
style="width: 120px;"
|
@change="handleQuery">
|
<el-option v-for="month in 12"
|
:key="month"
|
:label="month + '月'"
|
:value="month" />
|
</el-select>
|
</el-form-item>
|
<el-form-item label="能耗类型:">
|
<el-select v-model="searchForm.energyType"
|
placeholder="全部"
|
clearable
|
style="width: 140px;"
|
@change="handleQuery">
|
<el-option label="全部"
|
value="全部" />
|
<el-option label="水"
|
value="水" />
|
<el-option label="电"
|
value="电" />
|
<el-option label="蒸汽"
|
value="蒸汽" />
|
</el-select>
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary"
|
@click="handleQuery">查询</el-button>
|
<el-button @click="handleReset">重置</el-button>
|
</el-form-item>
|
</el-form>
|
<div>
|
<el-button type="success"
|
@click="handleExport">导出报表</el-button>
|
</div>
|
</div>
|
<!-- 图表区域 -->
|
<div class="chart-section">
|
<h2 class="section-header">
|
<el-icon class="header-icon">
|
<TrendCharts />
|
</el-icon>
|
能耗单耗趋势
|
</h2>
|
<div class="chart-card">
|
<div ref="consumptionChart"
|
class="chart-content"></div>
|
</div>
|
</div>
|
<!-- 数据表格 -->
|
<div class="table-section">
|
<h2 class="section-header">
|
<el-icon class="header-icon">
|
<List />
|
</el-icon>
|
能耗单耗数据
|
</h2>
|
<el-table :data="tableData"
|
v-loading="tableLoading"
|
border>
|
<el-table-column prop="meterReadingDate"
|
label="日期"
|
align="center"
|
width="120" />
|
<el-table-column prop="type"
|
label="类型"
|
align="center"
|
width="100">
|
<template #default="scope">
|
<el-tag :type="scope.row.type === '生产' ? 'primary' : 'success'">
|
{{ scope.row.type }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="energyTyep"
|
label="能耗类型"
|
align="center"
|
width="100">
|
<template #default="scope">
|
<el-tag :type="getEnergyTypeType(scope.row.energyTyep)">
|
{{ scope.row.energyTyep }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="consumption"
|
label="用量"
|
align="right"
|
width="120" />
|
<el-table-column prop="cost"
|
label="成本"
|
align="right"
|
width="120">
|
<template #default="scope">
|
<span class="data-value">¥{{ scope.row.cost }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column prop="unitConsumption"
|
label="单耗"
|
align="right">
|
<template #default="scope">
|
<span class="data-value">{{ scope.row.unitConsumption }}</span>
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, onMounted, nextTick } from "vue";
|
import { ElMessage } from "element-plus";
|
import { TrendCharts, List } from "@element-plus/icons-vue";
|
import * as echarts from "echarts";
|
import { energyConsumptionDetailStatistics } from "@/api/energyManagement/energyType";
|
|
// 搜索表单
|
const searchForm = reactive({
|
timeDimension: "year",
|
year: new Date().getFullYear(),
|
month: new Date().getMonth() + 1,
|
energyType: "",
|
});
|
|
// 生成年份选项
|
const years = [];
|
const currentYear = new Date().getFullYear();
|
for (let i = currentYear - 5; i <= currentYear; i++) {
|
years.push(i);
|
}
|
|
// 表格数据
|
const tableData = ref([]);
|
const tableLoading = ref(false);
|
|
// 图表引用
|
const consumptionChart = ref(null);
|
let consumptionChartInstance = null;
|
|
// 获取能耗类型标签类型
|
const getEnergyTypeType = type => {
|
const typeMap = {
|
水: "primary",
|
电: "warning",
|
蒸汽: "success",
|
};
|
return typeMap[type] || "info";
|
};
|
|
// 初始化图表
|
const initChart = () => {
|
nextTick(() => {
|
if (consumptionChart.value) {
|
consumptionChartInstance = echarts.init(consumptionChart.value);
|
updateChart();
|
}
|
});
|
};
|
|
// 更新图表
|
const updateChart = () => {
|
const data = tableData.value;
|
let xAxisData = [];
|
let seriesDataKey = "monthlyData";
|
let seriesDataMap = item => item.unitConsumption;
|
|
// 根据时间维度准备数据
|
if (searchForm.timeDimension === "year") {
|
// 年度模式:12个月
|
xAxisData = [
|
"1月",
|
"2月",
|
"3月",
|
"4月",
|
"5月",
|
"6月",
|
"7月",
|
"8月",
|
"9月",
|
"10月",
|
"11月",
|
"12月",
|
];
|
} else {
|
// 月度模式:该月的每一天
|
const year = searchForm.year;
|
const month = searchForm.month;
|
const daysInMonth = new Date(year, month, 0).getDate();
|
xAxisData = Array.from({ length: daysInMonth }, (_, i) => `${i + 1}日`);
|
seriesDataKey = "dailyData";
|
}
|
|
// 准备图表数据
|
const series = [];
|
const energyTypes = ["水", "电", "蒸汽"];
|
|
energyTypes.forEach(type => {
|
const typeData = data.find(item => item.energyTyep === type);
|
if (typeData) {
|
series.push({
|
name: type,
|
type: "line",
|
data: typeData.cost,
|
smooth: true,
|
symbol: "circle",
|
symbolSize: 8,
|
lineStyle: {
|
width: 3,
|
},
|
itemStyle: {
|
color:
|
getEnergyTypeType(type) === "primary"
|
? "#409EFF"
|
: getEnergyTypeType(type) === "warning"
|
? "#E6A23C"
|
: "#67C23A",
|
},
|
});
|
}
|
});
|
|
const option = {
|
tooltip: {
|
trigger: "axis",
|
backgroundColor: "rgba(255, 255, 255, 0.95)",
|
borderColor: "#409EFF",
|
borderWidth: 1,
|
textStyle: { color: "#303133" },
|
},
|
legend: {
|
data: energyTypes,
|
top: 0,
|
right: 10,
|
textStyle: { color: "#606266" },
|
},
|
grid: {
|
left: "3%",
|
right: "4%",
|
bottom: "10%",
|
top: "15%",
|
containLabel: true,
|
},
|
xAxis: {
|
type: "category",
|
data: xAxisData,
|
axisLabel: {
|
color: "#606266",
|
rotate: searchForm.timeDimension === "month" ? 45 : 0,
|
},
|
axisLine: { lineStyle: { color: "#ebeef5" } },
|
splitLine: { show: false },
|
},
|
yAxis: {
|
type: "value",
|
name: "单耗",
|
nameTextStyle: { color: "#606266" },
|
axisLabel: { color: "#606266" },
|
axisLine: { show: false },
|
splitLine: { lineStyle: { color: "#f0f2f5" } },
|
},
|
series: series,
|
};
|
|
consumptionChartInstance.setOption(option);
|
};
|
|
// 查询
|
const handleQuery = () => {
|
tableLoading.value = true;
|
|
const params = {
|
type: "",
|
state: searchForm.timeDimension === "year" ? "年" : "月",
|
};
|
|
if (searchForm.energyType && searchForm.energyType !== "全部") {
|
params.type = searchForm.energyType;
|
}
|
|
if (searchForm.timeDimension === "year") {
|
params.startDate = searchForm.year + "-01-01";
|
params.endDate = searchForm.year + "-12-31";
|
params.days = 365;
|
} else if (searchForm.timeDimension === "month") {
|
const year = searchForm.year;
|
const month = searchForm.month;
|
const lastDay = new Date(year, month, 0).getDate();
|
params.startDate = `${year}-${String(month).padStart(2, "0")}-01`;
|
params.endDate = `${year}-${String(month).padStart(2, "0")}-${String(
|
lastDay
|
).padStart(2, "0")}`;
|
params.days = lastDay;
|
}
|
|
energyConsumptionDetailStatistics(params)
|
.then(res => {
|
if (res.code === 200) {
|
const data = res.data;
|
tableData.value = data.energyCostDtos || [];
|
updateChart();
|
} else {
|
ElMessage.error(res.message || "获取数据失败");
|
tableData.value = [];
|
}
|
})
|
.catch(err => {
|
console.error("获取数据异常:", err);
|
ElMessage.error("系统异常,获取数据失败");
|
tableData.value = [];
|
})
|
.finally(() => {
|
tableLoading.value = false;
|
});
|
};
|
|
// 重置
|
const handleReset = () => {
|
searchForm.timeDimension = "year";
|
searchForm.year = new Date().getFullYear();
|
searchForm.month = new Date().getMonth() + 1;
|
searchForm.energyType = "";
|
handleQuery();
|
};
|
|
// 导出
|
const handleExport = () => {
|
ElMessage.success("报表导出成功");
|
};
|
|
// 窗口大小变化时重新渲染图表
|
const handleResize = () => {
|
consumptionChartInstance && consumptionChartInstance.resize();
|
};
|
|
onMounted(() => {
|
handleQuery();
|
initChart();
|
window.addEventListener("resize", handleResize);
|
});
|
</script>
|
|
<style scoped lang="scss">
|
.app-container {
|
padding: 20px;
|
}
|
|
.search_form {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 20px;
|
padding: 15px;
|
background-color: #f5f7fa;
|
border-radius: 8px;
|
}
|
|
.chart-section {
|
margin-bottom: 30px;
|
}
|
|
.table-section {
|
margin-bottom: 20px;
|
}
|
|
.section-header {
|
display: flex;
|
align-items: center;
|
font-size: 18px;
|
font-weight: bold;
|
color: #303133;
|
margin-bottom: 15px;
|
padding-left: 10px;
|
border-left: 3px solid #409eff;
|
|
.header-icon {
|
margin-right: 8px;
|
color: #409eff;
|
}
|
}
|
|
.chart-card {
|
background: #fff;
|
border-radius: 4px;
|
border: 1px solid #ebeef5;
|
padding: 20px;
|
|
.chart-content {
|
height: 400px;
|
}
|
}
|
|
.data-value {
|
font-weight: bold;
|
color: #409eff;
|
}
|
</style>
|