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:
@ -33,9 +33,13 @@
|
||||
class="quick-filter-input"
|
||||
placeholder="按字段名/展示名/设备名筛选"
|
||||
/>
|
||||
<div class="filter-actions">
|
||||
<div class="filter-actions" :class="{ 'single-battery-actions-visible': showSingleBatteryImportActions }">
|
||||
<el-button size="small" :disabled="!siteId" @click="openImportConfigDialog">导入配置</el-button>
|
||||
<el-button size="small" type="primary" :disabled="!siteId" @click="exportConfig">导出配置</el-button>
|
||||
<el-button size="small" :disabled="!siteId || singleBatteryImportLoading" @click="downloadSingleBatteryTemplate">下载单体模板</el-button>
|
||||
<el-button size="small" type="success" :disabled="!siteId || singleBatteryImportLoading" @click="openSingleBatteryImportDialog">
|
||||
{{ singleBatteryImportLoading ? '导入中...' : '导入单体电池' }}
|
||||
</el-button>
|
||||
<input
|
||||
ref="configInput"
|
||||
type="file"
|
||||
@ -43,6 +47,13 @@
|
||||
style="display: none"
|
||||
@change="handleConfigFileChange"
|
||||
/>
|
||||
<input
|
||||
ref="singleBatteryImportInput"
|
||||
type="file"
|
||||
accept=".xlsx,.xls"
|
||||
style="display: none"
|
||||
@change="handleSingleBatteryImportFileChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -459,17 +470,56 @@
|
||||
@current-change="handlePointSelectorPageChange"
|
||||
/>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
title="单体电池导入结果"
|
||||
:visible.sync="singleBatteryImportResultVisible"
|
||||
width="980px"
|
||||
append-to-body
|
||||
class="ems-dialog"
|
||||
>
|
||||
<el-alert
|
||||
:title="singleBatteryImportResult.message || '导入完成'"
|
||||
:type="singleBatteryImportResult.committed ? 'success' : 'warning'"
|
||||
:closable="false"
|
||||
style="margin-bottom: 16px;"
|
||||
/>
|
||||
<el-descriptions :column="3" border size="small">
|
||||
<el-descriptions-item label="总行数">{{ singleBatteryImportResult.totalRows || 0 }}</el-descriptions-item>
|
||||
<el-descriptions-item label="成功行数">{{ singleBatteryImportResult.successRows || 0 }}</el-descriptions-item>
|
||||
<el-descriptions-item label="失败行数">{{ singleBatteryImportResult.failureRows || 0 }}</el-descriptions-item>
|
||||
<el-descriptions-item label="新增单体">{{ singleBatteryImportResult.insertedBatteryCount || 0 }}</el-descriptions-item>
|
||||
<el-descriptions-item label="更新单体">{{ singleBatteryImportResult.updatedBatteryCount || 0 }}</el-descriptions-item>
|
||||
<el-descriptions-item label="是否已提交">{{ singleBatteryImportResult.committed ? '是' : '否' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="新增映射">{{ singleBatteryImportResult.insertedMappingCount || 0 }}</el-descriptions-item>
|
||||
<el-descriptions-item label="更新映射">{{ singleBatteryImportResult.updatedMappingCount || 0 }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div v-if="(singleBatteryImportResult.failureDetails || []).length > 0" style="margin-top: 16px;">
|
||||
<div class="import-result-title">失败明细</div>
|
||||
<el-table class="common-table" :data="singleBatteryImportResult.failureDetails" stripe max-height="360">
|
||||
<el-table-column prop="rowNum" label="Excel行号" width="100" />
|
||||
<el-table-column prop="siteId" label="站点ID" width="140" />
|
||||
<el-table-column prop="stackDeviceId" label="电池堆编号" width="140" />
|
||||
<el-table-column prop="clusterDeviceId" label="电池簇编号" width="140" />
|
||||
<el-table-column prop="batteryDeviceId" label="单体编号" width="120" />
|
||||
<el-table-column prop="errorMessage" label="失败原因" min-width="260" />
|
||||
</el-table>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
downloadSingleBatteryMonitorImportTemplate,
|
||||
getPointMatchList,
|
||||
getSingleMonitorProjectPointMapping,
|
||||
getSingleMonitorWorkStatusEnumMappings,
|
||||
importSingleBatteryMonitorMappings,
|
||||
saveSingleMonitorProjectPointMapping,
|
||||
saveSingleMonitorWorkStatusEnumMappings
|
||||
} from '@/api/ems/site'
|
||||
import { saveAs } from 'file-saver'
|
||||
import { blobValidate } from '@/utils/ems'
|
||||
|
||||
export default {
|
||||
name: 'MonitorPointMapping',
|
||||
@ -519,6 +569,20 @@ export default {
|
||||
suppressAutoSave: false,
|
||||
isSaving: false,
|
||||
saveStatusText: '自动保存已开启',
|
||||
singleBatteryImportLoading: false,
|
||||
singleBatteryImportResultVisible: false,
|
||||
singleBatteryImportResult: {
|
||||
committed: false,
|
||||
totalRows: 0,
|
||||
successRows: 0,
|
||||
failureRows: 0,
|
||||
insertedBatteryCount: 0,
|
||||
updatedBatteryCount: 0,
|
||||
insertedMappingCount: 0,
|
||||
updatedMappingCount: 0,
|
||||
message: '',
|
||||
failureDetails: []
|
||||
},
|
||||
lastSavedPointSignature: '',
|
||||
lastSavedEnumSignature: '',
|
||||
workStatusEnumMappings: []
|
||||
@ -561,6 +625,19 @@ export default {
|
||||
this.schedulePointSelectorSearch()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
showSingleBatteryImportActions() {
|
||||
const currentTopMenu = this.topMenuList.find(item => item.code === this.activeTopMenu)
|
||||
if (!currentTopMenu) {
|
||||
return false
|
||||
}
|
||||
if (currentTopMenu.code === 'SBJK_DTDC') {
|
||||
return true
|
||||
}
|
||||
const activeChildCode = this.activeChildMap[this.activeTopMenu] || ''
|
||||
return activeChildCode === 'SBJK_DTDC'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async initMenuStructure() {
|
||||
if (!this.siteId) {
|
||||
@ -716,6 +793,83 @@ export default {
|
||||
this.$refs.configInput.click()
|
||||
}
|
||||
},
|
||||
openSingleBatteryImportDialog() {
|
||||
if (!this.siteId || !this.$refs.singleBatteryImportInput) {
|
||||
return
|
||||
}
|
||||
this.$refs.singleBatteryImportInput.value = ''
|
||||
this.$refs.singleBatteryImportInput.click()
|
||||
},
|
||||
async downloadSingleBatteryTemplate() {
|
||||
if (!this.siteId) {
|
||||
this.$message.warning('璇峰厛閫夋嫨绔欑偣')
|
||||
return
|
||||
}
|
||||
try {
|
||||
const data = await downloadSingleBatteryMonitorImportTemplate(this.siteId)
|
||||
if (!blobValidate(data)) {
|
||||
const text = await data.text()
|
||||
const json = JSON.parse(text)
|
||||
this.$message.error(json.msg || '模板下载失败')
|
||||
return
|
||||
}
|
||||
saveAs(data, `单体电池导入模板_${this.siteId}.xlsx`)
|
||||
} catch (error) {
|
||||
this.$message.error('模板下载失败,请稍后重试')
|
||||
}
|
||||
},
|
||||
handleSingleBatteryImportFileChange(event) {
|
||||
const file = event && event.target && event.target.files && event.target.files[0]
|
||||
if (!file) {
|
||||
return
|
||||
}
|
||||
const isExcel = /\.(xlsx|xls)$/i.test(file.name || '')
|
||||
if (!isExcel) {
|
||||
this.$message.error('仅支持导入 Excel 文件')
|
||||
return
|
||||
}
|
||||
this.importSingleBatteryFile(file)
|
||||
},
|
||||
async importSingleBatteryFile(file) {
|
||||
if (!this.siteId) {
|
||||
this.$message.warning('璇峰厛閫夋嫨绔欑偣')
|
||||
return
|
||||
}
|
||||
const formData = new FormData()
|
||||
formData.append('siteId', this.siteId)
|
||||
formData.append('file', file)
|
||||
this.singleBatteryImportLoading = true
|
||||
try {
|
||||
const response = await importSingleBatteryMonitorMappings(formData)
|
||||
this.singleBatteryImportResult = this.normalizeSingleBatteryImportResult(response?.data || {})
|
||||
this.singleBatteryImportResultVisible = true
|
||||
if (this.singleBatteryImportResult.committed) {
|
||||
await this.initMenuStructure()
|
||||
this.$message.success('单体电池导入成功')
|
||||
} else {
|
||||
this.$message.warning(this.singleBatteryImportResult.message || '导入校验未通过')
|
||||
}
|
||||
} catch (error) {
|
||||
this.$message.error('导入失败,请稍后重试')
|
||||
} finally {
|
||||
this.singleBatteryImportLoading = false
|
||||
}
|
||||
},
|
||||
normalizeSingleBatteryImportResult(result) {
|
||||
const source = result || {}
|
||||
return {
|
||||
committed: !!source.committed,
|
||||
totalRows: Number(source.totalRows || 0),
|
||||
successRows: Number(source.successRows || 0),
|
||||
failureRows: Number(source.failureRows || 0),
|
||||
insertedBatteryCount: Number(source.insertedBatteryCount || 0),
|
||||
updatedBatteryCount: Number(source.updatedBatteryCount || 0),
|
||||
insertedMappingCount: Number(source.insertedMappingCount || 0),
|
||||
updatedMappingCount: Number(source.updatedMappingCount || 0),
|
||||
message: source.message || '',
|
||||
failureDetails: Array.isArray(source.failureDetails) ? source.failureDetails : []
|
||||
}
|
||||
},
|
||||
handleConfigFileChange(event) {
|
||||
const file = event && event.target && event.target.files && event.target.files[0]
|
||||
if (!file) {
|
||||
@ -1570,6 +1724,18 @@ export default {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.filter-actions:not(.single-battery-actions-visible) > .el-button:nth-of-type(3),
|
||||
.filter-actions:not(.single-battery-actions-visible) > .el-button:nth-of-type(4) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.import-result-title {
|
||||
margin-bottom: 10px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.quick-wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
|
||||
Reference in New Issue
Block a user