设备管理调整

main
liutao 16 hours ago
parent 84101b7866
commit d0db5f5a90

@ -38,7 +38,7 @@
</div>
</div>
<div v-for="row in pagedRows" :key="row.id" class="timeline-table__row">
<div v-for="row in timelineRows" :key="row.id" class="timeline-table__row">
<div class="timeline-table__meta">
<div class="timeline-table__device">{{ row.name }}</div>
<div class="timeline-table__rate">{{ row.utilizationRate.toFixed(2) }}%</div>
@ -116,12 +116,20 @@ const legendItems = computed(() => [
{ status: 'offline' as const, color: statusColors.offline, label: t('DataCollection.RunOverview.legend.offline') }
])
const hourTicks = Array.from({ length: 13 }, (_, index) => `${String(index * 2).padStart(2, '0')}:00`)
const pagedRows = computed(() => {
const start = (props.pageNo - 1) * props.pageSize
return props.rows.slice(start, start + props.pageSize)
})
const hourTicks = Array.from({ length: 24 }, (_, index) => `${String(index).padStart(2, '0')}:00`)
const timelineRows = computed(() =>
props.rows.map((row) => ({
...row,
segments: (row.segments || []).filter(
(segment) =>
!!statusColors[segment.status] &&
Number.isFinite(segment.startHour) &&
Number.isFinite(segment.endHour) &&
segment.endHour > segment.startHour
)
}))
)
</script>
<style scoped lang="scss">
@ -239,7 +247,6 @@ const pagedRows = computed(() => {
.timeline-track {
height: 20px;
background: #f5f7fb;
border-radius: 999px;
overflow: hidden;
}

@ -56,7 +56,7 @@ import OverviewFilterBar from './components/OverviewFilterBar.vue'
import OverviewMetricCards from './components/OverviewMetricCards.vue'
import OperationTimelineChart from './components/OperationTimelineChart.vue'
import StatusDistributionChart from './components/StatusDistributionChart.vue'
import { buildDefaultQueryParams, buildRunOverviewTimelineData } from './mock'
import { buildDefaultQueryParams } from './mock'
import type {
OrganizationFilterItem,
OrganizationTreeOption,
@ -165,19 +165,20 @@ const currentDeviceIds = computed(() =>
const buildOverviewRequestParams = () => ({
ids: currentDeviceIds.value.join(','),
startTime: queryParams.value.timeRange[0],
endTime: queryParams.value.timeRange[1]
endTime: queryParams.value.timeRange[1],
timelinePageNo: pageNo.value,
timelinePageSize: pageSize.value
})
const refreshData = async () => {
const response = await DeviceOperationOverviewApi.getRunOverview(buildOverviewRequestParams())
const timelineData = buildRunOverviewTimelineData(queryParams.value, deviceOptions.value)
overviewData.value = {
metrics: response?.metrics || [],
hourlyStatus: response?.hourlyStatus || [],
summary: response?.summary || [],
summaryTotalHours: response?.summaryTotalHours || 0,
timelineRows: timelineData.timelineRows,
totalDevices: timelineData.totalDevices
timelineRows: response?.timelineRows || [],
totalDevices: response?.totalDevices || 0
}
const maxPage = Math.max(1, Math.ceil(overviewData.value.totalDevices / pageSize.value))
if (pageNo.value > maxPage) pageNo.value = maxPage
@ -190,7 +191,6 @@ const handleQuickRangeChange = (key: QuickRangeKey) => {
timeRange: createDateRangeByQuickKey(key)
}
pageNo.value = 1
void refreshData()
}
const handleQuery = () => {
@ -202,7 +202,6 @@ const resetQuery = () => {
queryParams.value = buildDefaultQueryParams()
pageNo.value = 1
pageSize.value = 10
void refreshData()
}
const handleExport = () => {
@ -212,8 +211,13 @@ const handleExport = () => {
const handlePageSizeChange = (size: number) => {
pageSize.value = size
pageNo.value = 1
void refreshData()
}
watch(pageNo, () => {
void refreshData()
})
const getOrganizationOptions = async () => {
const data = await OrganizationApi.getOrganizationList()
organizationList.value = Array.isArray(data)
@ -251,7 +255,6 @@ watch(
onMounted(async () => {
await getOrganizationOptions()
await refreshData()
})
</script>

@ -1,59 +1,8 @@
import dayjs from 'dayjs'
import type { DeviceTimelineRow, OverviewOption, RunOverviewData, RunOverviewQueryParams, RunStatus } from './components/types'
import type { RunOverviewQueryParams } from './components/types'
const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'
const FALLBACK_DEVICE_OPTIONS: OverviewOption[] = [
{ label: '模拟设备01', value: 'device-01' },
{ label: '模拟设备02', value: 'device-02' },
{ label: '模拟设备03', value: 'device-03' },
{ label: '模拟设备04', value: 'device-04' },
{ label: '模拟设备05', value: 'device-05' },
{ label: '模拟设备06', value: 'device-06' },
{ label: '模拟设备07', value: 'device-07' },
{ label: '模拟设备08', value: 'device-08' },
{ label: '模拟设备09', value: 'device-09' },
{ label: '模拟设备10', value: 'device-10' },
{ label: '模拟设备11', value: 'device-11' },
{ label: '模拟设备12', value: 'device-12' },
{ label: '模拟设备13', value: 'device-13' }
]
const UTILIZATION_RATES = [82.35, 76.12, 68.54, 75.63, 72.18, 91.24, 65.32, 78.44, 71.05, 83.67, 69.18, 87.42, 74.56]
const TIMELINE_OFFSETS = [0, -0.3, 0.8, -0.5, 0.45, 1.05, -1.1, 0.25, -0.75, 0.6, -0.2, 1.2, -0.45]
const BASE_SEGMENTS = [
{ status: 'running' as const, startHour: 0, endHour: 2.7 },
{ status: 'standby' as const, startHour: 2.7, endHour: 3.1 },
{ status: 'running' as const, startHour: 3.1, endHour: 6.6 },
{ status: 'standby' as const, startHour: 6.6, endHour: 7.15 },
{ status: 'running' as const, startHour: 7.15, endHour: 13.9 },
{ status: 'standby' as const, startHour: 13.9, endHour: 14.25 },
{ status: 'offline' as const, startHour: 14.25, endHour: 14.95 },
{ status: 'running' as const, startHour: 14.95, endHour: 17.45 },
{ status: 'fault' as const, startHour: 17.45, endHour: 18.15 },
{ status: 'standby' as const, startHour: 18.15, endHour: 18.8 },
{ status: 'running' as const, startHour: 18.8, endHour: 20.55 },
{ status: 'standby' as const, startHour: 20.55, endHour: 20.95 },
{ status: 'running' as const, startHour: 20.95, endHour: 22.25 },
{ status: 'offline' as const, startHour: 22.25, endHour: 23.05 },
{ status: 'running' as const, startHour: 23.05, endHour: 23.7 },
{ status: 'offline' as const, startHour: 23.7, endHour: 24 }
]
const shiftTimeline = (segments: Array<{ status: RunStatus; startHour: number; endHour: number }>, offset: number) =>
segments.map((segment, index) => {
let nextStart = segment.startHour + offset
let nextEnd = segment.endHour + offset
if (index === 0 && nextStart < 0) nextStart = 0
if (index === segments.length - 1 && nextEnd > 24) nextEnd = 24
return {
...segment,
startHour: Math.max(0, Math.min(24, Number(nextStart.toFixed(2)))),
endHour: Math.max(0, Math.min(24, Number(nextEnd.toFixed(2))))
}
})
export const buildDefaultQueryParams = (): RunOverviewQueryParams => {
const start = dayjs().startOf('day')
const end = dayjs().endOf('day')
@ -64,23 +13,3 @@ export const buildDefaultQueryParams = (): RunOverviewQueryParams => {
timeRange: [start.format(DATE_TIME_FORMAT), end.format(DATE_TIME_FORMAT)]
}
}
const toTimelineRows = (deviceOptions: OverviewOption[]): DeviceTimelineRow[] =>
deviceOptions.map((device, index) => ({
id: device.value,
name: device.label,
utilizationRate: UTILIZATION_RATES[index % UTILIZATION_RATES.length],
segments: shiftTimeline(BASE_SEGMENTS, TIMELINE_OFFSETS[index % TIMELINE_OFFSETS.length])
}))
export const buildRunOverviewTimelineData = (
query: RunOverviewQueryParams,
deviceOptions: OverviewOption[] = FALLBACK_DEVICE_OPTIONS
): Pick<RunOverviewData, 'timelineRows' | 'totalDevices'> => {
const rows = toTimelineRows(deviceOptions.length > 0 ? deviceOptions : FALLBACK_DEVICE_OPTIONS)
const filteredRows = query.deviceId.length > 0 ? rows.filter((row) => query.deviceId.includes(row.id)) : rows
return {
timelineRows: filteredRows,
totalDevices: filteredRows.length
}
}

Loading…
Cancel
Save