Files
emsfront/src/views/ems/dzjk/tjbb/sybb/index.vue

317 lines
9.9 KiB
Vue
Raw Normal View History

2025-11-26 17:50:06 +08:00
<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"
2025-11-26 17:50:06 +08:00
></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>
2026-01-28 21:34:58 +08:00
<el-form-item>
<el-button type="primary" @click="exportTable" native-type="button">导出</el-button>
</el-form-item>
2025-11-26 17:50:06 +08:00
</el-form>
2025-11-26 17:50:06 +08:00
<el-table
class="common-table"
:data="tableData"
:summary-method="getSummaries"
show-summary
stripe
style="width: 100%; margin-top: 25px;"
>
2026-01-23 14:18:22 +08:00
<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>
2025-12-08 16:58:43 +08:00
</el-table-column>
2025-12-08 16:58:43 +08:00
<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>
2025-12-08 16:58:43 +08:00
</el-table-column>
2025-12-08 16:58:43 +08:00
<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>
2025-12-08 16:58:43 +08:00
</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>
2026-01-23 14:18:22 +08:00
</el-table-column>
2025-12-08 16:58:43 +08:00
</el-table>
2025-12-08 16:58:43 +08:00
<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"
2025-12-08 16:58:43 +08:00
>
</el-pagination>
2025-11-26 17:50:06 +08:00
</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";
2025-12-08 16:58:43 +08:00
2025-11-26 17:50:06 +08:00
export default {
name: "DzjkTjbbSybb",
2025-11-26 17:50:06 +08:00
mixins: [getQuerySiteId],
data() {
return {
2025-12-08 16:58:43 +08:00
loading: false,
pickerOptions: {
2025-11-26 17:50:06 +08:00
disabledDate(time) {
return time.getTime() > Date.now();
},
},
defaultDateRange: [],
2025-12-08 16:58:43 +08:00
dateRange: [],
tableData: [],
summaryTotals: {},
pageSize: 10,
pageNum: 1,
totalSize: 0,
};
2025-11-26 17:50:06 +08:00
},
2025-12-08 16:58:43 +08:00
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)) : "";
});
},
2026-01-28 21:34:58 +08:00
exportTable() {
if (!this.dateRange?.length) return;
const [startTime, endTime] = this.dateRange;
this.download(
"ems/statsReport/exportAmmeterRevenueData",
{
siteId: this.siteId,
startTime,
endTime,
},
`收益报表_${startTime}-${endTime}.xlsx`
);
},
2025-12-08 16:58:43 +08:00
onSearch() {
this.pageNum = 1;
this.getData();
2025-11-26 17:50:06 +08:00
},
2025-12-08 16:58:43 +08:00
onReset() {
this.dateRange = this.defaultDateRange;
this.pageNum = 1;
this.getData();
2025-11-26 17:50:06 +08:00
},
handleSizeChange(val) {
this.pageSize = val;
2025-12-08 16:58:43 +08:00
this.$nextTick(() => {
this.getData();
});
2025-11-26 17:50:06 +08:00
},
handleCurrentChange(val) {
this.pageNum = val;
2025-12-08 16:58:43 +08:00
this.$nextTick(() => {
this.getData();
});
},
editRemark(row) {
this.$prompt("请输入备注", "编辑备注", {
inputValue: row.remark || "",
inputType: "textarea",
inputPlaceholder: "可输入该日报表备注",
confirmButtonText: "保存",
cancelButtonText: "取消",
2025-11-26 17:50:06 +08:00
})
.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(() => {});
2025-11-26 17:50:06 +08:00
},
2025-12-08 16:58:43 +08:00
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;
});
2025-11-26 17:50:06 +08:00
},
2025-12-08 16:58:43 +08:00
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();
2026-01-13 16:38:21 +08:00
this.defaultDateRange = [formatDate(firstDay), formatDate(lastDay)];
this.dateRange = [formatDate(firstDay), formatDate(lastDay)];
this.getData();
2025-11-26 17:50:06 +08:00
},
},
};
2025-11-26 17:50:06 +08:00
</script>
<style scoped lang="scss">
2025-12-08 16:58:43 +08:00
::v-deep {
2026-01-13 16:38:21 +08:00
.common-table.el-table {
.el-table__header-wrapper th,
.common-table.el-table .el-table__fixed-header-wrapper th {
2026-01-13 16:38:21 +08:00
border-bottom: 1px solid #dfe6ec;
}
.el-table__footer-wrapper {
tbody td.el-table__cell {
color: #000;
font-weight: bolder;
}
}
2025-11-26 17:50:06 +08:00
}
}
2026-01-13 16:38:21 +08:00
.remark-cell {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
2025-11-26 17:50:06 +08:00
}
.remark-text {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: left;
}
2025-11-26 17:50:06 +08:00
</style>