From 41a3ab45b36a64c528764124ad48abc1a3f59a42 Mon Sep 17 00:00:00 2001 From: dashixiong Date: Sun, 15 Feb 2026 16:24:29 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/ems/dzjk.js | 583 +++++++- src/api/ems/site.js | 35 +- src/components/Ems/SingleSquareBox/index.vue | 16 +- src/layout/components/Navbar.vue | 7 +- .../ems/dzjk/clpz/runtimeParam/index.vue | 156 ++- src/views/ems/dzjk/home/ActiveChart.vue | 75 +- src/views/ems/dzjk/home/WeekChart.vue | 77 +- src/views/ems/dzjk/home/index.vue | 79 +- src/views/ems/dzjk/sbjk/RealTimeBaseInfo.vue | 101 +- src/views/ems/dzjk/sbjk/bmsdcc/index.vue | 210 ++- src/views/ems/dzjk/sbjk/bmszl/index.vue | 185 ++- src/views/ems/dzjk/sbjk/db/index.vue | 426 +++--- src/views/ems/dzjk/sbjk/dh/index.vue | 28 +- src/views/ems/dzjk/sbjk/ems/index.vue | 316 +++-- src/views/ems/dzjk/sbjk/index.vue | 1 - src/views/ems/dzjk/sbjk/pcs/index.vue | 241 +++- src/views/ems/dzjk/sbjk/ssyx/CnglqxChart.vue | 139 +- src/views/ems/dzjk/sbjk/ssyx/DcpjsocChart.vue | 88 +- src/views/ems/dzjk/sbjk/ssyx/DcpjwdChart.vue | 90 +- src/views/ems/dzjk/sbjk/ssyx/PocpjwdChart.vue | 108 +- src/views/ems/dzjk/sbjk/ssyx/index.vue | 29 +- src/views/ems/dzjk/sbjk/xf/index.vue | 29 +- src/views/ems/dzjk/sbjk/yl/index.vue | 280 +++- src/views/ems/dzjk/tjbb/gltj/Dlzb.vue | 6 + src/views/ems/search/index.vue | 441 ++---- src/views/ems/site/mqtt/AddMqtt.vue | 26 +- src/views/ems/site/mqtt/index.vue | 2 +- src/views/ems/site/pointConfig/index.vue | 450 ++++++- .../ems/site/powerTariff/AddPowerTariff.vue | 28 +- src/views/ems/site/powerTariff/index.vue | 2 +- src/views/ems/site/sbbh/AddPlan.vue | 1183 ++++++++--------- src/views/ems/site/sbbh/index.vue | 289 ++-- src/views/ems/site/sblb/AddDevice.vue | 247 ++-- src/views/ems/site/sblb/PointTable.vue | 14 +- src/views/ems/site/sblb/index.vue | 35 +- .../ems/site/zdlb/MonitorPointMapping.vue | 963 +++++++++++++- 36 files changed, 4896 insertions(+), 2089 deletions(-) diff --git a/src/api/ems/dzjk.js b/src/api/ems/dzjk.js index 41b52a6..4c6a407 100644 --- a/src/api/ems/dzjk.js +++ b/src/api/ems/dzjk.js @@ -181,12 +181,319 @@ export function createTicketNo(data) { }) } -// 概率统计 -//获取概率统计 电量指标接口 -export function getElectricData({siteId, startDate, endDate}) { +function getFieldNameByCode(fieldCode) { + const raw = String(fieldCode || '').trim() + if (!raw) return '' + const idx = raw.lastIndexOf('__') + return idx >= 0 ? raw.slice(idx + 2) : raw +} + +function normalizeRows(displayResponse) { + const rows = displayResponse?.data || [] + return Array.isArray(rows) ? rows : [] +} + +function filterByMenu(rows, menuCode) { + return (rows || []).filter(item => item && item.menuCode === menuCode) +} + +function toDateLabel(valueTime) { + if (!valueTime) return '' + const date = new Date(valueTime) + if (isNaN(date.getTime())) return '' + const p = (n) => String(n).padStart(2, '0') + return `${date.getFullYear()}-${p(date.getMonth() + 1)}-${p(date.getDate())}` +} + +function toDateTimeLabel(valueTime) { + if (!valueTime) return '' + const date = new Date(valueTime) + if (isNaN(date.getTime())) return '' + const p = (n) => String(n).padStart(2, '0') + return `${date.getFullYear()}-${p(date.getMonth() + 1)}-${p(date.getDate())} ${p(date.getHours())}:${p(date.getMinutes())}` +} + +function toValueMap(rows) { + const map = {} + ;(rows || []).forEach(item => { + const fieldName = getFieldNameByCode(item?.fieldCode) + if (fieldName) { + map[fieldName] = item?.fieldValue + } + }) + return map +} + +function groupRowsByDevice(rows) { + const map = new Map() + ;(rows || []).forEach(item => { + const deviceId = String(item?.deviceId || '').trim() || 'DEFAULT' + if (!map.has(deviceId)) { + map.set(deviceId, []) + } + map.get(deviceId).push(item) + }) + return map +} + +function paginateRows(rows, pageNum = 1, pageSize = 10) { + const safePageNum = Number(pageNum) > 0 ? Number(pageNum) : 1 + const safePageSize = Number(pageSize) > 0 ? Number(pageSize) : 10 + const start = (safePageNum - 1) * safePageSize + return (rows || []).slice(start, start + safePageSize) +} + +function toNumber(value) { + const num = Number(value) + return Number.isFinite(num) ? num : null +} + +function normalizeDateInput(dateStr) { + if (dateStr) return dateStr + return toDateLabel(new Date()) +} + +function resolveElectricUnit(startDate, endDate) { + const start = new Date(`${normalizeDateInput(startDate)} 00:00:00`) + const end = new Date(`${normalizeDateInput(endDate)} 00:00:00`) + if (isNaN(start.getTime()) || isNaN(end.getTime())) return '日' + const diffDays = Math.floor((end.getTime() - start.getTime()) / (24 * 60 * 60 * 1000)) + if (diffDays <= 0) return '时' + if (diffDays < 30) return '日' + return '月' +} + +function formatByUnit(date, unit) { + const p = (n) => String(n).padStart(2, '0') + if (unit === '时') return `${p(date.getHours())}:${p(date.getMinutes())}` + if (unit === '月') return `${date.getFullYear()}-${p(date.getMonth() + 1)}` + return `${date.getFullYear()}-${p(date.getMonth() + 1)}-${p(date.getDate())}` +} + +function aggregateCurveByUnit(curveRows, unit) { + const result = new Map() + ;(curveRows || []).forEach(item => { + const time = item?.dataTime ? new Date(item.dataTime) : null + if (!time || isNaN(time.getTime())) return + const value = toNumber(item?.pointValue) + if (value == null) return + const label = formatByUnit(time, unit) + result.set(label, value) + }) + return result +} + +function getLatestCurveValue(curveRows) { + let latestTime = null + let latestValue = null + ;(curveRows || []).forEach(item => { + const time = item?.dataTime ? new Date(item.dataTime) : null + if (!time || isNaN(time.getTime())) return + const value = toNumber(item?.pointValue) + if (value == null) return + if (latestTime == null || time.getTime() > latestTime) { + latestTime = time.getTime() + latestValue = value + } + }) + return latestValue +} + +function findMappingByField(rows, fieldNames = []) { + const targetSet = new Set((fieldNames || []).map(name => String(name || '').trim())) + return (rows || []).find(item => targetSet.has(getFieldNameByCode(item?.fieldCode))) +} + +function getDataPointFromMapping(mapping) { + if (!mapping) return '' + const useFixedDisplay = Number(mapping?.useFixedDisplay) === 1 + const fixedDataPoint = String(mapping?.fixedDataPoint || '').trim() + const dataPoint = String(mapping?.dataPoint || '').trim() + if (useFixedDisplay && fixedDataPoint) return fixedDataPoint + return dataPoint || fixedDataPoint +} + +function queryPointCurveByPointId({siteId, pointId, startDate, endDate}) { + if (!siteId || !pointId) return Promise.resolve([]) + const start = `${normalizeDateInput(startDate)} 00:00:00` + const end = `${normalizeDateInput(endDate)} 23:59:59` return request({ - url: `/ems/statsReport/getElectricData?siteId=${siteId}&startDate=${startDate}&endDate=${endDate}`, - method: 'get' + url: `/ems/pointConfig/curve`, + method: 'post', + headers: { + repeatSubmit: false + }, + data: { + siteId, + pointId, + rangeType: 'custom', + startTime: start, + endTime: end + } + }).then(resp => (Array.isArray(resp?.data) ? resp.data : [])) +} + +function sortCurveRows(curveRows = []) { + return [...(curveRows || [])].sort((a, b) => { + const ta = new Date(a?.dataTime).getTime() + const tb = new Date(b?.dataTime).getTime() + return (isNaN(ta) ? 0 : ta) - (isNaN(tb) ? 0 : tb) + }) +} + +function resolveRangeKind(startDate, endDate) { + const start = new Date(`${normalizeDateInput(startDate)} 00:00:00`) + const end = new Date(`${normalizeDateInput(endDate || startDate)} 00:00:00`) + if (isNaN(start.getTime()) || isNaN(end.getTime())) return 'day' + const diffDays = Math.floor((end.getTime() - start.getTime()) / (24 * 60 * 60 * 1000)) + if (diffDays <= 0) return 'minute' + if (diffDays < 30) return 'day' + return 'month' +} + +function formatTimeLabelByKind(date, kind = 'day') { + const p = (n) => String(n).padStart(2, '0') + if (kind === 'minute') return `${p(date.getHours())}:${p(date.getMinutes())}` + if (kind === 'month') return `${date.getFullYear()}-${p(date.getMonth() + 1)}` + return `${date.getFullYear()}-${p(date.getMonth() + 1)}-${p(date.getDate())}` +} + +function buildSortedLabels(labelSet, kind = 'day') { + const labels = Array.from(labelSet || []) + if (kind === 'minute') { + return labels.sort((a, b) => { + const [ah = 0, am = 0] = String(a || '').split(':').map(v => Number(v) || 0) + const [bh = 0, bm = 0] = String(b || '').split(':').map(v => Number(v) || 0) + return ah * 60 + am - (bh * 60 + bm) + }) + } + return labels.sort() +} + +function normalizePointValue(raw) { + const num = toNumber(raw) + if (num != null) return num + return raw == null ? '' : raw +} + +function resolveAliasByField(aliasMap, fieldName) { + const raw = String(fieldName || '').trim() + if (!raw) return '' + if (aliasMap[raw]) return aliasMap[raw] + const withoutStat = raw.replace(/_stat$/, '') + return aliasMap[withoutStat] || '' +} + +function queryMenuPointCurves({siteId, menuCode, startDate, endDate, mappingFilter}) { + return getProjectPointMapping(siteId).then((mappingResp) => { + const allMappings = Array.isArray(mappingResp?.data) ? mappingResp.data : [] + let menuMappings = allMappings.filter(item => item?.menuCode === menuCode) + if (typeof mappingFilter === 'function') { + menuMappings = menuMappings.filter(mappingFilter) + } + const tasks = menuMappings.map((mapping) => { + const pointId = getDataPointFromMapping(mapping) + if (!pointId) return Promise.resolve(null) + return queryPointCurveByPointId({siteId, pointId, startDate, endDate}) + .then(curve => ({ + deviceId: String(mapping?.deviceId || '').trim(), + fieldName: getFieldNameByCode(mapping?.fieldCode), + curve: sortCurveRows(curve || []), + })) + .catch(() => ({ + deviceId: String(mapping?.deviceId || '').trim(), + fieldName: getFieldNameByCode(mapping?.fieldCode), + curve: [], + })) + }) + return Promise.all(tasks).then(rows => rows.filter(Boolean)) + }) +} + +// 电量指标 +export function getElectricData({siteId, startDate, endDate}) { + return getProjectPointMapping(siteId).then((mappingResp) => { + const allMappings = Array.isArray(mappingResp?.data) ? mappingResp.data : [] + const gltjMappings = allMappings.filter(item => item?.menuCode === 'TJBB_GLTJ') + + const chargedMap = findMappingByField(gltjMappings, ['chargedCap_stat', 'chargedCap']) + const disChargedMap = findMappingByField(gltjMappings, ['disChargedCap_stat', 'disChargedCap']) + const dailyEfficiencyMap = findMappingByField(gltjMappings, ['dailyEfficiency']) + const totalChargedMap = findMappingByField(gltjMappings, ['totalChargedCap_stat', 'totalChargedCap']) + const totalDisChargedMap = findMappingByField(gltjMappings, ['totalDisChargedCap_stat', 'totalDisChargedCap']) + const totalEfficiencyMap = findMappingByField(gltjMappings, ['efficiency']) + + const pointMap = { + charged: getDataPointFromMapping(chargedMap), + disCharged: getDataPointFromMapping(disChargedMap), + dailyEfficiency: getDataPointFromMapping(dailyEfficiencyMap), + totalCharged: getDataPointFromMapping(totalChargedMap), + totalDisCharged: getDataPointFromMapping(totalDisChargedMap), + totalEfficiency: getDataPointFromMapping(totalEfficiencyMap), + } + + const queryTasks = Object.keys(pointMap).map((key) => { + const pointId = pointMap[key] + return queryPointCurveByPointId({siteId, pointId, startDate, endDate}) + .then(curve => ({key, curve})) + .catch(() => ({key, curve: []})) + }) + + return Promise.all(queryTasks).then((queryResult) => { + const curveMap = {} + queryResult.forEach(item => { + curveMap[item.key] = item.curve || [] + }) + + const unit = resolveElectricUnit(startDate, endDate) + const chargedSeries = aggregateCurveByUnit(curveMap.charged, unit) + const disChargedSeries = aggregateCurveByUnit(curveMap.disCharged, unit) + const efficiencySeries = aggregateCurveByUnit(curveMap.dailyEfficiency, unit) + + const labels = Array.from(new Set([ + ...chargedSeries.keys(), + ...disChargedSeries.keys(), + ...efficiencySeries.keys(), + ])).sort() + + const sevenDayDisChargeStats = labels.map((label) => { + const chargedCap = chargedSeries.get(label) + const disChargedCap = disChargedSeries.get(label) + let dailyEfficiency = efficiencySeries.get(label) + if (dailyEfficiency == null && chargedCap != null && chargedCap !== 0 && disChargedCap != null) { + dailyEfficiency = Number(((disChargedCap / chargedCap) * 100).toFixed(2)) + } + return { + ammeterDate: label, + chargedCap: chargedCap == null ? '' : chargedCap, + disChargedCap: disChargedCap == null ? '' : disChargedCap, + dailyEfficiency: dailyEfficiency == null ? '' : dailyEfficiency, + } + }) + + const fallbackTotalCharged = sevenDayDisChargeStats.reduce((acc, item) => acc + (toNumber(item.chargedCap) || 0), 0) + const fallbackTotalDisCharged = sevenDayDisChargeStats.reduce((acc, item) => acc + (toNumber(item.disChargedCap) || 0), 0) + + const totalChargedCap = getLatestCurveValue(curveMap.totalCharged) + const totalDisChargedCap = getLatestCurveValue(curveMap.totalDisCharged) + const totalEfficiency = getLatestCurveValue(curveMap.totalEfficiency) + + const resultTotalCharged = totalChargedCap == null ? fallbackTotalCharged : totalChargedCap + const resultTotalDisCharged = totalDisChargedCap == null ? fallbackTotalDisCharged : totalDisChargedCap + const resultEfficiency = totalEfficiency == null + ? (resultTotalCharged > 0 ? Number(((resultTotalDisCharged / resultTotalCharged) * 100).toFixed(2)) : 0) + : totalEfficiency + + return { + data: { + totalChargedCap: resultTotalCharged, + totalDisChargedCap: resultTotalDisCharged, + efficiency: resultEfficiency, + unit, + sevenDayDisChargeStats, + } + } + }) }) } @@ -198,27 +505,147 @@ export function getPcsNameList(siteId) { }) } -//pcs曲线 -export function getPCSData({siteId, startTime, endTime, dataType}) { - return request({ - url: `/ems/statsReport/getPCSData?siteId=${siteId}&startDate=${startTime}&endDate=${endTime}&dataType=${dataType}`, - method: 'get' +// pcs曲线 +export function getPCSData({siteId, startTime, endTime}) { + const kind = resolveRangeKind(startTime, endTime) + const aliasMap = { + activePower_stat: 'activePower', + activePower: 'activePower', + reactivePower_stat: 'reactivePower', + reactivePower: 'reactivePower', + uCurrent: 'uCurrent', + vCurrent: 'vCurrent', + wCurrent: 'wCurrent', + } + return queryMenuPointCurves({ + siteId, + menuCode: 'TJBB_PCSQX', + startDate: startTime, + endDate: endTime, + }).then((records) => { + const byDevice = new Map() + records.forEach((record) => { + const alias = resolveAliasByField(aliasMap, record.fieldName) + if (!alias) return + const deviceId = record.deviceId || '' + if (!byDevice.has(deviceId)) byDevice.set(deviceId, new Map()) + const rowMap = byDevice.get(deviceId) + ;(record.curve || []).forEach((point) => { + const time = point?.dataTime ? new Date(point.dataTime) : null + if (!time || isNaN(time.getTime())) return + const label = formatTimeLabelByKind(time, kind) + if (!rowMap.has(label)) rowMap.set(label, {statisDate: label}) + rowMap.get(label)[alias] = normalizePointValue(point?.pointValue) + }) + }) + const data = [] + byDevice.forEach((rowMap, deviceId) => { + const labels = buildSortedLabels(new Set(Array.from(rowMap.keys())), kind) + data.push({ + deviceId, + dataList: labels.map(label => rowMap.get(label)), + }) + }) + return {data} }) } -//电池堆曲线 -export function getStackData({siteId, startTime, endTime, dataType}) { - return request({ - url: `/ems/statsReport/getStackData?siteId=${siteId}&startDate=${startTime}&endDate=${endTime}&dataType=${dataType}`, - method: 'get' +// 电池堆曲线 +export function getStackData({siteId, startTime, endTime}) { + const kind = resolveRangeKind(startTime, endTime) + const aliasMap = { + temp: 'temp', + voltage_stat: 'voltage', + voltage: 'voltage', + current: 'current', + soc_stat: 'soc', + soc: 'soc', + } + return queryMenuPointCurves({ + siteId, + menuCode: 'TJBB_DCDQX', + startDate: startTime, + endDate: endTime, + }).then((records) => { + const byDevice = new Map() + records.forEach((record) => { + const alias = resolveAliasByField(aliasMap, record.fieldName) + if (!alias) return + const deviceId = record.deviceId || '' + if (!byDevice.has(deviceId)) byDevice.set(deviceId, new Map()) + const rowMap = byDevice.get(deviceId) + ;(record.curve || []).forEach((point) => { + const time = point?.dataTime ? new Date(point.dataTime) : null + if (!time || isNaN(time.getTime())) return + const label = formatTimeLabelByKind(time, kind) + if (!rowMap.has(label)) rowMap.set(label, {statisDate: label}) + rowMap.get(label)[alias] = normalizePointValue(point?.pointValue) + }) + }) + const data = [] + byDevice.forEach((rowMap, deviceId) => { + const labels = buildSortedLabels(new Set(Array.from(rowMap.keys())), kind) + data.push({ + deviceId, + dataList: labels.map(label => rowMap.get(label)), + }) + }) + return {data} }) } -//电池温度 +// 电池温度 export function getClusterData({siteId, stackId, clusterId, dateTime, pageNum, pageSize}) { - return request({ - url: `/ems/statsReport/getClusterData?siteId=${siteId}&stackId=${stackId}&clusterId=${clusterId}&dateTime=${dateTime}&pageNum=${pageNum}&pageSize=${pageSize}`, - method: 'get' + const startDate = dateTime || normalizeDateInput('') + const endDate = dateTime || normalizeDateInput('') + const kind = 'minute' + const aliasMap = { + maxTemp: 'maxTemp', + maxTempId: 'maxTempId', + minTemp: 'minTemp', + minTempId: 'minTempId', + maxVoltage: 'maxVoltage', + maxVoltageId: 'maxVoltageId', + minVoltage: 'minVoltage', + minVoltageId: 'minVoltageId', + } + const queryClusterCurves = (withClusterFilter) => queryMenuPointCurves({ + siteId, + menuCode: 'TJBB_DCWD', + startDate, + endDate, + mappingFilter: withClusterFilter + ? (item) => { + if (!clusterId) return true + return String(item?.deviceId || '').trim() === String(clusterId || '').trim() + } + : undefined + }) + + return queryClusterCurves(true).then((records) => { + if (clusterId && (!records || records.length === 0)) { + return queryClusterCurves(false) + } + return records + }).then((records) => { + const rowMap = new Map() + records.forEach((record) => { + const alias = resolveAliasByField(aliasMap, record.fieldName) + if (!alias) return + ;(record.curve || []).forEach((point) => { + const time = point?.dataTime ? new Date(point.dataTime) : null + if (!time || isNaN(time.getTime())) return + const label = formatTimeLabelByKind(time, kind) + if (!rowMap.has(label)) rowMap.set(label, {statisDate: label}) + rowMap.get(label)[alias] = normalizePointValue(point?.pointValue) + }) + }) + const labels = buildSortedLabels(new Set(Array.from(rowMap.keys())), kind) + const fullRows = labels.map(label => rowMap.get(label)) + return { + rows: paginateRows(fullRows, pageNum, pageSize), + total: fullRows.length, + } }) } @@ -258,9 +685,37 @@ export function batteryAveTemp(siteId, startTime, endTime) { // 功率曲线 export function getPowerData({siteId, startDate, endDate}) { - return request({ - url: `/ems/statsReport/getPowerData?siteId=${siteId}&startDate=${startDate}&endDate=${endDate}`, - method: 'get' + const kind = resolveRangeKind(startDate, endDate) + const aliasMap = { + gridPower_stat: 'gridPower', + gridPower: 'gridPower', + loadPower_stat: 'loadPower', + loadPower: 'loadPower', + storagePower_stat: 'storagePower', + storagePower: 'storagePower', + pvPower_stat: 'pvPower', + pvPower: 'pvPower', + } + return queryMenuPointCurves({ + siteId, + menuCode: 'TJBB_GLQX', + startDate, + endDate, + }).then((records) => { + const rowMap = new Map() + records.forEach((record) => { + const alias = resolveAliasByField(aliasMap, record.fieldName) + if (!alias) return + ;(record.curve || []).forEach((point) => { + const time = point?.dataTime ? new Date(point.dataTime) : null + if (!time || isNaN(time.getTime())) return + const label = formatTimeLabelByKind(time, kind) + if (!rowMap.has(label)) rowMap.set(label, {statisDate: label}) + rowMap.get(label)[alias] = normalizePointValue(point?.pointValue) + }) + }) + const labels = buildSortedLabels(new Set(Array.from(rowMap.keys())), kind) + return {data: labels.map(label => rowMap.get(label))} }) } @@ -274,18 +729,88 @@ export function getLoadNameList(siteId) { // 电表报表 export function getAmmeterData({siteId, startTime, endTime, pageSize, pageNum}) { - return request({ - url: `/ems/statsReport/getAmmeterData?siteId=${siteId}&startTime=${startTime}&endTime=${endTime}&pageSize=${pageSize}&pageNum=${pageNum}`, - method: 'get' + const kind = 'day' + const aliasMap = { + activePeakKwh: 'activePeakKwh', + activeHighKwh: 'activeHighKwh', + activeFlatKwh: 'activeFlatKwh', + activeValleyKwh: 'activeValleyKwh', + activeTotalKwh: 'activeTotalKwh', + reActivePeakKwh: 'reActivePeakKwh', + reActiveHighKwh: 'reActiveHighKwh', + reActiveFlatKwh: 'reActiveFlatKwh', + reActiveValleyKwh: 'reActiveValleyKwh', + reActiveTotalKwh: 'reActiveTotalKwh', + effect: 'effect', + } + return queryMenuPointCurves({ + siteId, + menuCode: 'TJBB_DBBB', + startDate: startTime, + endDate: endTime, + }).then((records) => { + const rowMap = new Map() + records.forEach((record) => { + const alias = aliasMap[record.fieldName] + if (!alias) return + ;(record.curve || []).forEach((point) => { + const time = point?.dataTime ? new Date(point.dataTime) : null + if (!time || isNaN(time.getTime())) return + const label = formatTimeLabelByKind(time, kind) + if (!rowMap.has(label)) rowMap.set(label, {dataTime: label}) + rowMap.get(label)[alias] = normalizePointValue(point?.pointValue) + }) + }) + const labels = buildSortedLabels(new Set(Array.from(rowMap.keys())), kind) + const fullRows = labels.map(label => rowMap.get(label)) + return { + rows: paginateRows(fullRows, pageNum, pageSize), + total: fullRows.length, + } }) } // 电价报表 export function getAmmeterRevenueData(data) { - return request({ - url: `/ems/statsReport/getAmmeterRevenueData`, - method: 'get', - params: data + const {siteId, startTime, endTime, pageNum, pageSize} = data || {} + const kind = 'day' + const aliasMap = { + activePeakPrice: 'activePeakPrice', + activeHighPrice: 'activeHighPrice', + activeFlatPrice: 'activeFlatPrice', + activeValleyPrice: 'activeValleyPrice', + activeTotalPrice: 'activeTotalPrice', + reActivePeakPrice: 'reActivePeakPrice', + reActiveHighPrice: 'reActiveHighPrice', + reActiveFlatPrice: 'reActiveFlatPrice', + reActiveValleyPrice: 'reActiveValleyPrice', + reActiveTotalPrice: 'reActiveTotalPrice', + actualRevenue: 'actualRevenue', + } + return queryMenuPointCurves({ + siteId, + menuCode: 'TJBB_SYBB', + startDate: startTime, + endDate: endTime, + }).then((records) => { + const rowMap = new Map() + records.forEach((record) => { + const alias = aliasMap[record.fieldName] + if (!alias) return + ;(record.curve || []).forEach((point) => { + const time = point?.dataTime ? new Date(point.dataTime) : null + if (!time || isNaN(time.getTime())) return + const label = formatTimeLabelByKind(time, kind) + if (!rowMap.has(label)) rowMap.set(label, {dataTime: label}) + rowMap.get(label)[alias] = normalizePointValue(point?.pointValue) + }) + }) + const labels = buildSortedLabels(new Set(Array.from(rowMap.keys())), kind) + const fullRows = labels.map(label => rowMap.get(label)) + return { + rows: paginateRows(fullRows, pageNum, pageSize), + total: fullRows.length, + } }) } diff --git a/src/api/ems/site.js b/src/api/ems/site.js index 60233a5..77ec512 100644 --- a/src/api/ems/site.js +++ b/src/api/ems/site.js @@ -133,7 +133,30 @@ export function saveSingleMonitorProjectPointMapping(data) { return request({ url: `/ems/siteConfig/saveSingleMonitorProjectPointMapping`, method: 'post', - data + data, + headers: { + repeatSubmit: false + } + }) +} + +// 获取单站监控工作状态枚举映射(PCS) +export function getSingleMonitorWorkStatusEnumMappings(siteId) { + return request({ + url: `/ems/siteConfig/getSingleMonitorWorkStatusEnumMappings?siteId=${siteId}`, + method: 'get', + }) +} + +// 保存单站监控工作状态枚举映射(PCS) +export function saveSingleMonitorWorkStatusEnumMappings(data) { + return request({ + url: `/ems/siteConfig/saveSingleMonitorWorkStatusEnumMappings`, + method: 'post', + data, + headers: { + repeatSubmit: false + } }) } @@ -267,7 +290,10 @@ export function getPointConfigLatestValues(data) { return request({ url: `/ems/pointConfig/latestValues`, method: 'post', - data + data, + headers: { + repeatSubmit: false + } }) } @@ -276,7 +302,10 @@ export function getPointConfigCurve(data) { return request({ url: `/ems/pointConfig/curve`, method: 'post', - data + data, + headers: { + repeatSubmit: false + } }) } diff --git a/src/components/Ems/SingleSquareBox/index.vue b/src/components/Ems/SingleSquareBox/index.vue index 0a39ca2..2402d4d 100644 --- a/src/components/Ems/SingleSquareBox/index.vue +++ b/src/components/Ems/SingleSquareBox/index.vue @@ -2,7 +2,10 @@ @@ -23,10 +26,21 @@ line-height: 26px; font-weight: 500; } + .point-loading-icon{ + color: #409eff; + display: inline-block; + transform-origin: center; + animation: pointLoadingSpinPulse 1.1s linear infinite; + } ::v-deep .el-card__body{ padding: 12px 10px; } } + @keyframes pointLoadingSpinPulse { + 0% { opacity: 0.45; transform: rotate(0deg) scale(0.9); } + 50% { opacity: 1; transform: rotate(180deg) scale(1.08); } + 100% { opacity: 0.45; transform: rotate(360deg) scale(0.9); } + } diff --git a/src/views/ems/dzjk/sbjk/bmszl/index.vue b/src/views/ems/dzjk/sbjk/bmszl/index.vue index c120058..0815165 100644 --- a/src/views/ems/dzjk/sbjk/bmszl/index.vue +++ b/src/views/ems/dzjk/sbjk/bmszl/index.vue @@ -1,6 +1,28 @@ diff --git a/src/views/ems/dzjk/sbjk/db/index.vue b/src/views/ems/dzjk/sbjk/db/index.vue index fe5d411..afa7e4f 100644 --- a/src/views/ems/dzjk/sbjk/db/index.vue +++ b/src/views/ems/dzjk/sbjk/db/index.vue @@ -1,229 +1,239 @@ @@ -232,6 +242,38 @@ export default { &.list:not(:last-child) { margin-bottom: 25px; } + + .info { + float: right; + text-align: right; + font-size: 12px; + color: #666; + line-height: 18px; + } } +.pcs-tags { + margin: 0 0 12px; + display: flex; + flex-wrap: wrap; + gap: 8px; + justify-content: flex-start; + align-items: center; +} + +.pcs-tag-item { + cursor: pointer; +} + +.point-loading-icon { + color: #409eff; + display: inline-block; + transform-origin: center; + animation: pointLoadingSpinPulse 1.1s linear infinite; +} +@keyframes pointLoadingSpinPulse { + 0% { opacity: 0.45; transform: rotate(0deg) scale(0.9); } + 50% { opacity: 1; transform: rotate(180deg) scale(1.08); } + 100% { opacity: 0.45; transform: rotate(360deg) scale(0.9); } +} diff --git a/src/views/ems/dzjk/sbjk/dh/index.vue b/src/views/ems/dzjk/sbjk/dh/index.vue index 0e424df..5d6ec8f 100644 --- a/src/views/ems/dzjk/sbjk/dh/index.vue +++ b/src/views/ems/dzjk/sbjk/dh/index.vue @@ -1,5 +1,5 @@ - diff --git a/src/views/ems/site/sbbh/index.vue b/src/views/ems/site/sbbh/index.vue index 2a970aa..93a4e95 100644 --- a/src/views/ems/site/sbbh/index.vue +++ b/src/views/ems/site/sbbh/index.vue @@ -1,109 +1,92 @@ - + diff --git a/src/views/ems/site/sblb/AddDevice.vue b/src/views/ems/site/sblb/AddDevice.vue index 6e580a6..9f8ec8b 100644 --- a/src/views/ems/site/sblb/AddDevice.vue +++ b/src/views/ems/site/sblb/AddDevice.vue @@ -7,10 +7,12 @@ - - - + @@ -25,12 +27,6 @@ :style="{width: '100%'}"> - - - - - @@ -86,50 +82,43 @@ - -
PCS配置
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- + + + + + + + + + + + + + + + + + + + + + + +
+
电池簇地址
+ +
@@ -141,7 +130,6 @@ diff --git a/src/views/ems/site/sblb/PointTable.vue b/src/views/ems/site/sblb/PointTable.vue index 5b41dc4..11de1d5 100644 --- a/src/views/ems/site/sblb/PointTable.vue +++ b/src/views/ems/site/sblb/PointTable.vue @@ -110,6 +110,11 @@ sortable="custom" > + + + - - ({ + ...item, + siteName: normalizedSiteName + })) } }, data() { @@ -119,6 +126,7 @@ export default { mode: '',//新增、编辑设备 editDeviceId: '',//编辑设备id siteId: '', + selectedSiteName: '', deviceCategory: '',//搜索栏设备类型 deviceCategoryList: [],//设备类别 tableData: [], @@ -153,6 +161,17 @@ export default { hasValidSiteId(siteId) { return !!(siteId !== undefined && siteId !== null && String(siteId).trim()) }, + getSelectedSiteName(routeSiteName) { + const name = routeSiteName === undefined || routeSiteName === null ? '' : String(routeSiteName).trim() + if (name) { + return name + } + const matchedSite = (this.$store.getters.zdList || []).find(item => item.siteId === this.siteId) + if (matchedSite && matchedSite.siteName) { + return matchedSite.siteName + } + return this.siteId || '' + }, // 获取设备类别 getDeviceCategoryList() { getAllDeviceCategory().then(response => { @@ -259,7 +278,12 @@ export default { this.loading = true const {siteId, deviceCategory, pageNum, pageSize} = this getDeviceInfoList({siteId, deviceCategory, pageNum, pageSize}).then(response => { - this.tableData = response?.rows || []; + const selectedSiteName = this.getSelectedSiteName(this.$route.query.siteName) + this.selectedSiteName = selectedSiteName + this.tableData = (response?.rows || []).map(item => ({ + ...item, + siteName: selectedSiteName + })); this.totalSize = response?.total || 0 }).finally(() => { this.loading = false @@ -268,6 +292,7 @@ export default { }, mounted() { this.siteId = this.hasValidSiteId(this.$route.query.siteId) ? String(this.$route.query.siteId).trim() : '' + this.selectedSiteName = this.getSelectedSiteName(this.$route.query.siteName) this.pageNum = 1//每次搜索从1开始搜索 this.getDeviceCategoryList() this.getData() diff --git a/src/views/ems/site/zdlb/MonitorPointMapping.vue b/src/views/ems/site/zdlb/MonitorPointMapping.vue index d5ee3f0..5470303 100644 --- a/src/views/ems/site/zdlb/MonitorPointMapping.vue +++ b/src/views/ems/site/zdlb/MonitorPointMapping.vue @@ -8,10 +8,6 @@ {{ siteName || siteId || '-' }} -
- 返回 - 保存 -
- + + +
+ + 列表配置 + 快速配置 + 分组填报 + +
{{ saveStatusText }}
+ +
+ + + + + + + + + @@ -67,6 +279,7 @@ 删除 @@ -91,13 +304,21 @@ + + + @@ -121,6 +342,7 @@ 删除 @@ -131,12 +353,112 @@
+
+ + + + +
+ 状态枚举映射 +
+ 恢复默认 + 新增映射 +
+
+ + {{ scope.label }} + + + + + + + + + + + + + + + + + + +
说明:按上方状态项分别维护“站点上送值 -> 系统状态编码/名称”的映射关系。
+
+
+ + + + + + + + + + 搜索 + 重置 + + + + + + + + + + + + + + + +