|
|
|
@ -292,7 +292,7 @@
|
|
|
|
</el-tag>
|
|
|
|
</el-tag>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="device-mgmt__metricValue">
|
|
|
|
<div class="device-mgmt__metricValue">
|
|
|
|
<span class="device-mgmt__metricNumber">{{ m.value || '-' }}</span>
|
|
|
|
<span class="device-mgmt__metricNumber">{{ m.addressValue || '-' }}</span>
|
|
|
|
<span class="device-mgmt__metricUnit">{{ m.dataUnit || '' }}</span>
|
|
|
|
<span class="device-mgmt__metricUnit">{{ m.dataUnit || '' }}</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</el-card>
|
|
|
|
</el-card>
|
|
|
|
@ -313,12 +313,12 @@
|
|
|
|
<div class="device-mgmt__filters">
|
|
|
|
<div class="device-mgmt__filters">
|
|
|
|
<div class="device-mgmt__filter">
|
|
|
|
<div class="device-mgmt__filter">
|
|
|
|
<div class="device-mgmt__filterLabel">参数选择</div>
|
|
|
|
<div class="device-mgmt__filterLabel">参数选择</div>
|
|
|
|
<el-select v-model="historyMetricKey" size="small" class="!w-160px" clearable>
|
|
|
|
<el-select v-model="historyMetricKey" class="!w-160px" clearable>
|
|
|
|
<el-option
|
|
|
|
<el-option
|
|
|
|
v-for="m in historyMetricOptions"
|
|
|
|
v-for="m in historyMetricOptions"
|
|
|
|
:key="m.key"
|
|
|
|
:key="m.id"
|
|
|
|
:label="m.name"
|
|
|
|
:label="m.attributeName"
|
|
|
|
:value="m.key"
|
|
|
|
:value="m.id"
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</el-select>
|
|
|
|
</el-select>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
@ -327,7 +327,6 @@
|
|
|
|
<el-date-picker
|
|
|
|
<el-date-picker
|
|
|
|
v-model="historyTimeRange"
|
|
|
|
v-model="historyTimeRange"
|
|
|
|
type="datetimerange"
|
|
|
|
type="datetimerange"
|
|
|
|
size="small"
|
|
|
|
|
|
|
|
range-separator="-"
|
|
|
|
range-separator="-"
|
|
|
|
start-placeholder="开始时间"
|
|
|
|
start-placeholder="开始时间"
|
|
|
|
end-placeholder="结束时间"
|
|
|
|
end-placeholder="结束时间"
|
|
|
|
@ -335,13 +334,13 @@
|
|
|
|
class="!w-320px"
|
|
|
|
class="!w-320px"
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<el-button type="primary" @click="loadHistoryData">查询</el-button>
|
|
|
|
<div class="device-mgmt__filterActions">
|
|
|
|
<div class="device-mgmt__filterActions">
|
|
|
|
<el-button type="primary" @click="loadHistoryData" size="small">查询</el-button>
|
|
|
|
<el-radio-group v-model="historyViewType" class="ml-16px">
|
|
|
|
<el-radio-group v-model="historyViewType" size="small" class="ml-16px">
|
|
|
|
|
|
|
|
<el-radio-button label="chart">曲线</el-radio-button>
|
|
|
|
<el-radio-button label="chart">曲线</el-radio-button>
|
|
|
|
<el-radio-button label="list">列表</el-radio-button>
|
|
|
|
<el-radio-button label="list">列表</el-radio-button>
|
|
|
|
</el-radio-group>
|
|
|
|
</el-radio-group>
|
|
|
|
<el-button size="small" class="ml-16px">导出</el-button>
|
|
|
|
<el-button class="ml-16px">导出</el-button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
@ -843,14 +842,30 @@ const historyViewType = ref<'chart' | 'list'>('chart')
|
|
|
|
const historyList = ref<any[]>([])
|
|
|
|
const historyList = ref<any[]>([])
|
|
|
|
const historyLoading = ref(false)
|
|
|
|
const historyLoading = ref(false)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const parseHistoryTime = (timeText?: string) => {
|
|
|
|
|
|
|
|
if (!timeText) return { display: '-', timestamp: 0 }
|
|
|
|
|
|
|
|
const raw = String(timeText).trim()
|
|
|
|
|
|
|
|
const shortYearMatch = raw.match(/^(\d{2})-(\d{2})-(\d{2})\s+(\d{2}:\d{2}:\d{2})$/)
|
|
|
|
|
|
|
|
if (shortYearMatch) {
|
|
|
|
|
|
|
|
const [, yy, mm, dd, hms] = shortYearMatch
|
|
|
|
|
|
|
|
const isoText = `20${yy}-${mm}-${dd}T${hms}`
|
|
|
|
|
|
|
|
const timestamp = new Date(isoText).getTime()
|
|
|
|
|
|
|
|
return { display: raw, timestamp: Number.isNaN(timestamp) ? 0 : timestamp }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const timestamp = new Date(raw).getTime()
|
|
|
|
|
|
|
|
return { display: raw, timestamp: Number.isNaN(timestamp) ? 0 : timestamp }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const loadHistoryMetrics = async () => {
|
|
|
|
const loadHistoryMetrics = async () => {
|
|
|
|
if (!selectedDeviceDetail.value?.id) return
|
|
|
|
if (!selectedDeviceDetail.value?.id) return
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
const list = await DeviceApi.getDeviceAttributeList(selectedDeviceDetail.value.id)
|
|
|
|
const list = await DeviceApi.getDeviceAttributeList(selectedDeviceDetail.value.id)
|
|
|
|
historyMetricOptions.value = Array.isArray(list) ? list : []
|
|
|
|
historyMetricOptions.value = Array.isArray(list) ? list : []
|
|
|
|
if (historyMetricOptions.value.length > 0 && !historyMetricKey.value) {
|
|
|
|
const hasCurrent = historyMetricOptions.value.some(
|
|
|
|
historyMetricKey.value =
|
|
|
|
(item) => Number(item.id) === Number(historyMetricKey.value)
|
|
|
|
historyMetricOptions.value[0].attributeCode || historyMetricOptions.value[0].attributeName
|
|
|
|
)
|
|
|
|
|
|
|
|
if (historyMetricOptions.value.length > 0 && !hasCurrent) {
|
|
|
|
|
|
|
|
historyMetricKey.value = historyMetricOptions.value[0].id
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e)
|
|
|
|
console.error(e)
|
|
|
|
@ -859,11 +874,18 @@ const loadHistoryMetrics = async () => {
|
|
|
|
|
|
|
|
|
|
|
|
const loadHistoryData = async () => {
|
|
|
|
const loadHistoryData = async () => {
|
|
|
|
if (!selectedDeviceDetail.value?.id) return
|
|
|
|
if (!selectedDeviceDetail.value?.id) return
|
|
|
|
|
|
|
|
if (!historyMetricOptions.value.length) {
|
|
|
|
|
|
|
|
await loadHistoryMetrics()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!historyMetricOptions.value.length) return
|
|
|
|
|
|
|
|
if (!historyMetricKey.value) {
|
|
|
|
|
|
|
|
historyMetricKey.value = historyMetricOptions.value[0].id
|
|
|
|
|
|
|
|
}
|
|
|
|
historyLoading.value = true
|
|
|
|
historyLoading.value = true
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
const params: any = {
|
|
|
|
const params: any = {
|
|
|
|
deviceId: selectedDeviceDetail.value.id,
|
|
|
|
deviceId: selectedDeviceDetail.value.id,
|
|
|
|
modelId: selectedDeviceDetail.value.deviceModelId
|
|
|
|
modelId: Number(historyMetricKey.value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (historyTimeRange.value && historyTimeRange.value.length === 2) {
|
|
|
|
if (historyTimeRange.value && historyTimeRange.value.length === 2) {
|
|
|
|
params.collectionStartTime = historyTimeRange.value[0]
|
|
|
|
params.collectionStartTime = historyTimeRange.value[0]
|
|
|
|
@ -872,14 +894,18 @@ const loadHistoryData = async () => {
|
|
|
|
const res = await DeviceModelAttributeApi.operationAnalysisDetails(params)
|
|
|
|
const res = await DeviceModelAttributeApi.operationAnalysisDetails(params)
|
|
|
|
let data = Array.isArray(res) ? res : res?.list || []
|
|
|
|
let data = Array.isArray(res) ? res : res?.list || []
|
|
|
|
|
|
|
|
|
|
|
|
// Convert property names if necessary, assuming common names like createTime/time, addressValue/value, etc.
|
|
|
|
historyList.value = data.map((item: any) => {
|
|
|
|
historyList.value = data.map((item: any) => ({
|
|
|
|
const timeRaw = item.collectTime || item.time || item.createTime || item.collectionTime
|
|
|
|
...item,
|
|
|
|
const parsedTime = parseHistoryTime(timeRaw)
|
|
|
|
time: item.time || item.createTime || item.collectionTime,
|
|
|
|
return {
|
|
|
|
value: item.value || item.addressValue || item.dataValue,
|
|
|
|
...item,
|
|
|
|
attributeName: item.attributeName || item.parameter || item.name,
|
|
|
|
time: parsedTime.display,
|
|
|
|
unit: item.unit || item.dataUnit || ''
|
|
|
|
timeValue: parsedTime.timestamp,
|
|
|
|
}))
|
|
|
|
value: item.addressValue ?? item.value ?? item.dataValue ?? '-',
|
|
|
|
|
|
|
|
attributeName: item.attributeName || item.parameter || item.name,
|
|
|
|
|
|
|
|
unit: item.dataUnit || item.unit || ''
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
} catch (e) {
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e)
|
|
|
|
console.error(e)
|
|
|
|
} finally {
|
|
|
|
} finally {
|
|
|
|
@ -888,27 +914,16 @@ const loadHistoryData = async () => {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const historyChartOptions = computed<EChartsOption>(() => {
|
|
|
|
const historyChartOptions = computed<EChartsOption>(() => {
|
|
|
|
let data = historyList.value
|
|
|
|
|
|
|
|
if (historyMetricKey.value) {
|
|
|
|
|
|
|
|
data = data.filter(
|
|
|
|
|
|
|
|
(item) =>
|
|
|
|
|
|
|
|
item.attributeCode === historyMetricKey.value ||
|
|
|
|
|
|
|
|
item.attributeName === historyMetricKey.value
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Sort by time ascending for chart
|
|
|
|
// Sort by time ascending for chart
|
|
|
|
const sortedData = [...data].sort(
|
|
|
|
const sortedData = [...historyList.value].sort(
|
|
|
|
(a, b) => new Date(a.time).getTime() - new Date(b.time).getTime()
|
|
|
|
(a, b) => Number(a.timeValue || 0) - Number(b.timeValue || 0)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
const labels = sortedData.map((item) => formatDate(item.time))
|
|
|
|
const labels = sortedData.map((item) => item.time || '-')
|
|
|
|
const values = sortedData.map((item) => Number(item.value) || 0)
|
|
|
|
const values = sortedData.map((item) => Number(item.value) || 0)
|
|
|
|
const metricName =
|
|
|
|
const metricName =
|
|
|
|
historyMetricOptions.value.find(
|
|
|
|
historyMetricOptions.value.find((m) => Number(m.id) === Number(historyMetricKey.value))
|
|
|
|
(m) =>
|
|
|
|
?.attributeName || '数据'
|
|
|
|
m.attributeCode === historyMetricKey.value || m.attributeName === historyMetricKey.value
|
|
|
|
|
|
|
|
)?.attributeName || '数据'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
grid: { left: 20, right: 20, bottom: 20, top: 40, containLabel: true },
|
|
|
|
grid: { left: 20, right: 20, bottom: 20, top: 40, containLabel: true },
|
|
|
|
@ -933,10 +948,10 @@ const historyChartOptions = computed<EChartsOption>(() => {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
watch([() => activeTab.value, () => selectedDeviceDetail.value.id], ([tab, deviceId]) => {
|
|
|
|
watch([() => activeTab.value, () => selectedDeviceDetail.value.id], async ([tab, deviceId]) => {
|
|
|
|
if (tab === 'history' && deviceId) {
|
|
|
|
if (tab === 'history' && deviceId) {
|
|
|
|
loadHistoryMetrics()
|
|
|
|
await loadHistoryMetrics()
|
|
|
|
loadHistoryData()
|
|
|
|
await loadHistoryData()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|