1. 单体电池批量更改为一个批量生成的按钮

2. 运行曲线数据改用电表报表的数据
This commit is contained in:
xiaoyang
2026-04-15 22:44:21 +08:00
parent b73999bd23
commit 801d8eab1d
3 changed files with 262 additions and 242 deletions

View File

@ -36,9 +36,8 @@
<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 v-if="showSingleBatteryImportActions" size="small" type="success" :disabled="!siteId || singleBatteryInitLoading" @click="openSingleBatteryInitDialog">
{{ singleBatteryInitLoading ? '初始化中...' : '初始化单体电池配置' }}
</el-button>
<input
ref="configInput"
@ -47,13 +46,6 @@
style="display: none"
@change="handleConfigFileChange"
/>
<input
ref="singleBatteryImportInput"
type="file"
accept=".xlsx,.xls"
style="display: none"
@change="handleSingleBatteryImportFileChange"
/>
</div>
</div>
@ -471,55 +463,73 @@
/>
</el-dialog>
<el-dialog
title="单体电池导入结果"
:visible.sync="singleBatteryImportResultVisible"
title="初始化单体电池配置"
:visible.sync="singleBatteryInitDialogVisible"
width="560px"
append-to-body
class="ems-dialog"
>
<el-form label-width="110px" size="small">
<el-form-item label="电池堆">
<el-select v-model="singleBatteryInitForm.stackDeviceId" placeholder="请选择电池堆" style="width: 100%" @change="handleSingleBatteryStackChange">
<el-option v-for="item in singleBatteryStackOptions" :key="item.id || item.deviceId || item" :label="item.name || item.deviceName || item.id || item.deviceId || item" :value="item.id || item.deviceId || item" />
</el-select>
</el-form-item>
<el-form-item label="电池簇">
<el-select v-model="singleBatteryInitForm.clusterDeviceId" placeholder="请选择电池簇" style="width: 100%">
<el-option v-for="item in singleBatteryClusterOptions" :key="item.id || item.deviceId || item" :label="item.name || item.deviceName || item.id || item.deviceId || item" :value="item.id || item.deviceId || item" />
</el-select>
</el-form-item>
<el-form-item label="目标数量">
<el-input-number v-model="singleBatteryInitForm.targetCount" :min="1" :precision="0" controls-position="right" style="width: 220px" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="singleBatteryInitDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="singleBatteryInitLoading" @click="submitSingleBatteryInit">确定初始化</el-button>
</div>
</el-dialog>
<el-dialog
title="初始化结果"
:visible.sync="singleBatteryInitResultVisible"
width="980px"
append-to-body
class="ems-dialog"
>
<el-alert
:title="singleBatteryImportResult.message || '导入完成'"
:type="singleBatteryImportResult.committed ? 'success' : 'warning'"
:title="singleBatteryInitResult.message || '初始化完成'"
:type="singleBatteryInitResult.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-item label="站点ID">{{ singleBatteryInitResult.siteId || '-' }}</el-descriptions-item>
<el-descriptions-item label="初始化范围">{{ singleBatteryInitResult.scopeType === 'stack' ? '电池堆' : '电池簇' }}</el-descriptions-item>
<el-descriptions-item label="范围设备ID">{{ singleBatteryInitResult.scopeDeviceId || '-' }}</el-descriptions-item>
<el-descriptions-item label="目标数量">{{ singleBatteryInitResult.targetCount || 0 }}</el-descriptions-item>
<el-descriptions-item label="现有单体">{{ singleBatteryInitResult.existingBatteryCount || 0 }}</el-descriptions-item>
<el-descriptions-item label="已初始化单体">{{ singleBatteryInitResult.initializedBatteryCount || 0 }}</el-descriptions-item>
<el-descriptions-item label="新增单体">{{ singleBatteryInitResult.insertedBatteryCount || 0 }}</el-descriptions-item>
<el-descriptions-item label="命中点位">{{ singleBatteryInitResult.pointHitCount || 0 }}</el-descriptions-item>
<el-descriptions-item label="固定值回填">{{ singleBatteryInitResult.fixedValueFallbackCount || 0 }}</el-descriptions-item>
<el-descriptions-item label="新增映射">{{ singleBatteryInitResult.insertedMappingCount || 0 }}</el-descriptions-item>
<el-descriptions-item label="更新映射">{{ singleBatteryInitResult.updatedMappingCount || 0 }}</el-descriptions-item>
<el-descriptions-item label="是否成功">{{ singleBatteryInitResult.committed ? '是' : '否' }}</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,
initializeSingleBatteryMonitorMappings,
saveSingleMonitorProjectPointMapping,
saveSingleMonitorWorkStatusEnumMappings
} from '@/api/ems/site'
import { saveAs } from 'file-saver'
import { blobValidate } from '@/utils/ems'
import { getClusterNameList, getStackNameList } from '@/api/ems/dzjk'
export default {
name: 'MonitorPointMapping',
@ -569,19 +579,30 @@ export default {
suppressAutoSave: false,
isSaving: false,
saveStatusText: '自动保存已开启',
singleBatteryImportLoading: false,
singleBatteryImportResultVisible: false,
singleBatteryImportResult: {
singleBatteryInitLoading: false,
singleBatteryInitDialogVisible: false,
singleBatteryInitResultVisible: false,
singleBatteryStackOptions: [],
singleBatteryClusterOptions: [],
singleBatteryInitForm: {
stackDeviceId: '',
clusterDeviceId: '',
targetCount: 1
},
singleBatteryInitResult: {
committed: false,
totalRows: 0,
successRows: 0,
failureRows: 0,
siteId: '',
scopeType: 'stack',
scopeDeviceId: '',
targetCount: 0,
existingBatteryCount: 0,
initializedBatteryCount: 0,
insertedBatteryCount: 0,
updatedBatteryCount: 0,
pointHitCount: 0,
fixedValueFallbackCount: 0,
insertedMappingCount: 0,
updatedMappingCount: 0,
message: '',
failureDetails: []
message: ''
},
lastSavedPointSignature: '',
lastSavedEnumSignature: '',
@ -793,81 +814,85 @@ export default {
this.$refs.configInput.click()
}
},
openSingleBatteryImportDialog() {
if (!this.siteId || !this.$refs.singleBatteryImportInput) {
return
}
this.$refs.singleBatteryImportInput.value = ''
this.$refs.singleBatteryImportInput.click()
},
async downloadSingleBatteryTemplate() {
async openSingleBatteryInitDialog() {
if (!this.siteId) {
this.$message.warning('璇峰厛閫夋嫨绔欑偣')
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('模板下载失败,请稍后重试')
}
this.singleBatteryInitDialogVisible = true
this.singleBatteryInitForm.stackDeviceId = ''
this.singleBatteryInitForm.clusterDeviceId = ''
this.singleBatteryInitForm.targetCount = 1
await this.loadSingleBatteryStackOptions()
this.singleBatteryClusterOptions = []
},
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 loadSingleBatteryStackOptions() {
const response = await getStackNameList(this.siteId)
this.singleBatteryStackOptions = Array.isArray(response?.data) ? response.data : []
},
async importSingleBatteryFile(file) {
if (!this.siteId) {
this.$message.warning('璇峰厛閫夋嫨绔欑偣')
async handleSingleBatteryStackChange(stackDeviceId) {
this.singleBatteryInitForm.clusterDeviceId = ''
if (!stackDeviceId) {
this.singleBatteryClusterOptions = []
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
}
const response = await getClusterNameList({ stackDeviceId, siteId: this.siteId })
this.singleBatteryClusterOptions = Array.isArray(response?.data) ? response.data : []
},
normalizeSingleBatteryImportResult(result) {
normalizeSingleBatteryInitResult(result) {
const source = result || {}
return {
committed: !!source.committed,
totalRows: Number(source.totalRows || 0),
successRows: Number(source.successRows || 0),
failureRows: Number(source.failureRows || 0),
siteId: source.siteId || '',
scopeType: source.scopeType || 'stack',
scopeDeviceId: source.scopeDeviceId || '',
targetCount: Number(source.targetCount || 0),
existingBatteryCount: Number(source.existingBatteryCount || 0),
initializedBatteryCount: Number(source.initializedBatteryCount || 0),
insertedBatteryCount: Number(source.insertedBatteryCount || 0),
updatedBatteryCount: Number(source.updatedBatteryCount || 0),
pointHitCount: Number(source.pointHitCount || 0),
fixedValueFallbackCount: Number(source.fixedValueFallbackCount || 0),
insertedMappingCount: Number(source.insertedMappingCount || 0),
updatedMappingCount: Number(source.updatedMappingCount || 0),
message: source.message || '',
failureDetails: Array.isArray(source.failureDetails) ? source.failureDetails : []
message: source.message || ''
}
},
async submitSingleBatteryInit() {
if (!this.siteId) {
this.$message.warning('请先选择站点')
return
}
if (!this.singleBatteryInitForm.stackDeviceId) {
this.$message.warning('请选择电池堆')
return
}
if (!this.singleBatteryInitForm.clusterDeviceId) {
this.$message.warning('请选择电池簇')
return
}
const scopeType = 'cluster'
const scopeDeviceId = this.singleBatteryInitForm.clusterDeviceId
this.singleBatteryInitLoading = true
try {
const response = await initializeSingleBatteryMonitorMappings({
siteId: this.siteId,
scopeType,
scopeDeviceId,
targetCount: this.singleBatteryInitForm.targetCount
})
this.singleBatteryInitResult = this.normalizeSingleBatteryInitResult(response?.data || {})
this.singleBatteryInitDialogVisible = false
this.singleBatteryInitResultVisible = true
if (this.singleBatteryInitResult.committed) {
await this.initMenuStructure()
this.$message.success('初始化单体电池配置成功')
} else {
this.$message.warning(this.singleBatteryInitResult.message || '初始化未完成')
}
} catch (error) {
this.$message.error(error?.message || '初始化失败,请稍后重试')
} finally {
this.singleBatteryInitLoading = false
}
},
handleConfigFileChange(event) {