1.一周充放曲线改为了时间聚合柱状图。

2.PCS最高温度修复bug展示多PCS设备的数据
3.PCS的状态根据状态枚举映射配置的内容显示
4.BMS的总览,增加工作状态、与PCS通讯、与EMS通讯的配置,及关联展示
5.增加批量导入单体电池点位的功能
6.修复计算点可能会出现id与code在一个池子内的问题,再次计算后数据正常
7.计算点增加小数位限制的功能,实时计算与7天历史接口都已经按照配置的小数位进行限制
8.统计报表中的功率曲线改为了按照分钟显示
9.功率曲线出现断点的问题是因为数据计算太密集了导致的,增加了前端连线不断的显示
10.PCS和电池堆的曲线与配置增加了关联设备显示
11.点位映射中的电池温度,增加了多设备
12.收益报表增加升序排列,合并当月所有合计
13.增加业务报表备注功能,可以根据业务设计开发,目前电表报表与收益报表均有备注列可以修改
This commit is contained in:
xiaoyang
2026-04-12 15:18:00 +08:00
parent fd860597de
commit 20df411925
17 changed files with 1272 additions and 460 deletions

View File

@ -1,18 +1,17 @@
<template>
<div style="width:100%" v-loading="loading">
<!-- 搜索栏-->
<el-form :inline="true" class="select-container">
<el-form-item label="时间选择">
<el-date-picker
v-model="dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="yyyy-MM-dd"
:clearable="false"
:picker-options="pickerOptions"
:default-value="defaultDateRange"
v-model="dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="yyyy-MM-dd"
:clearable="false"
:picker-options="pickerOptions"
:default-value="defaultDateRange"
></el-date-picker>
</el-form-item>
<el-form-item>
@ -25,121 +24,77 @@
<el-button type="primary" @click="exportTable" native-type="button">导出</el-button>
</el-form-item>
</el-form>
<!--表格-->
<el-table
class="common-table"
:data="tableData"
show-summary
stripe
style="width: 100%;margin-top:25px;">
<!-- 汇总列-->
class="common-table"
:data="tableData"
:summary-method="getSummaries"
show-summary
stripe
style="width: 100%; margin-top: 25px;"
>
<el-table-column label="汇总" min-width="100px" align="center">
<el-table-column
prop="dataTime"
label="日期"
min-width="100px" align="center">
</el-table-column>
<el-table-column
prop="dayType"
label="日期类型"
min-width="100px" align="center">
</el-table-column>
<el-table-column
prop="weatherDesc"
label="天气情况"
min-width="180px"
align="center">
</el-table-column>
<el-table-column prop="dataTime" label="日期" min-width="100px" align="center"></el-table-column>
<el-table-column prop="dayType" label="日期类型" min-width="100px" align="center"></el-table-column>
<el-table-column prop="weatherDesc" label="天气情况" min-width="180px" align="center"></el-table-column>
</el-table-column>
<!--充电量列-->
<el-table-column label="充电价格" align="center">
<el-table-column
align="center"
prop="activePeakPrice"
label="">
</el-table-column>
<el-table-column
align="center"
prop="activeHighPrice"
label="峰">
</el-table-column>
<el-table-column
align="center"
prop="activeFlatPrice"
label="平">
</el-table-column>
<el-table-column
align="center"
prop="activeValleyPrice"
label="谷">
</el-table-column>
<el-table-column
align="center"
prop="activeTotalPrice"
label="总">
</el-table-column>
<el-table-column align="center" prop="activePeakPrice" label="尖"></el-table-column>
<el-table-column align="center" prop="activeHighPrice" label="峰"></el-table-column>
<el-table-column align="center" prop="activeFlatPrice" label="平"></el-table-column>
<el-table-column align="center" prop="activeValleyPrice" label=""></el-table-column>
<el-table-column align="center" prop="activeTotalPrice" label="总"></el-table-column>
</el-table-column>
<!--充电量列-->
<el-table-column label="放电价格" align="center">
<el-table-column
align="center"
prop="reActivePeakPrice"
label="">
</el-table-column>
<el-table-column
align="center"
prop="reActiveHighPrice"
label="峰">
</el-table-column>
<el-table-column
align="center"
prop="reActiveFlatPrice"
label="平">
</el-table-column>
<el-table-column
align="center"
prop="reActiveValleyPrice"
label="谷">
</el-table-column>
<el-table-column
align="center"
prop="reActiveTotalPrice"
label="总">
</el-table-column>
<el-table-column align="center" prop="reActivePeakPrice" label="尖"></el-table-column>
<el-table-column align="center" prop="reActiveHighPrice" label="峰"></el-table-column>
<el-table-column align="center" prop="reActiveFlatPrice" label="平"></el-table-column>
<el-table-column align="center" prop="reActiveValleyPrice" label=""></el-table-column>
<el-table-column align="center" prop="reActiveTotalPrice" label="总"></el-table-column>
</el-table-column>
<!-- 实际收益-->
<el-table-column label="" align="center" fixed="right">
<el-table-column
prop="actualRevenue"
label="实际收益"
align="center">
</el-table-column>
<el-table-column label="" align="center">
<el-table-column prop="actualRevenue" label="实际收益" align="center"></el-table-column>
</el-table-column>
<el-table-column label="备注" align="center" fixed="right" min-width="260">
<template slot-scope="scope">
<div class="remark-cell">
<span class="remark-text">{{ scope.row.remark || "-" }}</span>
<el-button type="text" @click="editRemark(scope.row)">编辑</el-button>
</div>
</template>
</el-table-column>
</el-table>
<el-pagination
v-show="tableData.length>0"
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-size="pageSize"
:page-sizes="[10, 20, 30, 40]"
layout="total, sizes, prev, pager, next, jumper"
:total="totalSize"
style="margin-top:15px;text-align: center"
v-show="tableData.length > 0"
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-size="pageSize"
:page-sizes="[10, 20, 30, 40]"
layout="total, sizes, prev, pager, next, jumper"
:total="totalSize"
style="margin-top: 15px; text-align: center"
>
</el-pagination>
</div>
</template>
<script>
import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
import {getAmmeterRevenueData} from '@/api/ems/dzjk'
import {formatDate} from "@/filters/ems";
import { batchGetBizRemark, getAmmeterRevenueData, saveBizRemark } from "@/api/ems/dzjk";
import { formatDate } from "@/filters/ems";
const BIZ_TYPE = "stats_report";
const REPORT_KEY = "SYBB";
export default {
name: 'DzjkTjbbSybb',
name: "DzjkTjbbSybb",
mixins: [getQuerySiteId],
data() {
return {
@ -149,81 +104,189 @@ export default {
return time.getTime() > Date.now();
},
},
defaultDateRange: [],//默认展示的时间
defaultDateRange: [],
dateRange: [],
tableData: [],
pageSize: 10,//分页栏当前每个数据总数
pageNum: 1,//分页栏当前页数
totalSize: 0,//table表格数据总数
}
summaryTotals: {},
pageSize: 10,
pageNum: 1,
totalSize: 0,
};
},
methods: {
// 导出表格
buildRemarkKey(dataTime) {
return `${this.siteId}_${dataTime || ""}`;
},
loadRemarks(rows) {
if (!rows.length) return Promise.resolve({});
return batchGetBizRemark({
bizType: BIZ_TYPE,
bizKey1: REPORT_KEY,
bizKey2List: rows.map(row => this.buildRemarkKey(row.dataTime)),
}).then(response => response?.data || {});
},
applyRemarks(rows, remarkMap) {
rows.forEach(row => {
this.$set(row, "remark", remarkMap[this.buildRemarkKey(row.dataTime)] || "");
});
},
toScaledInt(value) {
const num = Number(value);
return Number.isFinite(num) ? Math.round(num * 1000) : 0;
},
sumRowsByProp(rows, prop) {
const total = (rows || []).reduce((sum, row) => sum + this.toScaledInt(row?.[prop]), 0);
return total / 1000;
},
formatSummaryNumber(value) {
const num = Number(value);
if (!Number.isFinite(num)) return "";
return num.toFixed(3).replace(/\.?0+$/, "");
},
buildSummaryTotals(rows) {
const numericProps = [
"activePeakPrice",
"activeHighPrice",
"activeFlatPrice",
"activeValleyPrice",
"activeTotalPrice",
"reActivePeakPrice",
"reActiveHighPrice",
"reActiveFlatPrice",
"reActiveValleyPrice",
"reActiveTotalPrice",
"actualRevenue",
];
return numericProps.reduce((result, prop) => {
result[prop] = this.sumRowsByProp(rows, prop);
return result;
}, {});
},
getSummaries({ columns, data }) {
return columns.map((column, index) => {
if (index === 0) return "合计";
const prop = column.property;
if (!prop) return "";
if (Object.prototype.hasOwnProperty.call(this.summaryTotals, prop)) {
return this.formatSummaryNumber(this.summaryTotals[prop]);
}
const hasNumericValue = (data || []).some(item => Number.isFinite(Number(item?.[prop])));
return hasNumericValue ? this.formatSummaryNumber(this.sumRowsByProp(data, prop)) : "";
});
},
exportTable() {
if (!this.dateRange?.length) return
const [startTime, endTime] = this.dateRange
this.download('ems/statsReport/exportAmmeterRevenueData', {
siteId: this.siteId,
startTime,
endTime,
}, `收益报表_${startTime}-${endTime}.xlsx`)
if (!this.dateRange?.length) return;
const [startTime, endTime] = this.dateRange;
this.download(
"ems/statsReport/exportAmmeterRevenueData",
{
siteId: this.siteId,
startTime,
endTime,
},
`收益报表_${startTime}-${endTime}.xlsx`
);
},
// 搜索
onSearch() {
this.pageNum = 1//每次搜索从1开始搜索
this.getData()
this.pageNum = 1;
this.getData();
},
// 重置
onReset() {
this.dateRange = this.defaultDateRange
this.pageNum = 1//每次搜索从1开始搜索
this.getData()
this.dateRange = this.defaultDateRange;
this.pageNum = 1;
this.getData();
},
// 分页
handleSizeChange(val) {
this.pageSize = val;
this.$nextTick(() => {
this.getData()
})
this.getData();
});
},
handleCurrentChange(val) {
this.pageNum = val
this.pageNum = val;
this.$nextTick(() => {
this.getData()
})
this.getData();
});
},
// 获取数据
getData() {
this.loading = true
const {siteId, pageNum, pageSize} = this
const [startTime = '', endTime = ''] = (this.dateRange || [])
getAmmeterRevenueData({siteId: siteId, startTime, endTime, pageSize, pageNum}).then(response => {
const rows = response?.rows || [];
this.totalSize = response?.total || 0
this.tableData = rows
}).finally(() => {
this.loading = false
editRemark(row) {
this.$prompt("请输入备注", "编辑备注", {
inputValue: row.remark || "",
inputType: "textarea",
inputPlaceholder: "可输入该日报表备注",
confirmButtonText: "保存",
cancelButtonText: "取消",
})
.then(({ value }) => {
return saveBizRemark({
bizType: BIZ_TYPE,
bizKey1: REPORT_KEY,
bizKey2: this.buildRemarkKey(row.dataTime),
remark: value || "",
}).then(() => {
this.$set(row, "remark", value || "");
this.$message.success("备注保存成功");
});
})
.catch(() => {});
},
getData() {
this.loading = true;
const { siteId, pageNum, pageSize } = this;
const [startTime = "", endTime = ""] = this.dateRange || [];
getAmmeterRevenueData({ siteId, startTime, endTime, pageSize, pageNum })
.then(pageResponse => {
const rows = pageResponse?.rows || [];
const total = Number(pageResponse?.total || 0);
this.totalSize = total;
this.tableData = rows;
const tasks = [this.loadRemarks(rows)];
if (total > 0) {
tasks.push(
getAmmeterRevenueData({
siteId,
startTime,
endTime,
pageNum: 1,
pageSize: total,
})
);
}
return Promise.all(tasks);
})
.then(([remarkMap, allResponse]) => {
this.applyRemarks(this.tableData, remarkMap || {});
const allRows = allResponse?.rows || allResponse?.data || [];
this.summaryTotals = this.buildSummaryTotals(allRows);
})
.finally(() => {
this.loading = false;
});
},
init() {
this.dateRange = []
this.tableData = []
this.totalSize = 0
this.pageSize = 10
this.pageNum = 1
let now = new Date(), lastDay = now.getTime(), firstDay = new Date(now.setDate(1)).getTime();
this.dateRange = [];
this.tableData = [];
this.summaryTotals = {};
this.totalSize = 0;
this.pageSize = 10;
this.pageNum = 1;
const now = new Date();
const lastDay = now.getTime();
const firstDay = new Date(new Date().setDate(1)).getTime();
this.defaultDateRange = [formatDate(firstDay), formatDate(lastDay)];
this.dateRange = [formatDate(firstDay), formatDate(lastDay)];
this.getData()
this.getData();
},
},
}
};
</script>
<style scoped lang="scss">
::v-deep {
.common-table.el-table {
.el-table__header-wrapper th, .common-table.el-table .el-table__fixed-header-wrapper th {
.el-table__header-wrapper th,
.common-table.el-table .el-table__fixed-header-wrapper th {
border-bottom: 1px solid #dfe6ec;
}
@ -234,7 +297,20 @@ export default {
}
}
}
}
.remark-cell {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.remark-text {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: left;
}
</style>