2.PCS最高温度修复bug展示多PCS设备的数据 3.PCS的状态根据状态枚举映射配置的内容显示 4.BMS的总览,增加工作状态、与PCS通讯、与EMS通讯的配置,及关联展示 5.增加批量导入单体电池点位的功能 6.修复计算点可能会出现id与code在一个池子内的问题,再次计算后数据正常 7.计算点增加小数位限制的功能,实时计算与7天历史接口都已经按照配置的小数位进行限制 8.统计报表中的功率曲线改为了按照分钟显示 9.功率曲线出现断点的问题是因为数据计算太密集了导致的,增加了前端连线不断的显示 10.PCS和电池堆的曲线与配置增加了关联设备显示 11.点位映射中的电池温度,增加了多设备 12.收益报表增加升序排列,合并当月所有合计 13.增加业务报表备注功能,可以根据业务设计开发,目前电表报表与收益报表均有备注列可以修改
317 lines
9.9 KiB
Vue
317 lines
9.9 KiB
Vue
<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"
|
|
></el-date-picker>
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="primary" @click="onSearch" native-type="button">搜索</el-button>
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button @click="onReset" native-type="button">重置</el-button>
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="primary" @click="exportTable" native-type="button">导出</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
|
|
<el-table
|
|
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>
|
|
|
|
<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>
|
|
|
|
<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>
|
|
|
|
<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"
|
|
>
|
|
</el-pagination>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
|
|
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",
|
|
mixins: [getQuerySiteId],
|
|
data() {
|
|
return {
|
|
loading: false,
|
|
pickerOptions: {
|
|
disabledDate(time) {
|
|
return time.getTime() > Date.now();
|
|
},
|
|
},
|
|
defaultDateRange: [],
|
|
dateRange: [],
|
|
tableData: [],
|
|
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`
|
|
);
|
|
},
|
|
onSearch() {
|
|
this.pageNum = 1;
|
|
this.getData();
|
|
},
|
|
onReset() {
|
|
this.dateRange = this.defaultDateRange;
|
|
this.pageNum = 1;
|
|
this.getData();
|
|
},
|
|
handleSizeChange(val) {
|
|
this.pageSize = val;
|
|
this.$nextTick(() => {
|
|
this.getData();
|
|
});
|
|
},
|
|
handleCurrentChange(val) {
|
|
this.pageNum = val;
|
|
this.$nextTick(() => {
|
|
this.getData();
|
|
});
|
|
},
|
|
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.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();
|
|
},
|
|
},
|
|
};
|
|
</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 {
|
|
border-bottom: 1px solid #dfe6ec;
|
|
}
|
|
|
|
.el-table__footer-wrapper {
|
|
tbody td.el-table__cell {
|
|
color: #000;
|
|
font-weight: bolder;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.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>
|