From fa281e483a5fef9de01d8e08f258ebd8a7fca8eb Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期一, 23 三月 2026 13:47:28 +0800
Subject: [PATCH] 优化标准/实际成本对比分析页面的样式和功能,增加背景元素,改进KPI展示,支持自定义排序功能
---
src/views/costAccounting/energyCosts/index.vue | 232 ++++++++++++++++++++++++++++++++-------------------------
1 files changed, 131 insertions(+), 101 deletions(-)
diff --git a/src/views/costAccounting/energyCosts/index.vue b/src/views/costAccounting/energyCosts/index.vue
index e841483..89e1a2a 100644
--- a/src/views/costAccounting/energyCosts/index.vue
+++ b/src/views/costAccounting/energyCosts/index.vue
@@ -42,7 +42,7 @@
value="姘�" />
</el-select>
</el-form-item> -->
- <el-form-item label="鑳借�楃敤閫�">
+ <!-- <el-form-item label="鑳借�楃敤閫�">
<el-select
v-model="searchForm.type"
placeholder=""
@@ -53,7 +53,7 @@
<el-option label="鐢熶骇" value="鐢熶骇" />
<el-option label="鍔炲叕" value="鍔炲叕" />
</el-select>
- </el-form-item>
+ </el-form-item> -->
<el-form-item label="鏃堕棿鑼冨洿">
<el-date-picker
v-if="statisticsType === 'day'"
@@ -112,7 +112,7 @@
<div class="kpi-left">
<div class="kpi-label">鎬昏兘鑰楁垚鏈�</div>
<div class="kpi-value">
- 楼{{ formatMoney(animatedOverview.totalCost) }}
+ 楼{{ formatMoney(animatedOverview.totalEnergyCost) }}
</div>
<div class="kpi-meta">
<span
@@ -143,7 +143,7 @@
<button
class="kpi-action"
type="button"
- @click="copyKpi('totalCost')"
+ @click="copyKpi('totalEnergyCost')"
>
澶嶅埗
</button>
@@ -165,7 +165,7 @@
<div class="kpi-left">
<div class="kpi-label">鐢熶骇鑳借�楁垚鏈�</div>
<div class="kpi-value">
- 楼{{ formatMoney(animatedOverview.productionCost) }}
+ 楼{{ formatMoney(animatedOverview.productEnergyCost) }}
</div>
<div class="kpi-meta">
<span
@@ -196,7 +196,7 @@
<button
class="kpi-action"
type="button"
- @click="copyKpi('productionCost')"
+ @click="copyKpi('productEnergyCost')"
>
澶嶅埗
</button>
@@ -218,7 +218,7 @@
<div class="kpi-left">
<div class="kpi-label">鍔炲叕鑳借�楁垚鏈�</div>
<div class="kpi-value">
- 楼{{ formatMoney(animatedOverview.officeCost) }}
+ 楼{{ formatMoney(animatedOverview.officeEnergyCost) }}
</div>
<div class="kpi-meta">
<span
@@ -249,7 +249,7 @@
<button
class="kpi-action"
type="button"
- @click="copyKpi('officeCost')"
+ @click="copyKpi('officeEnergyCost')"
>
澶嶅埗
</button>
@@ -270,7 +270,7 @@
<div class="kpi-left">
<div class="kpi-label">骞冲潎鎴愭湰</div>
<div class="kpi-value">
- 楼{{ formatMoney(animatedOverview.avgCost) }}
+ 楼{{ formatMoney(animatedOverview.averageEnergyCost) }}
<span class="kpi-unit"
>/{{ statisticsType === "day" ? "鏃�" : "鏈�" }}</span
>
@@ -286,7 +286,7 @@
<button
class="kpi-action"
type="button"
- @click="copyKpi('avgCost')"
+ @click="copyKpi('averageEnergyCost')"
>
澶嶅埗
</button>
@@ -469,19 +469,19 @@
<el-card class="chart-card" shadow="never">
<template #header>
<div class="chart-head">
- <span class="chart-title">鑳借�楀崟浠峰姣�</span>
+ <span class="chart-title">鑳借�楃敤閲忓姣�</span>
<div class="chart-tools" @click.stop>
<button
class="chart-tool"
type="button"
- @click="downloadChart('price', '鑳借�楀崟浠峰姣�')"
+ @click="downloadChart('unit', '鑳借�楃敤閲忓姣�')"
>
涓嬭浇
</button>
<button
class="chart-tool"
type="button"
- @click="openBigChart('price', '鑳借�楀崟浠峰姣�')"
+ @click="openBigChart('unit', '鑳借�楃敤閲忓姣�')"
>
澶у浘
</button>
@@ -489,13 +489,13 @@
</div>
</template>
<div
- ref="priceChartWrap"
+ ref="unitChartWrap"
class="chart-wrap"
v-loading="tableLoading"
>
<div
- ref="priceChart"
- class="chart-content"
+ ref="unitChart"
+ class="chart-content"
v-show="hasTableData"
></div>
<div class="chart-empty" v-show="!hasTableData">
@@ -574,7 +574,7 @@
sortable="custom"
/>
<el-table-column
- prop="energyType"
+ prop="energyTyep"
label="鑳借�楃被鍨�"
width="100"
align="center"
@@ -583,8 +583,8 @@
filter-placement="bottom-end"
>
<template #default="scope">
- <el-tag :type="getEnergyTypeType(scope.row.energyType)">
- {{ scope.row.energyType }}
+ <el-tag :type="getEnergyTypeType(scope.row.energyTyep)">
+ {{ scope.row.energyTyep }}
</el-tag>
</template>
</el-table-column>
@@ -598,28 +598,28 @@
filter-placement="bottom-end"
>
<template #default="scope">
- <el-tag :type="scope.row.type === '鐢熶骇' ? 'primary' : 'info'">
+ <el-tag :type="scope.row.type === '鐢熶骇' ? 'primary' : 'warning'">
{{ scope.row.type }}
</el-tag>
</template>
</el-table-column>
- <el-table-column prop="consumption" label="鐢ㄩ噺" align="right">
+ <el-table-column prop="dosage" label="鐢ㄩ噺" align="right">
<template #default="scope">
- <span class="consumption-value">{{
- formatNumber(scope.row.consumption, 2)
+ <span class="unit-value">{{
+ formatNumber(scope.row.dosage, 2)
}}</span>
- <span class="consumption-unit">{{ scope.row.unit }}</span>
+ <span class="unit-unit">{{ scope.row.unit }}</span>
</template>
</el-table-column>
<el-table-column
- prop="price"
+ prop="unitPrice"
label="鍗曚环(鍏�)"
align="right"
sortable="custom"
>
<template #default="scope">
<span class="price-value">{{
- formatNumber(scope.row.price, 2)
+ formatNumber(scope.row.unitPrice, 2)
}}</span>
</template>
</el-table-column>
@@ -674,14 +674,14 @@
} from "@element-plus/icons-vue";
import * as echarts from "echarts";
// import { energyCostStatistics } from "@/api/costAccounting/energyCosts";
-import { energyConsumptionDetailStatistics } from "@/api/energyManagement/energyType";
+import { energyConsumptionDetailAccount } from "@/api/energyManagement/energyType";
// 缁熻缁村害锛歞ay-鎸夋棩锛宮onth-鎸夋湀
const statisticsType = ref("day");
// 鎼滅储琛ㄥ崟
const searchForm = reactive({
// energyType: "",
- type: "",
+ // type: "",
dateRange: (() => {
// 榛樿鏈�杩�7澶�
const end = new Date();
@@ -705,18 +705,18 @@
// 缁熻姒傝
const overview = reactive({
- totalCost: "0.00",
- productionCost: "0.00",
- officeCost: "0.00",
- avgCost: "0.00",
+ totalEnergyCost: "0.00",
+ productEnergyCost: "0.00",
+ officeEnergyCost: "0.00",
+ averageEnergyCost: "0.00",
});
const selectedKpi = ref("all"); // all | production | office
const animatedOverview = reactive({
- totalCost: 0,
- productionCost: 0,
- officeCost: 0,
- avgCost: 0,
+ totalEnergyCost: 0,
+ productEnergyCost: 0,
+ officeEnergyCost: 0,
+ averageEnergyCost: 0,
});
const formatMoney = (v) => {
@@ -754,10 +754,10 @@
watch(
() => ({ ...overview }),
(val) => {
- animateNumber("totalCost", Number.parseFloat(val.totalCost));
- animateNumber("productionCost", Number.parseFloat(val.productionCost));
- animateNumber("officeCost", Number.parseFloat(val.officeCost));
- animateNumber("avgCost", Number.parseFloat(val.avgCost));
+ animateNumber("totalEnergyCost", Number.parseFloat(val.totalEnergyCost));
+ animateNumber("productEnergyCost", Number.parseFloat(val.productEnergyCost));
+ animateNumber("officeEnergyCost", Number.parseFloat(val.officeEnergyCost));
+ animateNumber("averageEnergyCost", Number.parseFloat(val.averageEnergyCost));
},
{ deep: true, immediate: true }
);
@@ -846,10 +846,10 @@
const copyKpi = async (field) => {
const map = {
- totalCost: animatedOverview.totalCost,
- productionCost: animatedOverview.productionCost,
- officeCost: animatedOverview.officeCost,
- avgCost: animatedOverview.avgCost,
+ totalEnergyCost: animatedOverview.totalEnergyCost,
+ productEnergyCost: animatedOverview.productEnergyCost,
+ officeEnergyCost: animatedOverview.officeEnergyCost,
+ averageEnergyCost: animatedOverview.averageEnergyCost,
};
const raw = map[field];
const text = `楼${formatMoney(raw)}`;
@@ -875,13 +875,13 @@
if (key === "cost") return costChartInstance;
if (key === "type") return typeChartInstance;
if (key === "purpose") return purposeChartInstance;
- if (key === "price") return priceChartInstance;
+ if (key === "unit") return unitChartInstance;
return null;
};
const ensurePanelForChart = (key) => {
if (key === "cost" || key === "type") chartPanel.value = "core";
- if (key === "purpose" || key === "price") chartPanel.value = "advanced";
+ if (key === "purpose" || key === "unit") chartPanel.value = "advanced";
};
const downloadChart = (key, title) => {
@@ -967,7 +967,7 @@
const prop = sortState.prop;
const direction = sortState.order === "ascending" ? 1 : -1;
- const numFields = new Set(["price", "cost", "consumption"]);
+ const numFields = new Set(["price", "cost", "unit"]);
return data.sort((a, b) => {
const av = a?.[prop];
@@ -997,7 +997,7 @@
{ text: "鍔炲叕", value: "鍔炲叕" },
];
-const filterEnergyType = (value, row) => row.energyType === value;
+const filterEnergyType = (value, row) => row.energyTyep === value;
const filterEnergyPurpose = (value, row) => row.type === value;
// 鍒嗛〉
@@ -1011,12 +1011,12 @@
const costChart = ref(null);
const typeChart = ref(null);
const purposeChart = ref(null);
-const priceChart = ref(null);
+const unitChart = ref(null);
const costChartWrap = ref(null);
const typeChartWrap = ref(null);
const purposeChartWrap = ref(null);
-const priceChartWrap = ref(null);
+const unitChartWrap = ref(null);
const tableAnchor = ref(null);
@@ -1044,28 +1044,32 @@
let costChartInstance = null;
let typeChartInstance = null;
let purposeChartInstance = null;
-let priceChartInstance = null;
+let unitChartInstance = null;
// 鍥捐〃鍖哄垏鎹細core | advanced | none锛堢偣鍑诲綋鍓嶉�変腑鍙敹璧凤級
const chartPanel = ref("core");
const ensureChartsReady = (panel) => {
if (panel === "core") {
- if (costChart.value && !costChartInstance)
+ if (costChart.value && !costChartInstance) {
costChartInstance = echarts.init(costChart.value);
- if (typeChart.value && !typeChartInstance)
+ setTimeout(() => costChartInstance?.resize(), 50);
+ }
+ if (typeChart.value && !typeChartInstance) {
typeChartInstance = echarts.init(typeChart.value);
- if (costChartInstance) updateCostChart();
- if (typeChartInstance) updateTypeChart();
+ setTimeout(() => typeChartInstance?.resize(), 50);
+ }
return;
}
if (panel === "advanced") {
- if (purposeChart.value && !purposeChartInstance)
+ if (purposeChart.value && !purposeChartInstance) {
purposeChartInstance = echarts.init(purposeChart.value);
- if (priceChart.value && !priceChartInstance)
- priceChartInstance = echarts.init(priceChart.value);
- if (purposeChartInstance) updatePurposeChart();
- if (priceChartInstance) updatePriceChart();
+ setTimeout(() => purposeChartInstance?.resize(), 50);
+ }
+ if (unitChart.value && !unitChartInstance) {
+ unitChartInstance = echarts.init(unitChart.value);
+ setTimeout(() => unitChartInstance?.resize(), 50);
+ }
}
};
@@ -1089,6 +1093,16 @@
watch(chartPanel, (val) => {
if (val !== "none") resizeChartsAfterExpand();
});
+
+// 鐩戝惉琛ㄦ牸鏁版嵁鍙樺寲锛岀‘淇濇暟鎹姞杞藉悗鍥捐〃姝g‘娓叉煋
+watch(tableData, () => {
+ nextTick(() => {
+ updateCharts();
+ nextTick(() => {
+ handleResize();
+ });
+ });
+}, { deep: true });
// 鑾峰彇鑳借�楃被鍨嬫爣绛剧被鍨�
const getEnergyTypeType = (type) => {
@@ -1199,10 +1213,10 @@
const typeCosts = {};
data.forEach((item) => {
- if (!typeCosts[item.energyType]) {
- typeCosts[item.energyType] = 0;
+ if (!typeCosts[item.energyTyep]) {
+ typeCosts[item.energyTyep] = 0;
}
- typeCosts[item.energyType] += parseFloat(item.cost);
+ typeCosts[item.energyTyep] += parseFloat(item.cost);
});
const chartData = Object.entries(typeCosts).map(([name, value]) => ({
@@ -1331,26 +1345,32 @@
purposeChartInstance.setOption(option);
};
-// 鏇存柊鑳借�楀崟浠峰姣斿浘
-const updatePriceChart = () => {
+// 鏇存柊鑳借�楃敤閲忓姣斿浘
+const updateConsumptionChart = () => {
const data = tableData.value;
- const priceData = {};
+ const unitData = {};
data.forEach((item) => {
- if (!priceData[item.energyType]) {
- priceData[item.energyType] = {
+ if (!unitData[item.energyTyep]) {
+ unitData[item.energyTyep] = {
鐢熶骇: 0,
鍔炲叕: 0,
};
}
- if (priceData[item.energyType].hasOwnProperty(item.type)) {
- priceData[item.energyType][item.type] = parseFloat(item.price);
+ if (unitData[item.energyTyep].hasOwnProperty(item.type)) {
+ unitData[item.energyTyep][item.type] += parseFloat(
+ item.dosage || 0
+ );
}
});
- const energyTypes = Object.keys(priceData);
- const productionPrices = energyTypes.map((type) => priceData[type].鐢熶骇);
- const officePrices = energyTypes.map((type) => priceData[type].鍔炲叕);
+ const energyTypes = Object.keys(unitData);
+ const productionConsumptions = energyTypes.map(
+ (type) => unitData[type].鐢熶骇
+ );
+ const officeConsumptions = energyTypes.map(
+ (type) => unitData[type].鍔炲叕
+ );
const option = {
tooltip: {
@@ -1364,7 +1384,7 @@
"box-shadow: 0 14px 40px rgba(15,23,42,.14); border-radius: 12px;",
},
legend: {
- data: ["鐢熶骇鑳借�楀崟浠�", "鍔炲叕鑳借�楀崟浠�"],
+ data: ["鐢熶骇鑳借�楃敤閲�", "鍔炲叕鑳借�楃敤閲�"],
top: 0,
right: 10,
textStyle: { color: "rgba(15, 23, 42, 0.62)" },
@@ -1385,7 +1405,7 @@
},
yAxis: {
type: "value",
- name: "鍗曚环(鍏�)",
+ name: "鐢ㄩ噺",
nameTextStyle: { color: "rgba(15, 23, 42, 0.58)" },
axisLabel: { color: "rgba(15, 23, 42, 0.58)" },
axisLine: { show: false },
@@ -1393,9 +1413,9 @@
},
series: [
{
- name: "鐢熶骇鑳借�楀崟浠�",
+ name: "鐢熶骇鑳借�楃敤閲�",
type: "bar",
- data: productionPrices,
+ data: productionConsumptions,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#2f6fed" },
@@ -1405,9 +1425,9 @@
},
},
{
- name: "鍔炲叕鑳借�楀崟浠�",
+ name: "鍔炲叕鑳借�楃敤閲�",
type: "bar",
- data: officePrices,
+ data: officeConsumptions,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#16a34a" },
@@ -1418,7 +1438,7 @@
},
],
};
- priceChartInstance.setOption(option);
+ unitChartInstance.setOption(option);
};
// 缁熻缁村害鍒囨崲
@@ -1447,6 +1467,7 @@
// 鏌ヨ
const handleQuery = () => {
+
queryPulse.value = true;
window.setTimeout(() => {
queryPulse.value = false;
@@ -1457,7 +1478,7 @@
const params = {
days: 0,
// energyType: searchForm.energyType || undefined,
- type: searchForm.type || undefined,
+ // type: searchForm.type || undefined,
pageNum: page.current,
pageSize: page.size,
};
@@ -1505,36 +1526,36 @@
}
// 璋冪敤鎺ュ彛鑾峰彇鏁版嵁
- energyConsumptionDetailStatistics(params)
+ energyConsumptionDetailAccount(params)
.then((res) => {
if (res.code === 200) {
const data = res.data;
- overview.totalCost = data.totalEnergyConsumption || "0";
- overview.productionCost = data.totalEnergyCost || "0";
- overview.avgCost = data.averageConsumption || "0";
- overview.officeCost = data.changeVite || 0;
+ overview.totalEnergyCost = data.totalEnergyCost || "0";
+ overview.productEnergyCost = data.productEnergyCost || "0";
+ overview.officeEnergyCost = data.officeEnergyCost || "0";
+ overview.averageEnergyCost = data.averageEnergyCost || "0";
// 澶勭悊琛ㄦ牸鏁版嵁
- tableData.value = data.energyCostDtos || [];
+ tableData.value = data.energyConsumptionDetailDtoList || [];
page.total = tableData.value.length || 0;
} else {
ElMessage.error(res.message || "鑾峰彇鏁版嵁澶辫触");
tableData.value = [];
page.total = 0;
- overview.totalCost = "0.00";
- overview.productionCost = "0.00";
- overview.officeCost = "0.00";
- overview.avgCost = "0.00";
+ overview.totalEnergyCost = "0.00";
+ overview.productEnergyCost = "0.00";
+ overview.officeEnergyCost = "0.00";
+ overview.averageEnergyCost = "0.00";
}
})
.catch((err) => {
ElMessage.error("鑾峰彇鏁版嵁寮傚父");
tableData.value = [];
page.total = 0;
- overview.totalCost = "0.00";
- overview.productionCost = "0.00";
- overview.officeCost = "0.00";
- overview.avgCost = "0.00";
+ overview.totalEnergyCost = "0.00";
+ overview.productEnergyCost = "0.00";
+ overview.officeEnergyCost = "0.00";
+ overview.averageEnergyCost = "0.00";
})
.finally(() => {
tableLoading.value = false;
@@ -1545,10 +1566,19 @@
// 鏇存柊鎵�鏈夊浘琛�
const updateCharts = () => {
nextTick(() => {
+ // 纭繚 core 闈㈡澘鐨勫浘琛ㄥ缁堝垵濮嬪寲锛堝洜涓洪粯璁ゆ樉绀虹殑鏄� core锛�
+ ensureChartsReady("core");
+
+ // 鍚屾椂涔熷垵濮嬪寲褰撳墠鍙闈㈡澘鐨勫浘琛�
+ if (chartPanel.value === "advanced") {
+ ensureChartsReady("advanced");
+ }
+
+ // 鏇存柊鎵�鏈夊凡鍒濆鍖栫殑鍥捐〃
if (costChartInstance) updateCostChart();
if (typeChartInstance) updateTypeChart();
if (purposeChartInstance) updatePurposeChart();
- if (priceChartInstance) updatePriceChart();
+ if (unitChartInstance) updateConsumptionChart();
});
};
@@ -1600,7 +1630,7 @@
costChartInstance && costChartInstance.resize();
typeChartInstance && typeChartInstance.resize();
purposeChartInstance && purposeChartInstance.resize();
- priceChartInstance && priceChartInstance.resize();
+ unitChartInstance && unitChartInstance.resize();
};
onMounted(() => {
@@ -1715,7 +1745,7 @@
}
.filter-form {
- flex: 1 1 auto;
+ flex: 0.1 1 auto;
min-width: 0;
}
@@ -2607,12 +2637,12 @@
width: 100%;
}
-.consumption-value {
+.unit-value {
font-weight: bold;
color: var(--lux-primary);
}
-.consumption-unit {
+.unit-unit {
font-size: 12px;
color: var(--lux-muted);
margin-left: 2px;
@@ -2739,4 +2769,4 @@
max-height: 600px;
opacity: 1;
}
-</style>
\ No newline at end of file
+</style>
--
Gitblit v1.9.3